public inbox for gentoo-commits@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-commits] proj/riscv:master commit in: www-client/firefox/files/, www-client/firefox/
@ 2022-04-20 13:23 Yixun Lan
  0 siblings, 0 replies; 2+ messages in thread
From: Yixun Lan @ 2022-04-20 13:23 UTC (permalink / raw
  To: gentoo-commits

commit:     07c4b52e96d933d680ba43f71849bae09abd41f2
Author:     Yu Gu <guyu2876 <AT> gmail <DOT> com>
AuthorDate: Wed Apr 20 13:11:25 2022 +0000
Commit:     Yixun Lan <dlan <AT> gentoo <DOT> org>
CommitDate: Wed Apr 20 13:22:29 2022 +0000
URL:        https://gitweb.gentoo.org/proj/riscv.git/commit/?id=07c4b52e

www-client/firefox: bump to 98.0.2

Compared to the original ebuild, a patch was added and
the sandbox was disabled because too many failures with 'enable-sanbox' enabled
This feature is temporarily not supported on riscv.

Some logs like:
/var/tmp/portage/www-client/firefox-98.0.2/work/firefox-98.0.2/security/sandbox/linux/reporter/SandboxReporter.cpp:35:4: error: #error "unrecognized architecture"
164:47.00 /var/tmp/portage/www-client/firefox-98.0.2/work/firefox-98.0.2/security/sandbox/chromium/sandbox/linux/system_headers/linux_signal.h:65:2: error: #error "Unsupported platform"
164:47.58 /var/tmp/portage/www-client/firefox-98.0.2/work/firefox-98.0.2/security/sandbox/chromium/sandbox/linux/bpf_dsl/seccomp_macros.h:350:2: error: #error Unsupported target platform

Closes: https://github.com/gentoo/riscv/pull/3
Signed-off-by: Yu Gu <guyu2876 <AT> gmail.com>
Signed-off-by: Yixun Lan <dlan <AT> gentoo.org>

 ...o-riscv64-support-and-zenithal-backported.patch | 47126 +++++++++++++++++++
 www-client/firefox/firefox-98.0.2.ebuild           |     4 +-
 2 files changed, 47129 insertions(+), 1 deletion(-)

diff --git a/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch b/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch
new file mode 100644
index 0000000..39ebd6a
--- /dev/null
+++ b/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch
@@ -0,0 +1,47126 @@
+From: Zenithal <i@zenithal.me>
+
+Some changes would be rejected/ignored when patching firefox 92 src,
+so I commented out some blocks, see these #-leading block below
+
+From be9cbd86b4c121dbdb626f8c373fd809f25bc23e Mon Sep 17 00:00:00 2001
+From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
+Date: Sun, 13 Jun 2021 04:06:39 +0000
+Subject: [PATCH] Update authenticator-rs
+
+---
+ .cargo/config.in                              |    5 +
+ Cargo.lock                                    |    3 +-
+ .../rust/authenticator/.cargo-checksum.json   |    2 +-
+ third_party/rust/authenticator/.clippy.toml   |    2 +
+ third_party/rust/authenticator/.flake8        |    4 +
+ .../authenticator/.pre-commit-config.yaml     |   42 +
+ third_party/rust/authenticator/.travis.yml    |   42 +
+ third_party/rust/authenticator/Cargo.lock     | 1603 -----------------
+ third_party/rust/authenticator/Cargo.toml     |  131 +-
+ third_party/rust/authenticator/build.rs       |    2 +
+ .../authenticator/src/linux/hidwrapper.rs     |    3 +
+ .../authenticator/src/linux/ioctl_riscv64.rs  |    5 +
+ toolkit/library/rust/shared/Cargo.toml        |    2 +-
+ 13 files changed, 154 insertions(+), 1692 deletions(-)
+ create mode 100644 third_party/rust/authenticator/.clippy.toml
+ create mode 100644 third_party/rust/authenticator/.flake8
+ create mode 100644 third_party/rust/authenticator/.pre-commit-config.yaml
+ create mode 100644 third_party/rust/authenticator/.travis.yml
+ delete mode 100644 third_party/rust/authenticator/Cargo.lock
+ create mode 100644 third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
+
+diff --unified --recursive --text a/.cargo/config.in b/.cargo/config.in
+--- a/.cargo/config.in  2022-03-10 14:19:43.020478706 +0800
++++ b/.cargo/config.in  2022-03-10 14:21:21.873044017 +0800
+@@ -22,11 +22,6 @@
+ replace-with = "vendored-sources"
+ rev = "3bfc47d9a571d0842676043ba60716318e946c06"
+ 
+-[source."https://github.com/mozilla/midir.git"]
+-git = "https://github.com/mozilla/midir.git"
+-replace-with = "vendored-sources"
+-rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
+-
+ [source."https://github.com/mozilla/l10nregistry-rs.git"]
+ git = "https://github.com/mozilla/l10nregistry-rs.git"
+ replace-with = "vendored-sources"
+@@ -57,6 +52,16 @@
+ replace-with = "vendored-sources"
+ rev = "a1a6ba41f0c610ebe751639f25f037474ca52941"
+ 
++[source."https://github.com/makotokato/midir.git"]
++git = "https://github.com/makotokato/midir.git"
++replace-with = "vendored-sources"
++rev = "6140b2825dd4dc2b40e49e154ca7596e7b9a131a"
++
++[source."https://github.com/makotokato/authenticator-rs"]
++git = "https://github.com/makotokato/authenticator-rs"
++replace-with = "vendored-sources"
++rev = "eed8919d50559f4959e2d7d2af7b4d48869b5366"
++
+ [source."https://github.com/kinetiknz/mio-named-pipes"]
+ git = "https://github.com/kinetiknz/mio-named-pipes"
+ replace-with = "vendored-sources"
+diff --git a/Cargo.lock b/Cargo.lock
+index 7e17939fad48b..8519d3d0e95a6 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -316,8 +316,7 @@ dependencies = [
+ [[package]]
+ name = "authenticator"
+ version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "08cee7a0952628fde958e149507c2bb321ab4fccfafd225da0b20adc956ef88a"
++source = "git+https://github.com/makotokato/authenticator-rs?rev=eed8919d50559f4959e2d7d2af7b4d48869b5366#eed8919d50559f4959e2d7d2af7b4d48869b5366"
+ dependencies = [
+  "bitflags",
+  "core-foundation",
+diff --git a/third_party/rust/authenticator/.cargo-checksum.json b/third_party/rust/authenticator/.cargo-checksum.json
+index ce451ad09df4f..9791345c9de54 100644
+--- a/third_party/rust/authenticator/.cargo-checksum.json
++++ b/third_party/rust/authenticator/.cargo-checksum.json
+@@ -1 +1 @@
+-{"files":{"Cargo.lock":"abaed4932db2206e5fdb7cb73a8c100f6c91fc84a8f33e8763677040ae8ea9bf","Cargo.toml":"9b56d5495021e7cd8ab7e019cceda45e906a2a3629a68e9019c6e5cb682dbc43","Cross.toml":"8d132da818d48492aa9f4b78a348f0df3adfae45d988d42ebd6be8a5adadb6c3","LICENSE":"e866c8f5864d4cacfe403820e722e9dc03fe3c7565efa5e4dad9051d827bb92a","README.md":"c87d9c7cc44f1dd4ef861a3a9f8cd2eb68aedd3814768871f5fb63c2070806cd","build.rs":"bc308b771ae9741d775370e3efe45e9cca166fd1d0335f4214b00497042ccc55","examples/main.rs":"d899646fa396776d0bb66efb86099ffb195566ecdb6fc4c1765ae3d54d696a8d","rustfmt.toml":"ceb6615363d6fff16426eb56f5727f98a7f7ed459ba9af735b1d8b672e2c3b9b","src/authenticatorservice.rs":"9fc5bcdd1e4f32e58ae920f96f40619a870b0a1b8d05db650803b2402a37fbf9","src/capi.rs":"1d3145ce81293bec697b0d385357fb1b0b495b0c356e2da5e6f15d028d328c70","src/consts.rs":"3dbcdfced6241822062e1aa2e6c8628af5f539ea18ee41edab51a3d33ebb77c6","src/errors.rs":"de89e57435ed1f9ff10f1f2d997a5b29d61cb215551e0ab40861a08ca52d1447",
 "src/freebsd/device.rs":"595df4b3f66b90dd73f8df67e1a2ba9a20c0b5fd893afbadbec564aa34f89981","src/freebsd/mod.rs":"42dcb57fbeb00140003a8ad39acac9b547062b8f281a3fa5deb5f92a6169dde6","src/freebsd/monitor.rs":"c10b154632fbedc3dca27197f7fc890c3d50ac1744b927e9f1e44a9e8a13506e","src/freebsd/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/freebsd/uhid.rs":"84f564d337637c1cd107ccc536b8fce2230628e144e4031e8db4d7163c9c0cb3","src/hidproto.rs":"362fc8e24b94ba431aad5ee0002f5a3364badd937c706c0ae119a5a7a2abc7c2","src/lib.rs":"12f62285a3d33347f95236b71341462a76ea1ded67651fc96ba25d7bd1dd8298","src/linux/device.rs":"d27c5f877cf96b97668579ac5db0f2685f7c969e7a5d0ddc68043eb16bfcddb8","src/linux/hidraw.rs":"ed55caa40fd518d67bb67d5af08f9adcab34f89e0ca591142d45b87f172926dd","src/linux/hidwrapper.h":"72785db3a9b27ea72b6cf13a958fee032af54304522d002f56322473978a20f9","src/linux/hidwrapper.rs":"4be65676cf3220929700bf4906938dcbd1538ba53d40c60b08f9ba8890c910f6","src/linux/io
 ctl_aarch64le.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_armle.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_mips64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsle.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64be.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpcbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_s390xbe.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86_64.rs":"2d8b265cd39a9f46
 816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/mod.rs":"446e435126d2a58f167f648dd95cba28e8ac9c17f1f799e1eaeab80ea800fc57","src/linux/monitor.rs":"9ef4e22fdcf005dd5201b42595d958ea462998c75dbfc68c8a403e7be64328e4","src/linux/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/macos/device.rs":"cc97b773254a89526164987e4b8e4181910fc3decb32acf51ca86c596ad0147b","src/macos/iokit.rs":"7dc4e7bbf8e42e2fcde0cee8e48d14d6234a5a910bd5d3c4e966d8ba6b73992f","src/macos/mod.rs":"333e561554fc901d4f6092f6e4c85823e2b0c4ff31c9188d0e6d542b71a0a07c","src/macos/monitor.rs":"d059861b4739c9272fa305b6dd91ebeb08530bd0e70a013dd999565d6f06fb30","src/macos/transaction.rs":"935b4bc79b0e50a984604a1ada96a7ef723cc283b7d33ca07f3150b1752b99f7","src/manager.rs":"5a4cdc26b9fde20e1a3dc2389f15d38d9153109bfee5119c092fbfdbd19bad8d","src/netbsd/device.rs":"3a99a989a7a8411ddb9893c371644076662a3b488d40b436601c27fd92fdf159","src/netbsd/fd.rs":"260f1a8ae04896c0eb35ab0914e11ca9291e
 7317a086c94328aa219c0e1fc1d2","src/netbsd/mod.rs":"b1c52aa29537330cebe67427062d6c94871cab2a9b0c04b2305d686f07e88fd5","src/netbsd/monitor.rs":"dfd68e026c52271b68a3a9263837c793127e9d54ed19b748ef6d13ab4c44e09a","src/netbsd/transaction.rs":"9334a832a57e717a981c13c364ed4ee80ce9798460fc6c8954723d2fcf20585a","src/netbsd/uhid.rs":"154a4587767f151e3f846cc0b79f615d5137de67afed84f19176f27ac9097908","src/openbsd/device.rs":"ae1c8de90bb515a12d571372a30322fadb5122bc69ab71caf154452caa8a644f","src/openbsd/mod.rs":"514274d414042ff84b3667a41a736e78581e22fda87ccc97c2bc05617e381a30","src/openbsd/monitor.rs":"5eb071dd3719ea305eac21ec20596463f63790f8cd1f908a59e3f9cb0b71b5ad","src/openbsd/transaction.rs":"2380c9430f4c95a1fefaaab729d8ece0d149674708d705a71dd5d2513d9e1a4c","src/statecallback.rs":"6b16f97176db1ae3fc3851fe8394e4ffc324bc6fe59313845ac3a88132fd52f1","src/statemachine.rs":"27e2655411ebc1077c200f0aa2ba429ca656fc7dd6f90e08b51492b59ec72e61","src/stub/device.rs":"5e378147e113e20160a45d395b717bd3deecb3
 27247c24b6735035f7d50861b7","src/stub/mod.rs":"6a7fec504a52d403b0241b18cd8b95088a31807571f4c0a67e4055afc74f4453","src/stub/transaction.rs":"4a2ccb2d72070a8bc61442254e063278c68212d5565ba5bfe4d47cacebf5bd1c","src/u2fhid-capi.h":"10f2658df774bb7f7f197a9f217b9e20d67b232b60a554e8ee3c3f71480ea1f6","src/u2fprotocol.rs":"72120773a948ffd667b5976c26ae27a4327769d97b0eef7a3b1e6b2b4bbb46a9","src/u2ftypes.rs":"a02d2c29790c5edfec9af320b1d4bcb93be0bbf02b881fa5aa403cfb687a25ae","src/util.rs":"d2042b2db4864f2b1192606c3251709361de7fb7521e1519190ef26a77de8e64","src/virtualdevices/mod.rs":"2c7df7691d5c150757304241351612aed4260d65b70ab0f483edbc1a5cfb5674","src/virtualdevices/software_u2f.rs":"1b86b94c6eadec6a22dffdd2b003c5324247c6412eeddb28a6094feb1c523f8e","src/virtualdevices/webdriver/mod.rs":"4a36e6dfa9f45f941d863b4039bfbcfa8eaca660bd6ed78aeb1a2962db64be5a","src/virtualdevices/webdriver/testtoken.rs":"7146e02f1a5dad2c8827dd11c12ee408c0e42a0706ac65f139998feffd42570f","src/virtualdevices/webdriver/virtu
 almanager.rs":"a55a28995c81b5affb0a74207b6dd556d272086a554676df2e675fe991d730a9","src/virtualdevices/webdriver/web_api.rs":"27206ee09c83fe25b34cad62174e42383defd8c8a5e917d30691412aacdae08f","src/windows/device.rs":"bc3f9587677c185a624c0aae7537baf9f780484ab8337929db994800b9064ba9","src/windows/mod.rs":"218e7f2fe91ecb390c12bba5a5ffdad2c1f0b22861c937f4d386262e5b3dd617","src/windows/monitor.rs":"3804dc67de46a1a6b7925c83e0df95d94ddfa1aa53a88fc845f4ff26aede57f8","src/windows/transaction.rs":"ee639f28b2dcdb7e00c922d8762fe6aa33def8c7aaeb46ec93e3a772407a9d86","src/windows/winapi.rs":"de92afb17df26216161138f18eb3b9162f3fb2cdeb74aa78173afe804ba02e00","testing/cross/powerpc64le-unknown-linux-gnu.Dockerfile":"d7463ff4376e3e0ca3fed879fab4aa975c4c0a3e7924c5b88aef9381a5d013de","testing/cross/x86_64-unknown-linux-gnu.Dockerfile":"11c79c04b07a171b0c9b63ef75fa75f33263ce76e3c1eda0879a3e723ebd0c24","testing/run_cross.sh":"cc2a7e0359f210eba2e7121f81eb8ab0125cea6e0d0f2698177b0fe2ad0c33d8","webdriver-tools
 /requirements.txt":"8236aa3dedad886f213c9b778fec80b037212d30e640b458984110211d546005","webdriver-tools/webdriver-driver.py":"82327c26ba271d1689acc87b612ab8436cb5475f0a3c0dba7baa06e7f6f5e19c"},"package":"08cee7a0952628fde958e149507c2bb321ab4fccfafd225da0b20adc956ef88a"}
+\ No newline at end of file
++{"files":{".clippy.toml":"86011295a6e2cea043b8002238f9c96b39f17aa8241aa079f44bb6e71eb62421",".flake8":"04f55f4a3c02b50dfa568ce4f7c6a47a9374b6483256811f8be702d1382576cd",".pre-commit-config.yaml":"b7920a17d5a378c7702f9c39bf5156bb8c4ea15d8691217e0a5a8e8f571b4cf7",".travis.yml":"883be088379477e7fa6f3d06b1c8d59dc41da61b6c15d2675c62113341e7b2d5","Cargo.toml":"e7334212220a6d8ca01996888275cc0d11d098e36db1bf4c5b7429051897bf3f","Cross.toml":"8d132da818d48492aa9f4b78a348f0df3adfae45d988d42ebd6be8a5adadb6c3","LICENSE":"e866c8f5864d4cacfe403820e722e9dc03fe3c7565efa5e4dad9051d827bb92a","README.md":"c87d9c7cc44f1dd4ef861a3a9f8cd2eb68aedd3814768871f5fb63c2070806cd","build.rs":"a459ee1ace052f9692817b15c702cb6e5a6dac7c7dfe74fa075662dbcf808dbe","examples/main.rs":"d899646fa396776d0bb66efb86099ffb195566ecdb6fc4c1765ae3d54d696a8d","rustfmt.toml":"ceb6615363d6fff16426eb56f5727f98a7f7ed459ba9af735b1d8b672e2c3b9b","src/authenticatorservice.rs":"9fc5bcdd1e4f32e58ae920f96f40619a870b0a1b8d05db650803b2402a37
 fbf9","src/capi.rs":"1d3145ce81293bec697b0d385357fb1b0b495b0c356e2da5e6f15d028d328c70","src/consts.rs":"3dbcdfced6241822062e1aa2e6c8628af5f539ea18ee41edab51a3d33ebb77c6","src/errors.rs":"de89e57435ed1f9ff10f1f2d997a5b29d61cb215551e0ab40861a08ca52d1447","src/freebsd/device.rs":"595df4b3f66b90dd73f8df67e1a2ba9a20c0b5fd893afbadbec564aa34f89981","src/freebsd/mod.rs":"42dcb57fbeb00140003a8ad39acac9b547062b8f281a3fa5deb5f92a6169dde6","src/freebsd/monitor.rs":"c10b154632fbedc3dca27197f7fc890c3d50ac1744b927e9f1e44a9e8a13506e","src/freebsd/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/freebsd/uhid.rs":"84f564d337637c1cd107ccc536b8fce2230628e144e4031e8db4d7163c9c0cb3","src/hidproto.rs":"362fc8e24b94ba431aad5ee0002f5a3364badd937c706c0ae119a5a7a2abc7c2","src/lib.rs":"12f62285a3d33347f95236b71341462a76ea1ded67651fc96ba25d7bd1dd8298","src/linux/device.rs":"d27c5f877cf96b97668579ac5db0f2685f7c969e7a5d0ddc68043eb16bfcddb8","src/linux/hidraw.rs":"ed55caa40fd
 518d67bb67d5af08f9adcab34f89e0ca591142d45b87f172926dd","src/linux/hidwrapper.h":"72785db3a9b27ea72b6cf13a958fee032af54304522d002f56322473978a20f9","src/linux/hidwrapper.rs":"753c7459dbb73befdd186b6269ac33f7a4537b4c935928f50f2b2131756e787d","src/linux/ioctl_aarch64le.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_armle.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_mips64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsle.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64be.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpcbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9
 d5a5322c3047d474fd","src/linux/ioctl_riscv64.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_s390xbe.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86_64.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/mod.rs":"446e435126d2a58f167f648dd95cba28e8ac9c17f1f799e1eaeab80ea800fc57","src/linux/monitor.rs":"9ef4e22fdcf005dd5201b42595d958ea462998c75dbfc68c8a403e7be64328e4","src/linux/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/macos/device.rs":"cc97b773254a89526164987e4b8e4181910fc3decb32acf51ca86c596ad0147b","src/macos/iokit.rs":"7dc4e7bbf8e42e2fcde0cee8e48d14d6234a5a910bd5d3c4e966d8ba6b73992f","src/macos/mod.rs":"333e561554fc901d4f6092f6e4c85823e2b0c4ff31c9188d0e6d542b71a0a07c","src/macos/monitor.rs":"d059861b4739c9272fa305b6dd91ebeb08530bd0e
 70a013dd999565d6f06fb30","src/macos/transaction.rs":"935b4bc79b0e50a984604a1ada96a7ef723cc283b7d33ca07f3150b1752b99f7","src/manager.rs":"5a4cdc26b9fde20e1a3dc2389f15d38d9153109bfee5119c092fbfdbd19bad8d","src/netbsd/device.rs":"3a99a989a7a8411ddb9893c371644076662a3b488d40b436601c27fd92fdf159","src/netbsd/fd.rs":"260f1a8ae04896c0eb35ab0914e11ca9291e7317a086c94328aa219c0e1fc1d2","src/netbsd/mod.rs":"b1c52aa29537330cebe67427062d6c94871cab2a9b0c04b2305d686f07e88fd5","src/netbsd/monitor.rs":"dfd68e026c52271b68a3a9263837c793127e9d54ed19b748ef6d13ab4c44e09a","src/netbsd/transaction.rs":"9334a832a57e717a981c13c364ed4ee80ce9798460fc6c8954723d2fcf20585a","src/netbsd/uhid.rs":"154a4587767f151e3f846cc0b79f615d5137de67afed84f19176f27ac9097908","src/openbsd/device.rs":"ae1c8de90bb515a12d571372a30322fadb5122bc69ab71caf154452caa8a644f","src/openbsd/mod.rs":"514274d414042ff84b3667a41a736e78581e22fda87ccc97c2bc05617e381a30","src/openbsd/monitor.rs":"5eb071dd3719ea305eac21ec20596463f63790f8cd1f908a59e3
 f9cb0b71b5ad","src/openbsd/transaction.rs":"2380c9430f4c95a1fefaaab729d8ece0d149674708d705a71dd5d2513d9e1a4c","src/statecallback.rs":"6b16f97176db1ae3fc3851fe8394e4ffc324bc6fe59313845ac3a88132fd52f1","src/statemachine.rs":"27e2655411ebc1077c200f0aa2ba429ca656fc7dd6f90e08b51492b59ec72e61","src/stub/device.rs":"5e378147e113e20160a45d395b717bd3deecb327247c24b6735035f7d50861b7","src/stub/mod.rs":"6a7fec504a52d403b0241b18cd8b95088a31807571f4c0a67e4055afc74f4453","src/stub/transaction.rs":"4a2ccb2d72070a8bc61442254e063278c68212d5565ba5bfe4d47cacebf5bd1c","src/u2fhid-capi.h":"10f2658df774bb7f7f197a9f217b9e20d67b232b60a554e8ee3c3f71480ea1f6","src/u2fprotocol.rs":"72120773a948ffd667b5976c26ae27a4327769d97b0eef7a3b1e6b2b4bbb46a9","src/u2ftypes.rs":"a02d2c29790c5edfec9af320b1d4bcb93be0bbf02b881fa5aa403cfb687a25ae","src/util.rs":"d2042b2db4864f2b1192606c3251709361de7fb7521e1519190ef26a77de8e64","src/virtualdevices/mod.rs":"2c7df7691d5c150757304241351612aed4260d65b70ab0f483edbc1a5cfb5674","src/v
 irtualdevices/software_u2f.rs":"1b86b94c6eadec6a22dffdd2b003c5324247c6412eeddb28a6094feb1c523f8e","src/virtualdevices/webdriver/mod.rs":"4a36e6dfa9f45f941d863b4039bfbcfa8eaca660bd6ed78aeb1a2962db64be5a","src/virtualdevices/webdriver/testtoken.rs":"7146e02f1a5dad2c8827dd11c12ee408c0e42a0706ac65f139998feffd42570f","src/virtualdevices/webdriver/virtualmanager.rs":"a55a28995c81b5affb0a74207b6dd556d272086a554676df2e675fe991d730a9","src/virtualdevices/webdriver/web_api.rs":"27206ee09c83fe25b34cad62174e42383defd8c8a5e917d30691412aacdae08f","src/windows/device.rs":"bc3f9587677c185a624c0aae7537baf9f780484ab8337929db994800b9064ba9","src/windows/mod.rs":"218e7f2fe91ecb390c12bba5a5ffdad2c1f0b22861c937f4d386262e5b3dd617","src/windows/monitor.rs":"3804dc67de46a1a6b7925c83e0df95d94ddfa1aa53a88fc845f4ff26aede57f8","src/windows/transaction.rs":"ee639f28b2dcdb7e00c922d8762fe6aa33def8c7aaeb46ec93e3a772407a9d86","src/windows/winapi.rs":"de92afb17df26216161138f18eb3b9162f3fb2cdeb74aa78173afe804ba02e00",
 "testing/cross/powerpc64le-unknown-linux-gnu.Dockerfile":"d7463ff4376e3e0ca3fed879fab4aa975c4c0a3e7924c5b88aef9381a5d013de","testing/cross/x86_64-unknown-linux-gnu.Dockerfile":"11c79c04b07a171b0c9b63ef75fa75f33263ce76e3c1eda0879a3e723ebd0c24","testing/run_cross.sh":"cc2a7e0359f210eba2e7121f81eb8ab0125cea6e0d0f2698177b0fe2ad0c33d8","webdriver-tools/requirements.txt":"8236aa3dedad886f213c9b778fec80b037212d30e640b458984110211d546005","webdriver-tools/webdriver-driver.py":"82327c26ba271d1689acc87b612ab8436cb5475f0a3c0dba7baa06e7f6f5e19c"},"package":null}
+\ No newline at end of file
+diff --git a/third_party/rust/authenticator/.clippy.toml b/third_party/rust/authenticator/.clippy.toml
+new file mode 100644
+index 0000000000000..844d0757e91f4
+--- /dev/null
++++ b/third_party/rust/authenticator/.clippy.toml
+@@ -0,0 +1,2 @@
++type-complexity-threshold = 384
++too-many-arguments-threshold = 8
+diff --git a/third_party/rust/authenticator/.flake8 b/third_party/rust/authenticator/.flake8
+new file mode 100644
+index 0000000000000..5a725c9b4ce65
+--- /dev/null
++++ b/third_party/rust/authenticator/.flake8
+@@ -0,0 +1,4 @@
++[flake8]
++# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
++ignore = E121, E123, E126, E129, E133, E203, E226, E241, E242, E704, W503, E402, E741
++max-line-length = 99
+diff --git a/third_party/rust/authenticator/.pre-commit-config.yaml b/third_party/rust/authenticator/.pre-commit-config.yaml
+new file mode 100644
+index 0000000000000..e0ceb8ea5473c
+--- /dev/null
++++ b/third_party/rust/authenticator/.pre-commit-config.yaml
+@@ -0,0 +1,42 @@
++- repo: git://github.com/pre-commit/pre-commit-hooks
++  rev: HEAD
++  hooks:
++    - id: flake8
++    - id: check-ast
++    - id: detect-private-key
++    - id: detect-aws-credentials
++    - id: check-merge-conflict
++    - id: end-of-file-fixer
++    - id: requirements-txt-fixer
++    - id: trailing-whitespace
++- repo: local
++  hooks:
++    - id: rustfmt
++      name: Check rustfmt
++      language: system
++      entry: cargo fmt -- --check
++      pass_filenames: false
++      files: '.rs$'
++- repo: local
++  hooks:
++    - id: tests
++      name: Run tests
++      language: system
++      entry: cargo test --all-targets --all-features
++      pass_filenames: false
++      files: '.rs$'
++- repo: local
++  hooks:
++    - id: clippy
++      name: Check clippy
++      language: system
++      entry: cargo clippy --all-targets -- -A renamed_and_removed_lints -A clippy::new-ret-no-self -D warnings
++      pass_filenames: false
++      files: '.rs$'
++- repo: local
++  hooks:
++    - id: black
++      name: Check black
++      language: system
++      entry: black
++      files: '.py$'
+diff --git a/third_party/rust/authenticator/.travis.yml b/third_party/rust/authenticator/.travis.yml
+new file mode 100644
+index 0000000000000..70ea5c5581af2
+--- /dev/null
++++ b/third_party/rust/authenticator/.travis.yml
+@@ -0,0 +1,42 @@
++os:
++  - linux
++  - windows
++
++language: rust
++rust:
++  - stable
++  - nightly
++cache: cargo
++
++jobs:
++  allow_failures:
++    - rust: nightly
++
++addons:
++  apt:
++    packages:
++      - build-essential
++      - libudev-dev
++
++install:
++  - rustup component add rustfmt
++  - rustup component add clippy
++
++script:
++- |
++  if [ "$TRAVIS_RUST_VERSION" == "nightly" ] && [ "$TRAVIS_OS_NAME" == "linux" ] ; then
++    export ASAN_OPTIONS="detect_odr_violation=1:leak_check_at_exit=0:detect_leaks=0"
++    export RUSTFLAGS="-Z sanitizer=address"
++  fi
++- |
++  if [ "$TRAVIS_RUST_VERSION" == "stable" ] && [ "$TRAVIS_OS_NAME" == "linux" ] ; then
++    echo "Running rustfmt"
++    cargo fmt --all -- --check
++    echo "Running clippy"
++    cargo clippy --all-targets --all-features -- -A renamed_and_removed_lints -A clippy::new-ret-no-self -D warnings
++
++    rustup install nightly
++    cargo install cargo-fuzz
++    cargo +nightly fuzz build
++  fi
++- cargo test --all-targets --all-features
+diff --git a/third_party/rust/authenticator/Cargo.lock b/third_party/rust/authenticator/Cargo.lock
+deleted file mode 100644
+index 9f284b468deaa..0000000000000
+--- a/third_party/rust/authenticator/Cargo.lock
++++ /dev/null
+@@ -1,1603 +0,0 @@
+-# This file is automatically @generated by Cargo.
+-# It is not intended for manual editing.
+-[[package]]
+-name = "aho-corasick"
+-version = "0.7.13"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "ansi_term"
+-version = "0.11.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "assert_matches"
+-version = "1.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "atty"
+-version = "0.2.14"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "authenticator"
+-version = "0.3.1"
+-dependencies = [
+- "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "core-foundation 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "devd-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
+- "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "warp 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "autocfg"
+-version = "0.1.7"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "autocfg"
+-version = "1.0.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "base64"
+-version = "0.10.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "base64"
+-version = "0.12.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "bindgen"
+-version = "0.51.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "bitflags"
+-version = "1.2.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "block-buffer"
+-version = "0.7.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "block-buffer"
+-version = "0.9.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "block-padding"
+-version = "0.1.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "buf_redux"
+-version = "0.8.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "byte-tools"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "byteorder"
+-version = "1.3.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "bytes"
+-version = "0.5.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "cc"
+-version = "1.0.58"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "cexpr"
+-version = "0.3.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "cfg-if"
+-version = "0.1.10"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "clang-sys"
+-version = "0.28.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "clap"
+-version = "2.33.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "cloudabi"
+-version = "0.0.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "core-foundation"
+-version = "0.9.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "core-foundation-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "core-foundation-sys"
+-version = "0.8.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "cpuid-bool"
+-version = "0.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "devd-rs"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "digest"
+-version = "0.8.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "digest"
+-version = "0.9.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "dtoa"
+-version = "0.4.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "env_logger"
+-version = "0.6.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+- "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+- "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "fake-simd"
+-version = "0.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "fnv"
+-version = "1.0.7"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "fuchsia-cprng"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "fuchsia-zircon"
+-version = "0.3.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "fuchsia-zircon-sys"
+-version = "0.3.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "futures"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "futures-channel"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "futures-core"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "futures-io"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "futures-sink"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "futures-task"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "futures-util"
+-version = "0.3.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "generic-array"
+-version = "0.12.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "generic-array"
+-version = "0.14.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "getopts"
+-version = "0.2.21"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "getrandom"
+-version = "0.1.14"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "glob"
+-version = "0.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "h2"
+-version = "0.2.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "hashbrown"
+-version = "0.9.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "headers"
+-version = "0.3.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "headers-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+- "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "headers-core"
+-version = "0.2.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "hermit-abi"
+-version = "0.1.15"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "http"
+-version = "0.2.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "http-body"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "httparse"
+-version = "1.3.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "humantime"
+-version = "1.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "hyper"
+-version = "0.13.7"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+- "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+- "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "idna"
+-version = "0.2.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "indexmap"
+-version = "1.6.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "input_buffer"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "iovec"
+-version = "0.1.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "itoa"
+-version = "0.4.6"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "kernel32-sys"
+-version = "0.2.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "lazy_static"
+-version = "1.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "libc"
+-version = "0.2.73"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "libloading"
+-version = "0.5.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "libudev"
+-version = "0.2.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libudev-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "libudev-sys"
+-version = "0.1.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "log"
+-version = "0.4.11"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "matches"
+-version = "0.1.8"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "memchr"
+-version = "2.3.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "mime"
+-version = "0.3.16"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "mime_guess"
+-version = "2.0.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+- "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "mio"
+-version = "0.6.22"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
+- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "miow"
+-version = "0.2.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "multipart"
+-version = "0.17.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "net2"
+-version = "0.2.35"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "nom"
+-version = "4.2.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "nom"
+-version = "5.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "once_cell"
+-version = "1.4.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "opaque-debug"
+-version = "0.2.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "opaque-debug"
+-version = "0.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "peeking_take_while"
+-version = "0.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "percent-encoding"
+-version = "2.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "pin-project"
+-version = "0.4.23"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "pin-project-internal"
+-version = "0.4.23"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "pin-project-lite"
+-version = "0.1.7"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "pin-utils"
+-version = "0.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "pkg-config"
+-version = "0.3.18"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "ppv-lite86"
+-version = "0.2.8"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "proc-macro2"
+-version = "1.0.19"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "quick-error"
+-version = "1.2.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "quote"
+-version = "1.0.7"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand"
+-version = "0.6.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand"
+-version = "0.7.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_chacha"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_chacha"
+-version = "0.2.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_core"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_core"
+-version = "0.4.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "rand_core"
+-version = "0.5.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_hc"
+-version = "0.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_hc"
+-version = "0.2.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_isaac"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_jitter"
+-version = "0.1.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_os"
+-version = "0.1.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_pcg"
+-version = "0.1.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rand_xorshift"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "rdrand"
+-version = "0.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "redox_syscall"
+-version = "0.1.57"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "regex"
+-version = "1.3.9"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)",
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
+- "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "regex-syntax"
+-version = "0.6.18"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "remove_dir_all"
+-version = "0.5.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "runloop"
+-version = "0.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "rustc-hash"
+-version = "1.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "ryu"
+-version = "1.0.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "safemem"
+-version = "0.3.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "scoped-tls"
+-version = "1.0.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "serde"
+-version = "1.0.116"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "serde_derive"
+-version = "1.0.116"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "serde_json"
+-version = "1.0.57"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "serde_urlencoded"
+-version = "0.6.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+- "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "sha-1"
+-version = "0.8.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "sha-1"
+-version = "0.9.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "sha2"
+-version = "0.8.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "shlex"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "slab"
+-version = "0.4.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "socket2"
+-version = "0.3.15"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "strsim"
+-version = "0.8.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "syn"
+-version = "1.0.41"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tempfile"
+-version = "3.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
+- "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "termcolor"
+-version = "1.1.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "textwrap"
+-version = "0.11.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "thread_local"
+-version = "1.0.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "time"
+-version = "0.1.44"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+- "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tinyvec"
+-version = "0.3.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "tokio"
+-version = "0.2.22"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tokio-macros"
+-version = "0.2.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tokio-tungstenite"
+-version = "0.11.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tungstenite 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tokio-util"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tower-service"
+-version = "0.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "tracing"
+-version = "0.1.19"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tracing-core"
+-version = "0.1.16"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "tracing-futures"
+-version = "0.2.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "try-lock"
+-version = "0.2.3"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "tungstenite"
+-version = "0.11.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "input_buffer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "twoway"
+-version = "0.1.8"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "typenum"
+-version = "1.12.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "unicase"
+-version = "2.6.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "unicode-bidi"
+-version = "0.3.4"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "unicode-normalization"
+-version = "0.1.13"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "unicode-width"
+-version = "0.1.8"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "unicode-xid"
+-version = "0.2.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "url"
+-version = "2.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "urlencoding"
+-version = "1.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "utf-8"
+-version = "0.7.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "vec_map"
+-version = "0.8.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "version_check"
+-version = "0.1.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "version_check"
+-version = "0.9.2"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "want"
+-version = "0.3.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "warp"
+-version = "0.2.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
+- "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
+- "headers 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
+- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
+- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
+- "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
+- "multipart 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
+- "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
+- "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tokio-tungstenite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
+- "tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
+- "urlencoding 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "wasi"
+-version = "0.9.0+wasi-snapshot-preview1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "wasi"
+-version = "0.10.0+wasi-snapshot-preview1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "which"
+-version = "3.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "winapi"
+-version = "0.2.8"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "winapi"
+-version = "0.3.9"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "winapi-build"
+-version = "0.1.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "winapi-i686-pc-windows-gnu"
+-version = "0.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "winapi-util"
+-version = "0.1.5"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[[package]]
+-name = "winapi-x86_64-pc-windows-gnu"
+-version = "0.4.0"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-
+-[[package]]
+-name = "ws2_32-sys"
+-version = "0.2.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-dependencies = [
+- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+-]
+-
+-[metadata]
+-"checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
+-"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
+-"checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5"
+-"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+-"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
+-"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+-"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
+-"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
+-"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
+-"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+-"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
+-"checksum block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
+-"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
+-"checksum buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
+-"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
+-"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
+-"checksum bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
+-"checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
+-"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
+-"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+-"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
+-"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
+-"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
+-"checksum core-foundation 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5ed8e7e76c45974e15e41bfa8d5b0483cd90191639e01d8f5f1e606299d3fb"
+-"checksum core-foundation-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6"
+-"checksum cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
+-"checksum devd-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1945ccb7caedabdfb9347766ead740fb1e0582b7425598325f546adbd832cce1"
+-"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
+-"checksum digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
+-"checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
+-"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
+-"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
+-"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+-"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
+-"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+-"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+-"checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
+-"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
+-"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
+-"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
+-"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
+-"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
+-"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
+-"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
+-"checksum generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
+-"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
+-"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
+-"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+-"checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
+-"checksum hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
+-"checksum headers 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f"
+-"checksum headers-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
+-"checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
+-"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
+-"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
+-"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
+-"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
+-"checksum hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb"
+-"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
+-"checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
+-"checksum input_buffer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754"
+-"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+-"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
+-"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+-"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+-"checksum libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
+-"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
+-"checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
+-"checksum libudev-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
+-"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
+-"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+-"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
+-"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+-"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
+-"checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
+-"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
+-"checksum multipart 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8209c33c951f07387a8497841122fc6f712165e3f9bda3e6be4645b58188f676"
+-"checksum net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
+-"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
+-"checksum nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
+-"checksum once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
+-"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
+-"checksum opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
+-"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+-"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+-"checksum pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa"
+-"checksum pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
+-"checksum pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
+-"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+-"checksum pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
+-"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
+-"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
+-"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+-"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
+-"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
+-"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+-"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
+-"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+-"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
+-"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
+-"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+-"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
+-"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+-"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
+-"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
+-"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
+-"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
+-"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
+-"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
+-"checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
+-"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
+-"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
+-"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+-"checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
+-"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+-"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
+-"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
+-"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
+-"checksum serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
+-"checksum serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
+-"checksum serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
+-"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
+-"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
+-"checksum sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770"
+-"checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
+-"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
+-"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+-"checksum socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
+-"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
+-"checksum syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
+-"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
+-"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
+-"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+-"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
+-"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
+-"checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
+-"checksum tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
+-"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
+-"checksum tokio-tungstenite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c"
+-"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
+-"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
+-"checksum tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c"
+-"checksum tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a"
+-"checksum tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
+-"checksum try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+-"checksum tungstenite 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23"
+-"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
+-"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
+-"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+-"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
+-"checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
+-"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
+-"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
+-"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
+-"checksum urlencoding 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593"
+-"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
+-"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+-"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
+-"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
+-"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+-"checksum warp 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407"
+-"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+-"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+-"checksum which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
+-"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+-"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+-"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+-"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+-"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+-"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+-"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+diff --git a/third_party/rust/authenticator/Cargo.toml b/third_party/rust/authenticator/Cargo.toml
+index 57d24bd66b948..c49befae2178c 100644
+--- a/third_party/rust/authenticator/Cargo.toml
++++ b/third_party/rust/authenticator/Cargo.toml
+@@ -1,99 +1,60 @@
+-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+-#
+-# When uploading crates to the registry Cargo will automatically
+-# "normalize" Cargo.toml files for maximal compatibility
+-# with all versions of Cargo and also rewrite `path` dependencies
+-# to registry (e.g., crates.io) dependencies
+-#
+-# If you believe there's an error in this file please file an
+-# issue against the rust-lang/cargo repository. If you're
+-# editing this file be aware that the upstream Cargo.toml
+-# will likely look very different (and much more reasonable)
+-
+ [package]
+-edition = "2018"
+ name = "authenticator"
+ version = "0.3.1"
+ authors = ["J.C. Jones <jc@mozilla.com>", "Tim Taubert <ttaubert@mozilla.com>", "Kyle Machulis <kyle@nonpolynomial.com>"]
+-description = "Library for interacting with CTAP1/2 security keys for Web Authentication. Used by Firefox."
+ keywords = ["ctap2", "u2f", "fido", "webauthn"]
+ categories = ["cryptography", "hardware-support", "os"]
+-license = "MPL-2.0"
+ repository = "https://github.com/mozilla/authenticator-rs/"
+-[dependencies.base64]
+-version = "^0.10"
+-optional = true
+-
+-[dependencies.bitflags]
+-version = "1.0"
+-
+-[dependencies.bytes]
+-version = "0.5"
+-features = ["serde"]
+-optional = true
+-
+-[dependencies.libc]
+-version = "0.2"
+-
+-[dependencies.log]
+-version = "0.4"
+-
+-[dependencies.rand]
+-version = "0.7"
+-
+-[dependencies.runloop]
+-version = "0.1.0"
+-
+-[dependencies.serde]
+-version = "1.0"
+-features = ["derive"]
+-optional = true
+-
+-[dependencies.serde_json]
+-version = "1.0"
+-optional = true
+-
+-[dependencies.tokio]
+-version = "0.2"
+-features = ["macros"]
+-optional = true
++license = "MPL-2.0"
++description = "Library for interacting with CTAP1/2 security keys for Web Authentication. Used by Firefox."
++edition = "2018"
+ 
+-[dependencies.warp]
+-version = "0.2.4"
+-optional = true
+-[dev-dependencies.assert_matches]
+-version = "1.2"
++[badges]
++travis-ci = { repository = "mozilla/authenticator-rs", branch = "master" }
++maintenance = { status = "actively-developed" }
+ 
+-[dev-dependencies.base64]
+-version = "^0.10"
++[features]
++binding-recompile = ["bindgen"]
++webdriver = ["base64", "bytes", "warp", "tokio", "serde", "serde_json"]
+ 
+-[dev-dependencies.env_logger]
+-version = "^0.6"
++[target.'cfg(target_os = "linux")'.dependencies]
++libudev = "^0.2"
+ 
+-[dev-dependencies.getopts]
+-version = "^0.2"
++[target.'cfg(target_os = "freebsd")'.dependencies]
++devd-rs = "0.3"
+ 
+-[dev-dependencies.sha2]
+-version = "^0.8.2"
+-[build-dependencies.bindgen]
+-version = "^0.51"
+-optional = true
++[target.'cfg(target_os = "macos")'.dependencies]
++core-foundation = "0.9"
+ 
+-[features]
+-binding-recompile = ["bindgen"]
+-webdriver = ["base64", "bytes", "warp", "tokio", "serde", "serde_json"]
+-[target."cfg(target_os = \"freebsd\")".dependencies.devd-rs]
+-version = "0.3"
+-[target."cfg(target_os = \"linux\")".dependencies.libudev]
+-version = "^0.2"
+-[target."cfg(target_os = \"macos\")".dependencies.core-foundation]
+-version = "0.9"
+-[target."cfg(target_os = \"windows\")".dependencies.winapi]
++[target.'cfg(target_os = "windows")'.dependencies.winapi]
+ version = "^0.3"
+-features = ["handleapi", "hidclass", "hidpi", "hidusage", "setupapi"]
+-[badges.maintenance]
+-status = "actively-developed"
+-
+-[badges.travis-ci]
+-branch = "master"
+-repository = "mozilla/authenticator-rs"
++features = [
++    "handleapi",
++    "hidclass",
++    "hidpi",
++    "hidusage",
++    "setupapi",
++]
++
++[build-dependencies]
++bindgen = { version = "^0.58.1", optional = true }
++
++[dependencies]
++rand = "0.7"
++log = "0.4"
++libc = "0.2"
++runloop = "0.1.0"
++bitflags = "1.0"
++tokio = { version = "0.2", optional = true, features = ["macros"] }
++warp = { version = "0.2.4", optional = true }
++serde = { version = "1.0", optional = true, features = ["derive"] }
++serde_json = { version = "1.0", optional = true }
++bytes = { version = "0.5", optional = true, features = ["serde"] }
++base64 = { version = "^0.10", optional = true }
++
++[dev-dependencies]
++sha2 = "^0.8.2"
++base64 = "^0.10"
++env_logger = "^0.6"
++getopts = "^0.2"
++assert_matches = "1.2"
+diff --git a/third_party/rust/authenticator/build.rs b/third_party/rust/authenticator/build.rs
+index 299e4df6d7331..c972d85b898ea 100644
+--- a/third_party/rust/authenticator/build.rs
++++ b/third_party/rust/authenticator/build.rs
+@@ -45,6 +45,8 @@ fn main() {
+         "ioctl_aarch64be.rs"
+     } else if cfg!(all(target_arch = "s390x", target_endian = "big")) {
+         "ioctl_s390xbe.rs"
++    } else if cfg!(all(target_arch = "riscv64", target_endian = "little")) {
++        "ioctl_riscv64.rs"
+     } else {
+         panic!("architecture not supported");
+     };
+diff --git a/third_party/rust/authenticator/src/linux/hidwrapper.rs b/third_party/rust/authenticator/src/linux/hidwrapper.rs
+index ea1a39051b63a..82aabc6301017 100644
+--- a/third_party/rust/authenticator/src/linux/hidwrapper.rs
++++ b/third_party/rust/authenticator/src/linux/hidwrapper.rs
+@@ -46,3 +46,6 @@ include!("ioctl_aarch64be.rs");
+ 
+ #[cfg(all(target_arch = "s390x", target_endian = "big"))]
+ include!("ioctl_s390xbe.rs");
++
++#[cfg(all(target_arch = "riscv64", target_endian = "little"))]
++include!("ioctl_riscv64.rs");
+diff --git a/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs b/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
+new file mode 100644
+index 0000000000000..a784e9bf4600b
+--- /dev/null
++++ b/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
+@@ -0,0 +1,5 @@
++/* automatically generated by rust-bindgen */
++
++pub type __u32 = ::std::os::raw::c_uint;
++pub const _HIDIOCGRDESCSIZE: __u32 = 2147764225;
++pub const _HIDIOCGRDESC: __u32 = 2416199682;
+--- a/toolkit/library/rust/shared/Cargo.toml    2022-02-10 20:41:52.387673027 +0800
++++ b/toolkit/library/rust/shared/Cargo.toml    2022-02-12 17:34:42.861720793 +0800
+@@ -24,7 +24,7 @@
+ cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="f2456201dbfdc467b80f0ff6bbb1b8a6faf7df02", optional = true, features=["pulse-dlopen"] }
+ cubeb-sys = { version = "0.9", optional = true, features=["gecko-in-tree"] }
+ encoding_glue = { path = "../../../../intl/encoding_glue" }
+-authenticator = "0.3.1"
++authenticator = { git = "https://github.com/makotokato/authenticator-rs", rev = "eed8919d50559f4959e2d7d2af7b4d48869b5366" }
+ gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
+ gecko_logger = { path = "../../../../xpcom/rust/gecko_logger" }
+ rsdparsa_capi = { path = "../../../../dom/media/webrtc/sdp/rsdparsa_capi" }
+From a418c651c88cd2682c4cfe61e9f57b5389078c09 Mon Sep 17 00:00:00 2001
+From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
+Date: Thu, 17 Jun 2021 21:50:49 +0900
+Subject: [PATCH] signal handler
+
+---
+ js/src/wasm/WasmSignalHandlers.cpp | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+--- a/js/src/wasm/WasmSignalHandlers.cpp        2022-02-12 19:29:33.566924464 +0800
++++ b/js/src/wasm/WasmSignalHandlers.cpp        2022-02-12 19:50:29.499985612 +0800
+@@ -156,6 +156,11 @@
+ #      define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
+ #      define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
+ #    endif
++#  if defined(__linux__) && defined(__riscv) && __riscv_xlen == 64
++#    define EPC_sig(p) ((p)->uc_mcontext.__gregs[0])
++#    define X02_sig(p) ((p)->uc_mcontext.__gregs[2])
++#    define X08_sig(p) ((p)->uc_mcontext.__gregs[8])
++#  endif
+ #  elif defined(__NetBSD__)
+ #    define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
+ #    define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
+@@ -376,6 +381,10 @@
+ #    define PC_sig(p) R32_sig(p)
+ #    define SP_sig(p) R01_sig(p)
+ #    define FP_sig(p) R01_sig(p)
++#elif defined(__riscv) && __riscv_xlen == 64
++#  define PC_sig(p) EPC_sig(p)
++#  define SP_sig(p) X02_sig(p)
++#  define FP_sig(p) X08_sig(p)
+ #  endif
+ 
+ static void SetContextPC(CONTEXT* context, uint8_t* pc) {
+From b6be52755af09f55e78d86bdd02a99efa0d16f9f Mon Sep 17 00:00:00 2001
+From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
+Date: Fri, 28 Jan 2022 12:21:06 +0900
+Subject: [PATCH] mach vendor rust
+
+---
+ .cargo/config.in                              |   10 +-
+ Cargo.lock                                    |   29 +-
+ Cargo.toml                                    |    3 +-
+ .../mozbuild/mozbuild/vendor/vendor_rust.py   |    1 +
+ third_party/rust/alsa/.cargo-checksum.json    |    2 +-
+ third_party/rust/alsa/Cargo.toml              |    8 +-
+ third_party/rust/alsa/src/direct/pcm.rs       |    2 +-
+ third_party/rust/alsa/src/error.rs            |    1 -
+ third_party/rust/alsa/src/lib.rs              |    8 +-
+ third_party/rust/alsa/src/mixer.rs            |    8 +
+ third_party/rust/alsa/src/pcm.rs              |   78 +-
+ .../rust/bitflags/.cargo-checksum.json        |    2 +-
+ third_party/rust/bitflags/CHANGELOG.md        |   57 -
+ third_party/rust/bitflags/Cargo.toml          |   34 +-
+ third_party/rust/bitflags/README.md           |   12 +-
+ third_party/rust/bitflags/build.rs            |   44 +
+ third_party/rust/bitflags/src/lib.rs          |  873 ++----
+ third_party/rust/bitflags/tests/basic.rs      |   20 -
+ .../bitflags/tests/compile-fail/impls/copy.rs |   10 -
+ .../tests/compile-fail/impls/copy.stderr.beta |   27 -
+ .../bitflags/tests/compile-fail/impls/eq.rs   |   10 -
+ .../tests/compile-fail/impls/eq.stderr.beta   |   55 -
+ .../non_integer_base/all_defined.rs           |  123 -
+ .../non_integer_base/all_defined.stderr.beta  |   27 -
+ .../non_integer_base/all_missing.rs           |   13 -
+ .../non_integer_base/all_missing.stderr.beta  |   13 -
+ .../compile-fail/visibility/private_field.rs  |   13 -
+ .../visibility/private_field.stderr.beta      |   10 -
+ .../compile-fail/visibility/private_flags.rs  |   18 -
+ .../visibility/private_flags.stderr.beta      |   18 -
+ .../compile-fail/visibility/pub_const.rs      |    9 -
+ .../visibility/pub_const.stderr.beta          |    5 -
+ .../tests/compile-pass/impls/convert.rs       |   17 -
+ .../tests/compile-pass/impls/default.rs       |   10 -
+ .../compile-pass/impls/inherent_methods.rs    |   15 -
+ .../tests/compile-pass/redefinition/core.rs   |   14 -
+ .../compile-pass/redefinition/stringify.rs    |   19 -
+ .../bitflags/tests/compile-pass/repr/c.rs     |   10 -
+ .../tests/compile-pass/repr/transparent.rs    |   10 -
+ .../compile-pass/visibility/bits_field.rs     |   11 -
+ .../tests/compile-pass/visibility/pub_in.rs   |   19 -
+ third_party/rust/bitflags/tests/compile.rs    |   63 -
+ third_party/rust/midir/.cargo-checksum.json   |    2 +-
+ third_party/rust/midir/Cargo.toml             |    4 +-
+ .../rust/nix-0.15.0/.cargo-checksum.json      |    1 +
+ third_party/rust/nix-0.15.0/CHANGELOG.md      |  742 +++++
+ third_party/rust/nix-0.15.0/CONTRIBUTING.md   |  114 +
+ third_party/rust/nix-0.15.0/CONVENTIONS.md    |   87 +
+ third_party/rust/nix-0.15.0/Cargo.toml        |   71 +
+ third_party/rust/nix-0.15.0/LICENSE           |   21 +
+ third_party/rust/nix-0.15.0/README.md         |  111 +
+ third_party/rust/{nix => nix-0.15.0}/build.rs |    0
+ third_party/rust/nix-0.15.0/src/dir.rs        |  193 ++
+ third_party/rust/nix-0.15.0/src/errno.rs      | 1963 ++++++++++++++
+ .../{nix => nix-0.15.0}/src/errno_dragonfly.c |    0
+ third_party/rust/nix-0.15.0/src/fcntl.rs      |  506 ++++
+ third_party/rust/nix-0.15.0/src/features.rs   |  103 +
+ third_party/rust/nix-0.15.0/src/ifaddrs.rs    |  146 +
+ third_party/rust/nix-0.15.0/src/kmod.rs       |  123 +
+ third_party/rust/nix-0.15.0/src/lib.rs        |  284 ++
+ third_party/rust/nix-0.15.0/src/macros.rs     |  264 ++
+ third_party/rust/nix-0.15.0/src/mount.rs      |   98 +
+ third_party/rust/nix-0.15.0/src/mqueue.rs     |  162 ++
+ third_party/rust/nix-0.15.0/src/net/if_.rs    |  268 ++
+ third_party/rust/nix-0.15.0/src/net/mod.rs    |    4 +
+ third_party/rust/nix-0.15.0/src/poll.rs       |  143 +
+ third_party/rust/nix-0.15.0/src/pty.rs        |  326 +++
+ third_party/rust/nix-0.15.0/src/sched.rs      |  147 +
+ third_party/rust/nix-0.15.0/src/sys/aio.rs    | 1280 +++++++++
+ third_party/rust/nix-0.15.0/src/sys/epoll.rs  |  109 +
+ third_party/rust/nix-0.15.0/src/sys/event.rs  |  351 +++
+ .../rust/nix-0.15.0/src/sys/eventfd.rs        |   18 +
+ .../rust/nix-0.15.0/src/sys/inotify.rs        |  230 ++
+ .../rust/nix-0.15.0/src/sys/ioctl/bsd.rs      |  102 +
+ .../rust/nix-0.15.0/src/sys/ioctl/linux.rs    |  140 +
+ .../rust/nix-0.15.0/src/sys/ioctl/mod.rs      |  778 ++++++
+ third_party/rust/nix-0.15.0/src/sys/memfd.rs  |   20 +
+ third_party/rust/nix-0.15.0/src/sys/mman.rs   |  325 +++
+ third_party/rust/nix-0.15.0/src/sys/mod.rs    |  100 +
+ .../rust/nix-0.15.0/src/sys/pthread.rs        |   13 +
+ .../rust/nix-0.15.0/src/sys/ptrace/bsd.rs     |  170 ++
+ .../rust/nix-0.15.0/src/sys/ptrace/linux.rs   |  402 +++
+ .../rust/nix-0.15.0/src/sys/ptrace/mod.rs     |   22 +
+ third_party/rust/nix-0.15.0/src/sys/quota.rs  |  273 ++
+ third_party/rust/nix-0.15.0/src/sys/reboot.rs |   45 +
+ third_party/rust/nix-0.15.0/src/sys/select.rs |  334 +++
+ .../rust/nix-0.15.0/src/sys/sendfile.rs       |  200 ++
+ third_party/rust/nix-0.15.0/src/sys/signal.rs |  966 +++++++
+ .../rust/nix-0.15.0/src/sys/signalfd.rs       |  170 ++
+ .../rust/nix-0.15.0/src/sys/socket/addr.rs    | 1278 +++++++++
+ .../rust/nix-0.15.0/src/sys/socket/mod.rs     | 1294 +++++++++
+ .../rust/nix-0.15.0/src/sys/socket/sockopt.rs |  680 +++++
+ third_party/rust/nix-0.15.0/src/sys/stat.rs   |  294 ++
+ third_party/rust/nix-0.15.0/src/sys/statfs.rs |  548 ++++
+ .../rust/nix-0.15.0/src/sys/statvfs.rs        |  160 ++
+ .../rust/nix-0.15.0/src/sys/sysinfo.rs        |   72 +
+ .../rust/nix-0.15.0/src/sys/termios.rs        | 1107 ++++++++
+ third_party/rust/nix-0.15.0/src/sys/time.rs   |  542 ++++
+ third_party/rust/nix-0.15.0/src/sys/uio.rs    |  194 ++
+ .../rust/nix-0.15.0/src/sys/utsname.rs        |   67 +
+ third_party/rust/nix-0.15.0/src/sys/wait.rs   |  239 ++
+ third_party/rust/nix-0.15.0/src/ucontext.rs   |   39 +
+ third_party/rust/nix-0.15.0/src/unistd.rs     | 2394 +++++++++++++++++
+ third_party/rust/nix-0.15.0/test/sys/mod.rs   |   38 +
+ .../rust/nix-0.15.0/test/sys/test_aio.rs      |  654 +++++
+ .../rust/nix-0.15.0/test/sys/test_aio_drop.rs |   32 +
+ .../rust/nix-0.15.0/test/sys/test_epoll.rs    |   24 +
+ .../rust/nix-0.15.0/test/sys/test_inotify.rs  |   65 +
+ .../rust/nix-0.15.0/test/sys/test_ioctl.rs    |  334 +++
+ .../test/sys/test_lio_listio_resubmit.rs      |  111 +
+ .../rust/nix-0.15.0/test/sys/test_pthread.rs  |   15 +
+ .../rust/nix-0.15.0/test/sys/test_ptrace.rs   |  107 +
+ .../rust/nix-0.15.0/test/sys/test_select.rs   |   54 +
+ .../rust/nix-0.15.0/test/sys/test_signal.rs   |  104 +
+ .../rust/nix-0.15.0/test/sys/test_signalfd.rs |   25 +
+ .../rust/nix-0.15.0/test/sys/test_socket.rs   | 1066 ++++++++
+ .../rust/nix-0.15.0/test/sys/test_sockopt.rs  |   53 +
+ .../rust/nix-0.15.0/test/sys/test_sysinfo.rs  |   18 +
+ .../rust/nix-0.15.0/test/sys/test_termios.rs  |  136 +
+ .../rust/nix-0.15.0/test/sys/test_uio.rs      |  241 ++
+ .../rust/nix-0.15.0/test/sys/test_wait.rs     |  104 +
+ third_party/rust/nix-0.15.0/test/test.rs      |  149 +
+ third_party/rust/nix-0.15.0/test/test_dir.rs  |   46 +
+ .../rust/nix-0.15.0/test/test_fcntl.rs        |  234 ++
+ .../test/test_kmod/hello_mod/Makefile         |    7 +
+ .../test/test_kmod/hello_mod/hello.c          |   26 +
+ .../rust/nix-0.15.0/test/test_kmod/mod.rs     |  166 ++
+ .../rust/nix-0.15.0/test/test_mount.rs        |  238 ++
+ third_party/rust/nix-0.15.0/test/test_mq.rs   |  152 ++
+ third_party/rust/nix-0.15.0/test/test_net.rs  |   12 +
+ .../rust/nix-0.15.0/test/test_nix_path.rs     |    0
+ third_party/rust/nix-0.15.0/test/test_poll.rs |   50 +
+ third_party/rust/nix-0.15.0/test/test_pty.rs  |  235 ++
+ .../nix-0.15.0/test/test_ptymaster_drop.rs    |   21 +
+ .../rust/nix-0.15.0/test/test_sendfile.rs     |  129 +
+ third_party/rust/nix-0.15.0/test/test_stat.rs |  296 ++
+ .../rust/nix-0.15.0/test/test_unistd.rs       |  669 +++++
+ third_party/rust/nix/.cargo-checksum.json     |    2 +-
+ third_party/rust/nix/CHANGELOG.md             |  306 ++-
+ third_party/rust/nix/CONTRIBUTING.md          |   10 +-
+ third_party/rust/nix/CONVENTIONS.md           |    9 +-
+ third_party/rust/nix/Cargo.toml               |   40 +-
+ third_party/rust/nix/README.md                |   22 +-
+ third_party/rust/nix/src/dir.rs               |   99 +-
+ third_party/rust/nix/src/env.rs               |   53 +
+ third_party/rust/nix/src/errno.rs             |  480 +++-
+ third_party/rust/nix/src/fcntl.rs             |  268 +-
+ third_party/rust/nix/src/features.rs          |    7 +-
+ third_party/rust/nix/src/ifaddrs.rs           |   29 +-
+ third_party/rust/nix/src/kmod.rs              |    4 +-
+ third_party/rust/nix/src/lib.rs               |   74 +-
+ third_party/rust/nix/src/macros.rs            |   79 +-
+ third_party/rust/nix/src/mount.rs             |   43 +-
+ third_party/rust/nix/src/mqueue.rs            |   65 +-
+ third_party/rust/nix/src/net/if_.rs           |    3 +-
+ third_party/rust/nix/src/poll.rs              |   29 +-
+ third_party/rust/nix/src/pty.rs               |   80 +-
+ third_party/rust/nix/src/sched.rs             |  104 +-
+ third_party/rust/nix/src/sys/aio.rs           |   44 +-
+ third_party/rust/nix/src/sys/epoll.rs         |    8 +-
+ third_party/rust/nix/src/sys/event.rs         |   45 +-
+ third_party/rust/nix/src/sys/eventfd.rs       |    4 +-
+ third_party/rust/nix/src/sys/inotify.rs       |   37 +-
+ third_party/rust/nix/src/sys/ioctl/bsd.rs     |    4 +-
+ third_party/rust/nix/src/sys/ioctl/linux.rs   |    3 +-
+ third_party/rust/nix/src/sys/ioctl/mod.rs     |   12 +-
+ third_party/rust/nix/src/sys/memfd.rs         |    4 +-
+ third_party/rust/nix/src/sys/mman.rs          |  136 +-
+ third_party/rust/nix/src/sys/mod.rs           |   10 +
+ third_party/rust/nix/src/sys/personality.rs   |   70 +
+ third_party/rust/nix/src/sys/ptrace/bsd.rs    |   25 +-
+ third_party/rust/nix/src/sys/ptrace/linux.rs  |  164 +-
+ third_party/rust/nix/src/sys/quota.rs         |   16 +-
+ third_party/rust/nix/src/sys/reboot.rs        |    8 +-
+ third_party/rust/nix/src/sys/select.rs        |  140 +-
+ third_party/rust/nix/src/sys/sendfile.rs      |   11 +-
+ third_party/rust/nix/src/sys/signal.rs        |  300 ++-
+ third_party/rust/nix/src/sys/signalfd.rs      |   28 +-
+ third_party/rust/nix/src/sys/socket/addr.rs   |  205 +-
+ third_party/rust/nix/src/sys/socket/mod.rs    |  930 +++++--
+ .../rust/nix/src/sys/socket/sockopt.rs        |  117 +-
+ third_party/rust/nix/src/sys/stat.rs          |   39 +-
+ third_party/rust/nix/src/sys/statfs.rs        |  216 +-
+ third_party/rust/nix/src/sys/statvfs.rs       |   21 +-
+ third_party/rust/nix/src/sys/sysinfo.rs       |   19 +-
+ third_party/rust/nix/src/sys/termios.rs       |  217 +-
+ third_party/rust/nix/src/sys/time.rs          |   79 +-
+ third_party/rust/nix/src/sys/timerfd.rs       |  285 ++
+ third_party/rust/nix/src/sys/uio.rs           |   18 +-
+ third_party/rust/nix/src/sys/utsname.rs       |    8 +-
+ third_party/rust/nix/src/sys/wait.rs          |   43 +-
+ third_party/rust/nix/src/time.rs              |  260 ++
+ third_party/rust/nix/src/ucontext.rs          |   25 +-
+ third_party/rust/nix/src/unistd.rs            |  809 ++++--
+ third_party/rust/nix/test/common/mod.rs       |  127 +
+ third_party/rust/nix/test/sys/mod.rs          |    7 +
+ third_party/rust/nix/test/sys/test_aio.rs     |  104 +-
+ .../rust/nix/test/sys/test_aio_drop.rs        |    4 +-
+ third_party/rust/nix/test/sys/test_ioctl.rs   |   55 +-
+ .../nix/test/sys/test_lio_listio_resubmit.rs  |    4 -
+ third_party/rust/nix/test/sys/test_mman.rs    |   80 +
+ third_party/rust/nix/test/sys/test_pthread.rs |    4 +-
+ third_party/rust/nix/test/sys/test_ptrace.rs  |   79 +-
+ third_party/rust/nix/test/sys/test_select.rs  |    2 +-
+ third_party/rust/nix/test/sys/test_signal.rs  |   25 +-
+ .../rust/nix/test/sys/test_signalfd.rs        |    6 +-
+ third_party/rust/nix/test/sys/test_socket.rs  |  555 +++-
+ third_party/rust/nix/test/sys/test_sockopt.rs |   43 +
+ third_party/rust/nix/test/sys/test_termios.rs |   22 +-
+ third_party/rust/nix/test/sys/test_timerfd.rs |   61 +
+ third_party/rust/nix/test/sys/test_uio.rs     |   12 +-
+ third_party/rust/nix/test/sys/test_wait.rs    |   21 +-
+ third_party/rust/nix/test/test.rs             |   71 +-
+ third_party/rust/nix/test/test_clearenv.rs    |    9 +
+ third_party/rust/nix/test/test_dir.rs         |    7 +-
+ third_party/rust/nix/test/test_fcntl.rs       |  199 +-
+ third_party/rust/nix/test/test_kmod/mod.rs    |   31 +-
+ third_party/rust/nix/test/test_mount.rs       |    7 +-
+ third_party/rust/nix/test/test_mq.rs          |   28 +-
+ third_party/rust/nix/test/test_poll.rs        |   27 +-
+ third_party/rust/nix/test/test_pty.rs         |  104 +-
+ .../rust/nix/test/test_ptymaster_drop.rs      |   41 +-
+ third_party/rust/nix/test/test_sched.rs       |   32 +
+ third_party/rust/nix/test/test_stat.rs        |   61 +-
+ third_party/rust/nix/test/test_time.rs        |   56 +
+ third_party/rust/nix/test/test_unistd.rs      |  575 +++-
+ 226 files changed, 33484 insertions(+), 3322 deletions(-)
+ create mode 100644 third_party/rust/bitflags/build.rs
+ delete mode 100644 third_party/rust/bitflags/tests/basic.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/default.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/repr/c.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
+ delete mode 100644 third_party/rust/bitflags/tests/compile.rs
+ create mode 100644 third_party/rust/nix-0.15.0/.cargo-checksum.json
+ create mode 100644 third_party/rust/nix-0.15.0/CHANGELOG.md
+ create mode 100644 third_party/rust/nix-0.15.0/CONTRIBUTING.md
+ create mode 100644 third_party/rust/nix-0.15.0/CONVENTIONS.md
+ create mode 100644 third_party/rust/nix-0.15.0/Cargo.toml
+ create mode 100644 third_party/rust/nix-0.15.0/LICENSE
+ create mode 100644 third_party/rust/nix-0.15.0/README.md
+ rename third_party/rust/{nix => nix-0.15.0}/build.rs (100%)
+ create mode 100644 third_party/rust/nix-0.15.0/src/dir.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/errno.rs
+ rename third_party/rust/{nix => nix-0.15.0}/src/errno_dragonfly.c (100%)
+ create mode 100644 third_party/rust/nix-0.15.0/src/fcntl.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/features.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/ifaddrs.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/kmod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/lib.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/macros.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/mount.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/mqueue.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/net/if_.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/net/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/poll.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/pty.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sched.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/aio.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/epoll.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/event.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/eventfd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/inotify.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/memfd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/mman.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/pthread.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/quota.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/reboot.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/select.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/sendfile.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/signal.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/signalfd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/stat.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/statfs.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/statvfs.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/termios.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/time.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/uio.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/utsname.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/sys/wait.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/ucontext.rs
+ create mode 100644 third_party/rust/nix-0.15.0/src/unistd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_aio.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_select.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_signal.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_socket.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_termios.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_uio.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_wait.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_dir.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_fcntl.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_mount.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_mq.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_net.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_nix_path.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_poll.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_pty.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_sendfile.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_stat.rs
+ create mode 100644 third_party/rust/nix-0.15.0/test/test_unistd.rs
+ create mode 100644 third_party/rust/nix/src/env.rs
+ create mode 100644 third_party/rust/nix/src/sys/personality.rs
+ create mode 100644 third_party/rust/nix/src/sys/timerfd.rs
+ create mode 100644 third_party/rust/nix/src/time.rs
+ create mode 100644 third_party/rust/nix/test/common/mod.rs
+ create mode 100644 third_party/rust/nix/test/sys/test_mman.rs
+ create mode 100644 third_party/rust/nix/test/sys/test_timerfd.rs
+ create mode 100644 third_party/rust/nix/test/test_clearenv.rs
+ create mode 100644 third_party/rust/nix/test/test_sched.rs
+ create mode 100644 third_party/rust/nix/test/test_time.rs
+
+diff --git a/Cargo.lock b/Cargo.lock
+index edc5ef5ff2d98..f6240163e1440 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -25,14 +25,14 @@ dependencies = [
+ 
+ [[package]]
+ name = "alsa"
+-version = "0.4.3"
++version = "0.5.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"
++checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18"
+ dependencies = [
+  "alsa-sys",
+  "bitflags",
+  "libc",
+- "nix",
++ "nix 0.20.2",
+ ]
+ 
+ [[package]]
+@@ -427,9 +427,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+ 
+ [[package]]
+ name = "bitflags"
+-version = "1.3.2"
++version = "1.2.1"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
++checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+ 
+ [[package]]
+ name = "bitflags_serde_shim"
+@@ -3073,7 +3073,7 @@ dependencies = [
+ [[package]]
+ name = "midir"
+ version = "0.7.0"
+-source = "git+https://github.com/mozilla/midir.git?rev=4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f#4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
++source = "git+https://github.com/makotokato/midir.git?rev=6140b2825dd4dc2b40e49e154ca7596e7b9a131a#6140b2825dd4dc2b40e49e154ca7596e7b9a131a"
+ dependencies = [
+  "alsa",
+  "bitflags",
+@@ -3081,7 +3081,7 @@ dependencies = [
+  "js-sys",
+  "libc",
+  "memalloc",
+- "nix",
++ "nix 0.20.2",
+  "wasm-bindgen",
+  "web-sys",
+  "winapi",
+@@ -3123,7 +3123,7 @@ dependencies = [
+  "libc",
+  "memmap2 0.2.3",
+  "memoffset 0.5.6",
+- "nix",
++ "nix 0.15.0",
+  "tempfile",
+  "thiserror",
+ ]
+@@ -3535,6 +3535,19 @@ dependencies = [
+  "void",
+ ]
+ 
++[[package]]
++name = "nix"
++version = "0.20.2"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"
++dependencies = [
++ "bitflags",
++ "cc",
++ "cfg-if 1.0.0",
++ "libc",
++ "memoffset 0.6.5",
++]
++
+ [[package]]
+ name = "nom"
+ version = "5.1.2"
+diff --git a/Cargo.toml b/Cargo.toml
+index 1c2437f1f5675..2923c7e5ea9bf 100644
+--- a/Cargo.toml        2022-03-10 14:19:47.963772765 +0800
++++ b/Cargo.toml        2022-03-10 14:33:46.354649188 +0800
+@@ -103,13 +103,14 @@
+ moz_asserts = { path = "mozglue/static/rust/moz_asserts" }
+ 
+ # Other overrides
++authenticator = { git = "https://github.com/makotokato/authenticator-rs", rev="eed8919d50559f4959e2d7d2af7b4d48869b5366" }
+ async-task = { git = "https://github.com/smol-rs/async-task", rev="f6488e35beccb26eb6e85847b02aa78a42cd3d0e" }
+ chardetng = { git = "https://github.com/hsivonen/chardetng", rev="3484d3e3ebdc8931493aa5df4d7ee9360a90e76b" }
+ chardetng_c = { git = "https://github.com/hsivonen/chardetng_c", rev="ed8a4c6f900a90d4dbc1d64b856e61490a1c3570" }
+ coremidi = { git = "https://github.com/chris-zen/coremidi.git", rev="fc68464b5445caf111e41f643a2e69ccce0b4f83" }
+ libudev-sys = { path = "dom/webauthn/libudev-sys" }
+ packed_simd = { git = "https://github.com/hsivonen/packed_simd", rev="8b4bd7d8229660a749dbe419a57ea01df9de5453" }
+-midir = { git = "https://github.com/mozilla/midir.git", rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f" }
++midir = { git = "https://github.com/makotokato/midir.git", rev = "6140b2825dd4dc2b40e49e154ca7596e7b9a131a" }
+ minidump_writer_linux = { git = "https://github.com/msirringhaus/minidump_writer_linux.git", rev = "029ac0d54b237f27dc7d8d4e51bc0fb076e5e852" }
+ 
+ # Patch mio 0.6 to use winapi 0.3 and miow 0.3, getting rid of winapi 0.2.
+
+diff --git a/third_party/rust/alsa/.cargo-checksum.json b/third_party/rust/alsa/.cargo-checksum.json
+index 17227c0a74d16..2bd6b2e2ce47b 100644
+--- a/third_party/rust/alsa/.cargo-checksum.json
++++ b/third_party/rust/alsa/.cargo-checksum.json
+@@ -1 +1 @@
+-{"files":{"Cargo.toml":"5c7a276dd872b47ff86f892e5d8991f38fbe3d61b64eb7138a4ee7ed43d437b7","README.md":"4ccf86e184eda628989919a15560c1ada2c00808cf34740f6e8de466338a1d48","src/card.rs":"f49c6cd6afb83848d34ce7a2e71ede2741ef60262d073be631347871c2768401","src/chmap.rs":"c639f9018fe7d49179a64b73d4f7ef418483c7b150b7edba61d81963c4056770","src/ctl_int.rs":"ebff40ad723a62632ed59840c15c4ec8e4cea2053e4f61d49bdae95e7a74da70","src/device_name.rs":"1e8ad5efbca9c4f062289213e3de8c3429d97a4acf6312c2016553b06e7fa57b","src/direct.rs":"fbd40addd2458bb0b3e856e5b0225fd24dc0ad46ce3662aef12635cf34ef7f55","src/direct/asound_ioctl.rs":"27c8935a0e7bd6e1925d947411c37ca81befba60468a6f2206da9fb08805be89","src/direct/ffi.rs":"aeb0871bd764198558557b5af1a1f6038efe8c8a400d77b4ddfc91143029ac90","src/direct/pcm.rs":"a258e7ba908ef6a2d7d0851ce5279ccc9f7b1579511f48550927fbe4306edaae","src/error.rs":"c8e9839123d760d49b58f46574445550c2c48b90c738b4daaf48aab8dd9a205f","src/hctl.rs":"cc33947cb0810d3edeec7b71686f0231d06c88b421
 4994605de7f4fd0f6de1a1","src/io.rs":"a6e21b94a265b7de56388e035b104877c8b6a0f5d10002c5931dacc90dd577fd","src/lib.rs":"df35e75bb2d83ddddcc90f4ed76e4bcef6843b3b2be09d9b8197c9ede564fbdf","src/mixer.rs":"d6610712f80eb4fd292d5b6e1d10723dfb245be4d85d0370a675034d83010e75","src/pcm.rs":"4259a5b33421e0b144de59da938af1ff1f70a1a3f6e0d2ab665dda4b94441d8c","src/poll.rs":"a6472dbcc96bcbdcc574563f305550df66870e48820d5e90609b0f105d12bb07","src/rawmidi.rs":"ca891bf1cd43ad59b1657efd58356f78ea476d5de999ed756eba74b729f0c184","src/seq.rs":"d229b36f12bf0161c87e0820fd4a3313f19718790e38e0b6294b7e6b1123c611"},"package":"eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"}
+\ No newline at end of file
++{"files":{"Cargo.toml":"e057013b541a2bcf1d2b7aa79a2860fec402dad4ae434a66ad2cf1f4e40d31b9","README.md":"4ccf86e184eda628989919a15560c1ada2c00808cf34740f6e8de466338a1d48","src/card.rs":"f49c6cd6afb83848d34ce7a2e71ede2741ef60262d073be631347871c2768401","src/chmap.rs":"c639f9018fe7d49179a64b73d4f7ef418483c7b150b7edba61d81963c4056770","src/ctl_int.rs":"ebff40ad723a62632ed59840c15c4ec8e4cea2053e4f61d49bdae95e7a74da70","src/device_name.rs":"1e8ad5efbca9c4f062289213e3de8c3429d97a4acf6312c2016553b06e7fa57b","src/direct.rs":"fbd40addd2458bb0b3e856e5b0225fd24dc0ad46ce3662aef12635cf34ef7f55","src/direct/asound_ioctl.rs":"27c8935a0e7bd6e1925d947411c37ca81befba60468a6f2206da9fb08805be89","src/direct/ffi.rs":"aeb0871bd764198558557b5af1a1f6038efe8c8a400d77b4ddfc91143029ac90","src/direct/pcm.rs":"e8d464f08405e4edfc35be12d715012b3c765093794dd8fafc8991a5f4367c67","src/error.rs":"b37d9958dd200362c44d7015d1b03813efec183c9c76168f2608d1e798035ea1","src/hctl.rs":"cc33947cb0810d3edeec7b71686f0231d06c88b421
 4994605de7f4fd0f6de1a1","src/io.rs":"a6e21b94a265b7de56388e035b104877c8b6a0f5d10002c5931dacc90dd577fd","src/lib.rs":"b1235da87167b3a329b5a1a1d8670db0ab411676c0cdb2bfd1b8884bca34f469","src/mixer.rs":"a358bb2ad1db787348c29cdfeda339c4cd16c5a85f5cea8d7e0e9dda8335cbbd","src/pcm.rs":"6c5c87c9d959626d717c6e0e6f13248a56297a0cb390ab0e58d27ca7ad901cac","src/poll.rs":"a6472dbcc96bcbdcc574563f305550df66870e48820d5e90609b0f105d12bb07","src/rawmidi.rs":"ca891bf1cd43ad59b1657efd58356f78ea476d5de999ed756eba74b729f0c184","src/seq.rs":"d229b36f12bf0161c87e0820fd4a3313f19718790e38e0b6294b7e6b1123c611"},"package":"75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18"}
+\ No newline at end of file
+diff --git a/third_party/rust/alsa/Cargo.toml b/third_party/rust/alsa/Cargo.toml
+index c7578fb0785b9..b4af1a6dae284 100644
+--- a/third_party/rust/alsa/Cargo.toml
++++ b/third_party/rust/alsa/Cargo.toml
+@@ -13,7 +13,7 @@
+ [package]
+ edition = "2018"
+ name = "alsa"
+-version = "0.4.3"
++version = "0.5.0"
+ authors = ["David Henningsson <diwic@ubuntu.com>"]
+ description = "Thin but safe wrappers for ALSA (Linux sound API)"
+ documentation = "http://docs.rs/alsa"
+@@ -23,16 +23,16 @@ categories = ["multimedia::audio", "api-bindings"]
+ license = "Apache-2.0/MIT"
+ repository = "https://github.com/diwic/alsa-rs"
+ [dependencies.alsa-sys]
+-version = "0.3.0"
++version = "0.3.1"
+ 
+ [dependencies.bitflags]
+ version = "1.2.1"
+ 
+ [dependencies.libc]
+-version = "0.2.65"
++version = "0.2.88"
+ 
+ [dependencies.nix]
+-version = "0.15"
++version = "0.20"
+ [badges.is-it-maintained-issue-resolution]
+ repository = "diwic/alsa-rs"
+ 
+diff --git a/third_party/rust/alsa/src/direct/pcm.rs b/third_party/rust/alsa/src/direct/pcm.rs
+index 13a16a993b030..f248a70c67031 100644
+--- a/third_party/rust/alsa/src/direct/pcm.rs
++++ b/third_party/rust/alsa/src/direct/pcm.rs
+@@ -19,7 +19,7 @@ don't expect it to work with, e g, the PulseAudio plugin or so.
+ For an example of how to use this mode, look in the "synth-example" directory.
+ */
+ 
+-use {libc, nix};
++use libc;
+ use std::{mem, ptr, fmt, cmp};
+ use crate::error::{Error, Result};
+ use std::os::unix::io::RawFd;
+diff --git a/third_party/rust/alsa/src/error.rs b/third_party/rust/alsa/src/error.rs
+index 4711b0fd2016d..25089c4cbd1d7 100644
+--- a/third_party/rust/alsa/src/error.rs
++++ b/third_party/rust/alsa/src/error.rs
+@@ -3,7 +3,6 @@
+ use libc::{c_void, c_int, c_char, free};
+ use std::{fmt, ptr, str};
+ use std::ffi::CStr;
+-use nix;
+ use std::error::Error as StdError;
+ 
+ /// ALSA error
+diff --git a/third_party/rust/alsa/src/lib.rs b/third_party/rust/alsa/src/lib.rs
+index cf172cb6c60c6..b1a98df7804f3 100644
+--- a/third_party/rust/alsa/src/lib.rs
++++ b/third_party/rust/alsa/src/lib.rs
+@@ -18,7 +18,7 @@ extern crate libc;
+ #[macro_use]
+ extern crate bitflags;
+ #[macro_use]
+-extern crate nix;
++extern crate nix as nix_the_crate;
+ 
+ macro_rules! alsa_enum {
+  ($(#[$attr:meta])+ $name:ident, $static_name:ident [$count:expr], $( $a:ident = $b:ident),* ,) =>
+@@ -125,3 +125,9 @@ pub use crate::io::Output;
+ mod chmap;
+ 
+ pub mod direct;
++
++/// Re-exports from the nix crate.
++pub mod nix {
++    pub use nix_the_crate::Error;
++    pub use nix_the_crate::errno;
++}
+diff --git a/third_party/rust/alsa/src/mixer.rs b/third_party/rust/alsa/src/mixer.rs
+index cb16247a85b62..834aafaf35c18 100644
+--- a/third_party/rust/alsa/src/mixer.rs
++++ b/third_party/rust/alsa/src/mixer.rs
+@@ -112,11 +112,19 @@ impl ops::Add for MilliBel {
+     fn add(self, rhs: Self) -> Self { MilliBel(self.0 + rhs.0) }
+ }
+ 
++impl ops::AddAssign for MilliBel {
++    fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0 }
++}
++
+ impl ops::Sub for MilliBel {
+     type Output = MilliBel;
+     fn sub(self, rhs: Self) -> Self { MilliBel(self.0 - rhs.0) }
+ }
+ 
++impl ops::SubAssign for MilliBel {
++    fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0 }
++}
++
+ /// Wraps [snd_mixer_elem_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___mixer.html)
+ #[derive(Copy, Clone, Debug)]
+ pub struct Elem<'a>{
+diff --git a/third_party/rust/alsa/src/pcm.rs b/third_party/rust/alsa/src/pcm.rs
+index 359b44c6db2cb..5696df9dc691e 100644
+--- a/third_party/rust/alsa/src/pcm.rs
++++ b/third_party/rust/alsa/src/pcm.rs
+@@ -174,8 +174,7 @@ impl PCM {
+     }
+ 
+     pub fn status(&self) -> Result<Status> {
+-        let z = Status::new();
+-        acheck!(snd_pcm_status(self.0, z.ptr())).map(|_| z)
++        StatusBuilder::new().build(self)
+     }
+ 
+     fn verify_format(&self, f: Format) -> Result<()> {
+@@ -416,6 +415,7 @@ alsa_enum!(
+ );
+ 
+ alsa_enum!(
++    #[non_exhaustive]
+     /// [SND_PCM_FORMAT_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
+     Format, ALL_FORMATS[48],
+ 
+@@ -470,21 +470,21 @@ alsa_enum!(
+ );
+ 
+ impl Format {
+-    pub fn s16() -> Format { <i16 as IoFormat>::FORMAT }
+-    pub fn u16() -> Format { <u16 as IoFormat>::FORMAT }
+-    pub fn s32() -> Format { <i32 as IoFormat>::FORMAT }
+-    pub fn u32() -> Format { <u32 as IoFormat>::FORMAT }
+-    pub fn float() -> Format { <f32 as IoFormat>::FORMAT }
+-    pub fn float64() -> Format { <f64 as IoFormat>::FORMAT }
++    pub const fn s16() -> Format { <i16 as IoFormat>::FORMAT }
++    pub const fn u16() -> Format { <u16 as IoFormat>::FORMAT }
++    pub const fn s32() -> Format { <i32 as IoFormat>::FORMAT }
++    pub const fn u32() -> Format { <u32 as IoFormat>::FORMAT }
++    pub const fn float() -> Format { <f32 as IoFormat>::FORMAT }
++    pub const fn float64() -> Format { <f64 as IoFormat>::FORMAT }
+ 
+-    #[cfg(target_endian = "little")] pub fn s24() -> Format { Format::S24LE }
+-    #[cfg(target_endian = "big")] pub fn s24() -> Format { Format::S24BE }
++    #[cfg(target_endian = "little")] pub const fn s24() -> Format { Format::S24LE }
++    #[cfg(target_endian = "big")] pub const fn s24() -> Format { Format::S24BE }
+ 
+-    #[cfg(target_endian = "little")] pub fn u24() -> Format { Format::U24LE }
+-    #[cfg(target_endian = "big")] pub fn u24() -> Format { Format::U24BE }
++    #[cfg(target_endian = "little")] pub const fn u24() -> Format { Format::U24LE }
++    #[cfg(target_endian = "big")] pub const fn u24() -> Format { Format::U24BE }
+ 
+-    #[cfg(target_endian = "little")] pub fn iec958_subframe() -> Format { Format::IEC958SubframeLE }
+-    #[cfg(target_endian = "big")] pub fn iec958_subframe() -> Format { Format::IEC958SubframeBE }
++    #[cfg(target_endian = "little")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeLE }
++    #[cfg(target_endian = "big")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeBE }
+ }
+ 
+ 
+@@ -769,6 +769,15 @@ impl<'a> HwParams<'a> {
+         unsafe { alsa::snd_pcm_hw_params_can_resume(self.0) != 0 }
+     }
+ 
++    /// Returns true if the alsa stream supports the provided `AudioTstampType`, false if not.
++    ///
++    /// This function should only be called when the configuration space contains a single
++    /// configuration. Call `PCM::hw_params` to choose a single configuration from the
++    /// configuration space.
++    pub fn supports_audio_ts_type(&self, type_: AudioTstampType) -> bool {
++        unsafe { alsa::snd_pcm_hw_params_supports_audio_ts_type(self.0, type_ as libc::c_int) != 0 }
++    }
++
+     pub fn dump(&self, o: &mut Output) -> Result<()> {
+         acheck!(snd_pcm_hw_params_dump(self.0, super::io::output_handle(o))).map(|_| ())
+     }
+@@ -923,6 +932,47 @@ impl Status {
+     }
+ }
+ 
++/// Builder for [`Status`].
++///
++/// Allows setting the audio timestamp configuration before retrieving the
++/// status from the stream.
++pub struct StatusBuilder(Status);
++
++impl StatusBuilder {
++    pub fn new() -> Self {
++        StatusBuilder(Status::new())
++    }
++
++    pub fn audio_htstamp_config(
++        self,
++        type_requested: AudioTstampType,
++        report_delay: bool,
++    ) -> Self {
++        let mut cfg: alsa::snd_pcm_audio_tstamp_config_t = unsafe { std::mem::zeroed() };
++        cfg.set_type_requested(type_requested as _);
++        cfg.set_report_delay(report_delay as _);
++        unsafe { alsa::snd_pcm_status_set_audio_htstamp_config(self.0.ptr(), &mut cfg) };
++        self
++    }
++
++    pub fn build(self, pcm: &PCM) -> Result<Status> {
++        acheck!(snd_pcm_status(pcm.0, self.0.ptr())).map(|_| self.0)
++    }
++}
++
++alsa_enum!(
++    #[non_exhaustive]
++    /// [SND_PCM_AUDIO_TSTAMP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
++    AudioTstampType, ALL_AUDIO_TSTAMP_TYPES[6],
++
++    Compat = SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT,
++    Default = SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT,
++    Link = SND_PCM_AUDIO_TSTAMP_TYPE_LINK,
++    LinkAbsolute = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE,
++    LinkEstimated = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED,
++    LinkSynchronized = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED,
++);
++
+ #[test]
+ fn info_from_default() {
+     use std::ffi::CString;
+diff --git a/third_party/rust/bitflags/.cargo-checksum.json b/third_party/rust/bitflags/.cargo-checksum.json
+index 7e8d470b53a37..a8b031c6517a2 100644
+--- a/third_party/rust/bitflags/.cargo-checksum.json
++++ b/third_party/rust/bitflags/.cargo-checksum.json
+@@ -1 +1 @@
+-{"files":{"CHANGELOG.md":"d362fc1fccaaf4d421bcf0fe8b80ddb4f625dade0c1ee52d08bd0b95509a49d1","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"87aced7532a7974eb37ab5fe6037f0abafc36d6b2d74891ecd2bf2f14f50d11e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"baa8604f8afb34fd93b9c79729daafb884dedcaf34023e4af8ad037d916061fd","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"e6477688535ee326d27238aeedc9cb4320ac35b9d17a4deda09e0587b0ccdbd4","tests/basic.rs":"146f1cbf6279bc609242cd3349f29cb21b41294f5e4921875f5ec95bd83529a2","tests/compile-fail/impls/copy.rs":"b791371237ddc75a7c04d2130e03b462c9c00a80dca08bd45aa97433d9c0d13a","tests/compile-fail/impls/copy.stderr.beta":"77d83484ce221d4b6ff2f7de843929a452d779fcfff428122710dd8218c298e3","tests/compile-fail/i
 mpls/eq.rs":"0cee8b9e07d537890e0189710293b53972d0fab63c09366f33c391065afafa99","tests/compile-fail/impls/eq.stderr.beta":"381fc6143d45ce76d7cecc47aa59cb69fe5e79c0b60a4a85d5c6163b400b3cc7","tests/compile-fail/non_integer_base/all_defined.rs":"95e14cad9e94560262f2862c3c01865ac30369b69da1001b0e7285cb55e6cb75","tests/compile-fail/non_integer_base/all_defined.stderr.beta":"1760739a276690903bb03844025587d37939f5dfcbfab309db3c86f32bdbf748","tests/compile-fail/non_integer_base/all_missing.rs":"b3d9da619d23213731ba2581aa7999c796c3c79aaf4f0ee6b11ceec08a11537f","tests/compile-fail/non_integer_base/all_missing.stderr.beta":"37e102290d3867e175b21976be798939f294efb17580d5b51e7b17b590d55132","tests/compile-fail/visibility/private_field.rs":"38e4d3fe6471829360d12c8d09b097f6a21aa93fb51eac3b215d96bdae23316b","tests/compile-fail/visibility/private_field.stderr.beta":"5aa24a3ebb39326f31927721c5017b8beb66c3e501fb865a3fa814c9763bfa0f","tests/compile-fail/visibility/private_flags.rs":"2ce4235802aa4e9c96c4
 e77d9e31d8401ef58dcda4741325184f0764ab1fe393","tests/compile-fail/visibility/private_flags.stderr.beta":"f3eb9f7baf2689258f3519ff7ee5c6ec3c237264ebcfe63f40c40f2023e5022f","tests/compile-fail/visibility/pub_const.rs":"8f813a97ac518c5ea8ac65b184101912452384afaf7b8d6c5e62f8370eca3c0a","tests/compile-fail/visibility/pub_const.stderr.beta":"823976ae1794d7f5372e2ec9aabba497e7bb88004722904c38da342ed98e8962","tests/compile-pass/impls/convert.rs":"88fe80bfb9cd5779f0e1d92c9ec02a8b6bb67e334c07f2309e9c0ba5ef776eb0","tests/compile-pass/impls/default.rs":"c508f9a461691f44b45142fa5ad599f02326e1de4c0cbca6c0593f4652eba109","tests/compile-pass/impls/inherent_methods.rs":"ecc26388e9a394bfa7a5bb69a5d621ab3d4d1e53f28f657bb8e78fe79f437913","tests/compile-pass/redefinition/core.rs":"ff5b6e72f87acc6ebb12405d3c0f6e3fa62e669933656a454bb63b30ea44179c","tests/compile-pass/redefinition/stringify.rs":"1edbce42b900c14425d7ffa14e83e165ebe452d7dccd8c0a8a821bdec64f5c93","tests/compile-pass/repr/c.rs":"6fda17f7c2edfc
 d155314579e83d0fc8a16209e400f1f9a5ca77bd9a799041f2","tests/compile-pass/repr/transparent.rs":"6cdc87a2137d8a4e0c8ce9b6cba83c82255f8ea125951bf614418685600489ce","tests/compile-pass/visibility/bits_field.rs":"1f3e5ba5a047440066a9f6bf7b7af33f5b06f6b1da3dd9af6886168199a7ea0a","tests/compile-pass/visibility/pub_in.rs":"e95312ff60966d42ec4bc00225507895a9b8ec24056ce6a9edd9145be35d730f","tests/compile.rs":"f27c67a7dd183ca30efea1b6e0880e3469a6dd63b92b1fd711c082df182c9eec"},"package":"bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"}
+\ No newline at end of file
++{"files":{"CHANGELOG.md":"00224cc8d292567bdd212c36db66a1f662cd2e6c58e947900680234937e288a9","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"abacd42e33056c16008ab8eefd16eb2403cbc3393f8a6ed352a9a39d945ad3a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"6b236f8b62c82f189fabce0756e01a2c0ab1f32cb84cad9ff3c96b2ce5282bda","build.rs":"8923f38056f859b30aa9022980bb517755cbef57e1b09c34b33b27eb03b0626c","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"bd4e44ac35831c75af8815ba3a11ee1659afe0f72ce9c5f638a66bf50aa23d2a"},"package":"cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"}
+\ No newline at end of file
+diff --git a/third_party/rust/bitflags/CHANGELOG.md b/third_party/rust/bitflags/CHANGELOG.md
+index 12fea1673ac30..0d4910153d909 100644
+--- a/third_party/rust/bitflags/CHANGELOG.md
++++ b/third_party/rust/bitflags/CHANGELOG.md
+@@ -1,60 +1,3 @@
+-# 1.3.2
+-
+-- Allow `non_snake_case` in generated flags types ([#256])
+-
+-[#252]: https://github.com/bitflags/bitflags/pull/256
+-
+-# 1.3.1
+-
+-- Revert unconditional `#[repr(transparent)]` ([#252])
+-
+-[#252]: https://github.com/bitflags/bitflags/pull/252
+-
+-# 1.3.0 (yanked)
+-
+-- Add `#[repr(transparent)]` ([#187])
+-
+-- End `empty` doc comment with full stop ([#202])
+-
+-- Fix typo in crate root docs ([#206])
+-
+-- Document from_bits_unchecked unsafety ([#207])
+-
+-- Let `is_all` ignore extra bits ([#211])
+-
+-- Allows empty flag definition ([#225])
+-
+-- Making crate accessible from std ([#227])
+-
+-- Make `from_bits` a const fn ([#229])
+-
+-- Allow multiple bitflags structs in one macro invocation ([#235])
+-
+-- Add named functions to perform set operations ([#244])
+-
+-- Fix typos in method docs ([#245])
+-
+-- Modernization of the `bitflags` macro to take advantage of newer features and 2018 idioms ([#246])
+-
+-- Fix regression (in an unreleased feature) and simplify tests ([#247])
+-
+-- Use `Self` and fix bug when overriding `stringify!` ([#249])
+-
+-[#187]: https://github.com/bitflags/bitflags/pull/187
+-[#202]: https://github.com/bitflags/bitflags/pull/202
+-[#206]: https://github.com/bitflags/bitflags/pull/206
+-[#207]: https://github.com/bitflags/bitflags/pull/207
+-[#211]: https://github.com/bitflags/bitflags/pull/211
+-[#225]: https://github.com/bitflags/bitflags/pull/225
+-[#227]: https://github.com/bitflags/bitflags/pull/227
+-[#229]: https://github.com/bitflags/bitflags/pull/229
+-[#235]: https://github.com/bitflags/bitflags/pull/235
+-[#244]: https://github.com/bitflags/bitflags/pull/244
+-[#245]: https://github.com/bitflags/bitflags/pull/245
+-[#246]: https://github.com/bitflags/bitflags/pull/246
+-[#247]: https://github.com/bitflags/bitflags/pull/247
+-[#249]: https://github.com/bitflags/bitflags/pull/249
+-
+ # 1.2.1
+ 
+ - Remove extraneous `#[inline]` attributes ([#194])
+diff --git a/third_party/rust/bitflags/Cargo.toml b/third_party/rust/bitflags/Cargo.toml
+index 9d54c725a1c5d..b803644d44753 100644
+--- a/third_party/rust/bitflags/Cargo.toml
++++ b/third_party/rust/bitflags/Cargo.toml
+@@ -11,11 +11,11 @@
+ # will likely look very different (and much more reasonable)
+ 
+ [package]
+-edition = "2018"
+ name = "bitflags"
+-version = "1.3.2"
++version = "1.2.1"
+ authors = ["The Rust Project Developers"]
+-exclude = ["bors.toml"]
++build = "build.rs"
++exclude = [".travis.yml", "appveyor.yml", "bors.toml"]
+ description = "A macro to generate structures which behave like bitflags.\n"
+ homepage = "https://github.com/bitflags/bitflags"
+ documentation = "https://docs.rs/bitflags"
+@@ -26,33 +26,9 @@ license = "MIT/Apache-2.0"
+ repository = "https://github.com/bitflags/bitflags"
+ [package.metadata.docs.rs]
+ features = ["example_generated"]
+-[dependencies.compiler_builtins]
+-version = "0.1.2"
+-optional = true
+-
+-[dependencies.core]
+-version = "1.0.0"
+-optional = true
+-package = "rustc-std-workspace-core"
+-[dev-dependencies.rustversion]
+-version = "1.0"
+-
+-[dev-dependencies.serde]
+-version = "1.0"
+-
+-[dev-dependencies.serde_derive]
+-version = "1.0"
+-
+-[dev-dependencies.serde_json]
+-version = "1.0"
+-
+-[dev-dependencies.trybuild]
+-version = "1.0"
+-
+-[dev-dependencies.walkdir]
+-version = "2.3"
+ 
+ [features]
+ default = []
+ example_generated = []
+-rustc-dep-of-std = ["core", "compiler_builtins"]
++[badges.travis-ci]
++repository = "bitflags/bitflags"
+diff --git a/third_party/rust/bitflags/README.md b/third_party/rust/bitflags/README.md
+index 0da0f853661b0..df12934c3e28a 100644
+--- a/third_party/rust/bitflags/README.md
++++ b/third_party/rust/bitflags/README.md
+@@ -1,10 +1,11 @@
+ bitflags
+ ========
+ 
+-[![Rust](https://github.com/bitflags/bitflags/workflows/Rust/badge.svg)](https://github.com/bitflags/bitflags/actions)
++[![Build Status](https://travis-ci.com/bitflags/bitflags.svg?branch=master)](https://travis-ci.com/bitflags/bitflags)
+ [![Join the chat at https://gitter.im/bitflags/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bitflags/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
+ [![Latest version](https://img.shields.io/crates/v/bitflags.svg)](https://crates.io/crates/bitflags)
+ [![Documentation](https://docs.rs/bitflags/badge.svg)](https://docs.rs/bitflags)
++![Minimum rustc version](https://img.shields.io/badge/rustc-1.20+-yellow.svg)
+ ![License](https://img.shields.io/crates/l/bitflags.svg)
+ 
+ A Rust macro to generate structures which behave like a set of bitflags
+@@ -18,15 +19,16 @@ Add this to your `Cargo.toml`:
+ 
+ ```toml
+ [dependencies]
+-bitflags = "1.3"
++bitflags = "1.0"
+ ```
+ 
+-and this to your source code:
++and this to your crate root:
+ 
+ ```rust
+-use bitflags::bitflags;
++#[macro_use]
++extern crate bitflags;
+ ```
+ 
+ ## Rust Version Support
+ 
+-The minimum supported Rust version is 1.46 due to use of associated constants and const functions.
++The minimum supported Rust version is 1.20 due to use of associated constants.
+diff --git a/third_party/rust/bitflags/build.rs b/third_party/rust/bitflags/build.rs
+new file mode 100644
+index 0000000000000..985757a6f6126
+--- /dev/null
++++ b/third_party/rust/bitflags/build.rs
+@@ -0,0 +1,44 @@
++use std::env;
++use std::process::Command;
++use std::str::{self, FromStr};
++
++fn main(){
++    let minor = match rustc_minor_version() {
++        Some(minor) => minor,
++        None => return,
++    };
++
++    // const fn stabilized in Rust 1.31:
++    if minor >= 31 {
++        println!("cargo:rustc-cfg=bitflags_const_fn");
++    }
++}
++
++fn rustc_minor_version() -> Option<u32> {
++    let rustc = match env::var_os("RUSTC") {
++        Some(rustc) => rustc,
++        None => return None,
++    };
++
++    let output = match Command::new(rustc).arg("--version").output() {
++        Ok(output) => output,
++        Err(_) => return None,
++    };
++
++    let version = match str::from_utf8(&output.stdout) {
++        Ok(version) => version,
++        Err(_) => return None,
++    };
++
++    let mut pieces = version.split('.');
++    if pieces.next() != Some("rustc 1") {
++        return None;
++    }
++
++    let next = match pieces.next() {
++        Some(next) => next,
++        None => return None,
++    };
++
++    u32::from_str(next).ok()
++}
+\ No newline at end of file
+diff --git a/third_party/rust/bitflags/src/lib.rs b/third_party/rust/bitflags/src/lib.rs
+index 935e432f1701e..3929b02ac10d7 100644
+--- a/third_party/rust/bitflags/src/lib.rs
++++ b/third_party/rust/bitflags/src/lib.rs
+@@ -11,14 +11,15 @@
+ //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags.
+ //! It can be used for creating typesafe wrappers around C APIs.
+ //!
+-//! The `bitflags!` macro generates `struct`s that manage a set of flags. The
++//! The `bitflags!` macro generates a `struct` that manages a set of flags. The
+ //! flags should only be defined for integer types, otherwise unexpected type
+ //! errors may occur at compile time.
+ //!
+ //! # Example
+ //!
+ //! ```
+-//! use bitflags::bitflags;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
+ //! bitflags! {
+ //!     struct Flags: u32 {
+@@ -46,9 +47,10 @@
+ //! implementations:
+ //!
+ //! ```
+-//! use std::fmt;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
+-//! use bitflags::bitflags;
++//! use std::fmt;
+ //!
+ //! bitflags! {
+ //!     struct Flags: u32 {
+@@ -82,19 +84,21 @@
+ //!
+ //! # Visibility
+ //!
+-//! The generated structs and their associated flag constants are not exported
++//! The generated struct and its associated flag constants are not exported
+ //! out of the current module by default. A definition can be exported out of
+-//! the current module by adding `pub` before `struct`:
++//! the current module by adding `pub` before `flags`:
+ //!
+ //! ```
+-//! mod example {
+-//!     use bitflags::bitflags;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
++//! mod example {
+ //!     bitflags! {
+ //!         pub struct Flags1: u32 {
+ //!             const A = 0b00000001;
+ //!         }
+-//!
++//!     }
++//!     bitflags! {
+ //! #       pub
+ //!         struct Flags2: u32 {
+ //!             const B = 0b00000010;
+@@ -110,44 +114,26 @@
+ //!
+ //! # Attributes
+ //!
+-//! Attributes can be attached to the generated `struct`s by placing them
+-//! before the `struct` keyword.
+-//!
+-//! ## Representations
+-//!
+-//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type
+-//! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype.
+-//!
+-//! ```
+-//! use bitflags::bitflags;
+-//!
+-//! bitflags! {
+-//!     #[repr(transparent)]
+-//!     struct Flags: u32 {
+-//!         const A = 0b00000001;
+-//!         const B = 0b00000010;
+-//!         const C = 0b00000100;
+-//!     }
+-//! }
+-//! ```
++//! Attributes can be attached to the generated `struct` by placing them
++//! before the `flags` keyword.
+ //!
+ //! # Trait implementations
+ //!
+ //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
+-//! traits are automatically derived for the `struct`s using the `derive` attribute.
++//! traits automatically derived for the `struct` using the `derive` attribute.
+ //! Additional traits can be derived by providing an explicit `derive`
+-//! attribute on `struct`.
++//! attribute on `flags`.
+ //!
+-//! The `Extend` and `FromIterator` traits are implemented for the `struct`s,
++//! The `Extend` and `FromIterator` traits are implemented for the `struct`,
+ //! too: `Extend` adds the union of the instances of the `struct` iterated over,
+ //! while `FromIterator` calculates the union.
+ //!
+-//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also
++//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` trait is also
+ //! implemented by displaying the bits value of the internal struct.
+ //!
+ //! ## Operators
+ //!
+-//! The following operator traits are implemented for the generated `struct`s:
++//! The following operator traits are implemented for the generated `struct`:
+ //!
+ //! - `BitOr` and `BitOrAssign`: union
+ //! - `BitAnd` and `BitAndAssign`: intersection
+@@ -157,7 +143,7 @@
+ //!
+ //! # Methods
+ //!
+-//! The following methods are defined for the generated `struct`s:
++//! The following methods are defined for the generated `struct`:
+ //!
+ //! - `empty`: an empty set of flags
+ //! - `all`: the set of all defined flags
+@@ -173,34 +159,23 @@
+ //! - `is_empty`: `true` if no flags are currently stored
+ //! - `is_all`: `true` if currently set flags exactly equal all defined flags
+ //! - `intersects`: `true` if there are flags common to both `self` and `other`
+-//! - `contains`: `true` if all of the flags in `other` are contained within `self`
++//! - `contains`: `true` all of the flags in `other` are contained within `self`
+ //! - `insert`: inserts the specified flags in-place
+ //! - `remove`: removes the specified flags in-place
+ //! - `toggle`: the specified flags will be inserted if not present, and removed
+ //!             if they are.
+ //! - `set`: inserts or removes the specified flags depending on the passed value
+-//! - `intersection`: returns a new set of flags, containing only the flags present
+-//!                   in both `self` and `other` (the argument to the function).
+-//! - `union`: returns a new set of flags, containing any flags present in
+-//!            either `self` or `other` (the argument to the function).
+-//! - `difference`: returns a new set of flags, containing all flags present in
+-//!                 `self` without any of the flags present in `other` (the
+-//!                 argument to the function).
+-//! - `symmetric_difference`: returns a new set of flags, containing all flags
+-//!                           present in either `self` or `other` (the argument
+-//!                           to the function), but not both.
+-//! - `complement`: returns a new set of flags, containing all flags which are
+-//!                 not set in `self`, but which are allowed for this type.
+ //!
+ //! ## Default
+ //!
+-//! The `Default` trait is not automatically implemented for the generated structs.
++//! The `Default` trait is not automatically implemented for the generated struct.
+ //!
+ //! If your default value is equal to `0` (which is the same value as calling `empty()`
+ //! on the generated struct), you can simply derive `Default`:
+ //!
+ //! ```
+-//! use bitflags::bitflags;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
+ //! bitflags! {
+ //!     // Results in default value with bits: 0
+@@ -221,7 +196,8 @@
+ //! If your default value is not equal to `0` you need to implement `Default` yourself:
+ //!
+ //! ```
+-//! use bitflags::bitflags;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
+ //! bitflags! {
+ //!     struct Flags: u32 {
+@@ -249,7 +225,8 @@
+ //! Flags with a value equal to zero will have some strange behavior that one should be aware of.
+ //!
+ //! ```
+-//! use bitflags::bitflags;
++//! #[macro_use]
++//! extern crate bitflags;
+ //!
+ //! bitflags! {
+ //!     struct Flags: u32 {
+@@ -272,23 +249,28 @@
+ //!     assert!(none.is_empty());
+ //! }
+ //! ```
+-//!
+-//! Users should generally avoid defining a flag with a value of zero.
+ 
+-#![cfg_attr(not(test), no_std)]
+-#![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")]
++#![no_std]
++#![doc(html_root_url = "https://docs.rs/bitflags/1.2.1")]
++
++#[cfg(test)]
++#[macro_use]
++extern crate std;
+ 
++// Re-export libcore using an alias so that the macros can work without
++// requiring `extern crate core` downstream.
+ #[doc(hidden)]
+ pub extern crate core as _core;
+ 
+-/// The macro used to generate the flag structures.
++/// The macro used to generate the flag structure.
+ ///
+ /// See the [crate level docs](../bitflags/index.html) for complete documentation.
+ ///
+ /// # Example
+ ///
+ /// ```
+-/// use bitflags::bitflags;
++/// #[macro_use]
++/// extern crate bitflags;
+ ///
+ /// bitflags! {
+ ///     struct Flags: u32 {
+@@ -313,9 +295,10 @@ pub extern crate core as _core;
+ /// implementations:
+ ///
+ /// ```
+-/// use std::fmt;
++/// #[macro_use]
++/// extern crate bitflags;
+ ///
+-/// use bitflags::bitflags;
++/// use std::fmt;
+ ///
+ /// bitflags! {
+ ///     struct Flags: u32 {
+@@ -350,18 +333,78 @@ pub extern crate core as _core;
+ macro_rules! bitflags {
+     (
+         $(#[$outer:meta])*
+-        $vis:vis struct $BitFlags:ident: $T:ty {
++        pub struct $BitFlags:ident: $T:ty {
++            $(
++                $(#[$inner:ident $($args:tt)*])*
++                const $Flag:ident = $value:expr;
++            )+
++        }
++    ) => {
++        __bitflags! {
++            $(#[$outer])*
++            (pub) $BitFlags: $T {
++                $(
++                    $(#[$inner $($args)*])*
++                    $Flag = $value;
++                )+
++            }
++        }
++    };
++    (
++        $(#[$outer:meta])*
++        struct $BitFlags:ident: $T:ty {
++            $(
++                $(#[$inner:ident $($args:tt)*])*
++                const $Flag:ident = $value:expr;
++            )+
++        }
++    ) => {
++        __bitflags! {
++            $(#[$outer])*
++            () $BitFlags: $T {
++                $(
++                    $(#[$inner $($args)*])*
++                    $Flag = $value;
++                )+
++            }
++        }
++    };
++    (
++        $(#[$outer:meta])*
++        pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty {
+             $(
+                 $(#[$inner:ident $($args:tt)*])*
+                 const $Flag:ident = $value:expr;
+-            )*
++            )+
++        }
++    ) => {
++        __bitflags! {
++            $(#[$outer])*
++            (pub ($($vis)+)) $BitFlags: $T {
++                $(
++                    $(#[$inner $($args)*])*
++                    $Flag = $value;
++                )+
++            }
+         }
++    };
++}
+ 
+-        $($t:tt)*
++#[macro_export(local_inner_macros)]
++#[doc(hidden)]
++macro_rules! __bitflags {
++    (
++        $(#[$outer:meta])*
++        ($($vis:tt)*) $BitFlags:ident: $T:ty {
++            $(
++                $(#[$inner:ident $($args:tt)*])*
++                $Flag:ident = $value:expr;
++            )+
++        }
+     ) => {
+         $(#[$outer])*
+         #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
+-        $vis struct $BitFlags {
++        $($vis)* struct $BitFlags {
+             bits: $T,
+         }
+ 
+@@ -370,52 +413,63 @@ macro_rules! bitflags {
+                 $(
+                     $(#[$inner $($args)*])*
+                     $Flag = $value;
+-                )*
++                )+
+             }
+         }
++    };
++}
+ 
+-        bitflags! {
+-            $($t)*
+-        }
++#[macro_export(local_inner_macros)]
++#[doc(hidden)]
++#[cfg(bitflags_const_fn)]
++macro_rules! __fn_bitflags {
++    (
++        $(# $attr_args:tt)*
++        const fn $($item:tt)*
++    ) => {
++        $(# $attr_args)*
++        const fn $($item)*
++    };
++    (
++        $(# $attr_args:tt)*
++        pub const fn $($item:tt)*
++    ) => {
++        $(# $attr_args)*
++        pub const fn $($item)*
++    };
++    (
++        $(# $attr_args:tt)*
++        pub const unsafe fn $($item:tt)*
++    ) => {
++        $(# $attr_args)*
++        pub const unsafe fn $($item)*
+     };
+-    () => {};
+ }
+ 
+-// A helper macro to implement the `all` function.
+ #[macro_export(local_inner_macros)]
+ #[doc(hidden)]
+-macro_rules! __impl_all_bitflags {
++#[cfg(not(bitflags_const_fn))]
++macro_rules! __fn_bitflags {
+     (
+-        $BitFlags:ident: $T:ty {
+-            $(
+-                $(#[$attr:ident $($args:tt)*])*
+-                $Flag:ident = $value:expr;
+-            )+
+-        }
++        $(# $attr_args:tt)*
++        const fn $($item:tt)*
+     ) => {
+-        // See `Debug::fmt` for why this approach is taken.
+-        #[allow(non_snake_case)]
+-        trait __BitFlags {
+-            $(
+-                const $Flag: $T = 0;
+-            )+
+-        }
+-        #[allow(non_snake_case)]
+-        impl __BitFlags for $BitFlags {
+-            $(
+-                __impl_bitflags! {
+-                    #[allow(deprecated)]
+-                    $(? #[$attr $($args)*])*
+-                    const $Flag: $T = Self::$Flag.bits;
+-                }
+-            )+
+-        }
+-        Self { bits: $(<Self as __BitFlags>::$Flag)|+ }
++        $(# $attr_args)*
++        fn $($item)*
++    };
++    (
++        $(# $attr_args:tt)*
++        pub const fn $($item:tt)*
++    ) => {
++        $(# $attr_args)*
++        pub fn $($item)*
+     };
+     (
+-        $BitFlags:ident: $T:ty { }
++        $(# $attr_args:tt)*
++        pub const unsafe fn $($item:tt)*
+     ) => {
+-        Self { bits: 0 }
++        $(# $attr_args)*
++        pub unsafe fn $($item)*
+     };
+ }
+ 
+@@ -427,7 +481,7 @@ macro_rules! __impl_bitflags {
+             $(
+                 $(#[$attr:ident $($args:tt)*])*
+                 $Flag:ident = $value:expr;
+-            )*
++            )+
+         }
+     ) => {
+         impl $crate::_core::fmt::Debug for $BitFlags {
+@@ -445,12 +499,11 @@ macro_rules! __impl_bitflags {
+                     $(
+                         #[inline]
+                         fn $Flag(&self) -> bool { false }
+-                    )*
++                    )+
+                 }
+ 
+                 // Conditionally override the check for just those flags that
+                 // are not #[cfg]ed away.
+-                #[allow(non_snake_case)]
+                 impl __BitFlags for $BitFlags {
+                     $(
+                         __impl_bitflags! {
+@@ -465,20 +518,20 @@ macro_rules! __impl_bitflags {
+                                 }
+                             }
+                         }
+-                    )*
++                    )+
+                 }
+ 
+                 let mut first = true;
+                 $(
+-                    if <Self as __BitFlags>::$Flag(self) {
++                    if <$BitFlags as __BitFlags>::$Flag(self) {
+                         if !first {
+                             f.write_str(" | ")?;
+                         }
+                         first = false;
+-                        f.write_str($crate::_core::stringify!($Flag))?;
++                        f.write_str(__bitflags_stringify!($Flag))?;
+                     }
+-                )*
+-                let extra_bits = self.bits & !Self::all().bits();
++                )+
++                let extra_bits = self.bits & !$BitFlags::all().bits();
+                 if extra_bits != 0 {
+                     if !first {
+                         f.write_str(" | ")?;
+@@ -518,295 +571,227 @@ macro_rules! __impl_bitflags {
+         impl $BitFlags {
+             $(
+                 $(#[$attr $($args)*])*
+-                pub const $Flag: Self = Self { bits: $value };
+-            )*
++                pub const $Flag: $BitFlags = $BitFlags { bits: $value };
++            )+
+ 
+-            /// Returns an empty set of flags.
+-            #[inline]
+-            pub const fn empty() -> Self {
+-                Self { bits: 0 }
++            __fn_bitflags! {
++                /// Returns an empty set of flags
++                #[inline]
++                pub const fn empty() -> $BitFlags {
++                    $BitFlags { bits: 0 }
++                }
+             }
+ 
+-            /// Returns the set containing all flags.
+-            #[inline]
+-            pub const fn all() -> Self {
+-                __impl_all_bitflags! {
+-                    $BitFlags: $T {
++            __fn_bitflags! {
++                /// Returns the set containing all flags.
++                #[inline]
++                pub const fn all() -> $BitFlags {
++                    // See `Debug::fmt` for why this approach is taken.
++                    #[allow(non_snake_case)]
++                    trait __BitFlags {
+                         $(
+-                            $(#[$attr $($args)*])*
+-                            $Flag = $value;
+-                        )*
++                            const $Flag: $T = 0;
++                        )+
+                     }
++                    impl __BitFlags for $BitFlags {
++                        $(
++                            __impl_bitflags! {
++                                #[allow(deprecated)]
++                                $(? #[$attr $($args)*])*
++                                const $Flag: $T = Self::$Flag.bits;
++                            }
++                        )+
++                    }
++                    $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag)|+ }
+                 }
+             }
+ 
+-            /// Returns the raw value of the flags currently stored.
+-            #[inline]
+-            pub const fn bits(&self) -> $T {
+-                self.bits
++            __fn_bitflags! {
++                /// Returns the raw value of the flags currently stored.
++                #[inline]
++                pub const fn bits(&self) -> $T {
++                    self.bits
++                }
+             }
+ 
+             /// Convert from underlying bit representation, unless that
+             /// representation contains bits that do not correspond to a flag.
+             #[inline]
+-            pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> {
+-                if (bits & !Self::all().bits()) == 0 {
+-                    $crate::_core::option::Option::Some(Self { bits })
++            pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
++                if (bits & !$BitFlags::all().bits()) == 0 {
++                    $crate::_core::option::Option::Some($BitFlags { bits })
+                 } else {
+                     $crate::_core::option::Option::None
+                 }
+             }
+ 
+-            /// Convert from underlying bit representation, dropping any bits
+-            /// that do not correspond to flags.
+-            #[inline]
+-            pub const fn from_bits_truncate(bits: $T) -> Self {
+-                Self { bits: bits & Self::all().bits }
++            __fn_bitflags! {
++                /// Convert from underlying bit representation, dropping any bits
++                /// that do not correspond to flags.
++                #[inline]
++                pub const fn from_bits_truncate(bits: $T) -> $BitFlags {
++                    $BitFlags { bits: bits & $BitFlags::all().bits }
++                }
+             }
+ 
+-            /// Convert from underlying bit representation, preserving all
+-            /// bits (even those not corresponding to a defined flag).
+-            ///
+-            /// # Safety
+-            ///
+-            /// The caller of the `bitflags!` macro can chose to allow or
+-            /// disallow extra bits for their bitflags type.
+-            ///
+-            /// The caller of `from_bits_unchecked()` has to ensure that
+-            /// all bits correspond to a defined flag or that extra bits
+-            /// are valid for this bitflags type.
+-            #[inline]
+-            pub const unsafe fn from_bits_unchecked(bits: $T) -> Self {
+-                Self { bits }
++            __fn_bitflags! {
++                /// Convert from underlying bit representation, preserving all
++                /// bits (even those not corresponding to a defined flag).
++                #[inline]
++                pub const unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
++                    $BitFlags { bits }
++                }
+             }
+ 
+-            /// Returns `true` if no flags are currently stored.
+-            #[inline]
+-            pub const fn is_empty(&self) -> bool {
+-                self.bits() == Self::empty().bits()
++            __fn_bitflags! {
++                /// Returns `true` if no flags are currently stored.
++                #[inline]
++                pub const fn is_empty(&self) -> bool {
++                    self.bits() == $BitFlags::empty().bits()
++                }
+             }
+ 
+-            /// Returns `true` if all flags are currently set.
+-            #[inline]
+-            pub const fn is_all(&self) -> bool {
+-                Self::all().bits | self.bits == self.bits
++            __fn_bitflags! {
++                /// Returns `true` if all flags are currently set.
++                #[inline]
++                pub const fn is_all(&self) -> bool {
++                    self.bits == $BitFlags::all().bits
++                }
+             }
+ 
+-            /// Returns `true` if there are flags common to both `self` and `other`.
+-            #[inline]
+-            pub const fn intersects(&self, other: Self) -> bool {
+-                !(Self { bits: self.bits & other.bits}).is_empty()
++            __fn_bitflags! {
++                /// Returns `true` if there are flags common to both `self` and `other`.
++                #[inline]
++                pub const fn intersects(&self, other: $BitFlags) -> bool {
++                    !$BitFlags{ bits: self.bits & other.bits}.is_empty()
++                }
+             }
+ 
+-            /// Returns `true` if all of the flags in `other` are contained within `self`.
+-            #[inline]
+-            pub const fn contains(&self, other: Self) -> bool {
+-                (self.bits & other.bits) == other.bits
++            __fn_bitflags! {
++                /// Returns `true` all of the flags in `other` are contained within `self`.
++                #[inline]
++                pub const fn contains(&self, other: $BitFlags) -> bool {
++                    (self.bits & other.bits) == other.bits
++                }
+             }
+ 
+             /// Inserts the specified flags in-place.
+             #[inline]
+-            pub fn insert(&mut self, other: Self) {
++            pub fn insert(&mut self, other: $BitFlags) {
+                 self.bits |= other.bits;
+             }
+ 
+             /// Removes the specified flags in-place.
+             #[inline]
+-            pub fn remove(&mut self, other: Self) {
++            pub fn remove(&mut self, other: $BitFlags) {
+                 self.bits &= !other.bits;
+             }
+ 
+             /// Toggles the specified flags in-place.
+             #[inline]
+-            pub fn toggle(&mut self, other: Self) {
++            pub fn toggle(&mut self, other: $BitFlags) {
+                 self.bits ^= other.bits;
+             }
+ 
+             /// Inserts or removes the specified flags depending on the passed value.
+             #[inline]
+-            pub fn set(&mut self, other: Self, value: bool) {
++            pub fn set(&mut self, other: $BitFlags, value: bool) {
+                 if value {
+                     self.insert(other);
+                 } else {
+                     self.remove(other);
+                 }
+             }
+-
+-            /// Returns the intersection between the flags in `self` and
+-            /// `other`.
+-            ///
+-            /// Specifically, the returned set contains only the flags which are
+-            /// present in *both* `self` *and* `other`.
+-            ///
+-            /// This is equivalent to using the `&` operator (e.g.
+-            /// [`ops::BitAnd`]), as in `flags & other`.
+-            ///
+-            /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
+-            #[inline]
+-            #[must_use]
+-            pub const fn intersection(self, other: Self) -> Self {
+-                Self { bits: self.bits & other.bits }
+-            }
+-
+-            /// Returns the union of between the flags in `self` and `other`.
+-            ///
+-            /// Specifically, the returned set contains all flags which are
+-            /// present in *either* `self` *or* `other`, including any which are
+-            /// present in both (see [`Self::symmetric_difference`] if that
+-            /// is undesirable).
+-            ///
+-            /// This is equivalent to using the `|` operator (e.g.
+-            /// [`ops::BitOr`]), as in `flags | other`.
+-            ///
+-            /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
+-            #[inline]
+-            #[must_use]
+-            pub const fn union(self, other: Self) -> Self {
+-                Self { bits: self.bits | other.bits }
+-            }
+-
+-            /// Returns the difference between the flags in `self` and `other`.
+-            ///
+-            /// Specifically, the returned set contains all flags present in
+-            /// `self`, except for the ones present in `other`.
+-            ///
+-            /// It is also conceptually equivalent to the "bit-clear" operation:
+-            /// `flags & !other` (and this syntax is also supported).
+-            ///
+-            /// This is equivalent to using the `-` operator (e.g.
+-            /// [`ops::Sub`]), as in `flags - other`.
+-            ///
+-            /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
+-            #[inline]
+-            #[must_use]
+-            pub const fn difference(self, other: Self) -> Self {
+-                Self { bits: self.bits & !other.bits }
+-            }
+-
+-            /// Returns the [symmetric difference][sym-diff] between the flags
+-            /// in `self` and `other`.
+-            ///
+-            /// Specifically, the returned set contains the flags present which
+-            /// are present in `self` or `other`, but that are not present in
+-            /// both. Equivalently, it contains the flags present in *exactly
+-            /// one* of the sets `self` and `other`.
+-            ///
+-            /// This is equivalent to using the `^` operator (e.g.
+-            /// [`ops::BitXor`]), as in `flags ^ other`.
+-            ///
+-            /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
+-            /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
+-            #[inline]
+-            #[must_use]
+-            pub const fn symmetric_difference(self, other: Self) -> Self {
+-                Self { bits: self.bits ^ other.bits }
+-            }
+-
+-            /// Returns the complement of this set of flags.
+-            ///
+-            /// Specifically, the returned set contains all the flags which are
+-            /// not set in `self`, but which are allowed for this type.
+-            ///
+-            /// Alternatively, it can be thought of as the set difference
+-            /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`)
+-            ///
+-            /// This is equivalent to using the `!` operator (e.g.
+-            /// [`ops::Not`]), as in `!flags`.
+-            ///
+-            /// [`Self::all()`]: Self::all
+-            /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
+-            #[inline]
+-            #[must_use]
+-            pub const fn complement(self) -> Self {
+-                Self::from_bits_truncate(!self.bits)
+-            }
+-
+         }
+ 
+         impl $crate::_core::ops::BitOr for $BitFlags {
+-            type Output = Self;
++            type Output = $BitFlags;
+ 
+             /// Returns the union of the two sets of flags.
+             #[inline]
+-            fn bitor(self, other: $BitFlags) -> Self {
+-                Self { bits: self.bits | other.bits }
++            fn bitor(self, other: $BitFlags) -> $BitFlags {
++                $BitFlags { bits: self.bits | other.bits }
+             }
+         }
+ 
+         impl $crate::_core::ops::BitOrAssign for $BitFlags {
++
+             /// Adds the set of flags.
+             #[inline]
+-            fn bitor_assign(&mut self, other: Self) {
++            fn bitor_assign(&mut self, other: $BitFlags) {
+                 self.bits |= other.bits;
+             }
+         }
+ 
+         impl $crate::_core::ops::BitXor for $BitFlags {
+-            type Output = Self;
++            type Output = $BitFlags;
+ 
+             /// Returns the left flags, but with all the right flags toggled.
+             #[inline]
+-            fn bitxor(self, other: Self) -> Self {
+-                Self { bits: self.bits ^ other.bits }
++            fn bitxor(self, other: $BitFlags) -> $BitFlags {
++                $BitFlags { bits: self.bits ^ other.bits }
+             }
+         }
+ 
+         impl $crate::_core::ops::BitXorAssign for $BitFlags {
++
+             /// Toggles the set of flags.
+             #[inline]
+-            fn bitxor_assign(&mut self, other: Self) {
++            fn bitxor_assign(&mut self, other: $BitFlags) {
+                 self.bits ^= other.bits;
+             }
+         }
+ 
+         impl $crate::_core::ops::BitAnd for $BitFlags {
+-            type Output = Self;
++            type Output = $BitFlags;
+ 
+             /// Returns the intersection between the two sets of flags.
+             #[inline]
+-            fn bitand(self, other: Self) -> Self {
+-                Self { bits: self.bits & other.bits }
++            fn bitand(self, other: $BitFlags) -> $BitFlags {
++                $BitFlags { bits: self.bits & other.bits }
+             }
+         }
+ 
+         impl $crate::_core::ops::BitAndAssign for $BitFlags {
++
+             /// Disables all flags disabled in the set.
+             #[inline]
+-            fn bitand_assign(&mut self, other: Self) {
++            fn bitand_assign(&mut self, other: $BitFlags) {
+                 self.bits &= other.bits;
+             }
+         }
+ 
+         impl $crate::_core::ops::Sub for $BitFlags {
+-            type Output = Self;
++            type Output = $BitFlags;
+ 
+             /// Returns the set difference of the two sets of flags.
+             #[inline]
+-            fn sub(self, other: Self) -> Self {
+-                Self { bits: self.bits & !other.bits }
++            fn sub(self, other: $BitFlags) -> $BitFlags {
++                $BitFlags { bits: self.bits & !other.bits }
+             }
+         }
+ 
+         impl $crate::_core::ops::SubAssign for $BitFlags {
++
+             /// Disables all flags enabled in the set.
+             #[inline]
+-            fn sub_assign(&mut self, other: Self) {
++            fn sub_assign(&mut self, other: $BitFlags) {
+                 self.bits &= !other.bits;
+             }
+         }
+ 
+         impl $crate::_core::ops::Not for $BitFlags {
+-            type Output = Self;
++            type Output = $BitFlags;
+ 
+             /// Returns the complement of this set of flags.
+             #[inline]
+-            fn not(self) -> Self {
+-                Self { bits: !self.bits } & Self::all()
++            fn not(self) -> $BitFlags {
++                $BitFlags { bits: !self.bits } & $BitFlags::all()
+             }
+         }
+ 
+         impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
+-            fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) {
++            fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) {
+                 for item in iterator {
+                     self.insert(item)
+                 }
+@@ -814,7 +799,7 @@ macro_rules! __impl_bitflags {
+         }
+ 
+         impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
+-            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self {
++            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
+                 let mut result = Self::empty();
+                 result.extend(iterator);
+                 result
+@@ -832,7 +817,7 @@ macro_rules! __impl_bitflags {
+     // Input:
+     //
+     //     ? #[cfg(feature = "advanced")]
+-    //     ? #[deprecated(note = "Use something else.")]
++    //     ? #[deprecated(note = "Use somthing else.")]
+     //     ? #[doc = r"High quality documentation."]
+     //     fn f() -> i32 { /* ... */ }
+     //
+@@ -887,7 +872,7 @@ macro_rules! __impl_bitflags {
+     // Input:
+     //
+     //     ? #[cfg(feature = "advanced")]
+-    //     ? #[deprecated(note = "Use something else.")]
++    //     ? #[deprecated(note = "Use somthing else.")]
+     //     ? #[doc = r"High quality documentation."]
+     //     const f: i32 { /* ... */ }
+     //
+@@ -931,6 +916,16 @@ macro_rules! __impl_bitflags {
+     };
+ }
+ 
++// Same as std::stringify but callable from __impl_bitflags, which needs to use
++// local_inner_macros so can only directly call macros from this crate.
++#[macro_export]
++#[doc(hidden)]
++macro_rules! __bitflags_stringify {
++    ($s:ident) => {
++        stringify!($s)
++    };
++}
++
+ #[cfg(feature = "example_generated")]
+ pub mod example_generated;
+ 
+@@ -944,7 +939,6 @@ mod tests {
+         #[doc = "> you are the easiest person to fool."]
+         #[doc = "> "]
+         #[doc = "> - Richard Feynman"]
+-        #[derive(Default)]
+         struct Flags: u32 {
+             const A = 0b00000001;
+             #[doc = "<pcwalton> macros are way better at generating code than trans is"]
+@@ -955,7 +949,9 @@ mod tests {
+             #[doc = "<strcat> wait what?"]
+             const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+         }
++    }
+ 
++    bitflags! {
+         struct _CfgFlags: u32 {
+             #[cfg(unix)]
+             const _CFG_A = 0b01;
+@@ -964,18 +960,17 @@ mod tests {
+             #[cfg(unix)]
+             const _CFG_C = Self::_CFG_A.bits | 0b10;
+         }
++    }
+ 
++    bitflags! {
+         struct AnotherSetOfFlags: i8 {
+             const ANOTHER_FLAG = -1_i8;
+         }
+-
+-        struct LongFlags: u32 {
+-            const LONG_A = 0b1111111111111111;
+-        }
+     }
+ 
+     bitflags! {
+-        struct EmptyFlags: u32 {
++        struct LongFlags: u32 {
++            const LONG_A = 0b1111111111111111;
+         }
+     }
+ 
+@@ -987,8 +982,6 @@ mod tests {
+ 
+         assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
+         assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
+-
+-        assert_eq!(EmptyFlags::empty().bits(), 0b00000000);
+     }
+ 
+     #[test]
+@@ -1003,9 +996,6 @@ mod tests {
+             AnotherSetOfFlags::from_bits(!0_i8),
+             Some(AnotherSetOfFlags::ANOTHER_FLAG)
+         );
+-
+-        assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty()));
+-        assert_eq!(EmptyFlags::from_bits(0b1), None);
+     }
+ 
+     #[test]
+@@ -1021,9 +1011,6 @@ mod tests {
+             AnotherSetOfFlags::from_bits_truncate(0_i8),
+             AnotherSetOfFlags::empty()
+         );
+-
+-        assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty());
+-        assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty());
+     }
+ 
+     #[test]
+@@ -1032,25 +1019,9 @@ mod tests {
+         assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty());
+         assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A);
+         assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B);
+-
+-        assert_eq!(
+-            unsafe { Flags::from_bits_unchecked(0b11) },
+-            (Flags::A | Flags::B)
+-        );
+-        assert_eq!(
+-            unsafe { Flags::from_bits_unchecked(0b1000) },
+-            (extra | Flags::empty())
+-        );
+-        assert_eq!(
+-            unsafe { Flags::from_bits_unchecked(0b1001) },
+-            (extra | Flags::A)
+-        );
+-
+-        let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) };
+-        assert_eq!(
+-            unsafe { EmptyFlags::from_bits_unchecked(0b1000) },
+-            (extra | EmptyFlags::empty())
+-        );
++        assert_eq!(unsafe { Flags::from_bits_unchecked(0b11) }, (Flags::A | Flags::B));
++        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1000) }, (extra | Flags::empty()));
++        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1001) }, (extra | Flags::A));
+     }
+ 
+     #[test]
+@@ -1060,9 +1031,6 @@ mod tests {
+         assert!(!Flags::ABC.is_empty());
+ 
+         assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
+-
+-        assert!(EmptyFlags::empty().is_empty());
+-        assert!(EmptyFlags::all().is_empty());
+     }
+ 
+     #[test]
+@@ -1071,15 +1039,7 @@ mod tests {
+         assert!(!Flags::A.is_all());
+         assert!(Flags::ABC.is_all());
+ 
+-        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
+-        assert!(!extra.is_all());
+-        assert!(!(Flags::A | extra).is_all());
+-        assert!((Flags::ABC | extra).is_all());
+-
+         assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
+-
+-        assert!(EmptyFlags::all().is_all());
+-        assert!(EmptyFlags::empty().is_all());
+     }
+ 
+     #[test]
+@@ -1121,8 +1081,6 @@ mod tests {
+         assert!(Flags::ABC.contains(e2));
+ 
+         assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
+-
+-        assert!(EmptyFlags::empty().contains(EmptyFlags::empty()));
+     }
+ 
+     #[test]
+@@ -1183,188 +1141,6 @@ mod tests {
+         assert_eq!(e3, Flags::A | Flags::B | extra);
+     }
+ 
+-    #[test]
+-    fn test_set_ops_basic() {
+-        let ab = Flags::A.union(Flags::B);
+-        let ac = Flags::A.union(Flags::C);
+-        let bc = Flags::B.union(Flags::C);
+-        assert_eq!(ab.bits, 0b011);
+-        assert_eq!(bc.bits, 0b110);
+-        assert_eq!(ac.bits, 0b101);
+-
+-        assert_eq!(ab, Flags::B.union(Flags::A));
+-        assert_eq!(ac, Flags::C.union(Flags::A));
+-        assert_eq!(bc, Flags::C.union(Flags::B));
+-
+-        assert_eq!(ac, Flags::A | Flags::C);
+-        assert_eq!(bc, Flags::B | Flags::C);
+-        assert_eq!(ab.union(bc), Flags::ABC);
+-
+-        assert_eq!(ac, Flags::A | Flags::C);
+-        assert_eq!(bc, Flags::B | Flags::C);
+-
+-        assert_eq!(ac.union(bc), ac | bc);
+-        assert_eq!(ac.union(bc), Flags::ABC);
+-        assert_eq!(bc.union(ac), Flags::ABC);
+-
+-        assert_eq!(ac.intersection(bc), ac & bc);
+-        assert_eq!(ac.intersection(bc), Flags::C);
+-        assert_eq!(bc.intersection(ac), Flags::C);
+-
+-        assert_eq!(ac.difference(bc), ac - bc);
+-        assert_eq!(bc.difference(ac), bc - ac);
+-        assert_eq!(ac.difference(bc), Flags::A);
+-        assert_eq!(bc.difference(ac), Flags::B);
+-
+-        assert_eq!(bc.complement(), !bc);
+-        assert_eq!(bc.complement(), Flags::A);
+-        assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B));
+-        assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B));
+-    }
+-
+-    #[test]
+-    fn test_set_ops_const() {
+-        // These just test that these compile and don't cause use-site panics
+-        // (would be possible if we had some sort of UB)
+-        const INTERSECT: Flags = Flags::all().intersection(Flags::C);
+-        const UNION: Flags = Flags::A.union(Flags::C);
+-        const DIFFERENCE: Flags = Flags::all().difference(Flags::A);
+-        const COMPLEMENT: Flags = Flags::C.complement();
+-        const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE);
+-        assert_eq!(INTERSECT, Flags::C);
+-        assert_eq!(UNION, Flags::A | Flags::C);
+-        assert_eq!(DIFFERENCE, Flags::all() - Flags::A);
+-        assert_eq!(COMPLEMENT, !Flags::C);
+-        assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A));
+-    }
+-
+-    #[test]
+-    fn test_set_ops_unchecked() {
+-        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
+-        let e1 = Flags::A.union(Flags::C).union(extra);
+-        let e2 = Flags::B.union(Flags::C);
+-        assert_eq!(e1.bits, 0b1101);
+-        assert_eq!(e1.union(e2), (Flags::ABC | extra));
+-        assert_eq!(e1.intersection(e2), Flags::C);
+-        assert_eq!(e1.difference(e2), Flags::A | extra);
+-        assert_eq!(e2.difference(e1), Flags::B);
+-        assert_eq!(e2.complement(), Flags::A);
+-        assert_eq!(e1.complement(), Flags::B);
+-        assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle
+-    }
+-
+-    #[test]
+-    fn test_set_ops_exhaustive() {
+-        // Define a flag that contains gaps to help exercise edge-cases,
+-        // especially around "unknown" flags (e.g. ones outside of `all()`
+-        // `from_bits_unchecked`).
+-        // - when lhs and rhs both have different sets of unknown flags.
+-        // - unknown flags at both ends, and in the middle
+-        // - cases with "gaps".
+-        bitflags! {
+-            struct Test: u16 {
+-                // Intentionally no `A`
+-                const B = 0b000000010;
+-                // Intentionally no `C`
+-                const D = 0b000001000;
+-                const E = 0b000010000;
+-                const F = 0b000100000;
+-                const G = 0b001000000;
+-                // Intentionally no `H`
+-                const I = 0b100000000;
+-            }
+-        }
+-        let iter_test_flags =
+-            || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) });
+-
+-        for a in iter_test_flags() {
+-            assert_eq!(
+-                a.complement(),
+-                Test::from_bits_truncate(!a.bits),
+-                "wrong result: !({:?})",
+-                a,
+-            );
+-            assert_eq!(a.complement(), !a, "named != op: !({:?})", a);
+-            for b in iter_test_flags() {
+-                // Check that the named operations produce the expected bitwise
+-                // values.
+-                assert_eq!(
+-                    a.union(b).bits,
+-                    a.bits | b.bits,
+-                    "wrong result: `{:?}` | `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(
+-                    a.intersection(b).bits,
+-                    a.bits & b.bits,
+-                    "wrong result: `{:?}` & `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(
+-                    a.symmetric_difference(b).bits,
+-                    a.bits ^ b.bits,
+-                    "wrong result: `{:?}` ^ `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(
+-                    a.difference(b).bits,
+-                    a.bits & !b.bits,
+-                    "wrong result: `{:?}` - `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                // Note: Difference is checked as both `a - b` and `b - a`
+-                assert_eq!(
+-                    b.difference(a).bits,
+-                    b.bits & !a.bits,
+-                    "wrong result: `{:?}` - `{:?}`",
+-                    b,
+-                    a,
+-                );
+-                // Check that the named set operations are equivalent to the
+-                // bitwise equivalents
+-                assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,);
+-                assert_eq!(
+-                    a.intersection(b),
+-                    a & b,
+-                    "named != op: `{:?}` & `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(
+-                    a.symmetric_difference(b),
+-                    a ^ b,
+-                    "named != op: `{:?}` ^ `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,);
+-                // Note: Difference is checked as both `a - b` and `b - a`
+-                assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,);
+-                // Verify that the operations which should be symmetric are
+-                // actually symmetric.
+-                assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,);
+-                assert_eq!(
+-                    a.intersection(b),
+-                    b.intersection(a),
+-                    "asymmetry: `{:?}` & `{:?}`",
+-                    a,
+-                    b,
+-                );
+-                assert_eq!(
+-                    a.symmetric_difference(b),
+-                    b.symmetric_difference(a),
+-                    "asymmetry: `{:?}` ^ `{:?}`",
+-                    a,
+-                    b,
+-                );
+-            }
+-        }
+-    }
+-
+     #[test]
+     fn test_set() {
+         let mut e1 = Flags::A | Flags::C;
+@@ -1392,6 +1168,8 @@ mod tests {
+         assert_eq!(m1, e1);
+     }
+ 
++
++    #[cfg(bitflags_const_fn)]
+     #[test]
+     fn test_const_fn() {
+         const _M1: Flags = Flags::empty();
+@@ -1481,11 +1259,6 @@ mod tests {
+         assert_eq!(hash(&x), hash(&y));
+     }
+ 
+-    #[test]
+-    fn test_default() {
+-        assert_eq!(Flags::empty(), Flags::default());
+-    }
+-
+     #[test]
+     fn test_debug() {
+         assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
+@@ -1494,13 +1267,7 @@ mod tests {
+         let extra = unsafe { Flags::from_bits_unchecked(0xb8) };
+         assert_eq!(format!("{:?}", extra), "0xb8");
+         assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8");
+-
+-        assert_eq!(
+-            format!("{:?}", Flags::ABC | extra),
+-            "A | B | C | ABC | 0xb8"
+-        );
+-
+-        assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)");
++        assert_eq!(format!("{:?}", Flags::ABC | extra), "A | B | C | ABC | 0xb8");
+     }
+ 
+     #[test]
+@@ -1544,7 +1311,8 @@ mod tests {
+             pub struct PublicFlags: i8 {
+                 const X = 0;
+             }
+-
++        }
++        bitflags! {
+             struct PrivateFlags: i8 {
+                 const Y = 0;
+             }
+@@ -1659,71 +1427,4 @@ mod tests {
+         assert_eq!(format!("{:?}", Flags::empty()), "NONE");
+         assert_eq!(format!("{:?}", Flags::SOME), "SOME");
+     }
+-
+-    #[test]
+-    fn test_empty_bitflags() {
+-        bitflags! {}
+-    }
+-
+-    #[test]
+-    fn test_u128_bitflags() {
+-        bitflags! {
+-            struct Flags128: u128 {
+-                const A = 0x0000_0000_0000_0000_0000_0000_0000_0001;
+-                const B = 0x0000_0000_0000_1000_0000_0000_0000_0000;
+-                const C = 0x8000_0000_0000_0000_0000_0000_0000_0000;
+-                const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
+-            }
+-        }
+-
+-        assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C);
+-        assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001);
+-        assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000);
+-        assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000);
+-        assert_eq!(
+-            Flags128::ABC.bits,
+-            0x8000_0000_0000_1000_0000_0000_0000_0001
+-        );
+-        assert_eq!(format!("{:?}", Flags128::A), "A");
+-        assert_eq!(format!("{:?}", Flags128::B), "B");
+-        assert_eq!(format!("{:?}", Flags128::C), "C");
+-        assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC");
+-    }
+-
+-    #[test]
+-    fn test_serde_bitflags_serialize() {
+-        let flags = SerdeFlags::A | SerdeFlags::B;
+-
+-        let serialized = serde_json::to_string(&flags).unwrap();
+-
+-        assert_eq!(serialized, r#"{"bits":3}"#);
+-    }
+-
+-    #[test]
+-    fn test_serde_bitflags_deserialize() {
+-        let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap();
+-
+-        let expected = SerdeFlags::C | SerdeFlags::D;
+-
+-        assert_eq!(deserialized.bits, expected.bits);
+-    }
+-
+-    #[test]
+-    fn test_serde_bitflags_roundtrip() {
+-        let flags = SerdeFlags::A | SerdeFlags::B;
+-
+-        let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap();
+-
+-        assert_eq!(deserialized.bits, flags.bits);
+-    }
+-
+-    bitflags! {
+-        #[derive(serde::Serialize, serde::Deserialize)]
+-        struct SerdeFlags: u32 {
+-            const A = 1;
+-            const B = 2;
+-            const C = 4;
+-            const D = 8;
+-        }
+-    }
+ }
+diff --git a/third_party/rust/bitflags/tests/basic.rs b/third_party/rust/bitflags/tests/basic.rs
+deleted file mode 100644
+index 73a52bec50b60..0000000000000
+--- a/third_party/rust/bitflags/tests/basic.rs
++++ /dev/null
+@@ -1,20 +0,0 @@
+-#![no_std]
+-
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    /// baz
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-        #[doc = "bar"]
+-        const B = 0b00000010;
+-        const C = 0b00000100;
+-        #[doc = "foo"]
+-        const ABC = Flags::A.bits | Flags::B.bits | Flags::C.bits;
+-    }
+-}
+-
+-#[test]
+-fn basic() {
+-    assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C);
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs b/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
+deleted file mode 100644
+index 38f4822f5a5f2..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
++++ /dev/null
+@@ -1,10 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    #[derive(Clone, Copy)]
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
+deleted file mode 100644
+index 0c13aa5024197..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
++++ /dev/null
+@@ -1,27 +0,0 @@
+-error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Flags`
+- --> $DIR/copy.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(Clone, Copy)]
+-  | |              ----- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
+-
+-error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `Flags`
+- --> $DIR/copy.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(Clone, Copy)]
+-  | |                     ---- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs b/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
+deleted file mode 100644
+index 4abbd630c6e12..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
++++ /dev/null
+@@ -1,10 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    #[derive(PartialEq, Eq)]
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
+deleted file mode 100644
+index 8a1a3b410a0e0..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
++++ /dev/null
+@@ -1,55 +0,0 @@
+-error[E0119]: conflicting implementations of trait `std::cmp::PartialEq` for type `Flags`
+- --> $DIR/eq.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(PartialEq, Eq)]
+-  | |              --------- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+-
+-error[E0119]: conflicting implementations of trait `std::cmp::Eq` for type `Flags`
+- --> $DIR/eq.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(PartialEq, Eq)]
+-  | |                         -- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+-
+-error[E0119]: conflicting implementations of trait `std::marker::StructuralPartialEq` for type `Flags`
+- --> $DIR/eq.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(PartialEq, Eq)]
+-  | |              --------- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+-
+-error[E0119]: conflicting implementations of trait `std::marker::StructuralEq` for type `Flags`
+- --> $DIR/eq.rs:3:1
+-  |
+-3 | / bitflags! {
+-4 | |     #[derive(PartialEq, Eq)]
+-  | |                         -- first implementation here
+-5 | |     struct Flags: u32 {
+-6 | |         const A = 0b00000001;
+-7 | |     }
+-8 | | }
+-  | |_^ conflicting implementation for `Flags`
+-  |
+-  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
+deleted file mode 100644
+index c2856b10830d3..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
++++ /dev/null
+@@ -1,123 +0,0 @@
+-use std::{
+-    fmt::{
+-        self,
+-        Debug,
+-        Display,
+-        LowerHex,
+-        UpperHex,
+-        Octal,
+-        Binary,
+-    },
+-    ops::{
+-        BitAnd,
+-        BitOr,
+-        BitXor,
+-        BitAndAssign,
+-        BitOrAssign,
+-        BitXorAssign,
+-        Not,
+-    },
+-};
+-
+-use bitflags::bitflags;
+-
+-// Ideally we'd actually want this to work, but currently need something like `num`'s `Zero`
+-// With some design work it could be made possible
+-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+-struct MyInt(u8);
+-
+-impl BitAnd for MyInt {
+-    type Output = Self;
+-
+-    fn bitand(self, other: Self) -> Self {
+-        MyInt(self.0 & other.0)
+-    }
+-}
+-
+-impl BitOr for MyInt {
+-    type Output = Self;
+-
+-    fn bitor(self, other: Self) -> Self {
+-        MyInt(self.0 | other.0)
+-    }
+-}
+-
+-impl BitXor for MyInt {
+-    type Output = Self;
+-
+-    fn bitxor(self, other: Self) -> Self {
+-        MyInt(self.0 ^ other.0)
+-    }
+-}
+-
+-impl BitAndAssign for MyInt {
+-    fn bitand_assign(&mut self, other: Self) {
+-        self.0 &= other.0
+-    }
+-}
+-
+-impl BitOrAssign for MyInt {
+-    fn bitor_assign(&mut self, other: Self) {
+-        self.0 |= other.0
+-    }
+-}
+-
+-impl BitXorAssign for MyInt {
+-    fn bitxor_assign(&mut self, other: Self) {
+-        self.0 ^= other.0
+-    }
+-}
+-
+-impl Debug for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        Debug::fmt(&self.0, f)
+-    }
+-}
+-
+-impl Display for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        Display::fmt(&self.0, f)
+-    }
+-}
+-
+-impl LowerHex for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        LowerHex::fmt(&self.0, f)
+-    }
+-}
+-
+-impl UpperHex for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        UpperHex::fmt(&self.0, f)
+-    }
+-}
+-
+-impl Octal for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        Octal::fmt(&self.0, f)
+-    }
+-}
+-
+-impl Binary for MyInt {
+-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+-        Binary::fmt(&self.0, f)
+-    }
+-}
+-
+-impl Not for MyInt {
+-    type Output = MyInt;
+-
+-    fn not(self) -> Self {
+-        MyInt(!self.0)
+-    }
+-}
+-
+-bitflags! {
+-    struct Flags128: MyInt {
+-        const A = MyInt(0b0000_0001u8);
+-        const B = MyInt(0b0000_0010u8);
+-        const C = MyInt(0b0000_0100u8);
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
+deleted file mode 100644
+index 1f0fb5cf7ad0b..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
++++ /dev/null
+@@ -1,27 +0,0 @@
+-error[E0308]: mismatched types
+-   --> $DIR/all_defined.rs:115:1
+-    |
+-115 | / bitflags! {
+-116 | |     struct Flags128: MyInt {
+-117 | |         const A = MyInt(0b0000_0001u8);
+-118 | |         const B = MyInt(0b0000_0010u8);
+-119 | |         const C = MyInt(0b0000_0100u8);
+-120 | |     }
+-121 | | }
+-    | |_^ expected struct `MyInt`, found integer
+-    |
+-    = note: this error originates in the macro `__impl_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
+-
+-error[E0308]: mismatched types
+-   --> $DIR/all_defined.rs:115:1
+-    |
+-115 | / bitflags! {
+-116 | |     struct Flags128: MyInt {
+-117 | |         const A = MyInt(0b0000_0001u8);
+-118 | |         const B = MyInt(0b0000_0010u8);
+-119 | |         const C = MyInt(0b0000_0100u8);
+-120 | |     }
+-121 | | }
+-    | |_^ expected struct `MyInt`, found integer
+-    |
+-    = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
+diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
+deleted file mode 100644
+index fff6b2cc13062..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
++++ /dev/null
+@@ -1,13 +0,0 @@
+-use bitflags::bitflags;
+-
+-struct MyInt(u8);
+-
+-bitflags! {
+-    struct Flags128: MyInt {
+-        const A = MyInt(0b0000_0001);
+-        const B = MyInt(0b0000_0010);
+-        const C = MyInt(0b0000_0100);
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
+deleted file mode 100644
+index ee95f8365e33e..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
++++ /dev/null
+@@ -1,13 +0,0 @@
+-error[E0204]: the trait `Copy` may not be implemented for this type
+-  --> $DIR/all_missing.rs:5:1
+-   |
+-5  | / bitflags! {
+-6  | |     struct Flags128: MyInt {
+-7  | |         const A = MyInt(0b0000_0001);
+-8  | |         const B = MyInt(0b0000_0010);
+-9  | |         const C = MyInt(0b0000_0100);
+-10 | |     }
+-11 | | }
+-   | |_^ this field does not implement `Copy`
+-   |
+-   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
+deleted file mode 100644
+index a6a3912aea30a..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
++++ /dev/null
+@@ -1,13 +0,0 @@
+-mod example {
+-    use bitflags::bitflags;
+-
+-    bitflags! {
+-        pub struct Flags1: u32 {
+-            const FLAG_A = 0b00000001;
+-        }
+-    }
+-}
+-
+-fn main() {
+-    let flag1 = example::Flags1::FLAG_A.bits;
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
+deleted file mode 100644
+index 58a04660166a8..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
++++ /dev/null
+@@ -1,10 +0,0 @@
+-error[E0616]: field `bits` of struct `Flags1` is private
+-  --> $DIR/private_field.rs:12:41
+-   |
+-12 |     let flag1 = example::Flags1::FLAG_A.bits;
+-   |                                         ^^^^ private field
+-   |
+-help: a method `bits` also exists, call it with parentheses
+-   |
+-12 |     let flag1 = example::Flags1::FLAG_A.bits();
+-   |                                             ^^
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
+deleted file mode 100644
+index 85a5b1863dd43..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
++++ /dev/null
+@@ -1,18 +0,0 @@
+-mod example {
+-    use bitflags::bitflags;
+-
+-    bitflags! {
+-        pub struct Flags1: u32 {
+-            const FLAG_A = 0b00000001;
+-        }
+-
+-        struct Flags2: u32 {
+-            const FLAG_B = 0b00000010;
+-        }
+-    }
+-}
+-
+-fn main() {
+-    let flag1 = example::Flags1::FLAG_A;
+-    let flag2 = example::Flags2::FLAG_B;
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
+deleted file mode 100644
+index d23f83209ba90..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
++++ /dev/null
+@@ -1,18 +0,0 @@
+-error[E0603]: struct `Flags2` is private
+-  --> $DIR/private_flags.rs:17:26
+-   |
+-17 |     let flag2 = example::Flags2::FLAG_B;
+-   |                          ^^^^^^ private struct
+-   |
+-note: the struct `Flags2` is defined here
+-  --> $DIR/private_flags.rs:4:5
+-   |
+-4  | /     bitflags! {
+-5  | |         pub struct Flags1: u32 {
+-6  | |             const FLAG_A = 0b00000001;
+-7  | |         }
+-...  |
+-11 | |         }
+-12 | |     }
+-   | |_____^
+-   = note: this error originates in the macro `bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
+deleted file mode 100644
+index b90f0ce92d1e6..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
++++ /dev/null
+@@ -1,9 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    pub struct Flags1: u32 {
+-        pub const FLAG_A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
+deleted file mode 100644
+index b01122c7ad879..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
++++ /dev/null
+@@ -1,5 +0,0 @@
+-error: no rules expected the token `pub`
+- --> $DIR/pub_const.rs:5:9
+-  |
+-5 |         pub const FLAG_A = 0b00000001;
+-  |         ^^^ no rules expected this token in macro call
+diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs b/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
+deleted file mode 100644
+index 1f02982a8fa24..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
++++ /dev/null
+@@ -1,17 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-impl From<u32> for Flags {
+-    fn from(v: u32) -> Flags {
+-        Flags::from_bits_truncate(v)
+-    }
+-}
+-
+-fn main() {
+-
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/default.rs b/third_party/rust/bitflags/tests/compile-pass/impls/default.rs
+deleted file mode 100644
+index a97b6536f2b58..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/impls/default.rs
++++ /dev/null
+@@ -1,10 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    #[derive(Default)]
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs b/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
+deleted file mode 100644
+index 3052c460ec33a..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
++++ /dev/null
+@@ -1,15 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-impl Flags {
+-    pub fn new() -> Flags {
+-        Flags::A
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs b/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
+deleted file mode 100644
+index 47549215948d1..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
++++ /dev/null
+@@ -1,14 +0,0 @@
+-use bitflags::bitflags;
+-
+-// Checks for possible errors caused by overriding names used by `bitflags!` internally.
+-
+-mod core {}
+-mod _core {}
+-
+-bitflags! {
+-    struct Test: u8 {
+-        const A = 1;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs b/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
+deleted file mode 100644
+index b04f2f6a49332..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
++++ /dev/null
+@@ -1,19 +0,0 @@
+-use bitflags::bitflags;
+-
+-// Checks for possible errors caused by overriding names used by `bitflags!` internally.
+-
+-#[allow(unused_macros)]
+-macro_rules! stringify {
+-    ($($t:tt)*) => { "..." };
+-}
+-
+-bitflags! {
+-    struct Test: u8 {
+-        const A = 1;
+-    }
+-}
+-
+-fn main() {
+-    // Just make sure we don't call the redefined `stringify` macro
+-    assert_eq!(format!("{:?}", Test::A), "A");
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/repr/c.rs b/third_party/rust/bitflags/tests/compile-pass/repr/c.rs
+deleted file mode 100644
+index 6feba36ed82c1..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/repr/c.rs
++++ /dev/null
+@@ -1,10 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    #[repr(C)]
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs b/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
+deleted file mode 100644
+index e38db4dd11b99..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
++++ /dev/null
+@@ -1,10 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    #[repr(transparent)]
+-    struct Flags: u32 {
+-        const A = 0b00000001;
+-    }
+-}
+-
+-fn main() {}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs b/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
+deleted file mode 100644
+index 33a7967e629ef..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
++++ /dev/null
+@@ -1,11 +0,0 @@
+-use bitflags::bitflags;
+-
+-bitflags! {
+-    pub struct Flags1: u32 {
+-        const FLAG_A = 0b00000001;
+-    }
+-}
+-
+-fn main() {
+-    assert_eq!(0b00000001, Flags1::FLAG_A.bits);
+-}
+diff --git a/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs b/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
+deleted file mode 100644
+index c11050e3baf0c..0000000000000
+--- a/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
++++ /dev/null
+@@ -1,19 +0,0 @@
+-mod a {
+-    mod b {
+-        use bitflags::bitflags;
+-
+-        bitflags! {
+-            pub(in crate::a) struct Flags: u32 {
+-                const FLAG_A = 0b00000001;
+-            }
+-        }
+-    }
+-
+-    pub fn flags() -> u32 {
+-        b::Flags::FLAG_A.bits()
+-    }
+-}
+-
+-fn main() {
+-    assert_eq!(0b00000001, a::flags());
+-}
+diff --git a/third_party/rust/bitflags/tests/compile.rs b/third_party/rust/bitflags/tests/compile.rs
+deleted file mode 100644
+index ed02d01e9ca1b..0000000000000
+--- a/third_party/rust/bitflags/tests/compile.rs
++++ /dev/null
+@@ -1,63 +0,0 @@
+-use std::{
+-    fs,
+-    ffi::OsStr,
+-    io,
+-    path::Path,
+-};
+-
+-use walkdir::WalkDir;
+-
+-#[test]
+-fn fail() {
+-    prepare_stderr_files("tests/compile-fail").unwrap();
+-
+-    let t = trybuild::TestCases::new();
+-    t.compile_fail("tests/compile-fail/**/*.rs");
+-}
+-
+-#[test]
+-fn pass() {
+-    let t = trybuild::TestCases::new();
+-    t.pass("tests/compile-pass/**/*.rs");
+-}
+-
+-// Compiler messages may change between versions
+-// We don't want to have to track these too closely for `bitflags`, but
+-// having some message to check makes sure user-facing errors are sensical.
+-// 
+-// The approach we use is to run the test on all compilers, but only check stderr
+-// output on beta (which is the next stable release). We do this by default ignoring
+-// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files
+-// when we happen to be running on a beta compiler.
+-fn prepare_stderr_files(path: impl AsRef<Path>) -> io::Result<()> {
+-    for entry in WalkDir::new(path) {
+-        let entry = entry?;
+-
+-        if entry.path().extension().and_then(OsStr::to_str) == Some("beta") {
+-            let renamed = entry.path().with_extension("");
+-
+-            // Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta`
+-            // file if it exists. On `beta` compilers, we'll recreate it. On other compilers,
+-            // we don't want to end up checking it anyways.
+-            if renamed.exists() {
+-                fs::remove_file(&renamed)?;
+-            }
+-
+-            rename_beta_stderr(entry.path(), renamed)?;
+-        }
+-    }
+-
+-    Ok(())
+-}
+-
+-#[rustversion::beta]
+-fn rename_beta_stderr(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
+-    fs::copy(from, to)?;
+-
+-    Ok(())
+-}
+-
+-#[rustversion::not(beta)]
+-fn rename_beta_stderr(_: impl AsRef<Path>, _: impl AsRef<Path>) -> io::Result<()> {
+-    Ok(())
+-}
+diff --git a/third_party/rust/midir/.cargo-checksum.json b/third_party/rust/midir/.cargo-checksum.json
+index 390b25b1e0118..34b17c2c5c548 100644
+--- a/third_party/rust/midir/.cargo-checksum.json
++++ b/third_party/rust/midir/.cargo-checksum.json
+@@ -1 +1 @@
+-{"files":{"CHANGELOG.md":"10db6f8dbb1c5566e75f2eeda6b2ee8bb44fe4a76f57e0bfb98c62f7f8c04f89","Cargo.toml":"41aa086ea813af75458515ff515917bb48d20eaef42a74352ea12ff8d5d16bce","LICENSE":"6fe6f623b1fa80e90679aee2f917d8978a184988ebb995ebc254cc9633903cac","README.md":"4131b953217e77a4463fde307ba3262b4df11732c1ff209668df12dff3c73ffc","azure-pipelines-template.yml":"c787791a94e654226a299aaa875fcc48f6eedf4dae631855cb5a7067891dbe3a","azure-pipelines.yml":"1b4fab0afacc66732a385cb6e5b213c170fc9717219a03ccda9c5db78cd461dd","examples/test_forward.rs":"6cb060aba7e8c39eaf53ea95a72d4c7939ffb4bebc82c291135fdc35495078ce","examples/test_list_ports.rs":"41ba21ab1e56d76206abc8b291d27050cb1a788372f00f6761c78f03fb5981ff","examples/test_play.rs":"22630e46af9628d8193ad8e19ff095ad02542b7ab697be4e513da78210ad5c0c","examples/test_read_input.rs":"4901f18435c3f8021750ccd4687abe92194ab38f1e7721896a6a31f6650d524c","examples/test_reuse.rs":"fdb3b430aec42c7c648fbecf22e6c726ef8a20638936a1a70fb373dff94c0632","examples/
 test_sysex.rs":"ea06427a644c3639f1c49271be5d16c9d3890d3741eb6ebf2ff64d2f7fd36e96","src/backend/alsa/mod.rs":"6bc784435247c3302bf12c3f558b6027abfbec997a280baa113c7344e5b0479f","src/backend/coremidi/mod.rs":"f827cbc5db7086ea58c5927213a2c3e0246244d5939c2ba0ff787caae7089511","src/backend/jack/mod.rs":"8f2eace3e9046ec6de8c7fc37d3502d2b971a73fe2a96e5c2a423d51445f1505","src/backend/jack/wrappers.rs":"f18718f234e41c91bb5463546fbbe61be64e9581a4fae6ef2de20cafae487298","src/backend/mod.rs":"1a8106889ecd053af27b3a72515bfb286da1b08bb90909fa6d4e7b816b50c447","src/backend/webmidi/mod.rs":"4af5b288833ee99f047a638b368eca293f89356f1e82147c9a9c1633d950955d","src/backend/winmm/handler.rs":"45b36067fd280a38943f385d3d7f6885d7448153f53e9c8f66b58b484535ad1c","src/backend/winmm/mod.rs":"94d8c57fd2d327993d01ef06d8c68190c528fe52dd39e6b97c88d9f1f0afa753","src/backend/winrt/mod.rs":"ca7ac4ac310e7f6a6c28dd6374bfe97b38ed8656c7ca343494264cce45f93ae6","src/common.rs":"2cab2e987428522ca601544b516b64b858859730fbd1be0
 e53c828e82025319d","src/errors.rs":"495ba80f9dcfeefd343b460b74549b12cb1825c3e1b315848f859d0b4d66ddbe","src/lib.rs":"ecde030ca02a90a99577cd71446857a2c00aee8ff1bc7890c54a5d0d22d2be2c","src/os/mod.rs":"507dfa95e57805c489a883dcf9efddcb718d5178267f296294f72b3c397c12c7","src/os/unix.rs":"a1977659d270fcf31111d4446b949d2760d76e2077639e6008d634800861b77b","tests/virtual.rs":"b47501eeb313f3e255d2d1888c333ff994d958865272929fe7bf116be45b6805"},"package":null}
+\ No newline at end of file
++{"files":{"CHANGELOG.md":"10db6f8dbb1c5566e75f2eeda6b2ee8bb44fe4a76f57e0bfb98c62f7f8c04f89","Cargo.toml":"792c11a1ab6ce0443cb040994b02f1e80e07d19e6bf59f683a7fb227539bc028","LICENSE":"6fe6f623b1fa80e90679aee2f917d8978a184988ebb995ebc254cc9633903cac","README.md":"4131b953217e77a4463fde307ba3262b4df11732c1ff209668df12dff3c73ffc","azure-pipelines-template.yml":"c787791a94e654226a299aaa875fcc48f6eedf4dae631855cb5a7067891dbe3a","azure-pipelines.yml":"1b4fab0afacc66732a385cb6e5b213c170fc9717219a03ccda9c5db78cd461dd","examples/test_forward.rs":"6cb060aba7e8c39eaf53ea95a72d4c7939ffb4bebc82c291135fdc35495078ce","examples/test_list_ports.rs":"41ba21ab1e56d76206abc8b291d27050cb1a788372f00f6761c78f03fb5981ff","examples/test_play.rs":"22630e46af9628d8193ad8e19ff095ad02542b7ab697be4e513da78210ad5c0c","examples/test_read_input.rs":"4901f18435c3f8021750ccd4687abe92194ab38f1e7721896a6a31f6650d524c","examples/test_reuse.rs":"fdb3b430aec42c7c648fbecf22e6c726ef8a20638936a1a70fb373dff94c0632","examples/
 test_sysex.rs":"ea06427a644c3639f1c49271be5d16c9d3890d3741eb6ebf2ff64d2f7fd36e96","src/backend/alsa/mod.rs":"6bc784435247c3302bf12c3f558b6027abfbec997a280baa113c7344e5b0479f","src/backend/coremidi/mod.rs":"f827cbc5db7086ea58c5927213a2c3e0246244d5939c2ba0ff787caae7089511","src/backend/jack/mod.rs":"8f2eace3e9046ec6de8c7fc37d3502d2b971a73fe2a96e5c2a423d51445f1505","src/backend/jack/wrappers.rs":"f18718f234e41c91bb5463546fbbe61be64e9581a4fae6ef2de20cafae487298","src/backend/mod.rs":"1a8106889ecd053af27b3a72515bfb286da1b08bb90909fa6d4e7b816b50c447","src/backend/webmidi/mod.rs":"4af5b288833ee99f047a638b368eca293f89356f1e82147c9a9c1633d950955d","src/backend/winmm/handler.rs":"45b36067fd280a38943f385d3d7f6885d7448153f53e9c8f66b58b484535ad1c","src/backend/winmm/mod.rs":"94d8c57fd2d327993d01ef06d8c68190c528fe52dd39e6b97c88d9f1f0afa753","src/backend/winrt/mod.rs":"ca7ac4ac310e7f6a6c28dd6374bfe97b38ed8656c7ca343494264cce45f93ae6","src/common.rs":"2cab2e987428522ca601544b516b64b858859730fbd1be0
 e53c828e82025319d","src/errors.rs":"495ba80f9dcfeefd343b460b74549b12cb1825c3e1b315848f859d0b4d66ddbe","src/lib.rs":"ecde030ca02a90a99577cd71446857a2c00aee8ff1bc7890c54a5d0d22d2be2c","src/os/mod.rs":"507dfa95e57805c489a883dcf9efddcb718d5178267f296294f72b3c397c12c7","src/os/unix.rs":"a1977659d270fcf31111d4446b949d2760d76e2077639e6008d634800861b77b","tests/virtual.rs":"b47501eeb313f3e255d2d1888c333ff994d958865272929fe7bf116be45b6805"},"package":null}
+\ No newline at end of file
+diff --git a/third_party/rust/midir/Cargo.toml b/third_party/rust/midir/Cargo.toml
+index 49089e0ffe86e..ac48aab304db9 100644
+--- a/third_party/rust/midir/Cargo.toml
++++ b/third_party/rust/midir/Cargo.toml
+@@ -28,8 +28,8 @@ libc = { version = "0.2.21", optional = true }
+ winrt = { version = "0.7.0", optional = true}
+ 
+ [target.'cfg(target_os = "linux")'.dependencies]
+-alsa = "0.4.3"
+-nix = "0.15"
++alsa = "0.5.0"
++nix = "0.20"
+ libc = "0.2.21"
+ 
+ [target.'cfg(target_os = "macos")'.dependencies]
+diff --git a/third_party/rust/nix-0.15.0/.cargo-checksum.json b/third_party/rust/nix-0.15.0/.cargo-checksum.json
+new file mode 100644
+index 0000000000000..e5f2bc789185a
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/.cargo-checksum.json
+@@ -0,0 +1 @@
++{"files":{"CHANGELOG.md":"91af9fd5f2d9cdb9c8bb750e24b625742e95a6c74bcff419f3de70eb26578281","CONTRIBUTING.md":"a9101e3d1487170d691d5f062ff49a433c167582ac8984dd41a744be92652f74","CONVENTIONS.md":"e150ce43c1d188c392c1a3bf7f2e08e3cf84906705c7bef43f319037d29ea385","Cargo.toml":"af0cc0ae7ff4bf6c2e5b35fe062f54fe2d619f70ba67795f4f43a981420b5de0","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"80d71b9eaac7bf7f0d307372592ed1467f994291e6fad816a44f3c70e2887d0f","build.rs":"14c9c678c33f5894509da47f77d6a326b14aecb4190ce87a24cce98687ca63b2","src/dir.rs":"21e330cbe6594274335b94d9e9b6059f1fa8e53d2e5b5c697058c52ec6b3c5ff","src/errno.rs":"a009ccf18b45c0a4c9319c65b0dc5bc322d9ad43cfe462ec4661559f44162451","src/errno_dragonfly.c":"a857e47b114acb85fddcb252a610ab5734d225c26b7bedd7c35d7789d46c8526","src/fcntl.rs":"6ae2f7f01dd2568b82a4e57f86e02b1d63eec6c26111c5adb2ca5d78a2a99fe7","src/features.rs":"22ff626ff8287a07dd55bcfc63c9f518c19c56144e15f9b6f9e3bbdcda51c2a8","
 src/ifaddrs.rs":"9a93de176edcca4613e668b8ccc2c3e3b6b711aa2d8d94ccb0ba08694d1ef35f","src/kmod.rs":"4d8a695d3d761f351a39d654303a1bd168e74295b7d142b918737e355b24f34d","src/lib.rs":"fdd8049a79ffb92384c72f0a6b0bab717001ddfa9b01f2b33413c83f424f2ac8","src/macros.rs":"aec27fa0fd98900913fada926c9a4581cd28f2640e3a7b5480707f923c9200f8","src/mount.rs":"cdf5db8409017483132db9d7493b5d6cc96df5560d0fa5ad8f385aff72db10ca","src/mqueue.rs":"82af42b31381af73e7966f845d1ed93957f0b9976bf2da524b178fad15b2b08d","src/net/if_.rs":"f7e02076fcf3cadf3fdf141884c9bd2c468a7047ba60bc490f0057df802b53ce","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"7305e250066cd1a7318cd239ed3db787937ee98426fe9289cf00fa874d76b6c7","src/pty.rs":"6b965b586579933af47d4efef4c82c391b927037eaa08d8c83fc974ef17fc7c8","src/sched.rs":"f9b214fa60006b5450ffb3589a55ec59c3694bd49597c65c38ac813fcd96c7dd","src/sys/aio.rs":"a1ba629258b3ce1268e5fe8e5b41dce3581f77d415dc5e2455c1f82f26dd3085","src/sys/e
 poll.rs":"f0b539e0645569657f2142db91a38c94ebe1925f44852d64c61c818758dbbf0b","src/sys/event.rs":"ef8bc02a08d9ce7924c87f8f891fa051587b195a36913712fe85237a2fe0685b","src/sys/eventfd.rs":"08008cf3dc64c2216847c02c0dd8d7189cf08edbaafe35ba2c57c053fde09ef4","src/sys/inotify.rs":"687c8417d737939aa93f805d6003afc4f84f50828b1bd9429ef5d00bef0e0955","src/sys/ioctl/bsd.rs":"56ca6ecf5f7cfb566f4f3ba589fcc778f747a517dd45e13780981922e6215344","src/sys/ioctl/linux.rs":"6cfbdff4dbfa1a3782acdedebe89ffa9f000fdfc4ab68cb46f52890ebc1c6f2d","src/sys/ioctl/mod.rs":"20bc3cf1fcbbc7c31e4d507baa4e576a793ea42fb33618d2e7afeda730c4324f","src/sys/memfd.rs":"11cd93c867fdbdbc9588cecb94268691de42b2ef2a38fe33525be7c7f60c85d5","src/sys/mman.rs":"f77d28611a7ff3bf62784a3c4f26d7d79969395b1d9bbc6ff15e734f52dc404f","src/sys/mod.rs":"f39a08c72e37638c7cecfb9c087e0a41e2b69409aa545b0ef7bbd59c0a063ee2","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"8a7eacfc172b55763ae
 32109bf9b252669ba68b72cd5122f7504eb35c0c08345","src/sys/ptrace/linux.rs":"f09b45148004f4b28d8503c397a8d112d31046c98e68335bf4e89425d5b33f07","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"7eb8e797466b506f6ed882f18eda92c4639cf43d9384a19bc39cd1bf982989c9","src/sys/reboot.rs":"fde9da27c2928f7026231430fa14fec2058df4e49a0aeda2a237a60524f11241","src/sys/select.rs":"57d6c4403d1bf788bd52ab6f03cfc16a189d31b6bfb338b135cb775fe369121f","src/sys/sendfile.rs":"ea386e83baf9b5b23488aca26635aacdc92f2bfe238e4399a7380bd0331e0ef7","src/sys/signal.rs":"9216cdd609b4dfb9c2e559c411be6b7c722f7ddd8024682c0895a32126b488aa","src/sys/signalfd.rs":"bfcfce619bf199e50f9cc80a3eb778d48474a015cfdafc64a0c3517373a225a9","src/sys/socket/addr.rs":"8b297ce13cd8ad200b3e764888c26ceb582ee505385d1e172440de94ade99644","src/sys/socket/mod.rs":"e0353f04f3d098a8bf5e2aae431645897b96e0889fb76537dc0330159c6f233d","src/sys/socket/sockopt.rs":"c663505d6a7a7ae9d76e03fbc17e5
 3d308ea6b1eae92212812e1d76b2bf2916f","src/sys/stat.rs":"c4807048f86be67026756737cf81f448ec23c2a4745776cb40f40b533a88e0c8","src/sys/statfs.rs":"d2b72069f20aa7782ce5de4ec2d00c76a82a92376c2066bbb270cdac2167719e","src/sys/statvfs.rs":"2d328cf525ba04ab1e1351128624a7df7d0c55ea91fda6c8d620d13710d61606","src/sys/sysinfo.rs":"0c05244655aa9e6dff5138392c5c1ae97630d35bae0e5510d7f51a75c31fd425","src/sys/termios.rs":"a2e99afdfc3526641a2cb82b57bfd0a25a362fb9be5ad37ff9f11acaeb0b9439","src/sys/time.rs":"8a1224b9262026086af698630aedbed21b45d661fbd045fc6c6af41a16a23374","src/sys/uio.rs":"60a974275ff8c485ea183bdd6f7e25894e6f2360a5bfb25442391a825a3b9b8c","src/sys/utsname.rs":"c977a1aec6e051c72b27506395e942abab9cbd9523e6d345ea66dc10875ee87d","src/sys/wait.rs":"30b14a8f518d031805cae6c6ff644116f162d8c8a75fddcfce4479d8d55fd1c0","src/ucontext.rs":"075560ec08a362881534211f8c6b78844886d6b767c2f7067174600e38ed3f63","src/unistd.rs":"82308ec31b6293b55f86fafd04e976a41127fedebb8f158abd1399c7399af947","test/sys/mod.
 rs":"e0821cbc289ad952f17229609c7de4282cca1e44cd13e1a7494a6378ecbc12f8","test/sys/test_aio.rs":"b2544bfb321ca7fbed276ee637c769fb438156d14666cdc1e1d547b3514a44e3","test/sys/test_aio_drop.rs":"30dd1d238269d00381fa50f6d3cb2b13794b7cceb9f6455f3878fcbffa9aa62d","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"eea690ed386da0a666df5eb23a417421fddb99dc8e39556f63b30969bb6cf779","test/sys/test_lio_listio_resubmit.rs":"203a583313542593148f375b087ae30620222a745680173fa98fc448d1e5ae7f","test/sys/test_pthread.rs":"3890e5ecbf2082e0d05d102cc9cec6e76ede3c15f250d104e3483b1c1c3400b1","test/sys/test_ptrace.rs":"4e8d5dff5fe6bc56e4ae53bdfd10f5e8ea567d8099576d1c690cf7a6b2bc955f","test/sys/test_select.rs":"bdb20211fc6ec1e3f186337eac51e08757acb6901d307d67c71bf9011f0d54bd","test/sys/test_signal.rs":"84ae63c2baa49eebeabe5bbd347b9c5417e14ba97f342719d7
 53dc1c1c768d60","test/sys/test_signalfd.rs":"71b5d6d782283f6db64ca90f7fb06617faec71091d59d2587e41bbc9d8c43d5c","test/sys/test_socket.rs":"09a7ef0322e07b4579893e0307a7c4f81fbbc653d005b827a519c33a33e185ce","test/sys/test_sockopt.rs":"b3d386c8279f86bf9439c772317bafcdba5630fa806c8319e87ddac0ccfa3a03","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"fa4be3ade859b527bf33408f85a6f57b127917cf5f2afb662d09f6019d07913a","test/sys/test_uio.rs":"9da234e3bd5003fd200cc37c4a5be147ecda1a7670feb1d505f23d646d3e1c57","test/sys/test_wait.rs":"e6c5147e213daa93892cd828f53214995d2e019ff2372cc48d85ce9b93d26ec9","test/test.rs":"e6307f82a39426a949b8e925a2df4a62e31c0e43081d7a33d23759bdfeeece1f","test/test_dir.rs":"5d137a62f11d1a4993b4bb35dccc38a4c4416b7da374887f2335a9895b4fdee4","test/test_fcntl.rs":"730e64e99dc867ba5af7cc4ca83a4489c8b96b1a52f8937bcc666d673af27002","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c903
 33ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"f4754f028402a8ba788c87686288424cd3784e77c7eb5d96682ef491b1dd5262","test/test_mount.rs":"78ddc657f5098360c764fffa3a7d844503e4b6b65b44bfd42d9aa9045b415cb6","test/test_mq.rs":"5806f8825e91edc79dd0e2bc81d8be3ba094c2de6c0b2ac0268221ae2ad22701","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"46c71ee988fe1b85561ea0530d099750be8c1b8f95ab6e845c8a9f46f16f060c","test/test_pty.rs":"be04f99904fa47b60400c2bd156a388b73df4b9aec2eebf13df7dcdfc9aacf45","test/test_ptymaster_drop.rs":"5cfbbb79551c205ab510c2d4ef497bf937ceac9151fbe2f2e543d6515e406990","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"1dc420d3119bf4d863a7ae0ba63efa7f1416f6e46e4
 100ea161003fe1c3f66ba","test/test_unistd.rs":"0325c998acca1e826e9e2b3d351d55ab9723a6cb2ca2072245978e7f5a9acee8"},"package":"3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"}
+\ No newline at end of file
+diff --git a/third_party/rust/nix-0.15.0/CHANGELOG.md b/third_party/rust/nix-0.15.0/CHANGELOG.md
+new file mode 100644
+index 0000000000000..d93a5ce6bbfc9
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/CHANGELOG.md
+@@ -0,0 +1,742 @@
++# Change Log
++
++All notable changes to this project will be documented in this file.
++This project adheres to [Semantic Versioning](http://semver.org/).
++
++## [Unreleased] - ReleaseDate
++### Added
++### Changed
++### Fixed
++### Removed
++
++## [0.15.0] - 10 August 2019
++### Added
++- Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`.
++  ([#1079](https://github.com/nix-rust/nix/pull/1079))
++- Implemented `Clone`, `Copy`, `Debug`, `Eq`, `Hash`, and `PartialEq` for most
++  types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035))
++- Added `copy_file_range` wrapper
++  ([#1069](https://github.com/nix-rust/nix/pull/1069))
++- Add `mkdirat`.
++  ([#1084](https://github.com/nix-rust/nix/pull/1084))
++- Add `posix_fadvise`.
++  ([#1089](https://github.com/nix-rust/nix/pull/1089))
++- Added `AF_VSOCK` to `AddressFamily`.
++  ([#1091](https://github.com/nix-rust/nix/pull/1091))
++- Add `unlinkat`
++  ([#1058](https://github.com/nix-rust/nix/pull/1058))
++- Add `renameat`.
++  ([#1097](https://github.com/nix-rust/nix/pull/1097))
++
++### Changed
++- Support for `ifaddrs` now present when building for Android.
++  ([#1077](https://github.com/nix-rust/nix/pull/1077))
++- Minimum supported Rust version is now 1.31.0
++  ([#1035](https://github.com/nix-rust/nix/pull/1035))
++  ([#1095](https://github.com/nix-rust/nix/pull/1095))
++- Now functions `statfs()` and `fstatfs()` return result with `Statfs` wrapper
++  ([#928](https://github.com/nix-rust/nix/pull/928))
++
++### Fixed
++- Enabled `sched_yield` for all nix hosts.
++  ([#1090](https://github.com/nix-rust/nix/pull/1090))
++
++### Removed
++
++## [0.14.1] - 2019-06-06
++### Added
++- Macros exported by `nix` may now be imported via `use` on the Rust 2018
++  edition without importing helper macros on Linux targets.
++  ([#1066](https://github.com/nix-rust/nix/pull/1066))
++
++  For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
++  without importing the `convert_ioctl_res!` macro.
++
++  ```rust
++  use nix::ioctl_read_bad;
++
++  ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
++  ```
++
++### Changed
++- Changed some public types from reexports of libc types like `uint32_t` to the
++  native equivalents like `u32.`
++  ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
++
++### Fixed
++- Fix the build on Android and Linux/mips with recent versions of libc.
++  ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
++
++### Removed
++
++## [0.14.0] - 2019-05-21
++### Added
++- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd.
++  ([#1002](https://github.com/nix-rust/nix/pull/1002))
++- Added `inotify_init1`, `inotify_add_watch` and `inotify_rm_watch` wrappers for
++  Android and Linux. ([#1016](https://github.com/nix-rust/nix/pull/1016))
++- Add `ALG_SET_IV`, `ALG_SET_OP` and `ALG_SET_AEAD_ASSOCLEN` control messages and `AF_ALG`
++  socket types on Linux and Android ([#1031](https://github.com/nix-rust/nix/pull/1031))
++- Add killpg
++  ([#1034](https://github.com/nix-rust/nix/pull/1034))
++- Added ENOTSUP errno support for Linux and Android.
++  ([#969](https://github.com/nix-rust/nix/pull/969))
++- Add several errno constants from OpenBSD 6.2
++  ([#1036](https://github.com/nix-rust/nix/pull/1036))
++- Added `from_std` and `to_std` methods for `sys::socket::IpAddr`
++  ([#1043](https://github.com/nix-rust/nix/pull/1043))
++- Added `nix::unistd:seteuid` and `nix::unistd::setegid` for those platforms that do
++  not support `setresuid` nor `setresgid` respectively.
++  ([#1044](https://github.com/nix-rust/nix/pull/1044))
++- Added a `access` wrapper
++  ([#1045](https://github.com/nix-rust/nix/pull/1045))
++- Add `forkpty`
++  ([#1042](https://github.com/nix-rust/nix/pull/1042))
++- Add `sched_yield`
++  ([#1050](https://github.com/nix-rust/nix/pull/1050))
++
++### Changed
++- `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/))
++- `recvmsg` now returns an Iterator over `ControlMessageOwned` objects rather
++  than `ControlMessage` objects.  This is sadly not backwards-compatible.  Fix
++  code like this:
++  ```rust
++  if let ControlMessage::ScmRights(&fds) = cmsg {
++  ```
++
++  By replacing it with code like this:
++  ```rust
++  if let ControlMessageOwned::ScmRights(fds) = cmsg {
++  ```
++  ([#1020](https://github.com/nix-rust/nix/pull/1020))
++- Replaced `CmsgSpace` with the `cmsg_space` macro.
++  ([#1020](https://github.com/nix-rust/nix/pull/1020))
++
++### Fixed
++- Fixed multiple bugs when using `sendmsg` and `recvmsg` with ancillary control messages
++  ([#1020](https://github.com/nix-rust/nix/pull/1020))
++- Macros exported by `nix` may now be imported via `use` on the Rust 2018
++  edition without importing helper macros for BSD targets.
++  ([#1041](https://github.com/nix-rust/nix/pull/1041))
++
++  For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
++  without importing the `convert_ioctl_res!` macro.
++
++  ```rust
++  use nix::ioctl_read_bad;
++
++  ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
++  ```
++
++### Removed
++- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
++  and iOS.
++  ([#1033](https://github.com/nix-rust/nix/pull/1033))
++- `PTRACE_GETREGS`, `PTRACE_SETREGS`, `PTRACE_GETFPREGS`, and
++  `PTRACE_SETFPREGS` have been removed from some platforms where they never
++  should've been defined in the first place.
++  ([#1055](https://github.com/nix-rust/nix/pull/1055))
++
++## [0.13.0] - 2019-01-15
++### Added
++- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS.
++  ([#990](https://github.com/nix-rust/nix/pull/990))
++- Added support of CString type in `setsockopt`.
++  ([#972](https://github.com/nix-rust/nix/pull/972))
++- Added option `TCP_CONGESTION` in `setsockopt`.
++  ([#972](https://github.com/nix-rust/nix/pull/972))
++- Added `symlinkat` wrapper.
++  ([#997](https://github.com/nix-rust/nix/pull/997))
++- Added `ptrace::{getregs, setregs}`.
++  ([#1010](https://github.com/nix-rust/nix/pull/1010))
++- Added `nix::sys::signal::signal`.
++  ([#817](https://github.com/nix-rust/nix/pull/817))
++- Added an `mprotect` wrapper.
++  ([#991](https://github.com/nix-rust/nix/pull/991))
++
++### Changed
++### Fixed
++- `lutimes` never worked on OpenBSD as it is not implemented on OpenBSD. It has
++  been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
++- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
++  either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
++
++### Removed
++
++## [0.12.0] 2018-11-28
++
++### Added
++- Added `FromStr` and `Display` impls for `nix::sys::Signal`
++  ([#884](https://github.com/nix-rust/nix/pull/884))
++- Added a `sync` wrapper.
++  ([#961](https://github.com/nix-rust/nix/pull/961))
++- Added a `sysinfo` wrapper.
++  ([#922](https://github.com/nix-rust/nix/pull/922))
++- Support the `SO_PEERCRED` socket option and the `UnixCredentials` type on all Linux and Android targets.
++  ([#921](https://github.com/nix-rust/nix/pull/921))
++- Added support for `SCM_CREDENTIALS`, allowing to send process credentials over Unix sockets.
++  ([#923](https://github.com/nix-rust/nix/pull/923))
++- Added a `dir` module for reading directories (wraps `fdopendir`, `readdir`, and `rewinddir`).
++  ([#916](https://github.com/nix-rust/nix/pull/916))
++- Added `kmod` module that allows loading and unloading kernel modules on Linux.
++  ([#930](https://github.com/nix-rust/nix/pull/930))
++- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944)),
++  an `lutimes` wrapper ([#967](https://github.com/nix-rust/nix/pull/967)),
++  and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).
++- Added `AF_UNSPEC` wrapper to `AddressFamily` ([#948](https://github.com/nix-rust/nix/pull/948))
++- Added the `mode_t` public alias within `sys::stat`.
++  ([#954](https://github.com/nix-rust/nix/pull/954))
++- Added a `truncate` wrapper.
++  ([#956](https://github.com/nix-rust/nix/pull/956))
++- Added a `fchownat` wrapper.
++  ([#955](https://github.com/nix-rust/nix/pull/955))
++- Added support for `ptrace` on BSD operating systems ([#949](https://github.com/nix-rust/nix/pull/949))
++- Added `ptrace` functions for reads and writes to tracee memory and ptrace kill
++  ([#949](https://github.com/nix-rust/nix/pull/949)) ([#958](https://github.com/nix-rust/nix/pull/958))
++- Added a `acct` wrapper module for enabling and disabling process accounting
++  ([#952](https://github.com/nix-rust/nix/pull/952))
++- Added the `time_t` and `suseconds_t` public aliases within `sys::time`.
++  ([#968](https://github.com/nix-rust/nix/pull/968))
++- Added `unistd::execvpe` for Haiku, Linux and OpenBSD
++  ([#975](https://github.com/nix-rust/nix/pull/975))
++- Added `Error::as_errno`.
++  ([#977](https://github.com/nix-rust/nix/pull/977))
++
++### Changed
++- Increased required Rust version to 1.24.1
++  ([#900](https://github.com/nix-rust/nix/pull/900))
++  ([#966](https://github.com/nix-rust/nix/pull/966))
++
++### Fixed
++- Made `preadv` take immutable slice of IoVec.
++  ([#914](https://github.com/nix-rust/nix/pull/914))
++- Fixed passing multiple file descriptors over Unix Sockets.
++  ([#918](https://github.com/nix-rust/nix/pull/918))
++
++### Removed
++
++## [0.11.0] 2018-06-01
++
++### Added
++- Added `sendfile` on FreeBSD and Darwin.
++  ([#901](https://github.com/nix-rust/nix/pull/901))
++- Added `pselect`
++  ([#894](https://github.com/nix-rust/nix/pull/894))
++- Exposed `preadv` and `pwritev` on the BSDs.
++  ([#883](https://github.com/nix-rust/nix/pull/883))
++- Added `mlockall` and `munlockall`
++  ([#876](https://github.com/nix-rust/nix/pull/876))
++- Added `SO_MARK` on Linux.
++  ([#873](https://github.com/nix-rust/nix/pull/873))
++- Added safe support for nearly any buffer type in the `sys::aio` module.
++  ([#872](https://github.com/nix-rust/nix/pull/872))
++- Added `sys::aio::LioCb` as a wrapper for `libc::lio_listio`.
++  ([#872](https://github.com/nix-rust/nix/pull/872))
++- Added `unistd::getsid`
++  ([#850](https://github.com/nix-rust/nix/pull/850))
++- Added `alarm`. ([#830](https://github.com/nix-rust/nix/pull/830))
++- Added interface flags `IFF_NO_PI, IFF_TUN, IFF_TAP` on linux-like systems.
++  ([#853](https://github.com/nix-rust/nix/pull/853))
++- Added `statvfs` module to all MacOS and Linux architectures.
++  ([#832](https://github.com/nix-rust/nix/pull/832))
++- Added `EVFILT_EMPTY`, `EVFILT_PROCDESC`, and `EVFILT_SENDFILE` on FreeBSD.
++  ([#825](https://github.com/nix-rust/nix/pull/825))
++- Exposed `termios::cfmakesane` on FreeBSD.
++  ([#825](https://github.com/nix-rust/nix/pull/825))
++- Exposed `MSG_CMSG_CLOEXEC` on *BSD.
++  ([#825](https://github.com/nix-rust/nix/pull/825))
++- Added `fchmod`, `fchmodat`.
++  ([#857](https://github.com/nix-rust/nix/pull/857))
++- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
++  ([#833](https://github.com/nix-rust/nix/pull/833))
++
++### Changed
++- `Display` and `Debug` for `SysControlAddr` now includes all fields.
++  ([#837](https://github.com/nix-rust/nix/pull/837))
++- `ioctl!` has been replaced with a family of `ioctl_*!` macros.
++  ([#833](https://github.com/nix-rust/nix/pull/833))
++- `io!`, `ior!`, `iow!`, and `iorw!` has been renamed to `request_code_none!`, `request_code_read!`,
++  `request_code_write!`, and `request_code_readwrite!` respectively. These have also now been exposed
++  in the documentation.
++  ([#833](https://github.com/nix-rust/nix/pull/833))
++- Enabled more `ptrace::Request` definitions for uncommon Linux platforms
++  ([#892](https://github.com/nix-rust/nix/pull/892))
++- Emulation of `FD_CLOEXEC` and `O_NONBLOCK` was removed from `socket()`, `accept4()`, and
++  `socketpair()`.
++  ([#907](https://github.com/nix-rust/nix/pull/907))
++
++### Fixed
++- Fixed possible panics when using `SigAction::flags` on Linux
++  ([#869](https://github.com/nix-rust/nix/pull/869))
++- Properly exposed 460800 and 921600 baud rates on NetBSD
++  ([#837](https://github.com/nix-rust/nix/pull/837))
++- Fixed `ioctl_write_int!` on FreeBSD/DragonFlyBSD
++  ([#833](https://github.com/nix-rust/nix/pull/833))
++- `ioctl_write_int!` now properly supports passing a `c_ulong` as the parameter on Linux non-musl targets
++  ([#833](https://github.com/nix-rust/nix/pull/833))
++
++### Removed
++- Removed explicit support for the `bytes` crate from the `sys::aio` module.
++  See `sys::aio::AioCb::from_boxed_slice` examples for alternatives.
++  ([#872](https://github.com/nix-rust/nix/pull/872))
++- Removed `sys::aio::lio_listio`.  Use `sys::aio::LioCb::listio` instead.
++  ([#872](https://github.com/nix-rust/nix/pull/872))
++- Removed emulated `accept4()` from macos, ios, and netbsd targets
++  ([#907](https://github.com/nix-rust/nix/pull/907))
++- Removed `IFF_NOTRAILERS` on OpenBSD, as it has been removed in OpenBSD 6.3
++  ([#893](https://github.com/nix-rust/nix/pull/893))
++
++## [0.10.0] 2018-01-26
++
++### Added
++- Added specialized wrapper: `sys::ptrace::step`
++  ([#852](https://github.com/nix-rust/nix/pull/852))
++- Added `AioCb::from_ptr` and `AioCb::from_mut_ptr`
++  ([#820](https://github.com/nix-rust/nix/pull/820))
++- Added specialized wrappers: `sys::ptrace::{traceme, syscall, cont, attach}`. Using the matching routines
++  with `sys::ptrace::ptrace` is now deprecated.
++- Added `nix::poll` module for all platforms
++  ([#672](https://github.com/nix-rust/nix/pull/672))
++- Added `nix::ppoll` function for FreeBSD and DragonFly
++  ([#672](https://github.com/nix-rust/nix/pull/672))
++- Added protocol families in `AddressFamily` enum.
++  ([#647](https://github.com/nix-rust/nix/pull/647))
++- Added the `pid()` method to `WaitStatus` for extracting the PID.
++  ([#722](https://github.com/nix-rust/nix/pull/722))
++- Added `nix::unistd:fexecve`.
++  ([#727](https://github.com/nix-rust/nix/pull/727))
++- Expose `uname()` on all platforms.
++  ([#739](https://github.com/nix-rust/nix/pull/739))
++- Expose `signalfd` module on Android as well.
++  ([#739](https://github.com/nix-rust/nix/pull/739))
++- Added `nix::sys::ptrace::detach`.
++  ([#749](https://github.com/nix-rust/nix/pull/749))
++- Added timestamp socket control message variant:
++  `nix::sys::socket::ControlMessage::ScmTimestamp`
++  ([#663](https://github.com/nix-rust/nix/pull/663))
++- Added socket option variant that enables the timestamp socket
++  control message: `nix::sys::socket::sockopt::ReceiveTimestamp`
++  ([#663](https://github.com/nix-rust/nix/pull/663))
++- Added more accessor methods for `AioCb`
++  ([#773](https://github.com/nix-rust/nix/pull/773))
++- Add `nix::sys::fallocate`
++  ([#768](https:://github.com/nix-rust/nix/pull/768))
++- Added `nix::unistd::mkfifo`.
++  ([#602](https://github.com/nix-rust/nix/pull/774))
++- Added `ptrace::Options::PTRACE_O_EXITKILL` on Linux and Android.
++  ([#771](https://github.com/nix-rust/nix/pull/771))
++- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}` on Linux
++  ([#568](https://github.com/nix-rust/nix/pull/568))
++- Added `nix::unistd::{getgroups, setgroups, getgrouplist, initgroups}`. ([#733](https://github.com/nix-rust/nix/pull/733))
++- Added `nix::sys::socket::UnixAddr::as_abstract` on Linux and Android.
++  ([#785](https://github.com/nix-rust/nix/pull/785))
++- Added `nix::unistd::execveat` on Linux and Android.
++  ([#800](https://github.com/nix-rust/nix/pull/800))
++- Added the `from_raw()` method to `WaitStatus` for converting raw status values
++  to `WaitStatus` independent of syscalls.
++  ([#741](https://github.com/nix-rust/nix/pull/741))
++- Added more standard trait implementations for various types.
++  ([#814](https://github.com/nix-rust/nix/pull/814))
++- Added `sigprocmask` to the signal module.
++  ([#826](https://github.com/nix-rust/nix/pull/826))
++- Added `nix::sys::socket::LinkAddr` on Linux and all bsdlike system.
++  ([#813](https://github.com/nix-rust/nix/pull/813))
++- Add socket options for `IP_TRANSPARENT` / `BIND_ANY`.
++  ([#835](https://github.com/nix-rust/nix/pull/835))
++
++### Changed
++- Exposed the `mqueue` module for all supported operating systems.
++  ([#834](https://github.com/nix-rust/nix/pull/834))
++- Use native `pipe2` on all BSD targets.  Users should notice no difference.
++  ([#777](https://github.com/nix-rust/nix/pull/777))
++- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
++- Marked `sys::ptrace::ptrace` as `unsafe`.
++- Changed function signature of `socket()` and `socketpair()`. The `protocol` argument
++  has changed type from `c_int` to `SockProtocol`.
++  It accepts a `None` value for default protocol that was specified with zero using `c_int`.
++  ([#647](https://github.com/nix-rust/nix/pull/647))
++- Made `select` easier to use, adding the ability to automatically calculate the `nfds` parameter using the new
++  `FdSet::highest` ([#701](https://github.com/nix-rust/nix/pull/701))
++- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD
++  ([#721](https://github.com/nix-rust/nix/pull/721))
++- Refactored the `statvfs` module removing extraneous API functions and the
++  `statvfs::vfs` module. Additionally  `(f)statvfs()` now return the struct
++  directly. And the returned `Statvfs` struct now exposes its data through
++  accessor methods. ([#729](https://github.com/nix-rust/nix/pull/729))
++- The `addr` argument to `madvise` and `msync` is now `*mut` to better match the
++  libc API. ([#731](https://github.com/nix-rust/nix/pull/731))
++- `shm_open` and `shm_unlink` are no longer exposed on Android targets, where
++  they are not officially supported. ([#731](https://github.com/nix-rust/nix/pull/731))
++- `MapFlags`, `MmapAdvise`, and `MsFlags` expose some more variants and only
++  officially-supported variants are provided for each target.
++  ([#731](https://github.com/nix-rust/nix/pull/731))
++- Marked `pty::ptsname` function as `unsafe`
++  ([#744](https://github.com/nix-rust/nix/pull/744))
++- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly.
++  ([#749](https://github.com/nix-rust/nix/pull/749))
++- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#715](https://github.com/nix-rust/nix/pull/715))
++- Restricted `nix::sys::socket::UnixAddr::new_abstract` to Linux and Android only.
++  ([#785](https://github.com/nix-rust/nix/pull/785))
++- The `ucred` struct has been removed in favor of a `UserCredentials` struct that
++  contains only getters for its fields.
++  ([#814](https://github.com/nix-rust/nix/pull/814))
++- Both `ip_mreq` and `ipv6_mreq` have been replaced with `IpMembershipRequest` and
++  `Ipv6MembershipRequest`.
++  ([#814](https://github.com/nix-rust/nix/pull/814))
++- Removed return type from `pause`.
++  ([#829](https://github.com/nix-rust/nix/pull/829))
++- Changed the termios APIs to allow for using a `u32` instead of the `BaudRate`
++  enum on BSD platforms to support arbitrary baud rates. See the module docs for
++  `nix::sys::termios` for more details.
++  ([#843](https://github.com/nix-rust/nix/pull/843))
++
++### Fixed
++- Fix compilation and tests for OpenBSD targets
++  ([#688](https://github.com/nix-rust/nix/pull/688))
++- Fixed error handling in `AioCb::fsync`, `AioCb::read`, and `AioCb::write`.
++  It is no longer an error to drop an `AioCb` that failed to enqueue in the OS.
++  ([#715](https://github.com/nix-rust/nix/pull/715))
++- Fix potential memory corruption on non-Linux platforms when using
++  `sendmsg`/`recvmsg`, caused by mismatched `msghdr` definition.
++  ([#648](https://github.com/nix-rust/nix/pull/648))
++
++### Removed
++- `AioCb::from_boxed_slice` has been removed.  It was never actually safe.  Use
++  `from_bytes` or `from_bytes_mut` instead.
++  ([#820](https://github.com/nix-rust/nix/pull/820))
++- The syscall module has been removed. This only exposed enough functionality for
++  `memfd_create()` and `pivot_root()`, which are still exposed as separate functions.
++  ([#747](https://github.com/nix-rust/nix/pull/747))
++- The `Errno` variants are no longer reexported from the `errno` module. `Errno` itself is no longer reexported from the
++  crate root and instead must be accessed using the `errno` module. ([#696](https://github.com/nix-rust/nix/pull/696))
++- Removed `MS_VERBOSE`, `MS_NOSEC`, and `MS_BORN` from `MsFlags`. These
++  are internal kernel flags and should never have been exposed.
++  ([#814](https://github.com/nix-rust/nix/pull/814))
++
++
++## [0.9.0] 2017-07-23
++
++### Added
++- Added `sysconf`, `pathconf`, and `fpathconf`
++  ([#630](https://github.com/nix-rust/nix/pull/630)
++- Added `sys::signal::SigAction::{ flags, mask, handler}`
++  ([#611](https://github.com/nix-rust/nix/pull/609)
++- Added `nix::sys::pthread::pthread_self`
++  ([#591](https://github.com/nix-rust/nix/pull/591)
++- Added `AioCb::from_boxed_slice`
++  ([#582](https://github.com/nix-rust/nix/pull/582)
++- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
++  ([#551](https://github.com/nix-rust/nix/pull/551))
++- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}`
++  ([#556](https://github.com/nix-rust/nix/pull/556)
++- Added `nix::ptr::openpty`
++  ([#456](https://github.com/nix-rust/nix/pull/456))
++- Added `nix::ptrace::{ptrace_get_data, ptrace_getsiginfo, ptrace_setsiginfo
++  and nix::Error::UnsupportedOperation}`
++  ([#614](https://github.com/nix-rust/nix/pull/614))
++- Added `cfmakeraw`, `cfsetspeed`, and `tcgetsid`. ([#527](https://github.com/nix-rust/nix/pull/527))
++- Added "bad none", "bad write_ptr", "bad write_int", and "bad readwrite" variants to the `ioctl!`
++  macro. ([#670](https://github.com/nix-rust/nix/pull/670))
++- On Linux and Android, added support for receiving `PTRACE_O_TRACESYSGOOD`
++  events from `wait` and `waitpid` using `WaitStatus::PtraceSyscall`
++  ([#566](https://github.com/nix-rust/nix/pull/566)).
++
++### Changed
++- The `ioctl!` macro and its variants now allow the generated functions to have
++  doccomments. ([#661](https://github.com/nix-rust/nix/pull/661))
++- Changed `ioctl!(write ...)` into `ioctl!(write_ptr ...)` and `ioctl!(write_int ..)` variants
++  to more clearly separate those use cases. ([#670](https://github.com/nix-rust/nix/pull/670))
++- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.
++  ([#559](https://github.com/nix-rust/nix/pull/559))
++- Minimum supported Rust version is now 1.13.
++- Removed `revents` argument from `PollFd::new()` as it's an output argument and
++  will be overwritten regardless of value.
++  ([#542](https://github.com/nix-rust/nix/pull/542))
++- Changed type signature of `sys::select::FdSet::contains` to make `self`
++  immutable ([#564](https://github.com/nix-rust/nix/pull/564))
++- Introduced wrapper types for `gid_t`, `pid_t`, and `uid_t` as `Gid`, `Pid`, and `Uid`
++  respectively. Various functions have been changed to use these new types as
++  arguments. ([#629](https://github.com/nix-rust/nix/pull/629))
++- Fixed compilation on all Android and iOS targets ([#527](https://github.com/nix-rust/nix/pull/527))
++  and promoted them to Tier 2 support.
++- `nix::sys::statfs::{statfs,fstatfs}` uses statfs definition from `libc::statfs` instead of own linux specific type `nix::sys::Statfs`.
++  Also file system type constants like `nix::sys::statfs::ADFS_SUPER_MAGIC` were removed in favor of the libc equivalent.
++  ([#561](https://github.com/nix-rust/nix/pull/561))
++- Revised the termios API including additional tests and documentation and exposed it on iOS. ([#527](https://github.com/nix-rust/nix/pull/527))
++- `eventfd`, `signalfd`, and `pwritev`/`preadv` functionality is now included by default for all
++  supported platforms. ([#681](https://github.com/nix-rust/nix/pull/561))
++- The `ioctl!` macro's plain variants has been replaced with "bad read" to be consistent with
++  other variants. The generated functions also have more strict types for their arguments. The
++  "*_buf" variants also now calculate total array size and take slice references for improved type
++  safety. The documentation has also been dramatically improved.
++  ([#670](https://github.com/nix-rust/nix/pull/670))
++
++### Removed
++- Removed `io::Error` from `nix::Error` and the conversion from `nix::Error` to `Errno`
++  ([#614](https://github.com/nix-rust/nix/pull/614))
++- All feature flags have been removed in favor of conditional compilation on supported platforms.
++  `execvpe` is no longer supported, but this was already broken and will be added back in the next
++  release. ([#681](https://github.com/nix-rust/nix/pull/561))
++- Removed `ioc_*` functions and many helper constants and macros within the `ioctl` module. These
++  should always have been private and only the `ioctl!` should be used in public code.
++  ([#670](https://github.com/nix-rust/nix/pull/670))
++
++### Fixed
++- Fixed multiple issues compiling under different archetectures and OSes.
++  Now compiles on Linux/MIPS ([#538](https://github.com/nix-rust/nix/pull/538)),
++  `Linux/PPC` ([#553](https://github.com/nix-rust/nix/pull/553)),
++  `MacOS/x86_64,i686` ([#553](https://github.com/nix-rust/nix/pull/553)),
++  `NetBSD/x64_64` ([#538](https://github.com/nix-rust/nix/pull/538)),
++  `FreeBSD/x86_64,i686` ([#536](https://github.com/nix-rust/nix/pull/536)), and
++  `Android` ([#631](https://github.com/nix-rust/nix/pull/631)).
++- `bind` and `errno_location` now work correctly on `Android`
++  ([#631](https://github.com/nix-rust/nix/pull/631))
++- Added `nix::ptrace` on all Linux-kernel-based platforms
++  [#624](https://github.com/nix-rust/nix/pull/624). Previously it was
++  only available on x86, x86-64, and ARM, and also not on Android.
++- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter.
++  ([#623](https://github.com/nix-rust/nix/pull/623))
++- Multiple constants related to the termios API have now been properly defined for
++  all supported platforms. ([#527](https://github.com/nix-rust/nix/pull/527))
++- `ioctl!` macro now supports working with non-int datatypes and properly supports all platforms.
++  ([#670](https://github.com/nix-rust/nix/pull/670))
++
++## [0.8.1] 2017-04-16
++
++### Fixed
++- Fixed build on FreeBSD. (Cherry-picked
++  [a859ee3c](https://github.com/nix-rust/nix/commit/a859ee3c9396dfdb118fcc2c8ecc697e2d303467))
++
++## [0.8.0] 2017-03-02
++
++### Added
++- Added `::nix::sys::termios::BaudRate` enum to provide portable baudrate
++  values. ([#518](https://github.com/nix-rust/nix/pull/518))
++- Added a new `WaitStatus::PtraceEvent` to support ptrace events on Linux
++  and Android ([#438](https://github.com/nix-rust/nix/pull/438))
++- Added support for POSIX AIO
++  ([#483](https://github.com/nix-rust/nix/pull/483))
++  ([#506](https://github.com/nix-rust/nix/pull/506))
++- Added support for XNU system control sockets
++  ([#478](https://github.com/nix-rust/nix/pull/478))
++- Added support for `ioctl` calls on BSD platforms
++  ([#478](https://github.com/nix-rust/nix/pull/478))
++- Added struct `TimeSpec`
++  ([#475](https://github.com/nix-rust/nix/pull/475))
++  ([#483](https://github.com/nix-rust/nix/pull/483))
++- Added complete definitions for all kqueue-related constants on all supported
++  OSes
++  ([#415](https://github.com/nix-rust/nix/pull/415))
++- Added function `epoll_create1` and bitflags `EpollCreateFlags` in
++  `::nix::sys::epoll` in order to support `::libc::epoll_create1`.
++  ([#410](https://github.com/nix-rust/nix/pull/410))
++- Added `setresuid` and `setresgid` for Linux in `::nix::unistd`
++  ([#448](https://github.com/nix-rust/nix/pull/448))
++- Added `getpgid` in `::nix::unistd`
++  ([#433](https://github.com/nix-rust/nix/pull/433))
++- Added `tcgetpgrp` and `tcsetpgrp` in `::nix::unistd`
++  ([#451](https://github.com/nix-rust/nix/pull/451))
++- Added `CLONE_NEWCGROUP` in `::nix::sched`
++  ([#457](https://github.com/nix-rust/nix/pull/457))
++- Added `getpgrp` in `::nix::unistd`
++  ([#491](https://github.com/nix-rust/nix/pull/491))
++- Added `fchdir` in `::nix::unistd`
++  ([#497](https://github.com/nix-rust/nix/pull/497))
++- Added `major` and `minor` in `::nix::sys::stat` for decomposing `dev_t`
++  ([#508](https://github.com/nix-rust/nix/pull/508))
++- Fixed the style of many bitflags and use `libc` in more places.
++  ([#503](https://github.com/nix-rust/nix/pull/503))
++- Added `ppoll` in `::nix::poll`
++  ([#520](https://github.com/nix-rust/nix/pull/520))
++- Added support for getting and setting pipe size with fcntl(2) on Linux
++  ([#540](https://github.com/nix-rust/nix/pull/540))
++
++### Changed
++- `::nix::sys::termios::{cfgetispeed, cfsetispeed, cfgetospeed, cfsetospeed}`
++  switched  to use `BaudRate` enum from `speed_t`.
++  ([#518](https://github.com/nix-rust/nix/pull/518))
++- `epoll_ctl` now could accept None as argument `event`
++  when op is `EpollOp::EpollCtlDel`.
++  ([#480](https://github.com/nix-rust/nix/pull/480))
++- Removed the `bad` keyword from the `ioctl!` macro
++  ([#478](https://github.com/nix-rust/nix/pull/478))
++- Changed `TimeVal` into an opaque Newtype
++  ([#475](https://github.com/nix-rust/nix/pull/475))
++- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the
++  signal parameter has type `T: Into<Option<Signal>>`. `None` as an argument
++  for that parameter will result in a 0 passed to libc's `kill`, while a
++  `Some`-argument will result in the previous behavior for the contained
++  `Signal`.
++  ([#445](https://github.com/nix-rust/nix/pull/445))
++- The minimum supported version of rustc is now 1.7.0.
++  ([#444](https://github.com/nix-rust/nix/pull/444))
++- Changed `KEvent` to an opaque structure that may only be modified by its
++  constructor and the `ev_set` method.
++  ([#415](https://github.com/nix-rust/nix/pull/415))
++  ([#442](https://github.com/nix-rust/nix/pull/442))
++  ([#463](https://github.com/nix-rust/nix/pull/463))
++- `pipe2` now calls `libc::pipe2` where available. Previously it was emulated
++  using `pipe`, which meant that setting `O_CLOEXEC` was not atomic.
++  ([#427](https://github.com/nix-rust/nix/pull/427))
++- Renamed `EpollEventKind` to `EpollFlags` in `::nix::sys::epoll` in order for
++  it to conform with our conventions.
++  ([#410](https://github.com/nix-rust/nix/pull/410))
++- `EpollEvent` in `::nix::sys::epoll` is now an opaque proxy for
++  `::libc::epoll_event`. The formerly public field `events` is now be read-only
++  accessible with the new method `events()` of `EpollEvent`. Instances of
++  `EpollEvent` can be constructed using the new method `new()` of EpollEvent.
++  ([#410](https://github.com/nix-rust/nix/pull/410))
++- `SigFlags` in `::nix::sys::signal` has be renamed to `SigmaskHow` and its type
++  has changed from `bitflags` to `enum` in order to conform to our conventions.
++  ([#460](https://github.com/nix-rust/nix/pull/460))
++- `sethostname` now takes a `&str` instead of a `&[u8]` as this provides an API
++  that makes more sense in normal, correct usage of the API.
++- `gethostname` previously did not expose the actual length of the hostname
++  written from the underlying system call at all.  This has been updated to
++  return a `&CStr` within the provided buffer that is always properly
++  NUL-terminated (this is not guaranteed by the call with all platforms/libc
++  implementations).
++- Exposed all fcntl(2) operations at the module level, so they can be
++  imported direclty instead of via `FcntlArg` enum.
++  ([#541](https://github.com/nix-rust/nix/pull/541))
++
++### Fixed
++- Fixed multiple issues with Unix domain sockets on non-Linux OSes
++  ([#474](https://github.com/nix-rust/nix/pull/415))
++- Fixed using kqueue with `EVFILT_USER` on FreeBSD
++  ([#415](https://github.com/nix-rust/nix/pull/415))
++- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
++  functions on that same OS.
++  ([#397](https://github.com/nix-rust/nix/pull/397))
++- Fixed an off-by-one bug in `UnixAddr::new_abstract` in `::nix::sys::socket`.
++  ([#429](https://github.com/nix-rust/nix/pull/429))
++- Fixed clone passing a potentially unaligned stack.
++  ([#490](https://github.com/nix-rust/nix/pull/490))
++- Fixed mkdev not creating a `dev_t` the same way as libc.
++  ([#508](https://github.com/nix-rust/nix/pull/508))
++
++## [0.7.0] 2016-09-09
++
++### Added
++- Added `lseek` and `lseek64` in `::nix::unistd`
++  ([#377](https://github.com/nix-rust/nix/pull/377))
++- Added `mkdir` and `getcwd` in `::nix::unistd`
++  ([#416](https://github.com/nix-rust/nix/pull/416))
++- Added accessors `sigmask_mut` and `sigmask` to `UContext` in
++  `::nix::ucontext`.
++  ([#370](https://github.com/nix-rust/nix/pull/370))
++- Added `WUNTRACED` to `WaitPidFlag` in `::nix::sys::wait` for non-_linux_
++  targets.
++  ([#379](https://github.com/nix-rust/nix/pull/379))
++- Added new module `::nix::sys::reboot` with enumeration `RebootMode` and
++  functions `reboot` and `set_cad_enabled`. Currently for _linux_ only.
++  ([#386](https://github.com/nix-rust/nix/pull/386))
++- `FdSet` in `::nix::sys::select` now also implements `Clone`.
++  ([#405](https://github.com/nix-rust/nix/pull/405))
++- Added `F_FULLFSYNC` to `FcntlArg` in `::nix::fcntl` for _apple_ targets.
++  ([#407](https://github.com/nix-rust/nix/pull/407))
++- Added `CpuSet::unset` in `::nix::sched`.
++  ([#402](https://github.com/nix-rust/nix/pull/402))
++- Added constructor method `new()` to `PollFd` in `::nix::poll`, in order to
++  allow creation of objects, after removing public access to members.
++  ([#399](https://github.com/nix-rust/nix/pull/399))
++- Added method `revents()` to `PollFd` in `::nix::poll`, in order to provide
++  read access to formerly public member `revents`.
++  ([#399](https://github.com/nix-rust/nix/pull/399))
++- Added `MSG_CMSG_CLOEXEC` to `MsgFlags` in `::nix::sys::socket` for _linux_ only.
++  ([#422](https://github.com/nix-rust/nix/pull/422))
++
++### Changed
++- Replaced the reexported integer constants for signals by the enumeration
++  `Signal` in `::nix::sys::signal`.
++  ([#362](https://github.com/nix-rust/nix/pull/362))
++- Renamed `EventFdFlag` to `EfdFlags` in `::nix::sys::eventfd`.
++  ([#383](https://github.com/nix-rust/nix/pull/383))
++- Changed the result types of `CpuSet::is_set` and `CpuSet::set` in
++  `::nix::sched` to `Result<bool>` and `Result<()>`, respectively. They now
++  return `EINVAL`, if an invalid argument for the `field` parameter is passed.
++  ([#402](https://github.com/nix-rust/nix/pull/402))
++- `MqAttr` in `::nix::mqueue` is now an opaque proxy for `::libc::mq_attr`,
++  which has the same structure as the old `MqAttr`. The field `mq_flags` of
++  `::libc::mq_attr` is readable using the new method `flags()` of `MqAttr`.
++  `MqAttr` also no longer implements `Debug`.
++  ([#392](https://github.com/nix-rust/nix/pull/392))
++- The parameter `msq_prio` of `mq_receive` with type `u32` in `::nix::mqueue`
++  was replaced by a parameter named `msg_prio` with type `&mut u32`, so that
++  the message priority can be obtained by the caller.
++  ([#392](https://github.com/nix-rust/nix/pull/392))
++- The type alias `MQd` in `::nix::queue` was replaced by the type alias
++  `libc::mqd_t`, both of which are aliases for the same type.
++  ([#392](https://github.com/nix-rust/nix/pull/392))
++
++### Removed
++- Type alias `SigNum` from `::nix::sys::signal`.
++  ([#362](https://github.com/nix-rust/nix/pull/362))
++- Type alias `CpuMask` from `::nix::shed`.
++  ([#402](https://github.com/nix-rust/nix/pull/402))
++- Removed public fields from `PollFd` in `::nix::poll`. (See also added method
++  `revents()`.
++  ([#399](https://github.com/nix-rust/nix/pull/399))
++
++### Fixed
++- Fixed the build problem for NetBSD (Note, that we currently do not support
++  it, so it might already be broken again).
++  ([#389](https://github.com/nix-rust/nix/pull/389))
++- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
++  functions on that same OS.
++  ([#397](https://github.com/nix-rust/nix/pull/397))
++
++## [0.6.0] 2016-06-10
++
++### Added
++- Added `gettid` in `::nix::unistd` for _linux_ and _android_.
++  ([#293](https://github.com/nix-rust/nix/pull/293))
++- Some _mips_ support in `::nix::sched` and `::nix::sys::syscall`.
++  ([#301](https://github.com/nix-rust/nix/pull/301))
++- Added `SIGNALFD_SIGINFO_SIZE` in `::nix::sys::signalfd`.
++  ([#309](https://github.com/nix-rust/nix/pull/309))
++- Added new module `::nix::ucontext` with struct `UContext`. Currently for
++  _linux_ only.
++  ([#311](https://github.com/nix-rust/nix/pull/311))
++- Added `EPOLLEXCLUSIVE` to `EpollEventKind` in `::nix::sys::epoll`.
++  ([#330](https://github.com/nix-rust/nix/pull/330))
++- Added `pause` to `::nix::unistd`.
++  ([#336](https://github.com/nix-rust/nix/pull/336))
++- Added `sleep` to `::nix::unistd`.
++  ([#351](https://github.com/nix-rust/nix/pull/351))
++- Added `S_IFDIR`, `S_IFLNK`, `S_IFMT` to `SFlag` in `::nix::sys::stat`.
++  ([#359](https://github.com/nix-rust/nix/pull/359))
++- Added `clear` and `extend` functions to `SigSet`'s implementation in
++  `::nix::sys::signal`.
++  ([#347](https://github.com/nix-rust/nix/pull/347))
++- `sockaddr_storage_to_addr` in `::nix::sys::socket` now supports `sockaddr_nl`
++  on _linux_ and _android_.
++  ([#366](https://github.com/nix-rust/nix/pull/366))
++- Added support for `SO_ORIGINAL_DST` in `::nix::sys::socket` on _linux_.
++  ([#367](https://github.com/nix-rust/nix/pull/367))
++- Added `SIGINFO` in `::nix::sys::signal` for the _macos_ target as well as
++  `SIGPWR` and `SIGSTKFLT` in `::nix::sys::signal` for non-_macos_ targets.
++  ([#361](https://github.com/nix-rust/nix/pull/361))
++
++### Changed
++- Changed the structure `IoVec` in `::nix::sys::uio`.
++  ([#304](https://github.com/nix-rust/nix/pull/304))
++- Replaced `CREATE_NEW_FD` by `SIGNALFD_NEW` in `::nix::sys::signalfd`.
++  ([#309](https://github.com/nix-rust/nix/pull/309))
++- Renamed `SaFlag` to `SaFlags` and `SigFlag` to `SigFlags` in
++  `::nix::sys::signal`.
++  ([#314](https://github.com/nix-rust/nix/pull/314))
++- Renamed `Fork` to `ForkResult` and changed its fields in `::nix::unistd`.
++  ([#332](https://github.com/nix-rust/nix/pull/332))
++- Added the `signal` parameter to `clone`'s signature in `::nix::sched`.
++  ([#344](https://github.com/nix-rust/nix/pull/344))
++- `execv`, `execve`, and `execvp` now return `Result<Void>` instead of
++  `Result<()>` in `::nix::unistd`.
++  ([#357](https://github.com/nix-rust/nix/pull/357))
++
++### Fixed
++- Improved the conversion from `std::net::SocketAddr` to `InetAddr` in
++  `::nix::sys::socket::addr`.
++  ([#335](https://github.com/nix-rust/nix/pull/335))
++
++## [0.5.0] 2016-03-01
+diff --git a/third_party/rust/nix-0.15.0/CONTRIBUTING.md b/third_party/rust/nix-0.15.0/CONTRIBUTING.md
+new file mode 100644
+index 0000000000000..03a1f630dbb06
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/CONTRIBUTING.md
+@@ -0,0 +1,114 @@
++# Contributing to nix
++
++We're really glad you're interested in contributing to nix! This
++document has a few pointers and guidelines to help get you started.
++
++To have a welcoming and inclusive project, nix uses the Rust project's
++[Code of Conduct][conduct]. All contributors are expected to follow it.
++
++[conduct]: https://www.rust-lang.org/conduct.html
++
++
++# Issues
++
++We use GitHub's [issue tracker][issues].
++
++[issues]: https://github.com/nix-rust/nix/issues
++
++
++## Bug reports
++
++Before submitting a new bug report, please [search existing
++issues][issue-search] to see if there's something related. If not, just
++[open a new issue][new-issue]!
++
++As a reminder, the more information you can give in your issue, the
++easier it is to figure out how to fix it. For nix, this will likely
++include the OS and version, and the architecture.
++
++[issue-search]: https://github.com/nix-rust/nix/search?utf8=%E2%9C%93&q=is%3Aissue&type=Issues
++[new-issue]: https://github.com/nix-rust/nix/issues/new
++
++
++## Feature / API requests
++
++If you'd like a new API or feature added, please [open a new
++issue][new-issue] requesting it. As with reporting a bug, the more
++information you can provide, the better.
++
++
++## Labels
++
++We use labels to help manage issues. The structure is modeled after
++[Rust's issue labeling scheme][rust-labels]:
++- **A-**prefixed labels state which area of the project the issue
++  relates to
++- **E-**prefixed labels explain the level of experience necessary to fix the
++  issue
++- **O-**prefixed labels specify the OS for issues that are OS-specific
++- **R-**prefixed labels specify the architecture for issues that are
++  architecture-specific
++
++[rust-labels]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage
++
++
++# Pull requests
++
++GitHub pull requests are the primary mechanism we use to change nix. GitHub itself has
++some [great documentation][pr-docs] on using the Pull Request feature. We use the 'fork and
++pull' model described there.
++
++Please make pull requests against the `master` branch.
++
++If you change the API by way of adding, removing or changing something or if
++you fix a bug, please add an appropriate note to the [change log][cl]. We
++follow the conventions of [Keep A CHANGELOG][kacl].
++
++[cl]: https://github.com/nix-rust/nix/blob/master/CHANGELOG.md
++[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
++[pr-docs]: https://help.github.com/articles/using-pull-requests/
++
++## Testing
++
++nix has a test suite that you can run with `cargo test`. Ideally, we'd like pull
++requests to include tests where they make sense. For example, when fixing a bug,
++add a test that would have failed without the fix.
++
++After you've made your change, make sure the tests pass in your development
++environment. We also have [continuous integration set up on
++Travis-CI][travis-ci], which might find some issues on other platforms. The CI
++will run once you open a pull request.
++
++There is also infrastructure for running tests for other targets
++locally.  More information is available in the [CI Readme][ci-readme].
++
++[travis-ci]: https://travis-ci.org/nix-rust/nix
++[ci-readme]: ci/README.md
++
++### Disabling a test in the CI environment
++
++Sometimes there are features that cannot be tested in the CI environment.
++To stop a test from running under CI, add `#[cfg_attr(travis, ignore)]`
++to it. Please include a comment describing the reason it shouldn't run
++under CI, and a link to an upstream issue if possible!
++
++## bors, the bot who merges all the PRs
++
++All pull requests are merged via [bors], an integration bot. After the
++pull request has been reviewed, the reviewer will leave a comment like
++
++> bors r+
++
++to let bors know that it was approved. Then bors will check that it passes
++tests when merged with the latest changes in the `master` branch, and
++merge if the tests succeed.
++
++[bors]: https://bors-ng.github.io/
++
++
++## API conventions
++
++If you're adding a new API, we have a [document with
++conventions][conventions] to use throughout the nix project.
++
++[conventions]: https://github.com/nix-rust/nix/blob/master/CONVENTIONS.md
+diff --git a/third_party/rust/nix-0.15.0/CONVENTIONS.md b/third_party/rust/nix-0.15.0/CONVENTIONS.md
+new file mode 100644
+index 0000000000000..48daa937345d2
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/CONVENTIONS.md
+@@ -0,0 +1,87 @@
++# Conventions
++
++In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust
++constructs with minimal performance overhead, we follow the following
++conventions.
++
++Note that, thus far, not all the code follows these conventions and not all
++conventions we try to follow have been documented here. If you find an instance
++of either, feel free to remedy the flaw by opening a pull request with
++appropriate changes or additions.
++
++## Change Log
++
++We follow the conventions laid out in [Keep A CHANGELOG][kacl].
++
++[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
++
++## libc constants, functions and structs
++
++We do not define integer constants ourselves, but use or reexport them from the
++[libc crate][libc].
++
++We use the functions exported from [libc][libc] instead of writing our own
++`extern` declarations.
++
++We use the `struct` definitions from [libc][libc] internally instead of writing
++our own. If we want to add methods to a libc type, we use the newtype pattern.
++For example,
++
++```rust
++pub struct SigSet(libc::sigset_t);
++
++impl SigSet {
++    ...
++}
++```
++
++When creating newtypes, we use Rust's `CamelCase` type naming convention.
++
++## Bitflags
++
++Many C functions have flags parameters that are combined from constants using
++bitwise operations. We represent the types of these parameters by types defined
++using our `libc_bitflags!` macro, which is a convenience wrapper around the
++`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
++constant value from `libc`.
++
++We name the type for a set of constants whose element's names start with `FOO_`
++`FooFlags`.
++
++For example,
++
++```rust
++libc_bitflags!{
++    pub struct ProtFlags: libc::c_int {
++        PROT_NONE;
++        PROT_READ;
++        PROT_WRITE;
++        PROT_EXEC;
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        PROT_GROWSDOWN;
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        PROT_GROWSUP;
++    }
++}
++```
++
++
++## Enumerations
++
++We represent sets of constants that are intended as mutually exclusive arguments
++to parameters of functions by [enumerations][enum].
++
++
++## Structures Initialized by libc Functions
++
++Whenever we need to use a [libc][libc] function to properly initialize a
++variable and said function allows us to use uninitialized memory, we use
++[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized])
++when defining the variable. This allows us to avoid the overhead incurred by
++zeroing or otherwise initializing the variable.
++
++[bitflags]: https://crates.io/crates/bitflags/
++[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html
++[enum]: https://doc.rust-lang.org/reference.html#enumerations
++[libc]: https://crates.io/crates/libc/
++[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
+diff --git a/third_party/rust/nix-0.15.0/Cargo.toml b/third_party/rust/nix-0.15.0/Cargo.toml
+new file mode 100644
+index 0000000000000..555b99020d68f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/Cargo.toml
+@@ -0,0 +1,71 @@
++# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
++#
++# When uploading crates to the registry Cargo will automatically
++# "normalize" Cargo.toml files for maximal compatibility
++# with all versions of Cargo and also rewrite `path` dependencies
++# to registry (e.g., crates.io) dependencies
++#
++# If you believe there's an error in this file please file an
++# issue against the rust-lang/cargo repository. If you're
++# editing this file be aware that the upstream Cargo.toml
++# will likely look very different (and much more reasonable)
++
++[package]
++name = "nix"
++version = "0.15.0"
++authors = ["The nix-rust Project Developers"]
++exclude = ["/.gitignore", "/.travis.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
++description = "Rust friendly bindings to *nix APIs"
++categories = ["os::unix-apis"]
++license = "MIT"
++repository = "https://github.com/nix-rust/nix"
++
++[[test]]
++name = "test"
++path = "test/test.rs"
++
++[[test]]
++name = "test-aio-drop"
++path = "test/sys/test_aio_drop.rs"
++
++[[test]]
++name = "test-lio-listio-resubmit"
++path = "test/sys/test_lio_listio_resubmit.rs"
++
++[[test]]
++name = "test-mount"
++path = "test/test_mount.rs"
++harness = false
++
++[[test]]
++name = "test-ptymaster-drop"
++path = "test/test_ptymaster_drop.rs"
++[dependencies.bitflags]
++version = "1.0"
++
++[dependencies.cfg-if]
++version = "0.1.2"
++
++[dependencies.libc]
++version = "0.2.60"
++features = ["extra_traits"]
++
++[dependencies.void]
++version = "1.0.2"
++[dev-dependencies.bytes]
++version = "0.4.8"
++
++[dev-dependencies.lazy_static]
++version = "1.2"
++
++[dev-dependencies.rand]
++version = ">= 0.6, < 0.7"
++
++[dev-dependencies.tempfile]
++version = ">= 3.0.5, < 3.0.9"
++[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
++version = "0.3.1"
++[target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
++version = "1"
++[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
++version = "0.1"
+diff --git a/third_party/rust/nix-0.15.0/LICENSE b/third_party/rust/nix-0.15.0/LICENSE
+new file mode 100644
+index 0000000000000..aff9096fdf11d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/LICENSE
+@@ -0,0 +1,21 @@
++The MIT License (MIT)
++
++Copyright (c) 2015 Carl Lerche + nix-rust Authors
++
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in
++all copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
++THE SOFTWARE.
+diff --git a/third_party/rust/nix-0.15.0/README.md b/third_party/rust/nix-0.15.0/README.md
+new file mode 100644
+index 0000000000000..0e540ba5b968e
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/README.md
+@@ -0,0 +1,111 @@
++# Rust bindings to *nix APIs
++
++[![Build Status](https://travis-ci.org/nix-rust/nix.svg?branch=master)](https://travis-ci.org/nix-rust/nix)
++[![crates.io](http://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
++
++[Documentation (Releases)](https://docs.rs/nix/)
++
++Nix seeks to provide friendly bindings to various *nix platform APIs (Linux, Darwin,
++...). The goal is to not provide a 100% unified interface, but to unify
++what can be while still providing platform specific APIs.
++
++For many system APIs, Nix provides a safe alternative to the unsafe APIs
++exposed by the [libc crate](https://github.com/rust-lang/libc).  This is done by
++wrapping the libc functionality with types/abstractions that enforce legal/safe
++usage.
++
++
++As an example of what Nix provides, examine the differences between what is
++exposed by libc and nix for the
++[gethostname](http://man7.org/linux/man-pages/man2/gethostname.2.html) system
++call:
++
++```rust,ignore
++// libc api (unsafe, requires handling return code/errno)
++pub unsafe extern fn gethostname(name: *mut c_char, len: size_t) -> c_int;
++
++// nix api (returns a nix::Result<CStr>)
++pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr>;
++```
++
++## Supported Platforms
++
++nix target support consists of two tiers. While nix attempts to support all
++platforms supported by [libc](https://github.com/rust-lang/libc), only some
++platforms are actively supported due to either technical or manpower
++limitations. Support for platforms is split into three tiers:
++
++  * Tier 1 - Builds and tests for this target are run in CI. Failures of either
++             block the inclusion of new code.
++  * Tier 2 - Builds for this target are run in CI. Failures during the build
++             blocks the inclusion of new code. Tests may be run, but failures
++             in tests don't block the inclusion of new code.
++  * Tier 3 - Builds for this target are run in CI. Failures during the build
++             *do not* block the inclusion of new code. Testing may be run, but
++             failures in tests don't block the inclusion of new code.
++
++The following targets are supported by `nix`:
++
++Tier 1:
++  * aarch64-unknown-linux-gnu
++  * arm-unknown-linux-gnueabi
++  * armv7-unknown-linux-gnueabihf
++  * i686-apple-darwin
++  * i686-unknown-freebsd
++  * i686-unknown-linux-gnu
++  * i686-unknown-linux-musl
++  * mips-unknown-linux-gnu
++  * mips64-unknown-linux-gnuabi64
++  * mips64el-unknown-linux-gnuabi64
++  * mipsel-unknown-linux-gnu
++  * powerpc64-unknown-linux-gnu
++  * powerpc64le-unknown-linux-gnu
++  * x86_64-apple-darwin
++  * x86_64-unknown-freebsd
++  * x86_64-unknown-linux-gnu
++  * x86_64-unknown-linux-musl
++
++Tier 2:
++  * aarch64-apple-ios
++  * aarch64-linux-android
++  * arm-linux-androideabi
++  * arm-unknown-linux-musleabi
++  * armv7-apple-ios
++  * armv7-linux-androideabi
++  * armv7s-apple-ios
++  * i386-apple-ios
++  * i686-linux-android
++  * powerpc-unknown-linux-gnu
++  * s390x-unknown-linux-gnu
++  * x86_64-apple-ios
++  * x86_64-linux-android
++  * x86_64-unknown-netbsd
++
++## Usage
++
++`nix` requires Rust 1.31.0 or newer.
++
++To use `nix`, first add this to your `Cargo.toml`:
++
++```toml
++[dependencies]
++nix = "0.15.0"
++```
++
++Then, add this to your crate root:
++
++```rust,ignore
++extern crate nix;
++```
++
++## Contributing
++
++Contributions are very welcome.  Please See [CONTRIBUTING](CONTRIBUTING.md) for
++additional details.
++
++Feel free to join us in [the nix-rust/nix](https://gitter.im/nix-rust/nix) channel on Gitter to
++discuss `nix` development.
++
++## License
++
++Nix is licensed under the MIT license.  See [LICENSE](LICENSE) for more details.
+diff --git a/third_party/rust/nix/build.rs b/third_party/rust/nix-0.15.0/build.rs
+similarity index 100%
+rename from third_party/rust/nix/build.rs
+rename to third_party/rust/nix-0.15.0/build.rs
+diff --git a/third_party/rust/nix-0.15.0/src/dir.rs b/third_party/rust/nix-0.15.0/src/dir.rs
+new file mode 100644
+index 0000000000000..1820b5330ff60
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/dir.rs
+@@ -0,0 +1,193 @@
++use {Error, NixPath, Result};
++use errno::Errno;
++use fcntl::{self, OFlag};
++use libc;
++use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
++use std::{ffi, ptr};
++use sys;
++
++#[cfg(target_os = "linux")]
++use libc::{dirent64 as dirent, readdir64_r as readdir_r};
++
++#[cfg(not(target_os = "linux"))]
++use libc::{dirent, readdir_r};
++
++/// An open directory.
++///
++/// This is a lower-level interface than `std::fs::ReadDir`. Notable differences:
++///    * can be opened from a file descriptor (as returned by `openat`, perhaps before knowing
++///      if the path represents a file or directory).
++///    * implements `AsRawFd`, so it can be passed to `fstat`, `openat`, etc.
++///      The file descriptor continues to be owned by the `Dir`, so callers must not keep a `RawFd`
++///      after the `Dir` is dropped.
++///    * can be iterated through multiple times without closing and reopening the file
++///      descriptor. Each iteration rewinds when finished.
++///    * returns entries for `.` (current directory) and `..` (parent directory).
++///    * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
++///      does).
++#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++pub struct Dir(
++    ptr::NonNull<libc::DIR>
++);
++
++impl Dir {
++    /// Opens the given path as with `fcntl::open`.
++    pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag,
++                                     mode: sys::stat::Mode) -> Result<Self> {
++        let fd = fcntl::open(path, oflag, mode)?;
++        Dir::from_fd(fd)
++    }
++
++    /// Opens the given path as with `fcntl::openat`.
++    pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag,
++                                       mode: sys::stat::Mode) -> Result<Self> {
++        let fd = fcntl::openat(dirfd, path, oflag, mode)?;
++        Dir::from_fd(fd)
++    }
++
++    /// Converts from a descriptor-based object, closing the descriptor on success or failure.
++    #[inline]
++    pub fn from<F: IntoRawFd>(fd: F) -> Result<Self> {
++        Dir::from_fd(fd.into_raw_fd())
++    }
++
++    /// 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 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()))
++    }
++
++    /// Returns an iterator of `Result<Entry>` which rewinds when finished.
++    pub fn iter(&mut self) -> Iter {
++        Iter(self)
++    }
++}
++
++// `Dir` is not `Sync`. With the current implementation, it could be, but according to
++// https://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html,
++// future versions of POSIX are likely to obsolete `readdir_r` and specify that it's unsafe to
++// call `readdir` simultaneously from multiple threads.
++//
++// `Dir` is safe to pass from one thread to another, as it's not reference-counted.
++unsafe impl Send for Dir {}
++
++impl AsRawFd for Dir {
++    fn as_raw_fd(&self) -> RawFd {
++        unsafe { libc::dirfd(self.0.as_ptr()) }
++    }
++}
++
++impl Drop for Dir {
++    fn drop(&mut self) {
++        unsafe { libc::closedir(self.0.as_ptr()) };
++    }
++}
++
++#[derive(Debug, Eq, Hash, PartialEq)]
++pub struct Iter<'d>(&'d mut Dir);
++
++impl<'d> Iterator for Iter<'d> {
++    type Item = Result<Entry>;
++
++    fn next(&mut self) -> Option<Self::Item> {
++        unsafe {
++            // Note: POSIX specifies that portable applications should dynamically allocate a
++            // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
++            // for the NUL byte. It doesn't look like the std library does this; it just uses
++            // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
++            // Probably fine here too then.
++            let mut ent: Entry = Entry(::std::mem::uninitialized());
++            let mut result = ptr::null_mut();
++            if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) {
++                return Some(Err(e));
++            }
++            if result == ptr::null_mut() {
++                return None;
++            }
++            assert_eq!(result, &mut ent.0 as *mut dirent);
++            return Some(Ok(ent));
++        }
++    }
++}
++
++impl<'d> Drop for Iter<'d> {
++    fn drop(&mut self) {
++        unsafe { libc::rewinddir((self.0).0.as_ptr()) }
++    }
++}
++
++/// A directory entry, similar to `std::fs::DirEntry`.
++///
++/// Note that unlike the std version, this may represent the `.` or `..` entries.
++#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++pub struct Entry(dirent);
++
++#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++pub enum Type {
++    Fifo,
++    CharacterDevice,
++    Directory,
++    BlockDevice,
++    File,
++    Symlink,
++    Socket,
++}
++
++impl Entry {
++    /// Returns the inode number (`d_ino`) of the underlying `dirent`.
++    #[cfg(any(target_os = "android",
++              target_os = "emscripten",
++              target_os = "fuchsia",
++              target_os = "haiku",
++              target_os = "ios",
++              target_os = "l4re",
++              target_os = "linux",
++              target_os = "macos",
++              target_os = "solaris"))]
++    pub fn ino(&self) -> u64 {
++        self.0.d_ino as u64
++    }
++
++    /// Returns the inode number (`d_fileno`) of the underlying `dirent`.
++    #[cfg(not(any(target_os = "android",
++                  target_os = "emscripten",
++                  target_os = "fuchsia",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "l4re",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "solaris")))]
++    pub fn ino(&self) -> u64 {
++        self.0.d_fileno as u64
++    }
++
++    /// Returns the bare file name of this directory entry without any other leading path component.
++    pub fn file_name(&self) -> &ffi::CStr {
++        unsafe { ::std::ffi::CStr::from_ptr(self.0.d_name.as_ptr()) }
++    }
++
++    /// Returns the type of this directory entry, if known.
++    ///
++    /// See platform `readdir(3)` or `dirent(5)` manpage for when the file type is known;
++    /// 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> {
++        match self.0.d_type {
++            libc::DT_FIFO => Some(Type::Fifo),
++            libc::DT_CHR => Some(Type::CharacterDevice),
++            libc::DT_DIR => Some(Type::Directory),
++            libc::DT_BLK => Some(Type::BlockDevice),
++            libc::DT_REG => Some(Type::File),
++            libc::DT_LNK => Some(Type::Symlink),
++            libc::DT_SOCK => Some(Type::Socket),
++            /* libc::DT_UNKNOWN | */ _ => None,
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/errno.rs b/third_party/rust/nix-0.15.0/src/errno.rs
+new file mode 100644
+index 0000000000000..6a2447bc52675
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/errno.rs
+@@ -0,0 +1,1963 @@
++#[cfg(not(target_os = "dragonfly"))]
++use libc;
++use libc::{c_int, c_void};
++use std::{fmt, io, error};
++use {Error, Result};
++
++pub use self::consts::*;
++
++cfg_if! {
++    if #[cfg(any(target_os = "freebsd",
++                 target_os = "ios",
++                 target_os = "macos"))] {
++        unsafe fn errno_location() -> *mut c_int {
++            libc::__error()
++        }
++    } else if #[cfg(target_os = "dragonfly")] {
++        // DragonFly uses a thread-local errno variable, but #[thread_local] is
++        // feature-gated and not available in stable Rust as of this writing
++        // (Rust 1.21.0). We have to use a C extension to access it
++        // (src/errno_dragonfly.c).
++        //
++        // Tracking issue for `thread_local` stabilization:
++        //
++        //     https://github.com/rust-lang/rust/issues/29594
++        //
++        // Once this becomes stable, we can remove build.rs,
++        // src/errno_dragonfly.c, and use:
++        //
++        //     extern { #[thread_local] static errno: c_int; }
++        //
++        #[link(name="errno_dragonfly", kind="static")]
++        extern {
++            pub fn errno_location() -> *mut c_int;
++        }
++    } else if #[cfg(any(target_os = "android",
++                        target_os = "netbsd",
++                        target_os = "openbsd"))] {
++        unsafe fn errno_location() -> *mut c_int {
++            libc::__errno()
++        }
++    } else if #[cfg(target_os = "linux")] {
++        unsafe fn errno_location() -> *mut c_int {
++            libc::__errno_location()
++        }
++    }
++}
++
++/// Sets the platform-specific errno to no-error
++unsafe fn clear() -> () {
++    *errno_location() = 0;
++}
++
++/// Returns the platform-specific value of errno
++pub fn errno() -> i32 {
++    unsafe {
++        (*errno_location()) as i32
++    }
++}
++
++impl Errno {
++    pub fn last() -> Self {
++        last()
++    }
++
++    pub fn desc(self) -> &'static str {
++        desc(self)
++    }
++
++    pub fn from_i32(err: i32) -> Errno {
++        from_i32(err)
++    }
++
++    pub unsafe fn clear() -> () {
++        clear()
++    }
++
++    /// Returns `Ok(value)` if it does not contain the sentinel value. This
++    /// should not be used when `-1` is not the errno sentinel value.
++    pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
++        if value == S::sentinel() {
++            Err(Error::Sys(Self::last()))
++        } else {
++            Ok(value)
++        }
++    }
++}
++
++/// The sentinel value indicates that a function failed and more detailed
++/// information about the error can be found in `errno`
++pub trait ErrnoSentinel: Sized {
++    fn sentinel() -> Self;
++}
++
++impl ErrnoSentinel for isize {
++    fn sentinel() -> Self { -1 }
++}
++
++impl ErrnoSentinel for i32 {
++    fn sentinel() -> Self { -1 }
++}
++
++impl ErrnoSentinel for i64 {
++    fn sentinel() -> Self { -1 }
++}
++
++impl ErrnoSentinel for *mut c_void {
++    fn sentinel() -> Self { (-1 as isize) as *mut c_void }
++}
++
++impl ErrnoSentinel for libc::sighandler_t {
++    fn sentinel() -> Self { libc::SIG_ERR }
++}
++
++impl error::Error for Errno {
++    fn description(&self) -> &str {
++        self.desc()
++    }
++}
++
++impl fmt::Display for Errno {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        write!(f, "{:?}: {}", self, self.desc())
++    }
++}
++
++impl From<Errno> for io::Error {
++    fn from(err: Errno) -> Self {
++        io::Error::from_raw_os_error(err as i32)
++    }
++}
++
++fn last() -> Errno {
++    Errno::from_i32(errno())
++}
++
++fn desc(errno: Errno) -> &'static str {
++    use self::Errno::*;
++    match errno {
++        UnknownErrno    => "Unknown errno",
++        EPERM           => "Operation not permitted",
++        ENOENT          => "No such file or directory",
++        ESRCH           => "No such process",
++        EINTR           => "Interrupted system call",
++        EIO             => "I/O error",
++        ENXIO           => "No such device or address",
++        E2BIG           => "Argument list too long",
++        ENOEXEC         => "Exec format error",
++        EBADF           => "Bad file number",
++        ECHILD          => "No child processes",
++        EAGAIN          => "Try again",
++        ENOMEM          => "Out of memory",
++        EACCES          => "Permission denied",
++        EFAULT          => "Bad address",
++        ENOTBLK         => "Block device required",
++        EBUSY           => "Device or resource busy",
++        EEXIST          => "File exists",
++        EXDEV           => "Cross-device link",
++        ENODEV          => "No such device",
++        ENOTDIR         => "Not a directory",
++        EISDIR          => "Is a directory",
++        EINVAL          => "Invalid argument",
++        ENFILE          => "File table overflow",
++        EMFILE          => "Too many open files",
++        ENOTTY          => "Not a typewriter",
++        ETXTBSY         => "Text file busy",
++        EFBIG           => "File too large",
++        ENOSPC          => "No space left on device",
++        ESPIPE          => "Illegal seek",
++        EROFS           => "Read-only file system",
++        EMLINK          => "Too many links",
++        EPIPE           => "Broken pipe",
++        EDOM            => "Math argument out of domain of func",
++        ERANGE          => "Math result not representable",
++        EDEADLK         => "Resource deadlock would occur",
++        ENAMETOOLONG    => "File name too long",
++        ENOLCK          => "No record locks available",
++        ENOSYS          => "Function not implemented",
++        ENOTEMPTY       => "Directory not empty",
++        ELOOP           => "Too many symbolic links encountered",
++        ENOMSG          => "No message of desired type",
++        EIDRM           => "Identifier removed",
++        EINPROGRESS     => "Operation now in progress",
++        EALREADY        => "Operation already in progress",
++        ENOTSOCK        => "Socket operation on non-socket",
++        EDESTADDRREQ    => "Destination address required",
++        EMSGSIZE        => "Message too long",
++        EPROTOTYPE      => "Protocol wrong type for socket",
++        ENOPROTOOPT     => "Protocol not available",
++        EPROTONOSUPPORT => "Protocol not supported",
++        ESOCKTNOSUPPORT => "Socket type not supported",
++        EPFNOSUPPORT    => "Protocol family not supported",
++        EAFNOSUPPORT    => "Address family not supported by protocol",
++        EADDRINUSE      => "Address already in use",
++        EADDRNOTAVAIL   => "Cannot assign requested address",
++        ENETDOWN        => "Network is down",
++        ENETUNREACH     => "Network is unreachable",
++        ENETRESET       => "Network dropped connection because of reset",
++        ECONNABORTED    => "Software caused connection abort",
++        ECONNRESET      => "Connection reset by peer",
++        ENOBUFS         => "No buffer space available",
++        EISCONN         => "Transport endpoint is already connected",
++        ENOTCONN        => "Transport endpoint is not connected",
++        ESHUTDOWN       => "Cannot send after transport endpoint shutdown",
++        ETOOMANYREFS    => "Too many references: cannot splice",
++        ETIMEDOUT       => "Connection timed out",
++        ECONNREFUSED    => "Connection refused",
++        EHOSTDOWN       => "Host is down",
++        EHOSTUNREACH    => "No route to host",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ECHRNG          => "Channel number out of range",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EL2NSYNC        => "Level 2 not synchronized",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EL3HLT          => "Level 3 halted",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EL3RST          => "Level 3 reset",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELNRNG          => "Link number out of range",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EUNATCH         => "Protocol driver not attached",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOCSI          => "No CSI structure available",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EL2HLT          => "Level 2 halted",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADE           => "Invalid exchange",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADR           => "Invalid request descriptor",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EXFULL          => "Exchange full",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOANO          => "No anode",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADRQC         => "Invalid request code",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADSLT         => "Invalid slot",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBFONT          => "Bad font file format",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOSTR          => "Device not a stream",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENODATA         => "No data available",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ETIME           => "Timer expired",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOSR           => "Out of streams resources",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENONET          => "Machine is not on the network",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOPKG          => "Package not installed",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EREMOTE         => "Object is remote",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOLINK         => "Link has been severed",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EADV            => "Advertise error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ESRMNT          => "Srmount error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ECOMM           => "Communication error on send",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EPROTO          => "Protocol error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EMULTIHOP       => "Multihop attempted",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EDOTDOT         => "RFS specific error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADMSG         => "Not a data message",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EOVERFLOW       => "Value too large for defined data type",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOTUNIQ        => "Name not unique on network",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EBADFD          => "File descriptor in bad state",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EREMCHG         => "Remote address changed",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELIBACC         => "Can not access a needed shared library",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELIBBAD         => "Accessing a corrupted shared library",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELIBSCN         => ".lib section in a.out corrupted",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELIBMAX         => "Attempting to link in too many shared libraries",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ELIBEXEC        => "Cannot exec a shared library directly",
++
++        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
++        EILSEQ          => "Illegal byte sequence",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ERESTART        => "Interrupted system call should be restarted",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ESTRPIPE        => "Streams pipe error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EUSERS          => "Too many users",
++
++        #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
++        EOPNOTSUPP      => "Operation not supported on transport endpoint",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ESTALE          => "Stale file handle",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EUCLEAN         => "Structure needs cleaning",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOTNAM         => "Not a XENIX named type file",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENAVAIL         => "No XENIX semaphores available",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EISNAM          => "Is a named type file",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EREMOTEIO       => "Remote I/O error",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EDQUOT          => "Quota exceeded",
++
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "openbsd", target_os = "dragonfly"))]
++        ENOMEDIUM       => "No medium found",
++
++        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
++        EMEDIUMTYPE     => "Wrong medium type",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ECANCELED       => "Operation canceled",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOKEY          => "Required key not available",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EKEYEXPIRED     => "Key has expired",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EKEYREVOKED     => "Key has been revoked",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EKEYREJECTED    => "Key was rejected by service",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        EOWNERDEAD      => "Owner died",
++
++        #[cfg(any(target_os = "linux", target_os = "android"))]
++        ENOTRECOVERABLE => "State not recoverable",
++
++        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
++        ERFKILL         => "Operation not possible due to RF-kill",
++
++        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
++        EHWPOISON       => "Memory page has hardware error",
++
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        EDOOFUS         => "Programming error",
++
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        EMULTIHOP       => "Multihop attempted",
++
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        ENOLINK         => "Link has been severed",
++
++        #[cfg(target_os = "freebsd")]
++        ENOTCAPABLE     => "Capabilities insufficient",
++
++        #[cfg(target_os = "freebsd")]
++        ECAPMODE        => "Not permitted in capability mode",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ENEEDAUTH       => "Need authenticator",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EOVERFLOW       => "Value too large to be stored in data type",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "netbsd"))]
++        EILSEQ          => "Illegal byte sequence",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ENOATTR         => "Attribute not found",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EBADMSG         => "Bad message",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EPROTO          => "Protocol error",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "ios", target_os = "openbsd", ))]
++        ENOTRECOVERABLE => "State not recoverable",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "ios", target_os = "openbsd"))]
++        EOWNERDEAD      => "Previous owner died",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ENOTSUP         => "Operation not supported",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EPROCLIM        => "Too many processes",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EUSERS          => "Too many users",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EDQUOT          => "Disc quota exceeded",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ESTALE          => "Stale NFS file handle",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EREMOTE         => "Too many levels of remote in path",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EBADRPC         => "RPC struct is bad",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ERPCMISMATCH    => "RPC version wrong",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EPROGUNAVAIL    => "RPC prog. not avail",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EPROGMISMATCH   => "Program version wrong",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EPROCUNAVAIL    => "Bad procedure for program",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EFTYPE          => "Inappropriate file type or format",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        EAUTH           => "Authentication error",
++
++        #[cfg(any(target_os = "macos", target_os = "freebsd",
++                  target_os = "dragonfly", target_os = "ios",
++                  target_os = "openbsd", target_os = "netbsd"))]
++        ECANCELED       => "Operation canceled",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EPWROFF         => "Device power is off",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EDEVERR         => "Device error, e.g. paper out",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EBADEXEC        => "Bad executable",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EBADARCH        => "Bad CPU type in executable",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        ESHLIBVERS      => "Shared library version mismatch",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EBADMACHO       => "Malformed Macho file",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        EMULTIHOP       => "Reserved",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        ENODATA         => "No message available on STREAM",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        ENOLINK         => "Reserved",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        ENOSR           => "No STREAM resources",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        ENOSTR          => "Not a STREAM",
++
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        ETIME           => "STREAM ioctl timeout",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EOPNOTSUPP      => "Operation not supported on socket",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        ENOPOLICY       => "No such policy registered",
++
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EQFULL          => "Interface output queue is full",
++
++        #[cfg(target_os = "openbsd")]
++        EOPNOTSUPP      => "Operation not supported",
++
++        #[cfg(target_os = "openbsd")]
++        EIPSEC          => "IPsec processing failure",
++
++        #[cfg(target_os = "dragonfly")]
++        EASYNC          => "Async",
++    }
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        ELOOP           = libc::ELOOP,
++        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,
++        EBADE           = libc::EBADE,
++        EBADR           = libc::EBADR,
++        EXFULL          = libc::EXFULL,
++        ENOANO          = libc::ENOANO,
++        EBADRQC         = libc::EBADRQC,
++        EBADSLT         = libc::EBADSLT,
++        EBFONT          = libc::EBFONT,
++        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,
++        EMULTIHOP       = libc::EMULTIHOP,
++        EDOTDOT         = libc::EDOTDOT,
++        EBADMSG         = libc::EBADMSG,
++        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,
++        ERESTART        = libc::ERESTART,
++        ESTRPIPE        = libc::ESTRPIPE,
++        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,
++        EUCLEAN         = libc::EUCLEAN,
++        ENOTNAM         = libc::ENOTNAM,
++        ENAVAIL         = libc::ENAVAIL,
++        EISNAM          = libc::EISNAM,
++        EREMOTEIO       = libc::EREMOTEIO,
++        EDQUOT          = libc::EDQUOT,
++        ENOMEDIUM       = libc::ENOMEDIUM,
++        EMEDIUMTYPE     = libc::EMEDIUMTYPE,
++        ECANCELED       = libc::ECANCELED,
++        ENOKEY          = libc::ENOKEY,
++        EKEYEXPIRED     = libc::EKEYEXPIRED,
++        EKEYREVOKED     = libc::EKEYREVOKED,
++        EKEYREJECTED    = libc::EKEYREJECTED,
++        EOWNERDEAD      = libc::EOWNERDEAD,
++        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
++        #[cfg(not(any(target_os = "android", target_arch="mips")))]
++        ERFKILL         = libc::ERFKILL,
++        #[cfg(not(any(target_os = "android", target_arch="mips")))]
++        EHWPOISON       = libc::EHWPOISON,
++    }
++
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
++    pub const ENOTSUP:     Errno = Errno::EOPNOTSUPP;
++
++    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::EDEADLK => EDEADLK,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::ELOOP => ELOOP,
++            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::EBADE => EBADE,
++            libc::EBADR => EBADR,
++            libc::EXFULL => EXFULL,
++            libc::ENOANO => ENOANO,
++            libc::EBADRQC => EBADRQC,
++            libc::EBADSLT => EBADSLT,
++            libc::EBFONT => EBFONT,
++            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::EMULTIHOP => EMULTIHOP,
++            libc::EDOTDOT => EDOTDOT,
++            libc::EBADMSG => EBADMSG,
++            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::ERESTART => ERESTART,
++            libc::ESTRPIPE => ESTRPIPE,
++            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,
++            libc::EUCLEAN => EUCLEAN,
++            libc::ENOTNAM => ENOTNAM,
++            libc::ENAVAIL => ENAVAIL,
++            libc::EISNAM => EISNAM,
++            libc::EREMOTEIO => EREMOTEIO,
++            libc::EDQUOT => EDQUOT,
++            libc::ENOMEDIUM => ENOMEDIUM,
++            libc::EMEDIUMTYPE => EMEDIUMTYPE,
++            libc::ECANCELED => ECANCELED,
++            libc::ENOKEY => ENOKEY,
++            libc::EKEYEXPIRED => EKEYEXPIRED,
++            libc::EKEYREVOKED => EKEYREVOKED,
++            libc::EKEYREJECTED => EKEYREJECTED,
++            libc::EOWNERDEAD => EOWNERDEAD,
++            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
++            #[cfg(not(any(target_os = "android", target_arch="mips")))]
++            libc::ERFKILL => ERFKILL,
++            #[cfg(not(any(target_os = "android", target_arch="mips")))]
++            libc::EHWPOISON => EHWPOISON,
++            _   => UnknownErrno,
++        }
++    }
++}
++
++#[cfg(any(target_os = "macos", target_os = "ios"))]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        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,
++        EAGAIN          = libc::EAGAIN,
++        EINPROGRESS     = libc::EINPROGRESS,
++        EALREADY        = libc::EALREADY,
++        ENOTSOCK        = libc::ENOTSOCK,
++        EDESTADDRREQ    = libc::EDESTADDRREQ,
++        EMSGSIZE        = libc::EMSGSIZE,
++        EPROTOTYPE      = libc::EPROTOTYPE,
++        ENOPROTOOPT     = libc::ENOPROTOOPT,
++        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
++        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
++        ENOTSUP         = libc::ENOTSUP,
++        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,
++        ELOOP           = libc::ELOOP,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        EHOSTDOWN       = libc::EHOSTDOWN,
++        EHOSTUNREACH    = libc::EHOSTUNREACH,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        EPROCLIM        = libc::EPROCLIM,
++        EUSERS          = libc::EUSERS,
++        EDQUOT          = libc::EDQUOT,
++        ESTALE          = libc::ESTALE,
++        EREMOTE         = libc::EREMOTE,
++        EBADRPC         = libc::EBADRPC,
++        ERPCMISMATCH    = libc::ERPCMISMATCH,
++        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
++        EPROGMISMATCH   = libc::EPROGMISMATCH,
++        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        EFTYPE          = libc::EFTYPE,
++        EAUTH           = libc::EAUTH,
++        ENEEDAUTH       = libc::ENEEDAUTH,
++        EPWROFF         = libc::EPWROFF,
++        EDEVERR         = libc::EDEVERR,
++        EOVERFLOW       = libc::EOVERFLOW,
++        EBADEXEC        = libc::EBADEXEC,
++        EBADARCH        = libc::EBADARCH,
++        ESHLIBVERS      = libc::ESHLIBVERS,
++        EBADMACHO       = libc::EBADMACHO,
++        ECANCELED       = libc::ECANCELED,
++        EIDRM           = libc::EIDRM,
++        ENOMSG          = libc::ENOMSG,
++        EILSEQ          = libc::EILSEQ,
++        ENOATTR         = libc::ENOATTR,
++        EBADMSG         = libc::EBADMSG,
++        EMULTIHOP       = libc::EMULTIHOP,
++        ENODATA         = libc::ENODATA,
++        ENOLINK         = libc::ENOLINK,
++        ENOSR           = libc::ENOSR,
++        ENOSTR          = libc::ENOSTR,
++        EPROTO          = libc::EPROTO,
++        ETIME           = libc::ETIME,
++        EOPNOTSUPP      = libc::EOPNOTSUPP,
++        ENOPOLICY       = libc::ENOPOLICY,
++        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
++        EOWNERDEAD      = libc::EOWNERDEAD,
++        EQFULL          = libc::EQFULL,
++    }
++
++    pub const ELAST: Errno       = Errno::EQFULL;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    pub 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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            libc::ENOTSOCK => ENOTSOCK,
++            libc::EDESTADDRREQ => EDESTADDRREQ,
++            libc::EMSGSIZE => EMSGSIZE,
++            libc::EPROTOTYPE => EPROTOTYPE,
++            libc::ENOPROTOOPT => ENOPROTOOPT,
++            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
++            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
++            libc::ENOTSUP => ENOTSUP,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EPROCLIM => EPROCLIM,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::EBADRPC => EBADRPC,
++            libc::ERPCMISMATCH => ERPCMISMATCH,
++            libc::EPROGUNAVAIL => EPROGUNAVAIL,
++            libc::EPROGMISMATCH => EPROGMISMATCH,
++            libc::EPROCUNAVAIL => EPROCUNAVAIL,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EFTYPE => EFTYPE,
++            libc::EAUTH => EAUTH,
++            libc::ENEEDAUTH => ENEEDAUTH,
++            libc::EPWROFF => EPWROFF,
++            libc::EDEVERR => EDEVERR,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::EBADEXEC => EBADEXEC,
++            libc::EBADARCH => EBADARCH,
++            libc::ESHLIBVERS => ESHLIBVERS,
++            libc::EBADMACHO => EBADMACHO,
++            libc::ECANCELED => ECANCELED,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::EILSEQ => EILSEQ,
++            libc::ENOATTR => ENOATTR,
++            libc::EBADMSG => EBADMSG,
++            libc::EMULTIHOP => EMULTIHOP,
++            libc::ENODATA => ENODATA,
++            libc::ENOLINK => ENOLINK,
++            libc::ENOSR => ENOSR,
++            libc::ENOSTR => ENOSTR,
++            libc::EPROTO => EPROTO,
++            libc::ETIME => ETIME,
++            libc::EOPNOTSUPP => EOPNOTSUPP,
++            libc::ENOPOLICY => ENOPOLICY,
++            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
++            libc::EOWNERDEAD => EOWNERDEAD,
++            libc::EQFULL => EQFULL,
++            _   => UnknownErrno,
++        }
++    }
++}
++
++#[cfg(target_os = "freebsd")]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        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,
++        EAGAIN          = libc::EAGAIN,
++        EINPROGRESS     = libc::EINPROGRESS,
++        EALREADY        = libc::EALREADY,
++        ENOTSOCK        = libc::ENOTSOCK,
++        EDESTADDRREQ    = libc::EDESTADDRREQ,
++        EMSGSIZE        = libc::EMSGSIZE,
++        EPROTOTYPE      = libc::EPROTOTYPE,
++        ENOPROTOOPT     = libc::ENOPROTOOPT,
++        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
++        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
++        ENOTSUP         = libc::ENOTSUP,
++        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,
++        ELOOP           = libc::ELOOP,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        EHOSTDOWN       = libc::EHOSTDOWN,
++        EHOSTUNREACH    = libc::EHOSTUNREACH,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        EPROCLIM        = libc::EPROCLIM,
++        EUSERS          = libc::EUSERS,
++        EDQUOT          = libc::EDQUOT,
++        ESTALE          = libc::ESTALE,
++        EREMOTE         = libc::EREMOTE,
++        EBADRPC         = libc::EBADRPC,
++        ERPCMISMATCH    = libc::ERPCMISMATCH,
++        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
++        EPROGMISMATCH   = libc::EPROGMISMATCH,
++        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        EFTYPE          = libc::EFTYPE,
++        EAUTH           = libc::EAUTH,
++        ENEEDAUTH       = libc::ENEEDAUTH,
++        EIDRM           = libc::EIDRM,
++        ENOMSG          = libc::ENOMSG,
++        EOVERFLOW       = libc::EOVERFLOW,
++        ECANCELED       = libc::ECANCELED,
++        EILSEQ          = libc::EILSEQ,
++        ENOATTR         = libc::ENOATTR,
++        EDOOFUS         = libc::EDOOFUS,
++        EBADMSG         = libc::EBADMSG,
++        EMULTIHOP       = libc::EMULTIHOP,
++        ENOLINK         = libc::ENOLINK,
++        EPROTO          = libc::EPROTO,
++        ENOTCAPABLE     = libc::ENOTCAPABLE,
++        ECAPMODE        = libc::ECAPMODE,
++        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
++        EOWNERDEAD      = libc::EOWNERDEAD,
++    }
++
++    pub const ELAST: Errno       = Errno::EOWNERDEAD;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            libc::ENOTSOCK => ENOTSOCK,
++            libc::EDESTADDRREQ => EDESTADDRREQ,
++            libc::EMSGSIZE => EMSGSIZE,
++            libc::EPROTOTYPE => EPROTOTYPE,
++            libc::ENOPROTOOPT => ENOPROTOOPT,
++            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
++            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
++            libc::ENOTSUP => ENOTSUP,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EPROCLIM => EPROCLIM,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::EBADRPC => EBADRPC,
++            libc::ERPCMISMATCH => ERPCMISMATCH,
++            libc::EPROGUNAVAIL => EPROGUNAVAIL,
++            libc::EPROGMISMATCH => EPROGMISMATCH,
++            libc::EPROCUNAVAIL => EPROCUNAVAIL,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EFTYPE => EFTYPE,
++            libc::EAUTH => EAUTH,
++            libc::ENEEDAUTH => ENEEDAUTH,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::ECANCELED => ECANCELED,
++            libc::EILSEQ => EILSEQ,
++            libc::ENOATTR => ENOATTR,
++            libc::EDOOFUS => EDOOFUS,
++            libc::EBADMSG => EBADMSG,
++            libc::EMULTIHOP => EMULTIHOP,
++            libc::ENOLINK => ENOLINK,
++            libc::EPROTO => EPROTO,
++            libc::ENOTCAPABLE => ENOTCAPABLE,
++            libc::ECAPMODE => ECAPMODE,
++            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
++            libc::EOWNERDEAD => EOWNERDEAD,
++            _   => UnknownErrno,
++        }
++    }
++}
++
++
++#[cfg(target_os = "dragonfly")]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        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,
++        EAGAIN          = libc::EAGAIN,
++        EINPROGRESS     = libc::EINPROGRESS,
++        EALREADY        = libc::EALREADY,
++        ENOTSOCK        = libc::ENOTSOCK,
++        EDESTADDRREQ    = libc::EDESTADDRREQ,
++        EMSGSIZE        = libc::EMSGSIZE,
++        EPROTOTYPE      = libc::EPROTOTYPE,
++        ENOPROTOOPT     = libc::ENOPROTOOPT,
++        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
++        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
++        ENOTSUP         = libc::ENOTSUP,
++        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,
++        ELOOP           = libc::ELOOP,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        EHOSTDOWN       = libc::EHOSTDOWN,
++        EHOSTUNREACH    = libc::EHOSTUNREACH,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        EPROCLIM        = libc::EPROCLIM,
++        EUSERS          = libc::EUSERS,
++        EDQUOT          = libc::EDQUOT,
++        ESTALE          = libc::ESTALE,
++        EREMOTE         = libc::EREMOTE,
++        EBADRPC         = libc::EBADRPC,
++        ERPCMISMATCH    = libc::ERPCMISMATCH,
++        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
++        EPROGMISMATCH   = libc::EPROGMISMATCH,
++        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        EFTYPE          = libc::EFTYPE,
++        EAUTH           = libc::EAUTH,
++        ENEEDAUTH       = libc::ENEEDAUTH,
++        EIDRM           = libc::EIDRM,
++        ENOMSG          = libc::ENOMSG,
++        EOVERFLOW       = libc::EOVERFLOW,
++        ECANCELED       = libc::ECANCELED,
++        EILSEQ          = libc::EILSEQ,
++        ENOATTR         = libc::ENOATTR,
++        EDOOFUS         = libc::EDOOFUS,
++        EBADMSG         = libc::EBADMSG,
++        EMULTIHOP       = libc::EMULTIHOP,
++        ENOLINK         = libc::ENOLINK,
++        EPROTO          = libc::EPROTO,
++        ENOMEDIUM       = libc::ENOMEDIUM,
++        EASYNC          = libc::EASYNC,
++    }
++
++    pub const ELAST: Errno       = Errno::EASYNC;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
++    pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    pub 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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            libc::ENOTSOCK => ENOTSOCK,
++            libc::EDESTADDRREQ => EDESTADDRREQ,
++            libc::EMSGSIZE => EMSGSIZE,
++            libc::EPROTOTYPE => EPROTOTYPE,
++            libc::ENOPROTOOPT => ENOPROTOOPT,
++            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
++            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
++            libc::ENOTSUP => ENOTSUP,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EPROCLIM => EPROCLIM,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::EBADRPC => EBADRPC,
++            libc::ERPCMISMATCH => ERPCMISMATCH,
++            libc::EPROGUNAVAIL => EPROGUNAVAIL,
++            libc::EPROGMISMATCH => EPROGMISMATCH,
++            libc::EPROCUNAVAIL => EPROCUNAVAIL,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EFTYPE => EFTYPE,
++            libc::EAUTH => EAUTH,
++            libc::ENEEDAUTH => ENEEDAUTH,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::ECANCELED => ECANCELED,
++            libc::EILSEQ => EILSEQ,
++            libc::ENOATTR => ENOATTR,
++            libc::EDOOFUS => EDOOFUS,
++            libc::EBADMSG => EBADMSG,
++            libc::EMULTIHOP => EMULTIHOP,
++            libc::ENOLINK => ENOLINK,
++            libc::EPROTO => EPROTO,
++            libc::ENOMEDIUM => ENOMEDIUM,
++            libc::EASYNC => EASYNC,
++            _   => UnknownErrno,
++        }
++    }
++}
++
++
++#[cfg(target_os = "openbsd")]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        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,
++        EAGAIN          = libc::EAGAIN,
++        EINPROGRESS     = libc::EINPROGRESS,
++        EALREADY        = libc::EALREADY,
++        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,
++        ELOOP           = libc::ELOOP,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        EHOSTDOWN       = libc::EHOSTDOWN,
++        EHOSTUNREACH    = libc::EHOSTUNREACH,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        EPROCLIM        = libc::EPROCLIM,
++        EUSERS          = libc::EUSERS,
++        EDQUOT          = libc::EDQUOT,
++        ESTALE          = libc::ESTALE,
++        EREMOTE         = libc::EREMOTE,
++        EBADRPC         = libc::EBADRPC,
++        ERPCMISMATCH    = libc::ERPCMISMATCH,
++        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
++        EPROGMISMATCH   = libc::EPROGMISMATCH,
++        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        EFTYPE          = libc::EFTYPE,
++        EAUTH           = libc::EAUTH,
++        ENEEDAUTH       = libc::ENEEDAUTH,
++        EIPSEC          = libc::EIPSEC,
++        ENOATTR         = libc::ENOATTR,
++        EILSEQ          = libc::EILSEQ,
++        ENOMEDIUM       = libc::ENOMEDIUM,
++        EMEDIUMTYPE     = libc::EMEDIUMTYPE,
++        EOVERFLOW       = libc::EOVERFLOW,
++        ECANCELED       = libc::ECANCELED,
++        EIDRM           = libc::EIDRM,
++        ENOMSG          = libc::ENOMSG,
++        ENOTSUP         = libc::ENOTSUP,
++        EBADMSG         = libc::EBADMSG,
++        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
++        EOWNERDEAD      = libc::EOWNERDEAD,
++        EPROTO          = libc::EPROTO,
++    }
++
++    pub const ELAST: Errno       = Errno::ENOTSUP;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EPROCLIM => EPROCLIM,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::EBADRPC => EBADRPC,
++            libc::ERPCMISMATCH => ERPCMISMATCH,
++            libc::EPROGUNAVAIL => EPROGUNAVAIL,
++            libc::EPROGMISMATCH => EPROGMISMATCH,
++            libc::EPROCUNAVAIL => EPROCUNAVAIL,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EFTYPE => EFTYPE,
++            libc::EAUTH => EAUTH,
++            libc::ENEEDAUTH => ENEEDAUTH,
++            libc::EIPSEC => EIPSEC,
++            libc::ENOATTR => ENOATTR,
++            libc::EILSEQ => EILSEQ,
++            libc::ENOMEDIUM => ENOMEDIUM,
++            libc::EMEDIUMTYPE => EMEDIUMTYPE,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::ECANCELED => ECANCELED,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::ENOTSUP => ENOTSUP,
++            libc::EBADMSG => EBADMSG,
++            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
++            libc::EOWNERDEAD => EOWNERDEAD,
++            libc::EPROTO => EPROTO,
++            _   => UnknownErrno,
++        }
++    }
++}
++
++#[cfg(target_os = "netbsd")]
++mod consts {
++    use libc;
++
++    #[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,
++        EDEADLK         = libc::EDEADLK,
++        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,
++        EAGAIN          = libc::EAGAIN,
++        EINPROGRESS     = libc::EINPROGRESS,
++        EALREADY        = libc::EALREADY,
++        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,
++        ELOOP           = libc::ELOOP,
++        ENAMETOOLONG    = libc::ENAMETOOLONG,
++        EHOSTDOWN       = libc::EHOSTDOWN,
++        EHOSTUNREACH    = libc::EHOSTUNREACH,
++        ENOTEMPTY       = libc::ENOTEMPTY,
++        EPROCLIM        = libc::EPROCLIM,
++        EUSERS          = libc::EUSERS,
++        EDQUOT          = libc::EDQUOT,
++        ESTALE          = libc::ESTALE,
++        EREMOTE         = libc::EREMOTE,
++        EBADRPC         = libc::EBADRPC,
++        ERPCMISMATCH    = libc::ERPCMISMATCH,
++        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
++        EPROGMISMATCH   = libc::EPROGMISMATCH,
++        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
++        ENOLCK          = libc::ENOLCK,
++        ENOSYS          = libc::ENOSYS,
++        EFTYPE          = libc::EFTYPE,
++        EAUTH           = libc::EAUTH,
++        ENEEDAUTH       = libc::ENEEDAUTH,
++        EIDRM           = libc::EIDRM,
++        ENOMSG          = libc::ENOMSG,
++        EOVERFLOW       = libc::EOVERFLOW,
++        EILSEQ          = libc::EILSEQ,
++        ENOTSUP         = libc::ENOTSUP,
++        ECANCELED       = libc::ECANCELED,
++        EBADMSG         = libc::EBADMSG,
++        ENODATA         = libc::ENODATA,
++        ENOSR           = libc::ENOSR,
++        ENOSTR          = libc::ENOSTR,
++        ETIME           = libc::ETIME,
++        ENOATTR         = libc::ENOATTR,
++        EMULTIHOP       = libc::EMULTIHOP,
++        ENOLINK         = libc::ENOLINK,
++        EPROTO          = libc::EPROTO,
++    }
++
++    pub const ELAST: Errno       = Errno::ENOTSUP;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EPROCLIM => EPROCLIM,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::EBADRPC => EBADRPC,
++            libc::ERPCMISMATCH => ERPCMISMATCH,
++            libc::EPROGUNAVAIL => EPROGUNAVAIL,
++            libc::EPROGMISMATCH => EPROGMISMATCH,
++            libc::EPROCUNAVAIL => EPROCUNAVAIL,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EFTYPE => EFTYPE,
++            libc::EAUTH => EAUTH,
++            libc::ENEEDAUTH => ENEEDAUTH,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::EILSEQ => EILSEQ,
++            libc::ENOTSUP => ENOTSUP,
++            libc::ECANCELED => ECANCELED,
++            libc::EBADMSG => EBADMSG,
++            libc::ENODATA => ENODATA,
++            libc::ENOSR => ENOSR,
++            libc::ENOSTR => ENOSTR,
++            libc::ETIME => ETIME,
++            libc::ENOATTR => ENOATTR,
++            libc::EMULTIHOP => EMULTIHOP,
++            libc::ENOLINK => ENOLINK,
++            libc::EPROTO => EPROTO,
++            _   => UnknownErrno,
++        }
++    }
++}
+diff --git a/third_party/rust/nix/src/errno_dragonfly.c b/third_party/rust/nix-0.15.0/src/errno_dragonfly.c
+similarity index 100%
+rename from third_party/rust/nix/src/errno_dragonfly.c
+rename to third_party/rust/nix-0.15.0/src/errno_dragonfly.c
+diff --git a/third_party/rust/nix-0.15.0/src/fcntl.rs b/third_party/rust/nix-0.15.0/src/fcntl.rs
+new file mode 100644
+index 0000000000000..be6ee0f73a8be
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/fcntl.rs
+@@ -0,0 +1,506 @@
++use {Error, Result, NixPath};
++use errno::Errno;
++use libc::{self, c_int, c_uint, c_char, size_t, ssize_t};
++use sys::stat::Mode;
++use std::os::raw;
++use std::os::unix::io::RawFd;
++use std::ffi::OsStr;
++use std::os::unix::ffi::OsStrExt;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use std::ptr; // For splice and copy_file_range
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use sys::uio::IoVec;  // For vmsplice
++
++#[cfg(any(target_os = "linux",
++          target_os = "android",
++          target_os = "emscripten",
++          target_os = "fuchsia",
++          any(target_os = "wasi", target_env = "wasi"),
++          target_env = "uclibc",
++          target_env = "freebsd"))]
++pub use self::posix_fadvise::*;
++
++libc_bitflags!{
++    pub struct AtFlags: c_int {
++        AT_REMOVEDIR;
++        AT_SYMLINK_NOFOLLOW;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        AT_NO_AUTOMOUNT;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        AT_EMPTY_PATH;
++    }
++}
++
++libc_bitflags!(
++    /// Configuration options for opened files.
++    pub struct OFlag: c_int {
++        /// Mask for the access mode of the file.
++        O_ACCMODE;
++        /// Use alternate I/O semantics.
++        #[cfg(target_os = "netbsd")]
++        O_ALT_IO;
++        /// Open the file in append-only mode.
++        O_APPEND;
++        /// Generate a signal when input or output becomes possible.
++        O_ASYNC;
++        /// Closes the file descriptor once an `execve` call is made.
++        ///
++        /// Also sets the file offset to the beginning of the file.
++        O_CLOEXEC;
++        /// Create the file if it does not exist.
++        O_CREAT;
++        /// Try to minimize cache effects of the I/O for this file.
++        #[cfg(any(target_os = "android",
++                  target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd"))]
++        O_DIRECT;
++        /// If the specified path isn't a directory, fail.
++        O_DIRECTORY;
++        /// Implicitly follow each `write()` with an `fdatasync()`.
++        #[cfg(any(target_os = "android",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        O_DSYNC;
++        /// Error out if a file was not created.
++        O_EXCL;
++        /// Open for execute only.
++        #[cfg(target_os = "freebsd")]
++        O_EXEC;
++        /// Open with an exclusive file lock.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        O_EXLOCK;
++        /// Same as `O_SYNC`.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  all(target_os = "linux", not(target_env = "musl")),
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        O_FSYNC;
++        /// Allow files whose sizes can't be represented in an `off_t` to be opened.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        O_LARGEFILE;
++        /// Do not update the file last access time during `read(2)`s.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        O_NOATIME;
++        /// Don't attach the device as the process' controlling terminal.
++        O_NOCTTY;
++        /// Same as `O_NONBLOCK`.
++        O_NDELAY;
++        /// `open()` will fail if the given path is a symbolic link.
++        O_NOFOLLOW;
++        /// When possible, open the file in nonblocking mode.
++        O_NONBLOCK;
++        /// Don't deliver `SIGPIPE`.
++        #[cfg(target_os = "netbsd")]
++        O_NOSIGPIPE;
++        /// Obtain a file descriptor for low-level access.
++        ///
++        /// The file itself is not opened and other file operations will fail.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        O_PATH;
++        /// Only allow reading.
++        ///
++        /// This should not be combined with `O_WRONLY` or `O_RDWR`.
++        O_RDONLY;
++        /// Allow both reading and writing.
++        ///
++        /// This should not be combined with `O_WRONLY` or `O_RDONLY`.
++        O_RDWR;
++        /// Similar to `O_DSYNC` but applies to `read`s instead.
++        #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
++        O_RSYNC;
++        /// Skip search permission checks.
++        #[cfg(target_os = "netbsd")]
++        O_SEARCH;
++        /// Open with a shared file lock.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        O_SHLOCK;
++        /// Implicitly follow each `write()` with an `fsync()`.
++        O_SYNC;
++        /// Create an unnamed temporary file.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        O_TMPFILE;
++        /// Truncate an existing regular file to 0 length if it allows writing.
++        O_TRUNC;
++        /// Restore default TTY attributes.
++        #[cfg(target_os = "freebsd")]
++        O_TTY_INIT;
++        /// Only allow writing.
++        ///
++        /// This should not be combined with `O_RDONLY` or `O_RDWR`.
++        O_WRONLY;
++    }
++);
++
++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) }
++    })?;
++
++    Errno::result(fd)
++}
++
++pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
++    let fd = path.with_nix_path(|cstr| {
++        unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
++    })?;
++    Errno::result(fd)
++}
++
++pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<RawFd>, old_path: &P1,
++                                                            new_dirfd: Option<RawFd>, new_path: &P2)
++                                                            -> Result<()> {
++    let res = old_path.with_nix_path(|old_cstr| {
++        new_path.with_nix_path(|new_cstr| unsafe {
++            libc::renameat(at_rawfd(old_dirfd), old_cstr.as_ptr(),
++                           at_rawfd(new_dirfd), new_cstr.as_ptr())
++        })
++    })??;
++    Errno::result(res).map(drop)
++}
++
++fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
++    match Errno::result(res) {
++        Err(err) => Err(err),
++        Ok(len) => {
++            if (len as usize) >= buffer.len() {
++                Err(Error::Sys(Errno::ENAMETOOLONG))
++            } else {
++                Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
++            }
++        }
++    }
++}
++
++pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
++    })?;
++
++    wrap_readlink_result(buffer, res)
++}
++
++
++pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
++    })?;
++
++    wrap_readlink_result(buffer, res)
++}
++
++/// Computes the raw fd consumed by a function of the form `*at`.
++pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
++    match fd {
++        None => libc::AT_FDCWD,
++        Some(fd) => fd,
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++libc_bitflags!(
++    /// Additional flags for file sealing, which allows for limiting operations on a file.
++    pub struct SealFlag: c_int {
++        /// Prevents further calls to `fcntl()` with `F_ADD_SEALS`.
++        F_SEAL_SEAL;
++        /// The file cannot be reduced in size.
++        F_SEAL_SHRINK;
++        /// The size of the file cannot be increased.
++        F_SEAL_GROW;
++        /// The file contents cannot be modified.
++        F_SEAL_WRITE;
++    }
++);
++
++libc_bitflags!(
++    /// Additional configuration flags for `fcntl`'s `F_SETFD`.
++    pub struct FdFlag: c_int {
++        /// The file descriptor will automatically be closed during a successful `execve(2)`.
++        FD_CLOEXEC;
++    }
++);
++
++#[derive(Debug, Eq, Hash, PartialEq)]
++pub enum FcntlArg<'a> {
++    F_DUPFD(RawFd),
++    F_DUPFD_CLOEXEC(RawFd),
++    F_GETFD,
++    F_SETFD(FdFlag), // FD_FLAGS
++    F_GETFL,
++    F_SETFL(OFlag), // O_NONBLOCK
++    F_SETLK(&'a libc::flock),
++    F_SETLKW(&'a libc::flock),
++    F_GETLK(&'a mut libc::flock),
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    F_OFD_SETLK(&'a libc::flock),
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    F_OFD_SETLKW(&'a libc::flock),
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    F_OFD_GETLK(&'a mut libc::flock),
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    F_ADD_SEALS(SealFlag),
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    F_GET_SEALS,
++    #[cfg(any(target_os = "macos", target_os = "ios"))]
++    F_FULLFSYNC,
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    F_GETPIPE_SZ,
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    F_SETPIPE_SZ(c_int),
++
++    // TODO: Rest of flags
++}
++pub use self::FcntlArg::*;
++
++// TODO: Figure out how to handle value fcntl returns
++pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
++    let res = unsafe {
++        match arg {
++            F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
++            F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd),
++            F_GETFD => libc::fcntl(fd, libc::F_GETFD),
++            F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
++            F_GETFL => libc::fcntl(fd, libc::F_GETFL),
++            F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
++            F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
++            F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
++            F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
++            #[cfg(any(target_os = "macos", target_os = "ios"))]
++            F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
++            #[cfg(any(target_os = "linux", target_os = "android"))]
++            F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
++            #[cfg(any(target_os = "linux", target_os = "android"))]
++            F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
++            #[cfg(any(target_os = "linux", target_os = "android"))]
++            _ => unimplemented!()
++        }
++    };
++
++    Errno::result(res)
++}
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum FlockArg {
++    LockShared,
++    LockExclusive,
++    Unlock,
++    LockSharedNonblock,
++    LockExclusiveNonblock,
++    UnlockNonblock,
++}
++
++pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
++    use self::FlockArg::*;
++
++    let res = unsafe {
++        match arg {
++            LockShared => libc::flock(fd, libc::LOCK_SH),
++            LockExclusive => libc::flock(fd, libc::LOCK_EX),
++            Unlock => libc::flock(fd, libc::LOCK_UN),
++            LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB),
++            LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB),
++            UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
++        }
++    };
++
++    Errno::result(res).map(drop)
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++libc_bitflags! {
++    /// Additional flags to `splice` and friends.
++    pub struct SpliceFFlags: c_uint {
++        /// Request that pages be moved instead of copied.
++        ///
++        /// Not applicable to `vmsplice`.
++        SPLICE_F_MOVE;
++        /// Do not block on I/O.
++        SPLICE_F_NONBLOCK;
++        /// Hint that more data will be coming in a subsequent splice.
++        ///
++        /// Not applicable to `vmsplice`.
++        SPLICE_F_MORE;
++        /// Gift the user pages to the kernel.
++        ///
++        /// Not applicable to `splice`.
++        SPLICE_F_GIFT;
++    }
++}
++
++/// Copy a range of data from one file to another
++///
++/// The `copy_file_range` system call performs an in-kernel copy between
++/// file descriptors `fd_in` and `fd_out` without the additional cost of
++/// transferring data from the kernel to user space and then back into the
++/// kernel. It copies up to `len` bytes of data from file descriptor `fd_in` to
++/// file descriptor `fd_out`, overwriting any data that exists within the
++/// requested range of the target file.
++///
++/// If the `off_in` and/or `off_out` arguments are used, the values
++/// will be mutated to reflect the new position within the file after
++/// copying. If they are not used, the relevant filedescriptors will be seeked
++/// to the new position.
++///
++/// On successful completion the number of bytes actually copied will be
++/// returned.
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub fn copy_file_range(
++    fd_in: RawFd,
++    off_in: Option<&mut libc::loff_t>,
++    fd_out: RawFd,
++    off_out: Option<&mut libc::loff_t>,
++    len: usize,
++) -> Result<usize> {
++    let off_in = off_in
++        .map(|offset| offset as *mut libc::loff_t)
++        .unwrap_or(ptr::null_mut());
++    let off_out = off_out
++        .map(|offset| offset as *mut libc::loff_t)
++        .unwrap_or(ptr::null_mut());
++
++    let ret = unsafe {
++        libc::syscall(
++            libc::SYS_copy_file_range,
++            fd_in,
++            off_in,
++            fd_out,
++            off_out,
++            len,
++            0,
++        )
++    };
++    Errno::result(ret).map(|r| r as usize)
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn splice(
++    fd_in: RawFd,
++    off_in: Option<&mut libc::loff_t>,
++    fd_out: RawFd,
++    off_out: Option<&mut libc::loff_t>,
++    len: usize,
++    flags: SpliceFFlags,
++) -> Result<usize> {
++    let off_in = off_in
++        .map(|offset| offset as *mut libc::loff_t)
++        .unwrap_or(ptr::null_mut());
++    let off_out = off_out
++        .map(|offset| offset as *mut libc::loff_t)
++        .unwrap_or(ptr::null_mut());
++
++    let ret = unsafe {
++        libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
++    };
++    Errno::result(ret).map(|r| r as usize)
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result<usize> {
++    let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
++    Errno::result(ret).map(|r| r as usize)
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<usize> {
++    let ret = unsafe {
++        libc::vmsplice(fd, iov.as_ptr() as *const libc::iovec, iov.len(), flags.bits())
++    };
++    Errno::result(ret).map(|r| r as usize)
++}
++
++#[cfg(any(target_os = "linux"))]
++libc_bitflags!(
++    /// Mode argument flags for fallocate determining operation performed on a given range.
++    pub struct FallocateFlags: c_int {
++        /// File size is not changed.
++        ///
++        /// offset + len can be greater than file size.
++        FALLOC_FL_KEEP_SIZE;
++        /// Deallocates space by creating a hole.
++        ///
++        /// Must be ORed with FALLOC_FL_KEEP_SIZE. Byte range starts at offset and continues for len bytes.
++        FALLOC_FL_PUNCH_HOLE;
++        /// Removes byte range from a file without leaving a hole.
++        ///
++        /// Byte range to collapse starts at offset and continues for len bytes.
++        FALLOC_FL_COLLAPSE_RANGE;
++        /// Zeroes space in specified byte range.
++        ///
++        /// Byte range starts at offset and continues for len bytes.
++        FALLOC_FL_ZERO_RANGE;
++        /// Increases file space by inserting a hole within the file size.
++        ///
++        /// Does not overwrite existing data. Hole starts at offset and continues for len bytes.
++        FALLOC_FL_INSERT_RANGE;
++        /// Shared file data extants are made private to the file.
++        ///
++        /// Gaurantees that a subsequent write will not fail due to lack of space.
++        FALLOC_FL_UNSHARE_RANGE;
++    }
++);
++
++/// Manipulates file space.
++///
++/// Allows the caller to directly manipulate the allocated disk space for the
++/// file referred to by fd.
++#[cfg(any(target_os = "linux"))]
++pub fn fallocate(fd: RawFd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t) -> Result<c_int> {
++    let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
++    Errno::result(res)
++}
++
++#[cfg(any(target_os = "linux",
++          target_os = "android",
++          target_os = "emscripten",
++          target_os = "fuchsia",
++          any(target_os = "wasi", target_env = "wasi"),
++          target_env = "uclibc",
++          target_env = "freebsd"))]
++mod posix_fadvise {
++    use Result;
++    use libc;
++    use errno::Errno;
++    use std::os::unix::io::RawFd;
++
++    libc_enum! {
++        #[repr(i32)]
++        pub enum PosixFadviseAdvice {
++            POSIX_FADV_NORMAL,
++            POSIX_FADV_SEQUENTIAL,
++            POSIX_FADV_RANDOM,
++            POSIX_FADV_NOREUSE,
++            POSIX_FADV_WILLNEED,
++            POSIX_FADV_DONTNEED,
++        }
++    }
++
++    pub fn posix_fadvise(fd: RawFd,
++                         offset: libc::off_t,
++                         len: libc::off_t,
++                         advice: PosixFadviseAdvice) -> Result<libc::c_int> {
++        let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
++        Errno::result(res)
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/features.rs b/third_party/rust/nix-0.15.0/src/features.rs
+new file mode 100644
+index 0000000000000..76cdfd3a1a6f1
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/features.rs
+@@ -0,0 +1,103 @@
++//! Feature tests for OS functionality
++pub use self::os::*;
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++mod os {
++    use sys::utsname::uname;
++
++    // Features:
++    // * atomic cloexec on socket: 2.6.27
++    // * pipe2: 2.6.27
++    // * accept4: 2.6.28
++
++    static VERS_UNKNOWN: usize = 1;
++    static VERS_2_6_18:  usize = 2;
++    static VERS_2_6_27:  usize = 3;
++    static VERS_2_6_28:  usize = 4;
++    static VERS_3:       usize = 5;
++
++    #[inline]
++    fn digit(dst: &mut usize, b: u8) {
++        *dst *= 10;
++        *dst += (b - b'0') as usize;
++    }
++
++    fn parse_kernel_version() -> usize {
++        let u = uname();
++
++        let mut curr:  usize = 0;
++        let mut major: usize = 0;
++        let mut minor: usize = 0;
++        let mut patch: usize = 0;
++
++        for b in u.release().bytes() {
++            if curr >= 3 {
++                break;
++            }
++
++            match b {
++                b'.' | b'-' => {
++                    curr += 1;
++                }
++                b'0'..=b'9' => {
++                    match curr {
++                        0 => digit(&mut major, b),
++                        1 => digit(&mut minor, b),
++                        _ => digit(&mut patch, b),
++                    }
++                }
++                _ => break,
++            }
++        }
++
++        if major >= 3 {
++            VERS_3
++        } else if major >= 2 {
++            if minor >= 7 {
++                VERS_UNKNOWN
++            } else if minor >= 6 {
++                if patch >= 28 {
++                    VERS_2_6_28
++                } else if patch >= 27 {
++                    VERS_2_6_27
++                } else {
++                    VERS_2_6_18
++                }
++            } else {
++                VERS_UNKNOWN
++            }
++        } else {
++            VERS_UNKNOWN
++        }
++    }
++
++    fn kernel_version() -> usize {
++        static mut KERNEL_VERS: usize = 0;
++
++        unsafe {
++            if KERNEL_VERS == 0 {
++                KERNEL_VERS = parse_kernel_version();
++            }
++
++            KERNEL_VERS
++        }
++    }
++
++    /// Check if the OS supports atomic close-on-exec for sockets
++    pub fn socket_atomic_cloexec() -> bool {
++        kernel_version() >= VERS_2_6_27
++    }
++
++    #[test]
++    pub fn test_parsing_kernel_version() {
++        assert!(kernel_version() > 0);
++    }
++}
++
++#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))]
++mod os {
++    /// Check if the OS supports atomic close-on-exec for sockets
++    pub fn socket_atomic_cloexec() -> bool {
++        false
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/ifaddrs.rs b/third_party/rust/nix-0.15.0/src/ifaddrs.rs
+new file mode 100644
+index 0000000000000..12b59bcc92bef
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/ifaddrs.rs
+@@ -0,0 +1,146 @@
++//! Query network interface addresses
++//!
++//! Uses the Linux and/or BSD specific function `getifaddrs` to query the list
++//! of interfaces and their associated addresses.
++
++use std::ffi;
++use std::iter::Iterator;
++use std::mem;
++use std::option::Option;
++
++use libc;
++
++use {Result, Errno};
++use sys::socket::SockAddr;
++use net::if_::*;
++
++/// Describes a single address for an interface as returned by `getifaddrs`.
++#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++pub struct InterfaceAddress {
++    /// Name of the network interface
++    pub interface_name: String,
++    /// Flags as from `SIOCGIFFLAGS` ioctl
++    pub flags: InterfaceFlags,
++    /// Network address of this interface
++    pub address: Option<SockAddr>,
++    /// Netmask of this interface
++    pub netmask: Option<SockAddr>,
++    /// Broadcast address of this interface, if applicable
++    pub broadcast: Option<SockAddr>,
++    /// Point-to-point destination address
++    pub destination: Option<SockAddr>,
++}
++
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] {
++        fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
++            info.ifa_ifu
++        }
++    } else {
++        fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
++            info.ifa_dstaddr
++        }
++    }
++}
++
++impl InterfaceAddress {
++    /// Create an `InterfaceAddress` from the libc struct.
++    fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
++        let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
++        let address = unsafe { SockAddr::from_libc_sockaddr(info.ifa_addr) };
++        let netmask = unsafe { SockAddr::from_libc_sockaddr(info.ifa_netmask) };
++        let mut addr = InterfaceAddress {
++            interface_name: ifname.to_string_lossy().to_string(),
++            flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
++            address: address,
++            netmask: netmask,
++            broadcast: None,
++            destination: None,
++        };
++
++        let ifu = get_ifu_from_sockaddr(info);
++        if addr.flags.contains(InterfaceFlags::IFF_POINTOPOINT) {
++            addr.destination = unsafe { SockAddr::from_libc_sockaddr(ifu) };
++        } else if addr.flags.contains(InterfaceFlags::IFF_BROADCAST) {
++            addr.broadcast = unsafe { SockAddr::from_libc_sockaddr(ifu) };
++        }
++
++        addr
++    }
++}
++
++/// Holds the results of `getifaddrs`.
++///
++/// Use the function `getifaddrs` to create this Iterator. Note that the
++/// actual list of interfaces can be iterated once and will be freed as
++/// soon as the Iterator goes out of scope.
++#[derive(Debug, Eq, Hash, PartialEq)]
++pub struct InterfaceAddressIterator {
++    base: *mut libc::ifaddrs,
++    next: *mut libc::ifaddrs,
++}
++
++impl Drop for InterfaceAddressIterator {
++    fn drop(&mut self) {
++        unsafe { libc::freeifaddrs(self.base) };
++    }
++}
++
++impl Iterator for InterfaceAddressIterator {
++    type Item = InterfaceAddress;
++    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
++        match unsafe { self.next.as_ref() } {
++            Some(ifaddr) => {
++                self.next = ifaddr.ifa_next;
++                Some(InterfaceAddress::from_libc_ifaddrs(ifaddr))
++            }
++            None => None,
++        }
++    }
++}
++
++/// Get interface addresses using libc's `getifaddrs`
++///
++/// Note that the underlying implementation differs between OSes. Only the
++/// most common address families are supported by the nix crate (due to
++/// lack of time and complexity of testing). The address family is encoded
++/// in the specific variant of `SockAddr` returned for the fields `address`,
++/// `netmask`, `broadcast`, and `destination`. For any entry not supported,
++/// the returned list will contain a `None` entry.
++///
++/// # Example
++/// ```
++/// let addrs = nix::ifaddrs::getifaddrs().unwrap();
++/// for ifaddr in addrs {
++///   match ifaddr.address {
++///     Some(address) => {
++///       println!("interface {} address {}",
++///                ifaddr.interface_name, address);
++///     },
++///     None => {
++///       println!("interface {} with unsupported address family",
++///                ifaddr.interface_name);
++///     }
++///   }
++/// }
++/// ```
++pub fn getifaddrs() -> Result<InterfaceAddressIterator> {
++    let mut addrs: *mut libc::ifaddrs = unsafe { mem::uninitialized() };
++    Errno::result(unsafe { libc::getifaddrs(&mut addrs) }).map(|_| {
++        InterfaceAddressIterator {
++            base: addrs,
++            next: addrs,
++        }
++    })
++}
++
++#[cfg(test)]
++mod tests {
++    use super::*;
++
++    // Only checks if `getifaddrs` can be invoked without panicking.
++    #[test]
++    fn test_getifaddrs() {
++        let _ = getifaddrs();
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/kmod.rs b/third_party/rust/nix-0.15.0/src/kmod.rs
+new file mode 100644
+index 0000000000000..e853261b14f9d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/kmod.rs
+@@ -0,0 +1,123 @@
++//! Load and unload kernel modules.
++//!
++//! For more details see
++
++use libc;
++use std::ffi::CStr;
++use std::os::unix::io::AsRawFd;
++
++use errno::Errno;
++use Result;
++
++/// Loads a kernel module from a buffer.
++///
++/// It loads an ELF image into kernel space,
++/// performs any necessary symbol relocations,
++/// initializes module parameters to values provided by the caller,
++/// and then runs the module's init function.
++///
++/// This function requires `CAP_SYS_MODULE` privilege.
++///
++/// The `module_image` argument points to a buffer containing the binary image
++/// to be loaded. The buffer should contain a valid ELF image
++/// built for the running kernel.
++///
++/// The `param_values` argument is a string containing space-delimited specifications
++/// of the values for module parameters.
++/// Each of the parameter specifications has the form:
++///
++/// `name[=value[,value...]]`
++///
++/// # Example
++///
++/// ```no_run
++/// use std::fs::File;
++/// use std::io::Read;
++/// use std::ffi::CString;
++/// use nix::kmod::init_module;
++///
++/// let mut f = File::open("mykernel.ko").unwrap();
++/// let mut contents: Vec<u8> = Vec::new();
++/// f.read_to_end(&mut contents).unwrap();
++/// 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.
++pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
++    let res = unsafe {
++        libc::syscall(
++            libc::SYS_init_module,
++            module_image.as_ptr(),
++            module_image.len(),
++            param_values.as_ptr(),
++        )
++    };
++
++    Errno::result(res).map(drop)
++}
++
++libc_bitflags!(
++    /// Flags used by the `finit_module` function.
++    pub struct ModuleInitFlags: libc::c_uint {
++        /// Ignore symbol version hashes.
++        MODULE_INIT_IGNORE_MODVERSIONS;
++        /// Ignore kernel version magic.
++        MODULE_INIT_IGNORE_VERMAGIC;
++    }
++);
++
++/// Loads a kernel module from a given file descriptor.
++///
++/// # Example
++///
++/// ```no_run
++/// use std::fs::File;
++/// use std::ffi::CString;
++/// use nix::kmod::{finit_module, ModuleInitFlags};
++///
++/// let f = File::open("mymod.ko").unwrap();
++/// 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.
++pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
++    let res = unsafe {
++        libc::syscall(
++            libc::SYS_finit_module,
++            fd.as_raw_fd(),
++            param_values.as_ptr(),
++            flags.bits(),
++        )
++    };
++
++    Errno::result(res).map(drop)
++}
++
++libc_bitflags!(
++    /// Flags used by `delete_module`.
++    ///
++    /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html)
++    /// for a detailed description how these flags work.
++    pub struct DeleteModuleFlags: libc::c_int {
++        O_NONBLOCK;
++        O_TRUNC;
++    }
++);
++
++/// Unloads the kernel module with the given name.
++///
++/// # Example
++///
++/// ```no_run
++/// use std::ffi::CString;
++/// use nix::kmod::{delete_module, DeleteModuleFlags};
++///
++/// 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.
++pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
++    let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
++
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/lib.rs b/third_party/rust/nix-0.15.0/src/lib.rs
+new file mode 100644
+index 0000000000000..71485d2af1824
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/lib.rs
+@@ -0,0 +1,284 @@
++//! Rust friendly bindings to the various *nix system functions.
++//!
++//! Modules are structured according to the C header file that they would be
++//! defined in.
++#![crate_name = "nix"]
++#![cfg(unix)]
++#![allow(non_camel_case_types)]
++// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
++// warnings even though the macro expands into something with allow(dead_code)
++#![allow(dead_code)]
++#![cfg_attr(test, deny(warnings))]
++#![recursion_limit = "500"]
++#![deny(unused)]
++#![deny(unstable_features)]
++#![deny(missing_copy_implementations)]
++#![deny(missing_debug_implementations)]
++// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
++#![allow(deprecated)]
++
++// External crates
++#[macro_use]
++extern crate bitflags;
++#[macro_use]
++extern crate cfg_if;
++extern crate void;
++
++// Re-exported external crates
++pub extern crate libc;
++
++// Private internal modules
++#[macro_use] mod macros;
++
++// Public crates
++pub mod dir;
++pub mod errno;
++#[deny(missing_docs)]
++pub mod features;
++pub mod fcntl;
++#[deny(missing_docs)]
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub mod ifaddrs;
++#[cfg(any(target_os = "android",
++          target_os = "linux"))]
++pub mod kmod;
++#[cfg(any(target_os = "android",
++          target_os = "linux"))]
++pub mod mount;
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "fushsia",
++          target_os = "linux",
++          target_os = "netbsd"))]
++pub mod mqueue;
++#[deny(missing_docs)]
++pub mod net;
++#[deny(missing_docs)]
++pub mod poll;
++#[deny(missing_docs)]
++pub mod pty;
++pub mod sched;
++pub mod sys;
++// This can be implemented for other platforms as soon as libc
++// provides bindings for them.
++#[cfg(all(target_os = "linux",
++          any(target_arch = "x86", target_arch = "x86_64")))]
++pub mod ucontext;
++pub mod unistd;
++
++/*
++ *
++ * ===== Result / Error =====
++ *
++ */
++
++use libc::{c_char, PATH_MAX};
++
++use std::{error, fmt, ptr, result};
++use std::ffi::{CStr, OsStr};
++use std::os::unix::ffi::OsStrExt;
++use std::path::{Path, PathBuf};
++
++use errno::Errno;
++
++/// Nix Result Type
++pub type Result<T> = result::Result<T, Error>;
++
++/// Nix Error Type
++///
++/// The nix error type provides a common way of dealing with
++/// various system system/libc calls that might fail.  Each
++/// error has a corresponding errno (usually the one from the
++/// underlying OS) to which it can be mapped in addition to
++/// implementing other common traits.
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub enum Error {
++    Sys(Errno),
++    InvalidPath,
++    /// The operation involved a conversion to Rust's native String type, which failed because the
++    /// string did not contain all valid UTF-8.
++    InvalidUtf8,
++    /// The operation is not supported by Nix, in this instance either use the libc bindings or
++    /// consult the module documentation to see if there is a more appropriate interface available.
++    UnsupportedOperation,
++}
++
++impl Error {
++    /// Convert this `Error` to an [`Errno`](enum.Errno.html).
++    ///
++    /// # Example
++    ///
++    /// ```
++    /// # use nix::Error;
++    /// # use nix::errno::Errno;
++    /// let e = Error::from(Errno::EPERM);
++    /// assert_eq!(Some(Errno::EPERM), e.as_errno());
++    /// ```
++    pub fn as_errno(&self) -> Option<Errno> {
++        if let &Error::Sys(ref e) = self {
++            Some(*e)
++        } else {
++            None
++        }
++    }
++
++    /// Create a nix Error from a given errno
++    pub fn from_errno(errno: Errno) -> Error {
++        Error::Sys(errno)
++    }
++
++    /// Get the current errno and convert it to a nix Error
++    pub fn last() -> Error {
++        Error::Sys(Errno::last())
++    }
++
++    /// Create a new invalid argument error (`EINVAL`)
++    pub fn invalid_argument() -> Error {
++        Error::Sys(Errno::EINVAL)
++    }
++
++}
++
++impl From<Errno> for Error {
++    fn from(errno: Errno) -> Error { Error::from_errno(errno) }
++}
++
++impl From<std::string::FromUtf8Error> for Error {
++    fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
++}
++
++impl error::Error for Error {
++    fn description(&self) -> &str {
++        match *self {
++            Error::InvalidPath => "Invalid path",
++            Error::InvalidUtf8 => "Invalid UTF-8 string",
++            Error::UnsupportedOperation => "Unsupported Operation",
++            Error::Sys(ref errno) => errno.desc(),
++        }
++    }
++}
++
++impl fmt::Display for Error {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        match *self {
++            Error::InvalidPath => write!(f, "Invalid path"),
++            Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
++            Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
++            Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
++        }
++    }
++}
++
++pub trait NixPath {
++    fn len(&self) -> usize;
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
++        where F: FnOnce(&CStr) -> T;
++}
++
++impl NixPath for str {
++    fn len(&self) -> usize {
++        NixPath::len(OsStr::new(self))
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
++        where F: FnOnce(&CStr) -> T {
++            OsStr::new(self).with_nix_path(f)
++        }
++}
++
++impl NixPath for OsStr {
++    fn len(&self) -> usize {
++        self.as_bytes().len()
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
++        where F: FnOnce(&CStr) -> T {
++            self.as_bytes().with_nix_path(f)
++        }
++}
++
++impl NixPath for CStr {
++    fn len(&self) -> usize {
++        self.to_bytes().len()
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
++            where F: FnOnce(&CStr) -> T {
++        // Equivalence with the [u8] impl.
++        if self.len() >= PATH_MAX as usize {
++            return Err(Error::InvalidPath);
++        }
++
++        Ok(f(self))
++    }
++}
++
++impl NixPath for [u8] {
++    fn len(&self) -> usize {
++        self.len()
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
++            where F: FnOnce(&CStr) -> T {
++        let mut buf = [0u8; PATH_MAX as usize];
++
++        if self.len() >= PATH_MAX as usize {
++            return Err(Error::InvalidPath);
++        }
++
++        match self.iter().position(|b| *b == 0) {
++            Some(_) => Err(Error::InvalidPath),
++            None => {
++                unsafe {
++                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
++                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
++                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
++                }
++
++            }
++        }
++    }
++}
++
++impl NixPath for Path {
++    fn len(&self) -> usize {
++        NixPath::len(self.as_os_str())
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
++        self.as_os_str().with_nix_path(f)
++    }
++}
++
++impl NixPath for PathBuf {
++    fn len(&self) -> usize {
++        NixPath::len(self.as_os_str())
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
++        self.as_os_str().with_nix_path(f)
++    }
++}
++
++/// Treats `None` as an empty string.
++impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
++    fn len(&self) -> usize {
++        self.map_or(0, NixPath::len)
++    }
++
++    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
++        if let Some(nix_path) = *self {
++            nix_path.with_nix_path(f)
++        } else {
++            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/macros.rs b/third_party/rust/nix-0.15.0/src/macros.rs
+new file mode 100644
+index 0000000000000..3d1b0e4b7699c
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/macros.rs
+@@ -0,0 +1,264 @@
++/// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type
++/// with values from the libc crate. It is used the same way as the `bitflags!` macro, except
++/// that only the name of the flag value has to be given.
++///
++/// The `libc` crate must be in scope with the name `libc`.
++///
++/// # Example
++/// ```
++/// libc_bitflags!{
++///     pub struct ProtFlags: libc::c_int {
++///         PROT_NONE;
++///         PROT_READ;
++///         /// PROT_WRITE enables write protect
++///         PROT_WRITE;
++///         PROT_EXEC;
++///         #[cfg(any(target_os = "linux", target_os = "android"))]
++///         PROT_GROWSDOWN;
++///         #[cfg(any(target_os = "linux", target_os = "android"))]
++///         PROT_GROWSUP;
++///     }
++/// }
++/// ```
++///
++/// Example with casting, due to a mistake in libc. In this example, the
++/// various flags have different types, so we cast the broken ones to the right
++/// type.
++///
++/// ```
++/// libc_bitflags!{
++///     pub struct SaFlags: libc::c_ulong {
++///         SA_NOCLDSTOP as libc::c_ulong;
++///         SA_NOCLDWAIT;
++///         SA_NODEFER as libc::c_ulong;
++///         SA_ONSTACK;
++///         SA_RESETHAND as libc::c_ulong;
++///         SA_RESTART as libc::c_ulong;
++///         SA_SIGINFO;
++///     }
++/// }
++/// ```
++macro_rules! libc_bitflags {
++    (
++        $(#[$outer:meta])*
++        pub struct $BitFlags:ident: $T:ty {
++            $(
++                $(#[$inner:ident $($args:tt)*])*
++                $Flag:ident $(as $cast:ty)*;
++            )+
++        }
++    ) => {
++        bitflags! {
++            $(#[$outer])*
++            pub struct $BitFlags: $T {
++                $(
++                    $(#[$inner $($args)*])*
++                    const $Flag = libc::$Flag $(as $cast)*;
++                )+
++            }
++        }
++    };
++}
++
++/// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using
++/// values from the `libc` crate. This macro supports both `pub` and private `enum`s.
++///
++/// The `libc` crate must be in scope with the name `libc`.
++///
++/// # Example
++/// ```
++/// libc_enum!{
++///     pub enum ProtFlags {
++///         PROT_NONE,
++///         PROT_READ,
++///         PROT_WRITE,
++///         PROT_EXEC,
++///         #[cfg(any(target_os = "linux", target_os = "android"))]
++///         PROT_GROWSDOWN,
++///         #[cfg(any(target_os = "linux", target_os = "android"))]
++///         PROT_GROWSUP,
++///     }
++/// }
++/// ```
++macro_rules! libc_enum {
++    // (non-pub) Exit rule.
++    (@make_enum
++        {
++            name: $BitFlags:ident,
++            attrs: [$($attrs:tt)*],
++            entries: [$($entries:tt)*],
++        }
++    ) => {
++        $($attrs)*
++        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
++        enum $BitFlags {
++            $($entries)*
++        }
++    };
++
++    // (pub) Exit rule.
++    (@make_enum
++        {
++            pub,
++            name: $BitFlags:ident,
++            attrs: [$($attrs:tt)*],
++            entries: [$($entries:tt)*],
++        }
++    ) => {
++        $($attrs)*
++        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
++        pub enum $BitFlags {
++            $($entries)*
++        }
++    };
++
++    // (non-pub) Done accumulating.
++    (@accumulate_entries
++        {
++            name: $BitFlags:ident,
++            attrs: $attrs:tt,
++        },
++        $entries:tt;
++    ) => {
++        libc_enum! {
++            @make_enum
++            {
++                name: $BitFlags,
++                attrs: $attrs,
++                entries: $entries,
++            }
++        }
++    };
++
++    // (pub) Done accumulating.
++    (@accumulate_entries
++        {
++            pub,
++            name: $BitFlags:ident,
++            attrs: $attrs:tt,
++        },
++        $entries:tt;
++    ) => {
++        libc_enum! {
++            @make_enum
++            {
++                pub,
++                name: $BitFlags,
++                attrs: $attrs,
++                entries: $entries,
++            }
++        }
++    };
++
++    // Munch an attr.
++    (@accumulate_entries
++        $prefix:tt,
++        [$($entries:tt)*];
++        #[$attr:meta] $($tail:tt)*
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            $prefix,
++            [
++                $($entries)*
++                #[$attr]
++            ];
++            $($tail)*
++        }
++    };
++
++    // Munch last ident if not followed by a comma.
++    (@accumulate_entries
++        $prefix:tt,
++        [$($entries:tt)*];
++        $entry:ident
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            $prefix,
++            [
++                $($entries)*
++                $entry = libc::$entry,
++            ];
++        }
++    };
++
++    // Munch an ident; covers terminating comma case.
++    (@accumulate_entries
++        $prefix:tt,
++        [$($entries:tt)*];
++        $entry:ident, $($tail:tt)*
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            $prefix,
++            [
++                $($entries)*
++                $entry = libc::$entry,
++            ];
++            $($tail)*
++        }
++    };
++
++    // Munch an ident and cast it to the given type; covers terminating comma.
++    (@accumulate_entries
++        $prefix:tt,
++        [$($entries:tt)*];
++        $entry:ident as $ty:ty, $($tail:tt)*
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            $prefix,
++            [
++                $($entries)*
++                $entry = libc::$entry as $ty,
++            ];
++            $($tail)*
++        }
++    };
++
++    // (non-pub) Entry rule.
++    (
++        $(#[$attr:meta])*
++        enum $BitFlags:ident {
++            $($vals:tt)*
++        }
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            {
++                name: $BitFlags,
++                attrs: [$(#[$attr])*],
++            },
++            [];
++            $($vals)*
++        }
++    };
++
++    // (pub) Entry rule.
++    (
++        $(#[$attr:meta])*
++        pub enum $BitFlags:ident {
++            $($vals:tt)*
++        }
++    ) => {
++        libc_enum! {
++            @accumulate_entries
++            {
++                pub,
++                name: $BitFlags,
++                attrs: [$(#[$attr])*],
++            },
++            [];
++            $($vals)*
++        }
++    };
++}
++
++/// A Rust version of the familiar C `offset_of` macro.  It returns the byte
++/// offset of `field` within struct `ty`
++macro_rules! offset_of {
++    ($ty:ty, $field:ident) => {
++        &(*(0 as *const $ty)).$field as *const _ as usize
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/mount.rs b/third_party/rust/nix-0.15.0/src/mount.rs
+new file mode 100644
+index 0000000000000..a9902b170ace8
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/mount.rs
+@@ -0,0 +1,98 @@
++use libc::{self, c_ulong, c_int};
++use {Result, NixPath};
++use errno::Errno;
++
++libc_bitflags!(
++    pub struct MsFlags: c_ulong {
++        /// Mount read-only
++        MS_RDONLY;
++        /// Ignore suid and sgid bits
++        MS_NOSUID;
++        /// Disallow access to device special files
++        MS_NODEV;
++        /// Disallow program execution
++        MS_NOEXEC;
++        /// Writes are synced at once
++        MS_SYNCHRONOUS;
++        /// Alter flags of a mounted FS
++        MS_REMOUNT;
++        /// Allow mandatory locks on a FS
++        MS_MANDLOCK;
++        /// Directory modifications are synchronous
++        MS_DIRSYNC;
++        /// Do not update access times
++        MS_NOATIME;
++        /// Do not update directory access times
++        MS_NODIRATIME;
++        /// Linux 2.4.0 - Bind directory at different place
++        MS_BIND;
++        MS_MOVE;
++        MS_REC;
++        MS_SILENT;
++        MS_POSIXACL;
++        MS_UNBINDABLE;
++        MS_PRIVATE;
++        MS_SLAVE;
++        MS_SHARED;
++        MS_RELATIME;
++        MS_KERNMOUNT;
++        MS_I_VERSION;
++        MS_STRICTATIME;
++        MS_ACTIVE;
++        MS_NOUSER;
++        MS_RMT_MASK;
++        MS_MGC_VAL;
++        MS_MGC_MSK;
++    }
++);
++
++libc_bitflags!(
++    pub struct MntFlags: c_int {
++        MNT_FORCE;
++        MNT_DETACH;
++        MNT_EXPIRE;
++    }
++);
++
++pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
++        source: Option<&P1>,
++        target: &P2,
++        fstype: Option<&P3>,
++        flags: MsFlags,
++        data: Option<&P4>) -> Result<()> {
++
++    let res =
++        source.with_nix_path(|source| {
++            target.with_nix_path(|target| {
++                fstype.with_nix_path(|fstype| {
++                    data.with_nix_path(|data| {
++                        unsafe {
++                            libc::mount(source.as_ptr(),
++                                       target.as_ptr(),
++                                       fstype.as_ptr(),
++                                       flags.bits,
++                                       data.as_ptr() as *const libc::c_void)
++                        }
++                    })
++                })
++            })
++        })????;
++
++    Errno::result(res).map(drop)
++}
++
++pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
++    let res = target.with_nix_path(|cstr| {
++        unsafe { libc::umount(cstr.as_ptr()) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
++    let res = target.with_nix_path(|cstr| {
++        unsafe { libc::umount2(cstr.as_ptr(), flags.bits) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/mqueue.rs b/third_party/rust/nix-0.15.0/src/mqueue.rs
+new file mode 100644
+index 0000000000000..b958b71cddb46
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/mqueue.rs
+@@ -0,0 +1,162 @@
++//! Posix Message Queue functions
++//!
++//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
++
++use Result;
++use errno::Errno;
++
++use libc::{self, c_char, c_long, mqd_t, size_t};
++use std::ffi::CString;
++use sys::stat::Mode;
++use std::mem;
++
++libc_bitflags!{
++    pub struct MQ_OFlag: libc::c_int {
++        O_RDONLY;
++        O_WRONLY;
++        O_RDWR;
++        O_CREAT;
++        O_EXCL;
++        O_NONBLOCK;
++        O_CLOEXEC;
++    }
++}
++
++libc_bitflags!{
++    pub struct FdFlag: libc::c_int {
++        FD_CLOEXEC;
++    }
++}
++
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct MqAttr {
++    mq_attr: libc::mq_attr,
++}
++
++impl MqAttr {
++    pub fn new(mq_flags: c_long,
++               mq_maxmsg: c_long,
++               mq_msgsize: c_long,
++               mq_curmsgs: c_long)
++               -> MqAttr {
++        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
++        attr.mq_flags = mq_flags;
++        attr.mq_maxmsg = mq_maxmsg;
++        attr.mq_msgsize = mq_msgsize;
++        attr.mq_curmsgs = mq_curmsgs;
++        MqAttr { mq_attr: attr }
++    }
++
++    pub fn flags(&self) -> c_long {
++        self.mq_attr.mq_flags
++    }
++}
++
++
++/// Open a message queue
++///
++/// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
++pub fn mq_open(name: &CString,
++               oflag: MQ_OFlag,
++               mode: Mode,
++               attr: Option<&MqAttr>)
++               -> Result<mqd_t> {
++    let res = match attr {
++        Some(mq_attr) => unsafe {
++            libc::mq_open(name.as_ptr(),
++                          oflag.bits(),
++                          mode.bits() as libc::c_int,
++                          &mq_attr.mq_attr as *const libc::mq_attr)
++        },
++        None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
++    };
++    Errno::result(res)
++}
++
++/// Remove a message queue
++///
++/// See also [`mq_unlink(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
++pub fn mq_unlink(name: &CString) -> Result<()> {
++    let res = unsafe { libc::mq_unlink(name.as_ptr()) };
++    Errno::result(res).map(drop)
++}
++
++/// Close a message queue
++///
++/// See also [`mq_close(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
++pub fn mq_close(mqdes: mqd_t) -> Result<()> {
++    let res = unsafe { libc::mq_close(mqdes) };
++    Errno::result(res).map(drop)
++}
++
++/// Receive a message from a message queue
++///
++/// See also [`mq_receive(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
++pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
++    let len = message.len() as size_t;
++    let res = unsafe {
++        libc::mq_receive(mqdes,
++                         message.as_mut_ptr() as *mut c_char,
++                         len,
++                         msg_prio as *mut u32)
++    };
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Send a message to a message queue
++///
++/// See also [`mq_send(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
++pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
++    let res = unsafe {
++        libc::mq_send(mqdes,
++                      message.as_ptr() as *const c_char,
++                      message.len(),
++                      msq_prio)
++    };
++    Errno::result(res).map(drop)
++}
++
++/// Get message queue attributes
++///
++/// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
++pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
++    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
++    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
++    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
++}
++
++/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
++/// 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)
++pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
++    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
++    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
++    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
++}
++
++/// Convenience function.
++/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
++/// Returns the old attributes
++pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
++    let oldattr = mq_getattr(mqd)?;
++    let newattr = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long,
++                              oldattr.mq_attr.mq_maxmsg,
++                              oldattr.mq_attr.mq_msgsize,
++                              oldattr.mq_attr.mq_curmsgs);
++    mq_setattr(mqd, &newattr)
++}
++
++/// Convenience function.
++/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
++/// Returns the old attributes
++pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
++    let oldattr = mq_getattr(mqd)?;
++    let newattr = MqAttr::new(0,
++                              oldattr.mq_attr.mq_maxmsg,
++                              oldattr.mq_attr.mq_msgsize,
++                              oldattr.mq_attr.mq_curmsgs);
++    mq_setattr(mqd, &newattr)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/net/if_.rs b/third_party/rust/nix-0.15.0/src/net/if_.rs
+new file mode 100644
+index 0000000000000..58d677ae343d1
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/net/if_.rs
+@@ -0,0 +1,268 @@
++//! Network interface name resolution.
++//!
++//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
++//! or "socan1" into device numbers.
++
++use libc;
++use libc::c_uint;
++use {Result, Error, NixPath};
++
++/// Resolve an interface into a interface number.
++pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
++    let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
++
++    if if_index == 0 {
++        Err(Error::last())
++    } else {
++        Ok(if_index)
++    }
++}
++
++libc_bitflags!(
++    /// 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))
++        IFF_UP;
++        /// Valid broadcast address set. (see
++        /// [`netdevice(7)`](http://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))
++        IFF_DEBUG;
++        /// Interface is a loopback interface. (see
++        /// [`netdevice(7)`](http://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))
++        IFF_POINTOPOINT;
++        /// Avoid use of trailers. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        #[cfg(any(target_os = "android",
++                  target_os = "fuchsia",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "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))
++        #[cfg(any(target_os = "android",
++                  target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "fuchsia",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  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))
++        IFF_NOARP;
++        /// Interface is in promiscuous mode. (see
++        /// [`netdevice(7)`](http://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))
++        IFF_ALLMULTI;
++        /// Master of a load balancing bundle. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_MASTER;
++        /// transmission in progress, tx hardware queue is full
++        #[cfg(any(target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  target_os = "ios"))]
++        IFF_OACTIVE;
++        /// Protocol code on board.
++        #[cfg(target_os = "solaris")]
++        IFF_INTELLIGENT;
++        /// Slave of a load balancing bundle. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_SLAVE;
++        /// Can't hear own transmissions.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  target_os = "osx"))]
++        IFF_SIMPLEX;
++        /// Supports multicast. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        IFF_MULTICAST;
++        /// Per link layer defined bit.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  target_os = "ios"))]
++        IFF_LINK0;
++        /// Multicast using broadcast.
++        #[cfg(any(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))
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_PORTSEL;
++        /// Per link layer defined bit.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  target_os = "ios"))]
++        IFF_LINK1;
++        /// Non-unique address.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_UNNUMBERED;
++        /// Auto media selection active. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_AUTOMEDIA;
++        /// Per link layer defined bit.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd",
++                  target_os = "ios"))]
++        IFF_LINK2;
++        /// Use alternate physical connection.
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "ios"))]
++        IFF_ALTPHYS;
++        /// DHCP controlls interface.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_DHCPRUNNING;
++        /// The addresses are lost when the interface goes down. (see
++        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_DYNAMIC;
++        /// Do not advertise.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_PRIVATE;
++        /// Driver signals L1 up. Volatile.
++        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
++        IFF_LOWER_UP;
++        /// Interface is in polling mode.
++        #[cfg(any(target_os = "dragonfly"))]
++        IFF_POLLING_COMPAT;
++        /// Unconfigurable using ioctl(2).
++        #[cfg(any(target_os = "freebsd"))]
++        IFF_CANTCONFIG;
++        /// Do not transmit packets.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_NOXMIT;
++        /// Driver signals dormant. Volatile.
++        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
++        IFF_DORMANT;
++        /// User-requested promisc mode.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        IFF_PPROMISC;
++        /// Just on-link subnet.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_NOLOCAL;
++        /// Echo sent packets. Volatile.
++        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
++        IFF_ECHO;
++        /// User-requested monitor mode.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        IFF_MONITOR;
++        /// Address is deprecated.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_DEPRECATED;
++        /// Static ARP.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        IFF_STATICARP;
++        /// Address from stateless addrconf.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_ADDRCONF;
++        /// Interface is in polling mode.
++        #[cfg(any(target_os = "dragonfly"))]
++        IFF_NPOLLING;
++        /// Router on interface.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_ROUTER;
++        /// Interface is in polling mode.
++        #[cfg(any(target_os = "dragonfly"))]
++        IFF_IDIRECT;
++        /// Interface is winding down
++        #[cfg(any(target_os = "freebsd"))]
++        IFF_DYING;
++        /// No NUD on interface.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_NONUD;
++        /// Interface is being renamed
++        #[cfg(any(target_os = "freebsd"))]
++        IFF_RENAMING;
++        /// Anycast address.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_ANYCAST;
++        /// Don't exchange routing info.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_NORTEXCH;
++        /// Do not provide packet information
++        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
++        IFF_NO_PI as libc::c_int;
++        /// TUN device (no Ethernet headers) 
++        #[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"))]
++        IFF_IPV4;
++        /// IPv6 interface.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_IPV6;
++        /// in.mpathd test address
++        #[cfg(any(target_os = "solaris"))]
++        IFF_NOFAILOVER;
++        /// Interface has failed
++        #[cfg(any(target_os = "solaris"))]
++        IFF_FAILED;
++        /// Interface is a hot-spare
++        #[cfg(any(target_os = "solaris"))]
++        IFF_STANDBY;
++        /// Functioning but not used
++        #[cfg(any(target_os = "solaris"))]
++        IFF_INACTIVE;
++        /// Interface is offline
++        #[cfg(any(target_os = "solaris"))]
++        IFF_OFFLINE;
++        #[cfg(any(target_os = "solaris"))]
++        IFF_COS_ENABLED;
++        /// Prefer as source addr.
++        #[cfg(any(target_os = "solaris"))]
++        IFF_PREFERRED;
++        /// RFC3041
++        #[cfg(any(target_os = "solaris"))]
++        IFF_TEMPORARY;
++        /// MTU set with SIOCSLIFMTU
++        #[cfg(any(target_os = "solaris"))]
++        IFF_FIXEDMTU;
++        /// Cannot send / receive packets
++        #[cfg(any(target_os = "solaris"))]
++        IFF_VIRTUAL;
++        /// Local address in use
++        #[cfg(any(target_os = "solaris"))]
++        IFF_DUPLICATE;
++        /// IPMP IP interface
++        #[cfg(any(target_os = "solaris"))]
++        IFF_IPMP;
++    }
++);
+diff --git a/third_party/rust/nix-0.15.0/src/net/mod.rs b/third_party/rust/nix-0.15.0/src/net/mod.rs
+new file mode 100644
+index 0000000000000..079fcfde6fd44
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/net/mod.rs
+@@ -0,0 +1,4 @@
++//! Functionality involving network interfaces
++// To avoid clashing with the keyword "if", we use "if_" as the module name.
++// The original header is called "net/if.h".
++pub mod if_;
+diff --git a/third_party/rust/nix-0.15.0/src/poll.rs b/third_party/rust/nix-0.15.0/src/poll.rs
+new file mode 100644
+index 0000000000000..c603611e3176f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/poll.rs
+@@ -0,0 +1,143 @@
++//! Wait for events to trigger on specific file descriptors
++#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
++use sys::time::TimeSpec;
++#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
++use sys::signal::SigSet;
++use std::os::unix::io::RawFd;
++
++use libc;
++use Result;
++use errno::Errno;
++
++/// This is a wrapper around `libc::pollfd`.
++///
++/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
++/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest
++/// for a specific file descriptor.
++///
++/// After a call to `poll` or `ppoll`, the events that occured can be
++/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct PollFd {
++    pollfd: libc::pollfd,
++}
++
++impl PollFd {
++    /// Creates a new `PollFd` specifying the events of interest
++    /// for a given file descriptor.
++    pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
++        PollFd {
++            pollfd: libc::pollfd {
++                fd: fd,
++                events: events.bits(),
++                revents: PollFlags::empty().bits(),
++            },
++        }
++    }
++
++    /// Returns the events that occured in the last call to `poll` or `ppoll`.
++    pub fn revents(&self) -> Option<PollFlags> {
++        PollFlags::from_bits(self.pollfd.revents)
++    }
++}
++
++libc_bitflags! {
++    /// These flags define the different events that can be monitored by `poll` and `ppoll`
++    pub struct PollFlags: libc::c_short {
++        /// There is data to read.
++        POLLIN;
++        /// There is some exceptional condition on the file descriptor.
++        ///
++        /// 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)).
++        /// *  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)).
++        /// *  A cgroup.events file has been modified (see
++        ///    [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
++        POLLPRI;
++        /// Writing is now possible, though a write larger that the
++        /// available space in a socket or pipe will still block (unless
++        /// `O_NONBLOCK` is set).
++        POLLOUT;
++        /// Equivalent to [`POLLIN`](constant.POLLIN.html)
++        POLLRDNORM;
++        /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
++        POLLWRNORM;
++        /// Priority band data can be read (generally unused on Linux).
++        POLLRDBAND;
++        /// Priority data may be written.
++        POLLWRBAND;
++        /// Error condition (only returned in
++        /// [`PollFd::revents`](struct.PollFd.html#method.revents);
++        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
++        /// This bit is also set for a file descriptor referring to the
++        /// write end of a pipe when the read end has been closed.
++        POLLERR;
++        /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents);
++        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
++        /// Note that when reading from a channel such as a pipe or a stream
++        /// socket, this event merely indicates that the peer closed its
++        /// end of the channel.  Subsequent reads from the channel will
++        /// return 0 (end of file) only after all outstanding data in the
++        /// channel has been consumed.
++        POLLHUP;
++        /// Invalid request: `fd` not open (only returned in
++        /// [`PollFd::revents`](struct.PollFd.html#method.revents);
++        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
++        POLLNVAL;
++    }
++}
++
++/// `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))
++///
++/// `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.
++///
++/// The `timeout` argument specifies the number of milliseconds that `poll()`
++/// should block waiting for a file descriptor to become ready.  The call
++/// will block until either:
++///
++/// *  a file descriptor becomes ready;
++/// *  the call is interrupted by a signal handler; or
++/// *  the timeout expires.
++///
++/// Note that the timeout interval will be rounded up to the system clock
++/// granularity, and kernel scheduling delays mean that the blocking
++/// interval may overrun by a small amount.  Specifying a negative value
++/// in timeout means an infinite timeout.  Specifying a timeout of zero
++/// causes `poll()` to return immediately, even if no file descriptors are
++/// ready.
++pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
++    let res = unsafe {
++        libc::poll(fds.as_mut_ptr() as *mut libc::pollfd,
++                   fds.len() as libc::nfds_t,
++                   timeout)
++    };
++
++    Errno::result(res)
++}
++
++/// `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))
++///
++/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
++/// with the `sigmask` argument.
++///
++#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
++pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> {
++
++
++    let res = unsafe {
++        libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
++                    fds.len() as libc::nfds_t,
++                    timeout.as_ref(),
++                    sigmask.as_ref())
++    };
++    Errno::result(res)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/pty.rs b/third_party/rust/nix-0.15.0/src/pty.rs
+new file mode 100644
+index 0000000000000..db012d8158c53
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/pty.rs
+@@ -0,0 +1,326 @@
++//! Create master and slave virtual pseudo-terminals (PTYs)
++
++use libc;
++
++pub use libc::pid_t as SessionId;
++pub use libc::winsize as Winsize;
++
++use std::ffi::CStr;
++use std::mem;
++use std::os::unix::prelude::*;
++
++use sys::termios::Termios;
++use unistd::ForkResult;
++use {Result, Error, fcntl};
++use errno::Errno;
++
++/// Representation of a master/slave pty pair
++///
++/// This is returned by `openpty`.  Note that this type does *not* implement `Drop`, so the user
++/// must manually close the file descriptors.
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct OpenptyResult {
++    /// The master port in a virtual pty pair
++    pub master: RawFd,
++    /// The slave port in a virtual pty pair
++    pub slave: RawFd,
++}
++
++/// Representation of a master with a forked pty
++///
++/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
++/// must manually close the file descriptors.
++#[derive(Clone, Copy, Debug)]
++pub struct ForkptyResult {
++    /// The master port in a virtual pty pair
++    pub master: RawFd,
++    /// Metadata about forked process
++    pub fork_result: ForkResult,
++}
++
++
++/// Representation of the Master device in a master/slave pty pair
++///
++/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
++/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
++/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
++#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++pub struct PtyMaster(RawFd);
++
++impl AsRawFd for PtyMaster {
++    fn as_raw_fd(&self) -> RawFd {
++        self.0
++    }
++}
++
++impl IntoRawFd for PtyMaster {
++    fn into_raw_fd(self) -> RawFd {
++        let fd = self.0;
++        mem::forget(self);
++        fd
++    }
++}
++
++impl Drop for PtyMaster {
++    fn drop(&mut self) {
++        // On drop, we ignore errors like EINTR and EIO because there's no clear
++        // way to handle them, we can't return anything, and (on FreeBSD at
++        // least) the file descriptor is deallocated in these cases.  However,
++        // we must panic on EBADF, because it is always an error to close an
++        // invalid file descriptor.  That frequently indicates a double-close
++        // condition, which can cause confusing errors for future I/O
++        // operations.
++        let e = ::unistd::close(self.0);
++        if e == Err(Error::Sys(Errno::EBADF)) {
++            panic!("Closing an invalid file descriptor!");
++        };
++    }
++}
++
++/// Grant access to a slave pseudoterminal (see
++/// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
++///
++/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
++/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
++#[inline]
++pub fn grantpt(fd: &PtyMaster) -> Result<()> {
++    if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
++        return Err(Error::last());
++    }
++
++    Ok(())
++}
++
++/// Open a pseudoterminal device (see
++/// [`posix_openpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
++///
++/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
++///
++/// # Examples
++///
++/// A common use case with this function is to open both a master and slave PTY pair. This can be
++/// done as follows:
++///
++/// ```
++/// use std::path::Path;
++/// use nix::fcntl::{OFlag, open};
++/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt};
++/// use nix::sys::stat::Mode;
++///
++/// # #[allow(dead_code)]
++/// # fn run() -> nix::Result<()> {
++/// // Open a new PTY master
++/// let master_fd = posix_openpt(OFlag::O_RDWR)?;
++///
++/// // Allow a slave to be generated for it
++/// grantpt(&master_fd)?;
++/// unlockpt(&master_fd)?;
++///
++/// // Get the name of the slave
++/// let slave_name = unsafe { ptsname(&master_fd) }?;
++///
++/// // Try to open the slave
++/// let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
++/// # Ok(())
++/// # }
++/// ```
++#[inline]
++pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
++    let fd = unsafe {
++        libc::posix_openpt(flags.bits())
++    };
++
++    if fd < 0 {
++        return Err(Error::last());
++    }
++
++    Ok(PtyMaster(fd))
++}
++
++/// Get the name of the slave pseudoterminal (see
++/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
++///
++/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
++/// referred to by `fd`.
++///
++/// This value is useful for opening the slave pty once the master has already been opened with
++/// `posix_openpt()`.
++///
++/// # Safety
++///
++/// `ptsname()` mutates global variables and is *not* threadsafe.
++/// Mutating global variables is always considered `unsafe` by Rust and this
++/// function is marked as `unsafe` to reflect that.
++///
++/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
++#[inline]
++pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
++    let name_ptr = libc::ptsname(fd.as_raw_fd());
++    if name_ptr.is_null() {
++        return Err(Error::last());
++    }
++
++    let name = CStr::from_ptr(name_ptr);
++    Ok(name.to_string_lossy().into_owned())
++}
++
++/// Get the name of the slave pseudoterminal (see
++/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
++///
++/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
++/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
++/// POSIX standard and is instead a Linux-specific extension.
++///
++/// This value is useful for opening the slave ptty once the master has already been opened with
++/// `posix_openpt()`.
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[inline]
++pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
++    let mut name_buf = vec![0u8; 64];
++    let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
++    if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
++        return Err(Error::last());
++    }
++
++    // Find the first null-character terminating this string. This is guaranteed to succeed if the
++    // return value of `libc::ptsname_r` is 0.
++    let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
++    name_buf.truncate(null_index);
++
++    let name = String::from_utf8(name_buf)?;
++    Ok(name)
++}
++
++/// Unlock a pseudoterminal master/slave pseudoterminal pair (see
++/// [`unlockpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
++///
++/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
++/// referred to by `fd`. This must be called before trying to open the slave side of a
++/// pseuoterminal.
++#[inline]
++pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
++    if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
++        return Err(Error::last());
++    }
++
++    Ok(())
++}
++
++
++/// 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)).
++///
++/// 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`.
++#[inline]
++pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
++    use std::ptr;
++
++    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
++    let mut master: libc::c_int = unsafe { mem::uninitialized() };
++    let ret = {
++        match (termios.into(), winsize.into()) {
++            (Some(termios), Some(winsize)) => {
++                let inner_termios = termios.get_libc_termios();
++                unsafe {
++                    libc::openpty(
++                        &mut master,
++                        &mut slave,
++                        ptr::null_mut(),
++                        &*inner_termios as *const libc::termios as *mut _,
++                        winsize as *const Winsize as *mut _,
++                    )
++                }
++            }
++            (None, Some(winsize)) => {
++                unsafe {
++                    libc::openpty(
++                        &mut master,
++                        &mut slave,
++                        ptr::null_mut(),
++                        ptr::null_mut(),
++                        winsize as *const Winsize as *mut _,
++                    )
++                }
++            }
++            (Some(termios), None) => {
++                let inner_termios = termios.get_libc_termios();
++                unsafe {
++                    libc::openpty(
++                        &mut master,
++                        &mut slave,
++                        ptr::null_mut(),
++                        &*inner_termios as *const libc::termios as *mut _,
++                        ptr::null_mut(),
++                    )
++                }
++            }
++            (None, None) => {
++                unsafe {
++                    libc::openpty(
++                        &mut master,
++                        &mut slave,
++                        ptr::null_mut(),
++                        ptr::null_mut(),
++                        ptr::null_mut(),
++                    )
++                }
++            }
++        }
++    };
++
++    Errno::result(ret)?;
++
++    Ok(OpenptyResult {
++        master: master,
++        slave: slave,
++    })
++}
++
++/// 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)).
++///
++/// 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>>>(
++    winsize: T,
++    termios: U,
++) -> Result<ForkptyResult> {
++    use std::ptr;
++    use unistd::Pid;
++    use unistd::ForkResult::*;
++
++    let mut master: libc::c_int = unsafe { mem::uninitialized() };
++
++    let term = match termios.into() {
++        Some(termios) => {
++            let inner_termios = termios.get_libc_termios();
++            &*inner_termios as *const libc::termios as *mut _
++        },
++        None => ptr::null_mut(),
++    };
++
++    let win = winsize
++        .into()
++        .map(|ws| ws as *const Winsize as *mut _)
++        .unwrap_or(ptr::null_mut());
++
++    let res = unsafe {
++        libc::forkpty(&mut master, ptr::null_mut(), term, win)
++    };
++
++    let fork_result = Errno::result(res).map(|res| match res {
++        0 => Child,
++        res => Parent { child: Pid::from_raw(res) },
++    })?;
++
++    Ok(ForkptyResult {
++        master: master,
++        fork_result: fork_result,
++    })
++}
++
+diff --git a/third_party/rust/nix-0.15.0/src/sched.rs b/third_party/rust/nix-0.15.0/src/sched.rs
+new file mode 100644
+index 0000000000000..67188c57eef7d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sched.rs
+@@ -0,0 +1,147 @@
++use libc;
++use {Errno, Result};
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use self::sched_linux_like::*;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod sched_linux_like {
++    use errno::Errno;
++    use libc::{self, c_int, c_void};
++    use std::mem;
++    use std::option::Option;
++    use std::os::unix::io::RawFd;
++    use unistd::Pid;
++    use {Error, Result};
++
++    // For some functions taking with a parameter of type CloneFlags,
++    // only a subset of these flags have an effect.
++    libc_bitflags! {
++        pub struct CloneFlags: c_int {
++            CLONE_VM;
++            CLONE_FS;
++            CLONE_FILES;
++            CLONE_SIGHAND;
++            CLONE_PTRACE;
++            CLONE_VFORK;
++            CLONE_PARENT;
++            CLONE_THREAD;
++            CLONE_NEWNS;
++            CLONE_SYSVSEM;
++            CLONE_SETTLS;
++            CLONE_PARENT_SETTID;
++            CLONE_CHILD_CLEARTID;
++            CLONE_DETACHED;
++            CLONE_UNTRACED;
++            CLONE_CHILD_SETTID;
++            CLONE_NEWCGROUP;
++            CLONE_NEWUTS;
++            CLONE_NEWIPC;
++            CLONE_NEWUSER;
++            CLONE_NEWPID;
++            CLONE_NEWNET;
++            CLONE_IO;
++        }
++    }
++
++    pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
++
++    #[repr(C)]
++    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++    pub struct CpuSet {
++        cpu_set: libc::cpu_set_t,
++    }
++
++    impl CpuSet {
++        pub fn new() -> CpuSet {
++            CpuSet {
++                cpu_set: unsafe { mem::zeroed() },
++            }
++        }
++
++        pub fn is_set(&self, field: usize) -> Result<bool> {
++            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++                Err(Error::Sys(Errno::EINVAL))
++            } else {
++                Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
++            }
++        }
++
++        pub fn set(&mut self, field: usize) -> Result<()> {
++            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++                Err(Error::Sys(Errno::EINVAL))
++            } else {
++                Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
++            }
++        }
++
++        pub fn unset(&mut self, field: usize) -> Result<()> {
++            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++                Err(Error::Sys(Errno::EINVAL))
++            } else {
++                Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
++            }
++        }
++    }
++
++    pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
++        let res = unsafe {
++            libc::sched_setaffinity(
++                pid.into(),
++                mem::size_of::<CpuSet>() as libc::size_t,
++                &cpuset.cpu_set,
++            )
++        };
++
++        Errno::result(res).map(drop)
++    }
++
++    pub fn clone(
++        mut cb: CloneCb,
++        stack: &mut [u8],
++        flags: CloneFlags,
++        signal: Option<c_int>,
++    ) -> Result<Pid> {
++        extern "C" fn callback(data: *mut CloneCb) -> c_int {
++            let cb: &mut CloneCb = unsafe { &mut *data };
++            (*cb)() as c_int
++        }
++
++        let res = unsafe {
++            let combined = flags.bits() | signal.unwrap_or(0);
++            let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
++            let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
++            libc::clone(
++                mem::transmute(
++                    callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
++                ),
++                ptr_aligned as *mut c_void,
++                combined,
++                &mut cb as *mut _ as *mut c_void,
++            )
++        };
++
++        Errno::result(res).map(Pid::from_raw)
++    }
++
++    pub fn unshare(flags: CloneFlags) -> Result<()> {
++        let res = unsafe { libc::unshare(flags.bits()) };
++
++        Errno::result(res).map(drop)
++    }
++
++    pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
++        let res = unsafe { libc::setns(fd, nstype.bits()) };
++
++        Errno::result(res).map(drop)
++    }
++}
++
++/// Explicitly yield the processor to other threads.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
++pub fn sched_yield() -> Result<()> {
++    let res = unsafe { libc::sched_yield() };
++
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/aio.rs b/third_party/rust/nix-0.15.0/src/sys/aio.rs
+new file mode 100644
+index 0000000000000..9258a0657cc8a
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/aio.rs
+@@ -0,0 +1,1280 @@
++// vim: tw=80
++//! POSIX Asynchronous I/O
++//!
++//! The POSIX AIO interface is used for asynchronous I/O on files and disk-like
++//! devices.  It supports [`read`](struct.AioCb.html#method.read),
++//! [`write`](struct.AioCb.html#method.write), and
++//! [`fsync`](struct.AioCb.html#method.fsync) operations.  Completion
++//! notifications can optionally be delivered via
++//! [signals](../signal/enum.SigevNotify.html#variant.SigevSignal), via the
++//! [`aio_suspend`](fn.aio_suspend.html) function, or via polling.  Some
++//! platforms support other completion
++//! notifications, such as
++//! [kevent](../signal/enum.SigevNotify.html#variant.SigevKevent).
++//!
++//! Multiple operations may be submitted in a batch with
++//! [`lio_listio`](fn.lio_listio.html), though the standard does not guarantee
++//! that they will be executed atomically.
++//!
++//! Outstanding operations may be cancelled with
++//! [`cancel`](struct.AioCb.html#method.cancel) or
++//! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
++//! not support this for all filesystems and devices.
++
++use {Error, Result};
++use errno::Errno;
++use std::os::unix::io::RawFd;
++use libc::{c_void, off_t, size_t};
++use libc;
++use std::borrow::{Borrow, BorrowMut};
++use std::fmt;
++use std::fmt::Debug;
++use std::marker::PhantomData;
++use std::mem;
++use std::ptr::{null, null_mut};
++use sys::signal::*;
++use std::thread;
++use sys::time::TimeSpec;
++
++libc_enum! {
++    /// Mode for `AioCb::fsync`.  Controls whether only data or both data and
++    /// metadata are synced.
++    #[repr(i32)]
++    pub enum AioFsyncMode {
++        /// do it like `fsync`
++        O_SYNC,
++        /// on supported operating systems only, do it like `fdatasync`
++        #[cfg(any(target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        O_DSYNC
++    }
++}
++
++libc_enum! {
++    /// When used with [`lio_listio`](fn.lio_listio.html), determines whether a
++    /// given `aiocb` should be used for a read operation, a write operation, or
++    /// ignored.  Has no effect for any other aio functions.
++    #[repr(i32)]
++    pub enum LioOpcode {
++        LIO_NOP,
++        LIO_WRITE,
++        LIO_READ,
++    }
++}
++
++libc_enum! {
++    /// Mode for [`lio_listio`](fn.lio_listio.html)
++    #[repr(i32)]
++    pub enum LioMode {
++        /// Requests that [`lio_listio`](fn.lio_listio.html) block until all
++        /// requested operations have been completed
++        LIO_WAIT,
++        /// Requests that [`lio_listio`](fn.lio_listio.html) return immediately
++        LIO_NOWAIT,
++    }
++}
++
++/// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and
++/// [`aio_cancel_all`](fn.aio_cancel_all.html)
++#[repr(i32)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum AioCancelStat {
++    /// All outstanding requests were canceled
++    AioCanceled = libc::AIO_CANCELED,
++    /// Some requests were not canceled.  Their status should be checked with
++    /// `AioCb::error`
++    AioNotCanceled = libc::AIO_NOTCANCELED,
++    /// All of the requests have already finished
++    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]>>),
++}
++
++impl<'a> Debug for Buffer<'a> {
++    // Note: someday it may be possible to Derive Debug for a trait object, but
++    // not today.
++    // https://github.com/rust-lang/rust/issues/1563
++    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
++        match *self {
++            Buffer::None => write!(fmt, "None"),
++            Buffer::Phantom(p) => p.fmt(fmt),
++            Buffer::BoxedSlice(ref bs) => {
++                let borrowed : &dyn Borrow<[u8]> = bs.borrow();
++                write!(fmt, "BoxedSlice({:?})",
++                    borrowed as *const dyn Borrow<[u8]>)
++            },
++            Buffer::BoxedMutSlice(ref bms) => {
++                let borrowed : &dyn BorrowMut<[u8]> = bms.borrow();
++                write!(fmt, "BoxedMutSlice({:?})",
++                    borrowed as *const dyn BorrowMut<[u8]>)
++            }
++        }
++    }
++}
++
++/// AIO Control Block.
++///
++/// The basic structure used by all aio functions.  Each `AioCb` represents one
++/// I/O request.
++pub struct AioCb<'a> {
++    aiocb: libc::aiocb,
++    /// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable
++    mutable: bool,
++    /// Could this `AioCb` potentially have any in-kernel state?
++    in_progress: bool,
++    /// Optionally keeps a reference to the data.
++    ///
++    /// Used to keep buffers from `Drop`'ing, and may be returned once the
++    /// `AioCb` is completed by [`buffer`](#method.buffer).
++    buffer: Buffer<'a>
++}
++
++impl<'a> AioCb<'a> {
++    /// Remove the inner `Buffer` and return it
++    ///
++    /// It is an error to call this method while the `AioCb` is still in
++    /// progress.
++    pub fn buffer(&mut self) -> Buffer<'a> {
++        assert!(!self.in_progress);
++        let mut x = Buffer::None;
++        mem::swap(&mut self.buffer, &mut x);
++        x
++    }
++
++    /// Remove the inner boxed slice, if any, and return it.
++    ///
++    /// The returned value will be the argument that was passed to
++    /// `from_boxed_slice` when this `AioCb` was created.
++    ///
++    /// It is an error to call this method while the `AioCb` is still in
++    /// progress.
++    pub fn boxed_slice(&mut self) -> Option<Box<dyn Borrow<[u8]>>> {
++        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
++        if let Buffer::BoxedSlice(_) = self.buffer {
++            let mut oldbuffer = Buffer::None;
++            mem::swap(&mut self.buffer, &mut oldbuffer);
++            if let Buffer::BoxedSlice(inner) = oldbuffer {
++                Some(inner)
++            } else {
++                unreachable!();
++            }
++        } else {
++            None
++        }
++    }
++
++    /// Remove the inner boxed mutable slice, if any, and return it.
++    ///
++    /// The returned value will be the argument that was passed to
++    /// `from_boxed_mut_slice` when this `AioCb` was created.
++    ///
++    /// It is an error to call this method while the `AioCb` is still in
++    /// progress.
++    pub fn boxed_mut_slice(&mut self) -> Option<Box<dyn BorrowMut<[u8]>>> {
++        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
++        if let Buffer::BoxedMutSlice(_) = self.buffer {
++            let mut oldbuffer = Buffer::None;
++            mem::swap(&mut self.buffer, &mut oldbuffer);
++            if let Buffer::BoxedMutSlice(inner) = oldbuffer {
++                Some(inner)
++            } else {
++                unreachable!();
++            }
++        } else {
++            None
++        }
++    }
++
++    /// Returns the underlying file descriptor associated with the `AioCb`
++    pub fn fd(&self) -> RawFd {
++        self.aiocb.aio_fildes
++    }
++
++    /// Constructs a new `AioCb` with no associated buffer.
++    ///
++    /// The resulting `AioCb` structure is suitable for use with `AioCb::fsync`.
++    ///
++    /// # Parameters
++    ///
++    /// * `fd`:           File descriptor.  Required for all aio functions.
++    /// * `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.
++    ///
++    /// # Examples
++    ///
++    /// Create an `AioCb` from a raw file descriptor and use it for an
++    /// [`fsync`](#method.fsync) operation.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::errno::Errno;
++    /// # use nix::Error;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify::SigevNone;
++    /// # use std::{thread, time};
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// let f = tempfile().unwrap();
++    /// let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, SigevNone);
++    /// aiocb.fsync(AioFsyncMode::O_SYNC).expect("aio_fsync failed early");
++    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
++    ///     thread::sleep(time::Duration::from_millis(10));
++    /// }
++    /// aiocb.aio_return().expect("aio_fsync failed late");
++    /// # }
++    /// ```
++    pub fn from_fd(fd: RawFd, prio: libc::c_int,
++                    sigev_notify: SigevNotify) -> 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();
++
++        AioCb {
++            aiocb: a,
++            mutable: false,
++            in_progress: false,
++            buffer: Buffer::None
++        }
++    }
++
++    /// Constructs a new `AioCb` from a mutable slice.
++    ///
++    /// 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.
++    ///
++    /// # Parameters
++    ///
++    /// * `fd`:           File descriptor.  Required for all aio functions.
++    /// * `offs`:         File offset
++    /// * `buf`:          A memory buffer
++    /// * `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 mutable slice and read into it.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # 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 mut rbuf = vec![0; LEN];
++    /// let mut f = tempfile().unwrap();
++    /// f.write_all(INITIAL).unwrap();
++    /// {
++    ///     let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
++    ///         2,   //offset
++    ///         &mut 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);
++    /// }
++    /// assert_eq!(rbuf, b"cdef");
++    /// # }
++    /// ```
++    pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
++                          prio: libc::c_int, sigev_notify: SigevNotify,
++                          opcode: LioOpcode) -> 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;
++
++        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
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # 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
++    ///
++    /// ```
++    /// # extern crate bytes;
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # 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.
++    ///
++    /// ```
++    /// # extern crate bytes;
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # 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
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::errno::Errno;
++    /// # use nix::Error;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify;
++    /// # use std::{thread, time};
++    /// # use std::io::Write;
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// const INITIAL: &[u8] = b"abcdef123456";
++    /// const LEN: usize = 4;
++    /// let rbuf = Box::new(vec![0; LEN]);
++    /// let mut f = tempfile().unwrap();
++    /// f.write_all(INITIAL).unwrap();
++    /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
++    ///     2,   //offset
++    ///     rbuf,
++    ///     0,   //priority
++    ///     SigevNotify::SigevNone,
++    ///     LioOpcode::LIO_NOP);
++    /// aiocb.read().unwrap();
++    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
++    ///     thread::sleep(time::Duration::from_millis(10));
++    /// }
++    /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
++    /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
++    /// const EXPECT: &[u8] = b"cdef";
++    /// assert_eq!(buffer.borrow_mut(), EXPECT);
++    /// # }
++    /// ```
++    ///
++    /// [`from_boxed_slice`]: #method.from_boxed_slice
++    /// [`from_mut_slice`]: #method.from_mut_slice
++    pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
++                                mut buf: Box<dyn BorrowMut<[u8]>>,
++                                prio: libc::c_int, sigev_notify: SigevNotify,
++                                opcode: LioOpcode) -> AioCb<'a> {
++        let mut a = AioCb::common_init(fd, prio, sigev_notify);
++        {
++            let borrowed : &mut dyn BorrowMut<[u8]> = buf.borrow_mut();
++            let slice : &mut [u8] = borrowed.borrow_mut();
++            a.aio_nbytes = slice.len() as size_t;
++            a.aio_buf = slice.as_mut_ptr() as *mut c_void;
++        }
++        a.aio_offset = offs;
++        a.aio_lio_opcode = opcode as libc::c_int;
++
++        AioCb {
++            aiocb: a,
++            mutable: true,
++            in_progress: false,
++            buffer: Buffer::BoxedMutSlice(buf),
++        }
++    }
++
++    /// Constructs a new `AioCb` from a mutable raw pointer
++    ///
++    /// 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]>`
++    ///
++    /// # Parameters
++    ///
++    /// * `fd`:           File descriptor.  Required for all aio functions.
++    /// * `offs`:         File offset
++    /// * `buf`:          Pointer to the memory buffer
++    /// * `len`:          Length of the buffer pointed to by `buf`
++    /// * `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
++    ///
++    /// # Safety
++    ///
++    /// The caller must ensure that the storage pointed to by `buf` outlives the
++    /// `AioCb`.  The lifetime checker can't help here.
++    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> {
++        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;
++
++        AioCb {
++            aiocb: a,
++            mutable: true,
++            in_progress: false,
++            buffer: Buffer::None
++        }
++    }
++
++    /// Constructs a new `AioCb` from a raw pointer.
++    ///
++    /// Unlike `from_slice`, this method returns a structure suitable for
++    /// placement on the heap.  Due to its unsafety, this method is not
++    /// recommended.  It is most useful when heap allocation is required but for
++    /// some reason the data cannot be wrapped in a `struct` that implements
++    /// `Borrow<[u8]>`
++    ///
++    /// # Parameters
++    ///
++    /// * `fd`:           File descriptor.  Required for all aio functions.
++    /// * `offs`:         File offset
++    /// * `buf`:          Pointer to the memory buffer
++    /// * `len`:          Length of the buffer pointed to by `buf`
++    /// * `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
++    ///
++    /// # Safety
++    ///
++    /// The caller must ensure that the storage pointed to by `buf` outlives the
++    /// `AioCb`.  The lifetime checker can't help here.
++    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> {
++        let mut a = AioCb::common_init(fd, prio, sigev_notify);
++        a.aio_offset = offs;
++        a.aio_nbytes = len;
++        // casting a const ptr to a mutable ptr here is ok, because we set the
++        // AioCb's mutable field to false
++        a.aio_buf = buf as *mut c_void;
++        a.aio_lio_opcode = opcode as libc::c_int;
++
++        AioCb {
++            aiocb: a,
++            mutable: false,
++            in_progress: false,
++            buffer: Buffer::None
++        }
++    }
++
++    /// 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
++    /// `LioOpcode` cannot be set to `LIO_READ`.  This method is useful when
++    /// writing a const buffer with `AioCb::write`, since `from_mut_slice` can't
++    /// work with const buffers.
++    ///
++    /// # Examples
++    ///
++    /// Construct an `AioCb` from a slice and use it for writing.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::errno::Errno;
++    /// # use nix::Error;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify;
++    /// # use std::{thread, time};
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// const WBUF: &[u8] = b"abcdef123456";
++    /// let mut f = tempfile().unwrap();
++    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++    ///     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, WBUF.len());
++    /// # }
++    /// ```
++    // Note: another solution to the problem of writing const buffers would be
++    // to genericize AioCb for both &mut [u8] and &[u8] buffers.  AioCb::read
++    // could take the former and AioCb::write could take the latter.  However,
++    // then lio_listio wouldn't work, because that function needs a slice of
++    // 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,
++        }
++    }
++
++    fn common_init(fd: RawFd, prio: libc::c_int,
++                   sigev_notify: SigevNotify) -> libc::aiocb {
++        // Use mem::zeroed instead of explicitly zeroing each field, because the
++        // number and name of reserved fields is OS-dependent.  On some OSes,
++        // some reserved fields are used the kernel for state, and must be
++        // explicitly zeroed when allocated.
++        let mut a = unsafe { mem::zeroed::<libc::aiocb>()};
++        a.aio_fildes = fd;
++        a.aio_reqprio = prio;
++        a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
++        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();
++    }
++
++    /// Cancels an outstanding AIO request.
++    ///
++    /// The operating system is not required to implement cancellation for all
++    /// file and device types.  Even if it does, there is no guarantee that the
++    /// operation has not already completed.  So the caller must check the
++    /// result and handle operations that were not canceled or that have already
++    /// completed.
++    ///
++    /// # Examples
++    ///
++    /// Cancel an outstanding aio operation.  Note that we must still call
++    /// `aio_return` to free resources, even though we don't care about the
++    /// result.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # 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 = b"CDEF";
++    /// let mut f = tempfile().unwrap();
++    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++    ///     2,   //offset
++    ///     &wbuf[..],
++    ///     0,   //priority
++    ///     SigevNotify::SigevNone,
++    ///     LioOpcode::LIO_NOP);
++    /// aiocb.write().unwrap();
++    /// let cs = aiocb.cancel().unwrap();
++    /// if cs == AioCancelStat::AioNotCanceled {
++    ///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
++    ///         thread::sleep(time::Duration::from_millis(10));
++    ///     }
++    /// }
++    /// // Must call `aio_return`, but ignore the result
++    /// let _ = aiocb.aio_return();
++    /// # }
++    /// ```
++    ///
++    /// # References
++    ///
++    /// [aio_cancel](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
++    pub fn cancel(&mut self) -> Result<AioCancelStat> {
++        match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } {
++            libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
++            libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
++            libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
++            -1 => Err(Error::last()),
++            _ => panic!("unknown aio_cancel return value")
++        }
++    }
++
++    /// Retrieve error status of an asynchronous operation.
++    ///
++    /// If the request has not yet completed, returns `EINPROGRESS`.  Otherwise,
++    /// returns `Ok` or any other error.
++    ///
++    /// # Examples
++    ///
++    /// Issue an aio operation and use `error` to poll for completion.  Polling
++    /// is an alternative to `aio_suspend`, used by most of the other examples.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::errno::Errno;
++    /// # use nix::Error;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify;
++    /// # use std::{thread, time};
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// const WBUF: &[u8] = b"abcdef123456";
++    /// let mut f = tempfile().unwrap();
++    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++    ///     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, WBUF.len());
++    /// # }
++    /// ```
++    ///
++    /// # 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)
++        }
++    }
++
++    /// 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 {
++                libc::aio_fsync(mode as libc::c_int, p)
++        }).map(|_| {
++            self.in_progress = true;
++        })
++    }
++
++    /// Returns the `aiocb`'s `LioOpcode` field
++    ///
++    /// 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 {
++            libc::LIO_READ => Some(LioOpcode::LIO_READ),
++            libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
++            libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
++            _ => None
++        }
++    }
++
++    /// Returns the requested length of the aio operation in bytes
++    ///
++    /// This method returns the *requested* length of the operation.  To get the
++    /// number of bytes actually read or written by a completed operation, use
++    /// `aio_return` instead.
++    pub fn nbytes(&self) -> usize {
++        self.aiocb.aio_nbytes
++    }
++
++    /// Returns the file offset stored in the `AioCb`
++    pub fn offset(&self) -> off_t {
++        self.aiocb.aio_offset
++    }
++
++    /// Returns the priority of the `AioCb`
++    pub fn priority(&self) -> libc::c_int {
++        self.aiocb.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<()> {
++        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)
++        }).map(|_| {
++            self.in_progress = true;
++        })
++    }
++
++    /// Returns the `SigEvent` stored in the `AioCb`
++    pub fn sigevent(&self) -> SigEvent {
++        SigEvent::from(&self.aiocb.aio_sigevent)
++    }
++
++    /// Retrieve return status of an asynchronous operation.
++    ///
++    /// Should only be called once for each `AioCb`, after `AioCb::error`
++    /// indicates that it has completed.  The result is the same as for the
++    /// synchronous `read(2)`, `write(2)`, of `fsync(2)` functions.
++    ///
++    /// # References
++    ///
++    /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
++    // Note: this should be just `return`, but that's a reserved word
++    pub fn aio_return(&mut self) -> Result<isize> {
++        let p: *mut libc::aiocb = &mut self.aiocb;
++        self.in_progress = false;
++        Errno::result(unsafe { libc::aio_return(p) })
++    }
++
++    /// Asynchronously writes from a buffer to a file descriptor
++    ///
++    /// # References
++    ///
++    /// [aio_write](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
++    pub fn write(&mut self) -> Result<()> {
++        let p: *mut libc::aiocb = &mut self.aiocb;
++        Errno::result(unsafe {
++            libc::aio_write(p)
++        }).map(|_| {
++            self.in_progress = true;
++        })
++    }
++
++}
++
++/// Cancels outstanding AIO requests for a given file descriptor.
++///
++/// # Examples
++///
++/// Issue an aio operation, then cancel all outstanding operations on that file
++/// descriptor.
++///
++/// ```
++/// # extern crate tempfile;
++/// # extern crate nix;
++/// # 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 = b"CDEF";
++/// let mut f = tempfile().unwrap();
++/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++///     2,   //offset
++///     &wbuf[..],
++///     0,   //priority
++///     SigevNotify::SigevNone,
++///     LioOpcode::LIO_NOP);
++/// aiocb.write().unwrap();
++/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
++/// if cs == AioCancelStat::AioNotCanceled {
++///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
++///         thread::sleep(time::Duration::from_millis(10));
++///     }
++/// }
++/// // Must call `aio_return`, but ignore the result
++/// let _ = aiocb.aio_return();
++/// # }
++/// ```
++///
++/// # References
++///
++/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
++pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
++    match unsafe { libc::aio_cancel(fd, null_mut()) } {
++        libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
++        libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
++        libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
++        -1 => Err(Error::last()),
++        _ => panic!("unknown aio_cancel return value")
++    }
++}
++
++/// Suspends the calling process until at least one of the specified `AioCb`s
++/// has completed, a signal is delivered, or the timeout has passed.
++///
++/// If `timeout` is `None`, `aio_suspend` will block indefinitely.
++///
++/// # Examples
++///
++/// Use `aio_suspend` to block until an aio operation completes.
++///
++// Disable doctest due to a known bug in FreeBSD's 32-bit emulation.  The fix
++// will be included in release 11.2.
++// FIXME reenable the doc test when the CI machine gets upgraded to that release.
++// https://svnweb.freebsd.org/base?view=revision&revision=325018
++/// ```no_run
++/// # extern crate tempfile;
++/// # extern crate nix;
++/// # use nix::sys::aio::*;
++/// # use nix::sys::signal::SigevNotify;
++/// # use std::os::unix::io::AsRawFd;
++/// # use tempfile::tempfile;
++/// # fn main() {
++/// const WBUF: &[u8] = b"abcdef123456";
++/// let mut f = tempfile().unwrap();
++/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++///     2,   //offset
++///     WBUF,
++///     0,   //priority
++///     SigevNotify::SigevNone,
++///     LioOpcode::LIO_NOP);
++/// aiocb.write().unwrap();
++/// aio_suspend(&[&aiocb], 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];
++    let p = plist as *const *const libc::aiocb;
++    let timep = match timeout {
++        None    => null::<libc::timespec>(),
++        Some(x) => x.as_ref() as *const libc::timespec
++    };
++    Errno::result(unsafe {
++        libc::aio_suspend(p, list.len() as i32, timep)
++    }).map(drop)
++}
++
++impl<'a> Debug for AioCb<'a> {
++    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
++        fmt.debug_struct("AioCb")
++            .field("aiocb", &self.aiocb)
++            .field("mutable", &self.mutable)
++            .field("in_progress", &self.in_progress)
++            .finish()
++    }
++}
++
++impl<'a> Drop for AioCb<'a> {
++    /// If the `AioCb` has no remaining state in the kernel, just drop it.
++    /// Otherwise, dropping constitutes a resource leak, which is an error
++    fn drop(&mut self) {
++        assert!(thread::panicking() || !self.in_progress,
++                "Dropped an in-progress AioCb");
++    }
++}
++
++/// LIO Control Block.
++///
++/// The basic structure used to issue multiple AIO operations simultaneously.
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++pub struct LioCb<'a> {
++    /// A collection of [`AioCb`]s.  All of these will be issued simultaneously
++    /// by the [`listio`] method.
++    ///
++    /// [`AioCb`]: struct.AioCb.html
++    /// [`listio`]: #method.listio
++    pub aiocbs: Vec<AioCb<'a>>,
++
++    /// The actual list passed to `libc::lio_listio`.
++    ///
++    /// It must live for as long as any of the operations are still being
++    /// processesed, because the aio subsystem uses its address as a unique
++    /// identifier.
++    list: Vec<*mut libc::aiocb>,
++
++    /// A partial set of results.  This field will get populated by
++    /// `listio_resubmit` when an `LioCb` is resubmitted after an error
++    results: Vec<Option<Result<isize>>>
++}
++
++#[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)
++        }
++    }
++
++    /// Submits multiple asynchronous I/O requests with a single system call.
++    ///
++    /// They are not guaranteed to complete atomically, and the order in which
++    /// the requests are carried out is not specified.  Reads, writes, and
++    /// fsyncs may be freely mixed.
++    ///
++    /// This function is useful for reducing the context-switch overhead of
++    /// submitting many AIO operations.  It can also be used with
++    /// `LioMode::LIO_WAIT` to block on the result of several independent
++    /// operations.  Used that way, it is often useful in programs that
++    /// otherwise make little use of AIO.
++    ///
++    /// # Examples
++    ///
++    /// Use `listio` to submit an aio operation and wait for its completion.  In
++    /// this case, there is no need to use [`aio_suspend`] to wait or
++    /// [`AioCb::error`] to poll.
++    ///
++    /// ```
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify;
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// const WBUF: &[u8] = b"abcdef123456";
++    /// let mut f = tempfile().unwrap();
++    /// let mut liocb = LioCb::with_capacity(1);
++    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
++    ///     2,   //offset
++    ///     WBUF,
++    ///     0,   //priority
++    ///     SigevNotify::SigevNone,
++    ///     LioOpcode::LIO_WRITE));
++    /// liocb.listio(LioMode::LIO_WAIT,
++    ///              SigevNotify::SigevNone).unwrap();
++    /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
++    /// # }
++    /// ```
++    ///
++    /// # References
++    ///
++    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
++    ///
++    /// [`aio_suspend`]: fn.aio_suspend.html
++    /// [`AioCb::error`]: struct.AioCb.html#method.error
++    pub fn listio(&mut self, mode: LioMode,
++                  sigev_notify: SigevNotify) -> Result<()> {
++        let sigev = SigEvent::new(sigev_notify);
++        let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
++        self.list.clear();
++        for a in &mut self.aiocbs {
++            a.in_progress = true;
++            self.list.push(a as *mut AioCb<'a>
++                             as *mut libc::aiocb);
++        }
++        let p = self.list.as_ptr();
++        Errno::result(unsafe {
++            libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
++        }).map(drop)
++    }
++
++    /// Resubmits any incomplete operations with [`lio_listio`].
++    ///
++    /// Sometimes, due to system resource limitations, an `lio_listio` call will
++    /// return `EIO`, or `EAGAIN`.  Or, if a signal is received, it may return
++    /// `EINTR`.  In any of these cases, only a subset of its constituent
++    /// operations will actually have been initiated.  `listio_resubmit` will
++    /// resubmit any operations that are still uninitiated.
++    ///
++    /// After calling `listio_resubmit`, results should be collected by
++    /// [`LioCb::aio_return`].
++    ///
++    /// # Examples
++    /// ```no_run
++    /// # extern crate tempfile;
++    /// # extern crate nix;
++    /// # use nix::Error;
++    /// # use nix::errno::Errno;
++    /// # use nix::sys::aio::*;
++    /// # use nix::sys::signal::SigevNotify;
++    /// # use std::os::unix::io::AsRawFd;
++    /// # use std::{thread, time};
++    /// # use tempfile::tempfile;
++    /// # fn main() {
++    /// const WBUF: &[u8] = b"abcdef123456";
++    /// let mut f = tempfile().unwrap();
++    /// let mut liocb = LioCb::with_capacity(1);
++    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
++    ///     2,   //offset
++    ///     WBUF,
++    ///     0,   //priority
++    ///     SigevNotify::SigevNone,
++    ///     LioOpcode::LIO_WRITE));
++    /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
++    /// while err == Err(Error::Sys(Errno::EIO)) ||
++    ///       err == Err(Error::Sys(Errno::EAGAIN)) {
++    ///     thread::sleep(time::Duration::from_millis(10));
++    ///     err = liocb.listio_resubmit(LioMode::LIO_WAIT, SigevNotify::SigevNone);
++    /// }
++    /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
++    /// # }
++    /// ```
++    ///
++    /// # References
++    ///
++    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
++    ///
++    /// [`lio_listio`]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
++    /// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return
++    // Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be
++    // changed by this method, because the kernel relies on their addresses
++    // being stable.
++    // Note: aiocbs that are Ok(()) must be finalized by aio_return, or else the
++    // sigev_notify will immediately refire.
++    pub fn listio_resubmit(&mut self, mode:LioMode,
++                           sigev_notify: SigevNotify) -> Result<()> {
++        let sigev = SigEvent::new(sigev_notify);
++        let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
++        self.list.clear();
++
++        while self.results.len() < self.aiocbs.len() {
++            self.results.push(None);
++        }
++
++        for (i, a) in self.aiocbs.iter_mut().enumerate() {
++            if self.results[i].is_some() {
++                // Already collected final status for this operation
++                continue;
++            }
++            match a.error() {
++                Ok(()) => {
++                    // aiocb is complete; collect its status and don't resubmit
++                    self.results[i] = Some(a.aio_return());
++                },
++                Err(Error::Sys(Errno::EAGAIN)) => {
++                    self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
++                },
++                Err(Error::Sys(Errno::EINPROGRESS)) => {
++                    // aiocb is was successfully queued; no need to do anything
++                    ()
++                },
++                Err(Error::Sys(Errno::EINVAL)) => panic!(
++                    "AioCb was never submitted, or already finalized"),
++                _ => unreachable!()
++            }
++        }
++        let p = self.list.as_ptr();
++        Errno::result(unsafe {
++            libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
++        }).map(drop)
++    }
++
++    /// Collect final status for an individual `AioCb` submitted as part of an
++    /// `LioCb`.
++    ///
++    /// This is just like [`AioCb::aio_return`], except it takes into account
++    /// operations that were restarted by [`LioCb::listio_resubmit`]
++    ///
++    /// [`AioCb::aio_return`]: struct.AioCb.html#method.aio_return
++    /// [`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()
++        } else {
++            self.results[i].unwrap()
++        }
++    }
++
++    /// Retrieve error status of an individual `AioCb` submitted as part of an
++    /// `LioCb`.
++    ///
++    /// This is just like [`AioCb::error`], except it takes into account
++    /// operations that were restarted by [`LioCb::listio_resubmit`]
++    ///
++    /// [`AioCb::error`]: struct.AioCb.html#method.error
++    /// [`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()
++        } else {
++            Ok(())
++        }
++    }
++}
++
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++impl<'a> Debug for LioCb<'a> {
++    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
++        fmt.debug_struct("LioCb")
++            .field("aiocbs", &self.aiocbs)
++            .finish()
++    }
++}
++
++#[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,
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/epoll.rs b/third_party/rust/nix-0.15.0/src/sys/epoll.rs
+new file mode 100644
+index 0000000000000..fef6f4e3ec92c
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/epoll.rs
+@@ -0,0 +1,109 @@
++use Result;
++use errno::Errno;
++use libc::{self, c_int};
++use std::os::unix::io::RawFd;
++use std::ptr;
++use std::mem;
++use ::Error;
++
++libc_bitflags!(
++    pub struct EpollFlags: c_int {
++        EPOLLIN;
++        EPOLLPRI;
++        EPOLLOUT;
++        EPOLLRDNORM;
++        EPOLLRDBAND;
++        EPOLLWRNORM;
++        EPOLLWRBAND;
++        EPOLLMSG;
++        EPOLLERR;
++        EPOLLHUP;
++        EPOLLRDHUP;
++        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
++        EPOLLEXCLUSIVE;
++        #[cfg(not(target_arch = "mips"))]
++        EPOLLWAKEUP;
++        EPOLLONESHOT;
++        EPOLLET;
++    }
++);
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++#[repr(i32)]
++pub enum EpollOp {
++    EpollCtlAdd = libc::EPOLL_CTL_ADD,
++    EpollCtlDel = libc::EPOLL_CTL_DEL,
++    EpollCtlMod = libc::EPOLL_CTL_MOD,
++}
++
++libc_bitflags!{
++    pub struct EpollCreateFlags: c_int {
++        EPOLL_CLOEXEC;
++    }
++}
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++#[repr(C)]
++pub struct EpollEvent {
++    event: libc::epoll_event,
++}
++
++impl EpollEvent {
++    pub fn new(events: EpollFlags, data: u64) -> Self {
++        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
++    }
++
++    pub fn empty() -> Self {
++        unsafe { mem::zeroed::<EpollEvent>() }
++    }
++
++    pub fn events(&self) -> EpollFlags {
++        EpollFlags::from_bits(self.event.events as c_int).unwrap()
++    }
++
++    pub fn data(&self) -> u64 {
++        self.event.u64
++    }
++}
++
++#[inline]
++pub fn epoll_create() -> Result<RawFd> {
++    let res = unsafe { libc::epoll_create(1024) };
++
++    Errno::result(res)
++}
++
++#[inline]
++pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
++    let res = unsafe { libc::epoll_create1(flags.bits()) };
++
++    Errno::result(res)
++}
++
++#[inline]
++pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
++    where T: Into<Option<&'a mut EpollEvent>>
++{
++    let mut event: Option<&mut EpollEvent> = event.into();
++    if event.is_none() && op != EpollOp::EpollCtlDel {
++        Err(Error::Sys(Errno::EINVAL))
++    } else {
++        let res = unsafe {
++            if let Some(ref mut event) = event {
++                libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
++            } else {
++                libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
++            }
++        };
++        Errno::result(res).map(drop)
++    }
++}
++
++#[inline]
++pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
++    let res = unsafe {
++        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/event.rs b/third_party/rust/nix-0.15.0/src/sys/event.rs
+new file mode 100644
+index 0000000000000..8cd7372f88188
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/event.rs
+@@ -0,0 +1,351 @@
++/* TOOD: Implement for other kqueue based systems
++ */
++
++use {Errno, Result};
++#[cfg(not(target_os = "netbsd"))]
++use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
++#[cfg(target_os = "netbsd")]
++use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
++use libc;
++use std::os::unix::io::RawFd;
++use std::ptr;
++use std::mem;
++
++// Redefine kevent in terms of programmer-friendly enums and bitfields.
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct KEvent {
++    kevent: libc::kevent,
++}
++
++#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
++          target_os = "ios", target_os = "macos",
++          target_os = "openbsd"))]
++type type_of_udata = *mut libc::c_void;
++#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
++          target_os = "ios", target_os = "macos"))]
++type type_of_data = intptr_t;
++#[cfg(any(target_os = "netbsd"))]
++type type_of_udata = intptr_t;
++#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
++type type_of_data = libc::int64_t;
++
++#[cfg(target_os = "netbsd")]
++type type_of_event_filter = u32;
++#[cfg(not(target_os = "netbsd"))]
++type type_of_event_filter = i16;
++libc_enum! {
++    #[cfg_attr(target_os = "netbsd", repr(u32))]
++    #[cfg_attr(not(target_os = "netbsd"), repr(i16))]
++    pub enum EventFilter {
++        EVFILT_AIO,
++        /// Returns whenever there is no remaining data in the write buffer
++        #[cfg(target_os = "freebsd")]
++        EVFILT_EMPTY,
++        #[cfg(target_os = "dragonfly")]
++        EVFILT_EXCEPT,
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  target_os = "macos"))]
++        EVFILT_FS,
++        #[cfg(target_os = "freebsd")]
++        EVFILT_LIO,
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        EVFILT_MACHPORT,
++        EVFILT_PROC,
++        /// Returns events associated with the process referenced by a given
++        /// process descriptor, created by `pdfork()`. The events to monitor are:
++        ///
++        /// - NOTE_EXIT: the process has exited. The exit status will be stored in data.
++        #[cfg(target_os = "freebsd")]
++        EVFILT_PROCDESC,
++        EVFILT_READ,
++        /// Returns whenever an asynchronous `sendfile()` call completes.
++        #[cfg(target_os = "freebsd")]
++        EVFILT_SENDFILE,
++        EVFILT_SIGNAL,
++        EVFILT_TIMER,
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  target_os = "macos"))]
++        EVFILT_USER,
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        EVFILT_VM,
++        EVFILT_VNODE,
++        EVFILT_WRITE,
++    }
++}
++
++#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
++          target_os = "ios", target_os = "macos",
++          target_os = "openbsd"))]
++pub type type_of_event_flag = u16;
++#[cfg(any(target_os = "netbsd"))]
++pub type type_of_event_flag = u32;
++libc_bitflags!{
++    pub struct EventFlag: type_of_event_flag {
++        EV_ADD;
++        EV_CLEAR;
++        EV_DELETE;
++        EV_DISABLE;
++        // No released version of OpenBSD supports EV_DISPATCH or EV_RECEIPT.
++        // These have been commited to the -current branch though and are
++        // expected to be part of the OpenBSD 6.2 release in Nov 2017.
++        // See: https://marc.info/?l=openbsd-tech&m=149621427511219&w=2
++        // https://github.com/rust-lang/libc/pull/613
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
++                  target_os = "ios", target_os = "macos",
++                  target_os = "netbsd"))]
++        EV_DISPATCH;
++        #[cfg(target_os = "freebsd")]
++        EV_DROP;
++        EV_ENABLE;
++        EV_EOF;
++        EV_ERROR;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EV_FLAG0;
++        EV_FLAG1;
++        #[cfg(target_os = "dragonfly")]
++        EV_NODATA;
++        EV_ONESHOT;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EV_OOBAND;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        EV_POLL;
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
++                  target_os = "ios", target_os = "macos",
++                  target_os = "netbsd"))]
++        EV_RECEIPT;
++        EV_SYSFLAGS;
++    }
++}
++
++libc_bitflags!(
++    pub struct FilterFlag: u32 {
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_ABSOLUTE;
++        NOTE_ATTRIB;
++        NOTE_CHILD;
++        NOTE_DELETE;
++        #[cfg(target_os = "openbsd")]
++        NOTE_EOF;
++        NOTE_EXEC;
++        NOTE_EXIT;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
++        #[allow(deprecated)]
++        NOTE_EXIT_REPARENTED;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_EXITSTATUS;
++        NOTE_EXTEND;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFAND;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFCOPY;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFCTRLMASK;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFLAGSMASK;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFNOP;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_FFOR;
++        NOTE_FORK;
++        NOTE_LINK;
++        NOTE_LOWAT;
++        #[cfg(target_os = "freebsd")]
++        NOTE_MSECONDS;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_NONE;
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
++        NOTE_NSECONDS;
++        #[cfg(target_os = "dragonfly")]
++        NOTE_OOB;
++        NOTE_PCTRLMASK;
++        NOTE_PDATAMASK;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
++        #[allow(deprecated)]
++        NOTE_REAP;
++        NOTE_RENAME;
++        NOTE_REVOKE;
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
++        NOTE_SECONDS;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_SIGNAL;
++        NOTE_TRACK;
++        NOTE_TRACKERR;
++        #[cfg(any(target_os = "macos",
++                  target_os = "ios",
++                  target_os = "freebsd",
++                  target_os = "dragonfly"))]
++        NOTE_TRIGGER;
++        #[cfg(target_os = "openbsd")]
++        NOTE_TRUNCATE;
++        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
++        NOTE_USECONDS;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_VM_ERROR;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_VM_PRESSURE;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        NOTE_VM_PRESSURE_TERMINATE;
++        NOTE_WRITE;
++    }
++);
++
++pub fn kqueue() -> Result<RawFd> {
++    let res = unsafe { libc::kqueue() };
++
++    Errno::result(res)
++}
++
++
++// KEvent can't derive Send because on some operating systems, udata is defined
++// as a void*.  However, KEvent's public API always treats udata as an intptr_t,
++// which is safe to Send.
++unsafe impl Send for KEvent {
++}
++
++impl KEvent {
++    pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
++               fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
++        KEvent { kevent: libc::kevent {
++            ident: ident,
++            filter: filter as type_of_event_filter,
++            flags: flags.bits(),
++            fflags: fflags.bits(),
++            data: data as type_of_data,
++            udata: udata as type_of_udata
++        } }
++    }
++
++    pub fn ident(&self) -> uintptr_t {
++        self.kevent.ident
++    }
++
++    pub fn filter(&self) -> EventFilter {
++        unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
++    }
++
++    pub fn flags(&self) -> EventFlag {
++        EventFlag::from_bits(self.kevent.flags).unwrap()
++    }
++
++    pub fn fflags(&self) -> FilterFlag {
++        FilterFlag::from_bits(self.kevent.fflags).unwrap()
++    }
++
++    pub fn data(&self) -> intptr_t {
++        self.kevent.data as intptr_t
++    }
++
++    pub fn udata(&self) -> intptr_t {
++        self.kevent.udata as intptr_t
++    }
++}
++
++pub fn kevent(kq: RawFd,
++              changelist: &[KEvent],
++              eventlist: &mut [KEvent],
++              timeout_ms: usize) -> Result<usize> {
++
++    // Convert ms to timespec
++    let timeout = timespec {
++        tv_sec: (timeout_ms / 1000) as time_t,
++        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
++    };
++
++    kevent_ts(kq, changelist, eventlist, Some(timeout))
++}
++
++#[cfg(any(target_os = "macos",
++          target_os = "ios",
++          target_os = "freebsd",
++          target_os = "dragonfly",
++          target_os = "openbsd"))]
++type type_of_nchanges = c_int;
++#[cfg(target_os = "netbsd")]
++type type_of_nchanges = size_t;
++
++pub fn kevent_ts(kq: RawFd,
++              changelist: &[KEvent],
++              eventlist: &mut [KEvent],
++              timeout_opt: Option<timespec>) -> Result<usize> {
++
++    let res = unsafe {
++        libc::kevent(
++            kq,
++            changelist.as_ptr() as *const libc::kevent,
++            changelist.len() as type_of_nchanges,
++            eventlist.as_mut_ptr() as *mut libc::kevent,
++            eventlist.len() as type_of_nchanges,
++            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++#[inline]
++pub fn ev_set(ev: &mut KEvent,
++              ident: usize,
++              filter: EventFilter,
++              flags: EventFlag,
++              fflags: FilterFlag,
++              udata: intptr_t) {
++
++    ev.kevent.ident  = ident as uintptr_t;
++    ev.kevent.filter = filter as type_of_event_filter;
++    ev.kevent.flags  = flags.bits();
++    ev.kevent.fflags = fflags.bits();
++    ev.kevent.data   = 0;
++    ev.kevent.udata  = udata as type_of_udata;
++}
++
++#[test]
++fn test_struct_kevent() {
++    let udata : intptr_t = 12345;
++
++    let expected = libc::kevent{ident: 0xdead_beef,
++                                filter: libc::EVFILT_READ,
++                                flags: libc::EV_ONESHOT | libc::EV_ADD,
++                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
++                                data: 0x1337,
++                                udata: udata as type_of_udata};
++    let actual = KEvent::new(0xdead_beef,
++                             EventFilter::EVFILT_READ,
++                             EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
++                             FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
++                             0x1337,
++                             udata);
++    assert!(expected.ident == actual.ident());
++    assert!(expected.filter == actual.filter() as type_of_event_filter);
++    assert!(expected.flags == actual.flags().bits());
++    assert!(expected.fflags == actual.fflags().bits());
++    assert!(expected.data == actual.data() as type_of_data);
++    assert!(expected.udata == actual.udata() as type_of_udata);
++    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/eventfd.rs b/third_party/rust/nix-0.15.0/src/sys/eventfd.rs
+new file mode 100644
+index 0000000000000..c5a54e46a1735
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/eventfd.rs
+@@ -0,0 +1,18 @@
++use libc;
++use std::os::unix::io::RawFd;
++use Result;
++use errno::Errno;
++
++libc_bitflags! {
++    pub struct EfdFlags: libc::c_int {
++        EFD_CLOEXEC; // Since Linux 2.6.27
++        EFD_NONBLOCK; // Since Linux 2.6.27
++        EFD_SEMAPHORE; // Since Linux 2.6.30
++    }
++}
++
++pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
++    let res = unsafe { libc::eventfd(initval, flags.bits()) };
++
++    Errno::result(res).map(|r| r as RawFd)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/inotify.rs b/third_party/rust/nix-0.15.0/src/sys/inotify.rs
+new file mode 100644
+index 0000000000000..e6c2cf64d29dc
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/inotify.rs
+@@ -0,0 +1,230 @@
++//! Monitoring API for filesystem events.
++//!
++//! 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).
++//! 
++//! # Examples
++//!
++//! Monitor all events happening in directory "test":
++//! ```no_run
++//! # use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
++//! #
++//! // We create a new inotify instance.
++//! let instance = Inotify::init(InitFlags::empty()).unwrap();
++//!
++//! // We add a new watch on directory "test" for all events.
++//! let wd = instance.add_watch("test", AddWatchFlags::IN_ALL_EVENTS).unwrap();
++//!
++//! loop {
++//!     // We read from our inotify instance for events.
++//!     let events = instance.read_events().unwrap();
++//!     println!("Events: {:?}", events);
++//! }
++//! ```
++
++use libc;
++use libc::{
++    c_char,
++    c_int,
++};
++use std::ffi::{OsString,OsStr,CStr};
++use std::os::unix::ffi::OsStrExt;
++use std::mem::size_of;
++use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
++use unistd::read;
++use Result;
++use NixPath;
++use errno::Errno;
++
++libc_bitflags! {
++    /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
++    pub struct AddWatchFlags: u32 {
++        IN_ACCESS;
++        IN_MODIFY;
++        IN_ATTRIB;
++        IN_CLOSE_WRITE;
++        IN_CLOSE_NOWRITE;
++        IN_OPEN;
++        IN_MOVED_FROM;
++        IN_MOVED_TO;
++        IN_CREATE;
++        IN_DELETE;
++        IN_DELETE_SELF;
++        IN_MOVE_SELF;
++
++        IN_UNMOUNT;
++        IN_Q_OVERFLOW;
++        IN_IGNORED;
++
++        IN_CLOSE;
++        IN_MOVE;
++
++        IN_ONLYDIR;
++        IN_DONT_FOLLOW;
++
++        IN_ISDIR;
++        IN_ONESHOT;
++        IN_ALL_EVENTS;
++    }
++}
++
++libc_bitflags! {
++    /// Configuration options for [`inotify_init1`](fn.inotify_init1.html).
++    pub struct InitFlags: c_int {
++        IN_CLOEXEC;
++        IN_NONBLOCK;
++    }
++}
++
++/// An inotify instance. This is also a file descriptor, you can feed it to
++/// other interfaces consuming file descriptors, epoll for example.
++#[derive(Debug, Clone, Copy)]
++pub struct Inotify {
++    fd: RawFd
++}
++
++/// 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. 
++#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
++pub struct WatchDescriptor {
++    wd: i32
++}
++
++/// A single inotify event.
++///
++/// For more documentation see, [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
++#[derive(Debug)]
++pub struct InotifyEvent {
++    /// Watch descriptor. This field corresponds to the watch descriptor you
++    /// were issued when calling add_watch. It allows you to know which watch
++    /// this event comes from. 
++    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. 
++    pub cookie: u32,
++    /// Filename. This field exists only if the event was triggered for a file
++    /// inside the watched directory.
++    pub name: Option<OsString>
++}
++
++impl Inotify {
++    /// Initialize a new inotify instance.
++    ///
++    /// 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).
++    pub fn init(flags: InitFlags) -> Result<Inotify> {
++        let res = Errno::result(unsafe {
++            libc::inotify_init1(flags.bits())
++        });
++
++        res.map(|fd| Inotify { fd })
++    }
++
++    /// Adds a new watch on the target file or directory. 
++    ///
++    /// 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).
++    pub fn add_watch<P: ?Sized + NixPath>(&self,
++                                          path: &P,
++                                          mask: AddWatchFlags) 
++                                            -> Result<WatchDescriptor>
++    {
++        let res = path.with_nix_path(|cstr| {
++            unsafe {
++                libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
++            }
++        })?;
++
++        Errno::result(res).map(|wd| WatchDescriptor { wd })
++    }
++
++    /// Removes an existing watch using the watch descriptor returned by
++    /// inotify_add_watch.
++    ///
++    /// 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).
++    #[cfg(target_os = "linux")]
++    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
++        let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
++
++        Errno::result(res).map(drop)
++    }
++
++    #[cfg(target_os = "android")]
++    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
++        let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) };
++
++        Errno::result(res).map(drop)
++    }
++
++    /// 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. 
++    /// 
++    /// 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>> {
++        let header_size = size_of::<libc::inotify_event>();
++        let mut buffer = [0u8; 4096];
++        let mut events = Vec::new();
++        let mut offset = 0;
++
++        let nread = read(self.fd, &mut buffer)?;
++
++        while (nread - offset) >= header_size {
++            let event = unsafe {
++                &*(
++                    buffer
++                        .as_ptr()
++                        .offset(offset as isize) as *const libc::inotify_event
++                )
++            };
++
++            let name = match event.len {
++                0 => None,
++                _ => {
++                    let ptr = unsafe { 
++                        buffer
++                            .as_ptr()
++                            .offset(offset as isize + header_size as isize)
++                            as *const c_char
++                    };
++                    let cstr = unsafe { CStr::from_ptr(ptr) };
++                
++                    Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
++                }
++            };
++
++            events.push(InotifyEvent {
++                wd: WatchDescriptor { wd: event.wd },
++                mask: AddWatchFlags::from_bits_truncate(event.mask),
++                cookie: event.cookie,
++                name
++            });
++
++            offset += header_size + event.len as usize;
++        }
++
++        Ok(events)
++    }
++}
++
++impl AsRawFd for Inotify {
++    fn as_raw_fd(&self) -> RawFd {
++        self.fd
++    }
++}
++
++impl FromRawFd for Inotify {
++    unsafe fn from_raw_fd(fd: RawFd) -> Self {
++        Inotify { fd }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
+new file mode 100644
+index 0000000000000..9b8b0ff1a155f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
+@@ -0,0 +1,102 @@
++/// The datatype used for the ioctl number
++#[doc(hidden)]
++pub type ioctl_num_type = ::libc::c_ulong;
++/// The datatype used for the 3rd argument
++#[doc(hidden)]
++pub type ioctl_param_type = ::libc::c_int;
++
++mod consts {
++    use ::sys::ioctl::ioctl_num_type;
++    #[doc(hidden)]
++    pub const VOID: ioctl_num_type = 0x2000_0000;
++    #[doc(hidden)]
++    pub const OUT: ioctl_num_type = 0x4000_0000;
++    #[doc(hidden)]
++    pub const IN: ioctl_num_type = 0x8000_0000;
++    #[doc(hidden)]
++    pub const INOUT: ioctl_num_type = (IN|OUT);
++    #[doc(hidden)]
++    pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
++}
++
++pub use self::consts::*;
++
++#[macro_export]
++#[doc(hidden)]
++macro_rules! ioc {
++    ($inout:expr, $group:expr, $num:expr, $len:expr) => (
++        $inout | (($len as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as $crate::sys::ioctl::ioctl_num_type) << 8) | ($num as $crate::sys::ioctl::ioctl_num_type)
++    )
++}
++
++/// Generate an ioctl request code for a command that passes no data.
++///
++/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_none!()` directly.
++///
++/// # Example
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// const KVMIO: u8 = 0xAE;
++/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_none {
++    ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
++}
++
++/// Generate an ioctl request code for a command that passes an integer
++///
++/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_write_int {
++    ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>()))
++}
++
++/// Generate an ioctl request code for a command that reads.
++///
++/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_read!()` directly.
++///
++/// The read/write direction is relative to userland, so this
++/// command would be userland is reading and the kernel is
++/// writing.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_read {
++    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
++}
++
++/// Generate an ioctl request code for a command that writes.
++///
++/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_write!()` directly.
++///
++/// The read/write direction is relative to userland, so this
++/// command would be userland is writing and the kernel is
++/// reading.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_write {
++    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
++}
++
++/// Generate an ioctl request code for a command that reads and writes.
++///
++/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_readwrite {
++    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
+new file mode 100644
+index 0000000000000..9cdac72a4b80b
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
+@@ -0,0 +1,140 @@
++/// The datatype used for the ioctl number
++#[cfg(any(target_os = "android", target_env = "musl"))]
++#[doc(hidden)]
++pub type ioctl_num_type = ::libc::c_int;
++#[cfg(not(any(target_os = "android", target_env = "musl")))]
++#[doc(hidden)]
++pub type ioctl_num_type = ::libc::c_ulong;
++/// The datatype used for the 3rd argument
++#[doc(hidden)]
++pub type ioctl_param_type = ::libc::c_ulong;
++
++#[doc(hidden)]
++pub const NRBITS: ioctl_num_type = 8;
++#[doc(hidden)]
++pub const TYPEBITS: ioctl_num_type = 8;
++
++#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64"))]
++mod consts {
++    #[doc(hidden)]
++    pub const NONE: u8 = 1;
++    #[doc(hidden)]
++    pub const READ: u8 = 2;
++    #[doc(hidden)]
++    pub const WRITE: u8 = 4;
++    #[doc(hidden)]
++    pub const SIZEBITS: u8 = 13;
++    #[doc(hidden)]
++    pub const DIRBITS: u8 = 3;
++}
++
++// "Generic" ioctl protocol
++#[cfg(any(target_arch = "x86",
++          target_arch = "arm",
++          target_arch = "s390x",
++          target_arch = "x86_64",
++          target_arch = "aarch64"))]
++mod consts {
++    #[doc(hidden)]
++    pub const NONE: u8 = 0;
++    #[doc(hidden)]
++    pub const READ: u8 = 2;
++    #[doc(hidden)]
++    pub const WRITE: u8 = 1;
++    #[doc(hidden)]
++    pub const SIZEBITS: u8 = 14;
++    #[doc(hidden)]
++    pub const DIRBITS: u8 = 2;
++}
++
++pub use self::consts::*;
++
++#[doc(hidden)]
++pub const NRSHIFT: ioctl_num_type = 0;
++#[doc(hidden)]
++pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
++#[doc(hidden)]
++pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
++#[doc(hidden)]
++pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
++
++#[doc(hidden)]
++pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
++#[doc(hidden)]
++pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
++#[doc(hidden)]
++pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
++#[doc(hidden)]
++pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
++
++/// Encode an ioctl command.
++#[macro_export]
++#[doc(hidden)]
++macro_rules! ioc {
++    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
++        (($dir as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::DIRMASK) << $crate::sys::ioctl::DIRSHIFT) |
++        (($ty as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::TYPEMASK) << $crate::sys::ioctl::TYPESHIFT) |
++        (($nr as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::NRMASK) << $crate::sys::ioctl::NRSHIFT) |
++        (($sz as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::SIZEMASK) << $crate::sys::ioctl::SIZESHIFT))
++}
++
++/// Generate an ioctl request code for a command that passes no data.
++///
++/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_none!()` directly.
++///
++/// # Example
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// const KVMIO: u8 = 0xAE;
++/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_none {
++    ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
++}
++
++/// Generate an ioctl request code for a command that reads.
++///
++/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_read!()` directly.
++///
++/// The read/write direction is relative to userland, so this
++/// command would be userland is reading and the kernel is
++/// writing.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_read {
++    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
++}
++
++/// Generate an ioctl request code for a command that writes.
++///
++/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_write!()` directly.
++///
++/// The read/write direction is relative to userland, so this
++/// command would be userland is writing and the kernel is
++/// reading.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_write {
++    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
++}
++
++/// Generate an ioctl request code for a command that reads and writes.
++///
++/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
++///
++/// You should only use this macro directly if the `ioctl` you're working
++/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
++#[macro_export(local_inner_macros)]
++macro_rules! request_code_readwrite {
++    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
+new file mode 100644
+index 0000000000000..4513bf877434a
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
+@@ -0,0 +1,778 @@
++//! Provide helpers for making ioctl system calls.
++//!
++//! This library is pretty low-level and messy. `ioctl` is not fun.
++//!
++//! What is an `ioctl`?
++//! ===================
++//!
++//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
++//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
++//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
++//! descriptor.
++//!
++//! It is common to see `ioctl`s used for the following purposes:
++//!
++//!   * Provide read/write access to out-of-band data related to a device such as configuration
++//!     (for instance, setting serial port options)
++//!   * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
++//!     devices).
++//!   * Provide access to control functions on a device (for example, on Linux you can send
++//!     commands like pause, resume, and eject to the CDROM device.
++//!   * Do whatever else the device driver creator thought made most sense.
++//!
++//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
++//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
++//! Additionally they may read or write data and therefore need to pass along a data pointer.
++//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
++//! be difficult.
++//!
++//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
++//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
++//! subcomponents (For linux this is documented in
++//! [`Documentation/ioctl/ioctl-number.txt`](http://elixir.free-electrons.com/linux/latest/source/Documentation/ioctl/ioctl-number.txt)):
++//!
++//!   * Number: The actual ioctl ID
++//!   * Type: A grouping of ioctls for a common purpose or driver
++//!   * Size: The size in bytes of the data that will be transferred
++//!   * Direction: Whether there is any data and if it's read, write, or both
++//!
++//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
++//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
++//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
++//! commonly referred to as "bad" in `ioctl` documentation.
++//!
++//! Defining `ioctl`s
++//! =================
++//!
++//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public
++//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
++//! ways it can be used depending on the specific ioctl you're working with.
++//!
++//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
++//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
++//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
++//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
++//! const SPI_IOC_TYPE_MODE: u8 = 1;
++//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
++//! # fn main() {}
++//! ```
++//!
++//! This generates the function:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! # use std::mem;
++//! # use nix::{libc, Result};
++//! # use nix::errno::Errno;
++//! # use nix::libc::c_int as c_int;
++//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
++//! # const SPI_IOC_TYPE_MODE: u8 = 1;
++//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
++//!     let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
++//!     Errno::result(res)
++//! }
++//! # fn main() {}
++//! ```
++//!
++//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s.
++//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
++//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
++//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
++//!
++//! Writing `ioctl`s generally use pointers as their data source and these should use the
++//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the
++//! `ioctl_write_int!` macro. This variant does not take a type as the last argument:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! const HCI_IOC_MAGIC: u8 = b'k';
++//! const HCI_IOC_HCIDEVUP: u8 = 1;
++//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
++//! # fn main() {}
++//! ```
++//!
++//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro
++//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
++//!
++//! The mode for a given `ioctl` should be clear from the documentation if it has good
++//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
++//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite"
++//! 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
++//! large number of `ioctl`s and describes their argument data type.
++//!
++//! Using "bad" `ioctl`s
++//! --------------------
++//!
++//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
++//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the
++//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these
++//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
++//! the ioctl number and instead use the defined value directly.
++//!
++//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
++//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! # #[cfg(any(target_os = "android", target_os = "linux"))]
++//! # use nix::libc::TCGETS as TCGETS;
++//! # #[cfg(any(target_os = "android", target_os = "linux"))]
++//! # use nix::libc::termios as termios;
++//! # #[cfg(any(target_os = "android", target_os = "linux"))]
++//! ioctl_read_bad!(tcgets, TCGETS, termios);
++//! # fn main() {}
++//! ```
++//!
++//! The generated function has the same form as that generated by `ioctl_read!`:
++//!
++//! ```text
++//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
++//! ```
++//!
++//! Working with Arrays
++//! -------------------
++//!
++//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf`
++//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that
++//! there are no "bad" versions for working with buffers. The generated functions include a `len`
++//! argument to specify the number of elements (where the type of each element is specified in the
++//! macro).
++//!
++//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl`
++//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs.
++//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like:
++//!
++//! ```C
++//! #define SPI_IOC_MAGIC 'k'
++//! #define SPI_MSGSIZE(N) ...
++//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
++//! ```
++//!
++//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's
++//! needed to define this `ioctl` is:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
++//! const SPI_IOC_TYPE_MESSAGE: u8 = 0;
++//! # pub struct spi_ioc_transfer(u64);
++//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
++//! # fn main() {}
++//! ```
++//!
++//! This generates a function like:
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! # use std::mem;
++//! # use nix::{libc, Result};
++//! # use nix::errno::Errno;
++//! # use nix::libc::c_int as c_int;
++//! # const SPI_IOC_MAGIC: u8 = b'k';
++//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
++//! # pub struct spi_ioc_transfer(u64);
++//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
++//!     let res = libc::ioctl(fd,
++//!                           request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
++//!                           data);
++//!     Errno::result(res)
++//! }
++//! # fn main() {}
++//! ```
++//!
++//! Finding `ioctl` Documentation
++//! -----------------------------
++//!
++//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
++//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are
++//! documented directly in the headers defining their constants, but others have more extensive
++//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
++//!
++//! Documenting the Generated Functions
++//! ===================================
++//!
++//! In many cases, users will wish for the functions generated by the `ioctl`
++//! macro to be public and documented. For this reason, the generated functions
++//! are public by default. If you wish to hide the ioctl, you will need to put
++//! them in a private module.
++//!
++//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an
++//! example :
++//!
++//! ```
++//! # #[macro_use] extern crate nix;
++//! # use nix::libc::c_int;
++//! ioctl_read! {
++//!     /// Make the given terminal the controlling terminal of the calling process. The calling
++//!     /// process must be a session leader and not have a controlling terminal already. If the
++//!     /// terminal is already the controlling terminal of a different session group then the
++//!     /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
++//!     /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
++//!     /// and all processes that had it as controlling terminal lose it.
++//!     tiocsctty, b't', 19, c_int
++//! }
++//!
++//! # fn main() {}
++//! ```
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[macro_use]
++mod linux;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use self::linux::*;
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++#[macro_use]
++mod bsd;
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub use self::bsd::*;
++
++/// Convert raw ioctl return value to a Nix result
++#[macro_export]
++#[doc(hidden)]
++macro_rules! convert_ioctl_res {
++    ($w:expr) => (
++        {
++            $crate::errno::Errno::result($w)
++        }
++    );
++}
++
++/// Generates a wrapper function for an ioctl that passes no data to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as:
++///
++/// ```C
++/// #define VIDIOC_LOG_STATUS         _IO('V', 70)
++/// ```
++///
++/// This can be implemented in Rust like:
++///
++/// ```no_run
++/// # #[macro_use] extern crate nix;
++/// ioctl_none!(log_status, b'V', 70);
++/// fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_none {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
++        }
++    )
++}
++
++/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl request code
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```no_run
++/// # #[macro_use] extern crate nix;
++/// # extern crate libc;
++/// # use libc::TIOCNXCL;
++/// # use std::fs::File;
++/// # use std::os::unix::io::AsRawFd;
++/// ioctl_none_bad!(tiocnxcl, TIOCNXCL);
++/// fn main() {
++///     let file = File::open("/dev/ttyUSB0").unwrap();
++///     unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap();
++/// }
++/// ```
++// TODO: add an example using request_code_*!()
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_none_bad {
++    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that reads data from the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
++/// const SPI_IOC_TYPE_MODE: u8 = 1;
++/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_read {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *mut $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl request code
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```
++/// # extern crate libc;
++/// # #[macro_use] extern crate nix;
++/// # #[cfg(any(target_os = "android", target_os = "linux"))]
++/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_read_bad {
++    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *mut $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// # pub struct v4l2_audio {}
++/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_write_ptr {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *const $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl request code
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```
++/// # extern crate libc;
++/// # #[macro_use] extern crate nix;
++/// # #[cfg(any(target_os = "android", target_os = "linux"))]
++/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_write_ptr_bad {
++    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *const $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++cfg_if!{
++    if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
++        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
++        ///
++        /// The arguments to this macro are:
++        ///
++        /// * The function name
++        /// * The ioctl identifier
++        /// * The ioctl sequence number
++        ///
++        /// The generated function has the following signature:
++        ///
++        /// ```rust,ignore
++        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
++        /// ```
++        ///
++        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
++        /// *   BSD - `libc::c_int`
++        /// *   Linux - `libc::c_ulong`
++        ///
++        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++        ///
++        /// # Example
++        ///
++        /// ```
++        /// # #[macro_use] extern crate nix;
++        /// ioctl_write_int!(vt_activate, b'v', 4);
++        /// # fn main() {}
++        /// ```
++        #[macro_export(local_inner_macros)]
++        macro_rules! ioctl_write_int {
++            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
++                $(#[$attr])*
++                pub unsafe fn $name(fd: $crate::libc::c_int,
++                                    data: $crate::sys::ioctl::ioctl_param_type)
++                                    -> $crate::Result<$crate::libc::c_int> {
++                    convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
++                }
++            )
++        }
++    } else {
++        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
++        ///
++        /// The arguments to this macro are:
++        ///
++        /// * The function name
++        /// * The ioctl identifier
++        /// * The ioctl sequence number
++        ///
++        /// The generated function has the following signature:
++        ///
++        /// ```rust,ignore
++        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
++        /// ```
++        ///
++        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
++        /// *   BSD - `libc::c_int`
++        /// *   Linux - `libc::c_ulong`
++        ///
++        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++        ///
++        /// # Example
++        ///
++        /// ```
++        /// # #[macro_use] extern crate nix;
++        /// const HCI_IOC_MAGIC: u8 = b'k';
++        /// const HCI_IOC_HCIDEVUP: u8 = 1;
++        /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
++        /// # fn main() {}
++        /// ```
++        #[macro_export(local_inner_macros)]
++        macro_rules! ioctl_write_int {
++            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
++                $(#[$attr])*
++                pub unsafe fn $name(fd: $crate::libc::c_int,
++                                    data: $crate::sys::ioctl::ioctl_param_type)
++                                    -> $crate::Result<$crate::libc::c_int> {
++                    convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
++                }
++            )
++        }
++    }
++}
++
++/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl request code
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Examples
++///
++/// ```
++/// # extern crate libc;
++/// # #[macro_use] extern crate nix;
++/// # #[cfg(any(target_os = "android", target_os = "linux"))]
++/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
++/// # fn main() {}
++/// ```
++///
++/// ```rust
++/// # #[macro_use] extern crate nix;
++/// const KVMIO: u8 = 0xAE;
++/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_write_int_bad {
++    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: $crate::libc::c_int)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that reads and writes data to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Example
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// # pub struct v4l2_audio {}
++/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_readwrite {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *mut $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl request code
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++// TODO: Find an example for ioctl_readwrite_bad
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_readwrite_bad {
++    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: *mut $ty)
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++// TODO: Find an example for ioctl_read_buf
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_read_buf {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: &mut [$ty])
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++///
++/// # Examples
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
++/// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
++/// # pub struct spi_ioc_transfer(u64);
++/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
++/// # fn main() {}
++/// ```
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_write_buf {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: &[$ty])
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
++
++/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel.
++///
++/// The arguments to this macro are:
++///
++/// * The function name
++/// * The ioctl identifier
++/// * The ioctl sequence number
++/// * The data type passed by this ioctl
++///
++/// The generated function has the following signature:
++///
++/// ```rust,ignore
++/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
++/// ```
++///
++/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
++// TODO: Find an example for readwrite_buf
++#[macro_export(local_inner_macros)]
++macro_rules! ioctl_readwrite_buf {
++    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
++        $(#[$attr])*
++        pub unsafe fn $name(fd: $crate::libc::c_int,
++                            data: &mut [$ty])
++                            -> $crate::Result<$crate::libc::c_int> {
++            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
++        }
++    )
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/memfd.rs b/third_party/rust/nix-0.15.0/src/sys/memfd.rs
+new file mode 100644
+index 0000000000000..9672429b31e7f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/memfd.rs
+@@ -0,0 +1,20 @@
++use libc;
++use std::os::unix::io::RawFd;
++use Result;
++use errno::Errno;
++use std::ffi::CStr;
++
++libc_bitflags!(
++    pub struct MemFdCreateFlag: libc::c_uint {
++        MFD_CLOEXEC;
++        MFD_ALLOW_SEALING;
++    }
++);
++
++pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
++    let res = unsafe {
++        libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
++    };
++
++    Errno::result(res).map(|r| r as RawFd)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/mman.rs b/third_party/rust/nix-0.15.0/src/sys/mman.rs
+new file mode 100644
+index 0000000000000..4e250501dd0f0
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/mman.rs
+@@ -0,0 +1,325 @@
++use {Error, Result};
++#[cfg(not(target_os = "android"))]
++use NixPath;
++use errno::Errno;
++#[cfg(not(target_os = "android"))]
++use fcntl::OFlag;
++use libc::{self, c_int, c_void, size_t, off_t};
++#[cfg(not(target_os = "android"))]
++use sys::stat::Mode;
++use std::os::unix::io::RawFd;
++
++libc_bitflags!{
++    /// Desired memory protection of a memory mapping.
++    pub struct ProtFlags: c_int {
++        /// Pages cannot be accessed.
++        PROT_NONE;
++        /// Pages can be read.
++        PROT_READ;
++        /// Pages can be written.
++        PROT_WRITE;
++        /// Pages can be executed
++        PROT_EXEC;
++        /// Apply protection up to the end of a mapping that grows upwards.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        PROT_GROWSDOWN;
++        /// Apply protection down to the beginning of a mapping that grows downwards.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        PROT_GROWSUP;
++    }
++}
++
++libc_bitflags!{
++    /// Additional parameters for `mmap()`.
++    pub struct MapFlags: c_int {
++        /// Compatibility flag. Ignored.
++        MAP_FILE;
++        /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
++        MAP_SHARED;
++        /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
++        MAP_PRIVATE;
++        /// Place the mapping at exactly the address specified in `addr`.
++        MAP_FIXED;
++        /// Synonym for `MAP_ANONYMOUS`.
++        MAP_ANON;
++        /// The mapping is not backed by any file.
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
++        MAP_ANONYMOUS;
++        /// Put the mapping into the first 2GB of the process address space.
++        #[cfg(any(all(any(target_os = "android", target_os = "linux"),
++                      any(target_arch = "x86", target_arch = "x86_64")),
++                  all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
++                  all(target_os = "freebsd", target_pointer_width = "64")))]
++        MAP_32BIT;
++        /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_GROWSDOWN;
++        /// Compatibility flag. Ignored.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_DENYWRITE;
++        /// Compatibility flag. Ignored.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_EXECUTABLE;
++        /// Mark the mmaped region to be locked in the same way as `mlock(2)`.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_LOCKED;
++        /// Do not reserve swap space for this mapping.
++        ///
++        /// This was removed in FreeBSD 11.
++        #[cfg(not(target_os = "freebsd"))]
++        MAP_NORESERVE;
++        /// Populate page tables for a mapping.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_POPULATE;
++        /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_NONBLOCK;
++        /// Allocate the mapping using "huge pages."
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MAP_HUGETLB;
++        /// Lock the mapped region into memory as with `mlock(2)`.
++        #[cfg(target_os = "netbsd")]
++        MAP_WIRED;
++        /// Causes dirtied data in the specified range to be flushed to disk only when necessary.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        MAP_NOSYNC;
++        /// Rename private pages to a file.
++        ///
++        /// This was removed in FreeBSD 11.
++        #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
++        MAP_RENAME;
++        /// Region may contain semaphores.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
++        MAP_HASSEMAPHORE;
++        /// Region grows down, like a stack.
++        #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
++        MAP_STACK;
++        /// Pages in this mapping are not retained in the kernel's memory cache.
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MAP_NOCACHE;
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MAP_JIT;
++    }
++}
++
++libc_enum!{
++    /// Usage information for a range of memory to allow for performance optimizations by the kernel.
++    ///
++    /// Used by [`madvise`](./fn.madvise.html).
++    #[repr(i32)]
++    pub enum MmapAdvise {
++        /// No further special treatment. This is the default.
++        MADV_NORMAL,
++        /// Expect random page references.
++        MADV_RANDOM,
++        /// Expect sequential page references.
++        MADV_SEQUENTIAL,
++        /// Expect access in the near future.
++        MADV_WILLNEED,
++        /// Do not expect access in the near future.
++        MADV_DONTNEED,
++        /// Free up a given range of pages and its associated backing store.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_REMOVE,
++        /// Do not make pages in this range available to the child after a `fork(2)`.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_DONTFORK,
++        /// Undo the effect of `MADV_DONTFORK`.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_DOFORK,
++        /// Poison the given pages.
++        ///
++        /// Subsequent references to those pages are treated like hardware memory corruption.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_HWPOISON,
++        /// Enable Kernel Samepage Merging (KSM) for the given pages.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_MERGEABLE,
++        /// Undo the effect of `MADV_MERGEABLE`
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_UNMERGEABLE,
++        /// Preserve the memory of each page but offline the original page.
++        #[cfg(any(target_os = "android",
++            all(target_os = "linux", any(
++                target_arch = "aarch64",
++                target_arch = "arm",
++                target_arch = "ppc",
++                target_arch = "s390x",
++                target_arch = "x86",
++                target_arch = "x86_64",
++                target_arch = "sparc64"))))]
++        MADV_SOFT_OFFLINE,
++        /// Enable Transparent Huge Pages (THP) for pages in the given range.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_HUGEPAGE,
++        /// Undo the effect of `MADV_HUGEPAGE`.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_NOHUGEPAGE,
++        /// Exclude the given range from a core dump.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_DONTDUMP,
++        /// Undo the effect of an earlier `MADV_DONTDUMP`.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MADV_DODUMP,
++        /// Specify that the application no longer needs the pages in the given range.
++        MADV_FREE,
++        /// Request that the system not flush the current range to disk unless it needs to.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        MADV_NOSYNC,
++        /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        MADV_AUTOSYNC,
++        /// Region is not included in a core file.
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        MADV_NOCORE,
++        /// Include region in a core file
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        MADV_CORE,
++        #[cfg(any(target_os = "freebsd"))]
++        MADV_PROTECT,
++        /// Invalidate the hardware page table for the given region.
++        #[cfg(target_os = "dragonfly")]
++        MADV_INVAL,
++        /// Set the offset of the page directory page to `value` for the virtual page table.
++        #[cfg(target_os = "dragonfly")]
++        MADV_SETMAP,
++        /// Indicates that the application will not need the data in the given range.
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MADV_ZERO_WIRED_PAGES,
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MADV_FREE_REUSABLE,
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MADV_FREE_REUSE,
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MADV_CAN_REUSE,
++    }
++}
++
++libc_bitflags!{
++    /// Configuration flags for `msync`.
++    pub struct MsFlags: c_int {
++        /// Schedule an update but return immediately.
++        MS_ASYNC;
++        /// Invalidate all cached data.
++        MS_INVALIDATE;
++        /// Invalidate pages, but leave them mapped.
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MS_KILLPAGES;
++        /// Deactivate pages, but leave them mapped.
++        #[cfg(any(target_os = "ios", target_os = "macos"))]
++        MS_DEACTIVATE;
++        /// Perform an update and wait for it to complete.
++        MS_SYNC;
++    }
++}
++
++libc_bitflags!{
++    /// Flags for `mlockall`.
++    pub struct MlockAllFlags: c_int {
++        /// Lock pages that are currently mapped into the address space of the process.
++        MCL_CURRENT;
++        /// Lock pages which will become mapped into the address space of the process in the future.
++        MCL_FUTURE;
++    }
++}
++
++/// Locks all memory pages that contain part of the address range with `length` bytes starting at
++/// `addr`. Locked pages never move to the swap area.
++pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
++    Errno::result(libc::mlock(addr, length)).map(drop)
++}
++
++/// Unlocks all memory pages that contain part of the address range with `length` bytes starting at
++/// `addr`.
++pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
++    Errno::result(libc::munlock(addr, length)).map(drop)
++}
++
++/// Locks all memory pages mapped into this process' address space. Locked pages never move to the
++/// swap area.
++pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
++    unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
++}
++
++/// Unlocks all memory pages mapped into this process' address space.
++pub fn munlockall() -> Result<()> {
++    unsafe { Errno::result(libc::munlockall()) }.map(drop)
++}
++
++/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
++/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
++pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
++    let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
++
++    if ret == libc::MAP_FAILED {
++        Err(Error::Sys(Errno::last()))
++    } else {
++        Ok(ret)
++    }
++}
++
++pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
++    Errno::result(libc::munmap(addr, len)).map(drop)
++}
++
++pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
++    Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
++}
++
++/// Set protection of memory mapping.
++///
++/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
++/// details.
++///
++/// # Safety
++///
++/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to
++/// SIGSEGVs.
++///
++/// ```
++/// # use nix::libc::size_t;
++/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
++/// # use std::ptr;
++/// const ONE_K: size_t = 1024;
++/// let mut slice: &mut [u8] = unsafe {
++///     let mem = mmap(ptr::null_mut(), ONE_K, ProtFlags::PROT_NONE,
++///                    MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
++///     mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
++///     std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
++/// };
++/// assert_eq!(slice[0], 0x00);
++/// slice[0] = 0xFF;
++/// assert_eq!(slice[0], 0xFF);
++/// ```
++pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> {
++    Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
++}
++
++pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
++    Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
++}
++
++#[cfg(not(target_os = "android"))]
++pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
++    let ret = name.with_nix_path(|cstr| {
++        #[cfg(any(target_os = "macos", target_os = "ios"))]
++        unsafe {
++            libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
++        }
++        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
++        unsafe {
++            libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
++        }
++    })?;
++
++    Errno::result(ret)
++}
++
++#[cfg(not(target_os = "android"))]
++pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
++    let ret = name.with_nix_path(|cstr| {
++        unsafe { libc::shm_unlink(cstr.as_ptr()) }
++    })?;
++
++    Errno::result(ret).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/mod.rs b/third_party/rust/nix-0.15.0/src/sys/mod.rs
+new file mode 100644
+index 0000000000000..d3c2f92bbaaea
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/mod.rs
+@@ -0,0 +1,100 @@
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd"))]
++pub mod aio;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod epoll;
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub mod event;
++
++#[cfg(target_os = "linux")]
++pub mod eventfd;
++
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++#[macro_use]
++pub mod ioctl;
++
++#[cfg(target_os = "linux")]
++pub mod memfd;
++
++pub mod mman;
++
++pub mod pthread;
++
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub mod ptrace;
++
++#[cfg(target_os = "linux")]
++pub mod quota;
++
++#[cfg(any(target_os = "linux"))]
++pub mod reboot;
++
++pub mod select;
++
++#[cfg(any(target_os = "android",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos"))]
++pub mod sendfile;
++
++pub mod signal;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod signalfd;
++
++pub mod socket;
++
++pub mod stat;
++
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "openbsd"
++))]
++pub mod statfs;
++
++pub mod statvfs;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod sysinfo;
++
++pub mod termios;
++
++pub mod time;
++
++pub mod uio;
++
++pub mod utsname;
++
++pub mod wait;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod inotify;
+diff --git a/third_party/rust/nix-0.15.0/src/sys/pthread.rs b/third_party/rust/nix-0.15.0/src/sys/pthread.rs
+new file mode 100644
+index 0000000000000..a4d98250f2b8b
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/pthread.rs
+@@ -0,0 +1,13 @@
++use libc::{self, pthread_t};
++
++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)
++///
++/// The thread ID returned by `pthread_self()` is not the same thing as
++/// the kernel thread ID returned by a call to `gettid(2)`.
++#[inline]
++pub fn pthread_self() -> Pthread {
++    unsafe { libc::pthread_self() }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
+new file mode 100644
+index 0000000000000..7797d10647ef4
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
+@@ -0,0 +1,170 @@
++use errno::Errno;
++use libc::{self, c_int};
++use std::ptr;
++use sys::signal::Signal;
++use unistd::Pid;
++use Result;
++
++pub type RequestType = c_int;
++
++cfg_if! {
++    if #[cfg(any(target_os = "dragonfly", 
++                 target_os = "freebsd", 
++                 target_os = "macos",
++                 target_os = "openbsd"))] {
++        #[doc(hidden)]
++        pub type AddressType = *mut ::libc::c_char;
++    } else {
++        #[doc(hidden)]
++        pub type AddressType = *mut ::libc::c_void;
++    }
++}
++
++libc_enum! {
++    #[repr(i32)]
++    /// Ptrace Request enum defining the action to be taken.
++    pub enum Request {
++        PT_TRACE_ME,
++        PT_READ_I,
++        PT_READ_D,
++        #[cfg(target_os = "macos")]
++        PT_READ_U,
++        PT_WRITE_I,
++        PT_WRITE_D,
++        #[cfg(target_os = "macos")]
++        PT_WRITE_U,
++        PT_CONTINUE,
++        PT_KILL,
++        #[cfg(any(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos"),
++                  all(target_os = "openbsd", target_arch = "x86_64"),
++                  all(target_os = "netbsd", any(target_arch = "x86_64",
++                                                target_arch = "powerpc"))))]
++        PT_STEP,
++        PT_ATTACH,
++        PT_DETACH,
++        #[cfg(target_os = "macos")]
++        PT_SIGEXC,
++        #[cfg(target_os = "macos")]
++        PT_THUPDATE,
++        #[cfg(target_os = "macos")]
++        PT_ATTACHEXC
++    }
++}
++
++unsafe fn ptrace_other(
++    request: Request,
++    pid: Pid,
++    addr: AddressType,
++    data: c_int,
++) -> Result<c_int> {
++    Errno::result(libc::ptrace(
++        request as RequestType,
++        libc::pid_t::from(pid),
++        addr,
++        data,
++    )).map(|_| 0)
++}
++
++/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
++///
++/// Indicates that this process is to be traced by its parent.
++/// This is the only ptrace request to be issued by the tracee.
++pub fn traceme() -> Result<()> {
++    unsafe { ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0).map(drop) }
++}
++
++/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
++///
++/// Attaches to the process specified in pid, making it a tracee of the calling process.
++pub fn attach(pid: Pid) -> Result<()> {
++    unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
++}
++
++/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
++///
++/// Detaches from the process specified in pid allowing it to run freely
++pub fn detach(pid: Pid) -> Result<()> {
++    unsafe { ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), 0).map(drop) }
++}
++
++/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
++///
++/// Continues the execution of the process with PID `pid`, optionally
++/// delivering a signal specified by `sig`.
++pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as c_int,
++        None => 0,
++    };
++    unsafe {
++        // Ignore the useless return value
++        ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data).map(drop)
++    }
++}
++
++/// Issues a kill request as with `ptrace(PT_KILL, ...)`
++///
++/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);` 
++pub fn kill(pid: Pid) -> Result<()> {
++    unsafe {
++        ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop)
++    }
++}
++
++/// Move the stopped tracee process forward by a single step as with
++/// `ptrace(PT_STEP, ...)`
++///
++/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
++/// signal specified by `sig`.
++///
++/// # Example
++/// ```rust
++/// extern crate nix;
++/// use nix::sys::ptrace::step;
++/// 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);
++///         }
++///         _ => {},
++///     }
++/// }
++/// ```
++#[cfg(
++    any(
++        any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
++        all(target_os = "openbsd", target_arch = "x86_64"),
++        all(target_os = "netbsd",
++            any(target_arch = "x86_64", target_arch = "powerpc")
++        )
++    )
++)]
++pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as c_int,
++        None => 0,
++    };
++    unsafe { ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop) }
++}
++
++/// Reads a word from a processes memory at the given address
++pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
++    unsafe {
++        // Traditionally there was a difference between reading data or
++        // instruction memory but not in modern systems.
++        ptrace_other(Request::PT_READ_D, pid, addr, 0)
++    }
++}
++
++/// Writes a word into the processes memory at the given address
++pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> {
++    unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
+new file mode 100644
+index 0000000000000..df15e66527562
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
+@@ -0,0 +1,402 @@
++//! For detailed description of the ptrace requests, consult `man ptrace`.
++
++use std::{mem, ptr};
++use {Error, Result};
++use errno::Errno;
++use libc::{self, c_void, c_long, siginfo_t};
++use ::unistd::Pid;
++use sys::signal::Signal;
++
++pub type AddressType = *mut ::libc::c_void;
++
++#[cfg(all(target_os = "linux",
++          any(target_arch = "x86_64",
++              target_arch = "x86"),
++          target_env = "gnu"))]
++use libc::user_regs_struct;
++
++cfg_if! {
++    if #[cfg(any(all(target_os = "linux", target_arch = "s390x"),
++                 all(target_os = "linux", target_env = "gnu")))] {
++        #[doc(hidden)]
++        pub type RequestType = ::libc::c_uint;
++    } else {
++        #[doc(hidden)]
++        pub type RequestType = ::libc::c_int;
++    }
++}
++
++libc_enum!{
++    #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
++    #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
++    /// Ptrace Request enum defining the action to be taken.
++    pub enum Request {
++        PTRACE_TRACEME,
++        PTRACE_PEEKTEXT,
++        PTRACE_PEEKDATA,
++        PTRACE_PEEKUSER,
++        PTRACE_POKETEXT,
++        PTRACE_POKEDATA,
++        PTRACE_POKEUSER,
++        PTRACE_CONT,
++        PTRACE_KILL,
++        PTRACE_SINGLESTEP,
++        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
++                  all(target_os = "linux", any(target_env = "musl",
++                                               target_arch = "mips",
++                                               target_arch = "mips64",
++                                               target_arch = "x86_64",
++                                               target_pointer_width = "32"))))]
++        PTRACE_GETREGS,
++        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
++                  all(target_os = "linux", any(target_env = "musl",
++                                               target_arch = "mips",
++                                               target_arch = "mips64",
++                                               target_arch = "x86_64",
++                                               target_pointer_width = "32"))))]
++        PTRACE_SETREGS,
++        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
++                  all(target_os = "linux", any(target_env = "musl",
++                                               target_arch = "mips",
++                                               target_arch = "mips64",
++                                               target_arch = "x86_64",
++                                               target_pointer_width = "32"))))]
++        PTRACE_GETFPREGS,
++        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
++                  all(target_os = "linux", any(target_env = "musl",
++                                               target_arch = "mips",
++                                               target_arch = "mips64",
++                                               target_arch = "x86_64",
++                                               target_pointer_width = "32"))))]
++        PTRACE_SETFPREGS,
++        PTRACE_ATTACH,
++        PTRACE_DETACH,
++        #[cfg(all(target_os = "linux", any(target_env = "musl",
++                                           target_arch = "mips",
++                                           target_arch = "mips64",
++                                           target_arch = "x86",
++                                           target_arch = "x86_64")))]
++        PTRACE_GETFPXREGS,
++        #[cfg(all(target_os = "linux", any(target_env = "musl",
++                                           target_arch = "mips",
++                                           target_arch = "mips64",
++                                           target_arch = "x86",
++                                           target_arch = "x86_64")))]
++        PTRACE_SETFPXREGS,
++        PTRACE_SYSCALL,
++        PTRACE_SETOPTIONS,
++        PTRACE_GETEVENTMSG,
++        PTRACE_GETSIGINFO,
++        PTRACE_SETSIGINFO,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_GETREGSET,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_SETREGSET,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_SEIZE,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_INTERRUPT,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_LISTEN,
++        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
++                                               target_arch = "mips64"))))]
++        PTRACE_PEEKSIGINFO,
++    }
++}
++
++libc_enum!{
++    #[repr(i32)]
++    /// Using the ptrace options the tracer can configure the tracee to stop
++    /// at certain events. This enum is used to define those events as defined
++    /// in `man ptrace`.
++    pub enum Event {
++        /// Event that stops before a return from fork or clone.
++        PTRACE_EVENT_FORK,
++        /// Event that stops before a return from vfork or clone.
++        PTRACE_EVENT_VFORK,
++        /// Event that stops before a return from clone.
++        PTRACE_EVENT_CLONE,
++        /// Event that stops before a return from execve.
++        PTRACE_EVENT_EXEC,
++        /// Event for a return from vfork.
++        PTRACE_EVENT_VFORK_DONE,
++        /// Event for a stop before an exit. Unlike the waitpid Exit status program.
++        /// registers can still be examined
++        PTRACE_EVENT_EXIT,
++        /// STop triggered by a seccomp rule on a tracee.
++        PTRACE_EVENT_SECCOMP,
++        // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
++    }
++}
++
++libc_bitflags! {
++    /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
++    /// See `man ptrace` for more details.
++    pub struct Options: libc::c_int {
++        /// When delivering system call traps set a bit to allow tracer to
++        /// distinguish between normal stops or syscall stops. May not work on
++        /// all systems.
++        PTRACE_O_TRACESYSGOOD;
++        /// Stop tracee at next fork and start tracing the forked process.
++        PTRACE_O_TRACEFORK;
++        /// Stop tracee at next vfork call and trace the vforked process.
++        PTRACE_O_TRACEVFORK;
++        /// Stop tracee at next clone call and trace the cloned process.
++        PTRACE_O_TRACECLONE;
++        /// Stop tracee at next execve call.
++        PTRACE_O_TRACEEXEC;
++        /// Stop tracee at vfork completion.
++        PTRACE_O_TRACEVFORKDONE;
++        /// Stop tracee at next exit call. Stops before exit commences allowing
++        /// tracer to see location of exit and register states.
++        PTRACE_O_TRACEEXIT;
++        /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
++        /// details.
++        PTRACE_O_TRACESECCOMP;
++        /// Send a SIGKILL to the tracee if the tracer exits.  This is useful
++        /// for ptrace jailers to prevent tracees from escaping their control.
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        PTRACE_O_EXITKILL;
++    }
++}
++
++/// Performs a ptrace request. If the request in question is provided by a specialised function
++/// this function will return an unsupported operation error.
++#[deprecated(
++    since="0.10.0",
++    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
++)]
++pub unsafe fn ptrace(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
++    use self::Request::*;
++    match request {
++        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_GETSIGINFO | 
++            PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS | 
++            PTRACE_POKETEXT | PTRACE_POKEDATA | PTRACE_KILL => Err(Error::UnsupportedOperation),
++        _ => ptrace_other(request, pid, addr, data)
++    }
++}
++
++fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
++    let ret = unsafe {
++        Errno::clear();
++        libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
++    };
++    match Errno::result(ret) {
++        Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
++        err @ Err(..) => err,
++    }
++}
++
++/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
++#[cfg(all(target_os = "linux",
++          any(target_arch = "x86_64",
++              target_arch = "x86"),
++          target_env = "gnu"))]
++pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
++    ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
++}
++
++/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
++#[cfg(all(target_os = "linux",
++          any(target_arch = "x86_64",
++              target_arch = "x86"),
++          target_env = "gnu"))]
++pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
++    let res = unsafe {
++        libc::ptrace(Request::PTRACE_SETREGS as RequestType,
++                     libc::pid_t::from(pid),
++                     ptr::null_mut::<c_void>(),
++                     &regs as *const _ as *const c_void)
++    };
++    Errno::result(res).map(drop)
++}
++
++/// Function for ptrace requests that return values from the data field.
++/// Some ptrace get requests populate structs or larger elements than `c_long`
++/// and therefore use the data field to return values. This function handles these
++/// requests.
++fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
++    // Creates an uninitialized pointer to store result in
++    let data: T = unsafe { mem::uninitialized() };
++    let res = unsafe {
++        libc::ptrace(request as RequestType,
++                     libc::pid_t::from(pid),
++                     ptr::null_mut::<T>(),
++                     &data as *const _ as *const c_void)
++    };
++    Errno::result(res)?;
++    Ok(data)
++}
++
++unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
++    Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
++}
++
++/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
++pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
++    let res = unsafe {
++        libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
++                     libc::pid_t::from(pid),
++                     ptr::null_mut::<c_void>(),
++                     options.bits() as *mut c_void)
++    };
++    Errno::result(res).map(drop)
++}
++
++/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
++pub fn getevent(pid: Pid) -> Result<c_long> {
++    ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
++}
++
++/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
++pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
++    ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
++}
++
++/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
++pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
++    let ret = unsafe{
++        Errno::clear();
++        libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
++                     libc::pid_t::from(pid),
++                     ptr::null_mut::<c_void>(),
++                     sig as *const _ as *const c_void)
++    };
++    match Errno::result(ret) {
++        Ok(_) => Ok(()),
++        Err(e) => Err(e),
++    }
++}
++
++/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
++///
++/// Indicates that this process is to be traced by its parent.
++/// This is the only ptrace request to be issued by the tracee.
++pub fn traceme() -> Result<()> {
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_TRACEME,
++            Pid::from_raw(0),
++            ptr::null_mut(),
++            ptr::null_mut(),
++        ).map(drop) // ignore the useless return value
++    }
++}
++
++/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
++///
++/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
++pub fn syscall(pid: Pid) -> Result<()> {
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_SYSCALL,
++            pid,
++            ptr::null_mut(),
++            ptr::null_mut(),
++        ).map(drop) // ignore the useless return value
++    }
++}
++
++/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
++///
++/// Attaches to the process specified in pid, making it a tracee of the calling process.
++pub fn attach(pid: Pid) -> Result<()> {
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_ATTACH,
++            pid,
++            ptr::null_mut(),
++            ptr::null_mut(),
++        ).map(drop) // ignore the useless return value
++    }
++}
++
++/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
++///
++/// Detaches from the process specified in pid allowing it to run freely
++pub fn detach(pid: Pid) -> Result<()> {
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_DETACH,
++            pid,
++            ptr::null_mut(),
++            ptr::null_mut()
++        ).map(drop)
++    }
++}
++
++/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
++///
++/// Continues the execution of the process with PID `pid`, optionally
++/// delivering a signal specified by `sig`.
++pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
++    unsafe {
++        ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop) // ignore the useless return value
++    }
++}
++
++/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
++///
++/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
++pub fn kill(pid: Pid) -> Result<()> {
++    unsafe {
++        ptrace_other(Request::PTRACE_KILL, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
++    }
++}
++
++/// Move the stopped tracee process forward by a single step as with 
++/// `ptrace(PTRACE_SINGLESTEP, ...)`
++///
++/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
++/// signal specified by `sig`.
++///
++/// # Example
++/// ```rust
++/// extern crate nix;
++/// use nix::sys::ptrace::step;
++/// 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);
++///         }
++///         _ => {},
++///     }
++/// }
++/// ```
++pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
++    unsafe {
++        ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(drop)
++    }
++}
++
++
++/// Reads a word from a processes memory at the given address
++pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
++    ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut())
++}
++
++/// Writes a word into the processes memory at the given address
++pub fn write(pid: Pid, addr: AddressType, data: *mut c_void) -> Result<()> {
++    unsafe {
++        ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
+new file mode 100644
+index 0000000000000..782c30409bc12
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
+@@ -0,0 +1,22 @@
++///! Provides helpers for making ptrace system calls 
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod linux;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use self::linux::*;
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++mod bsd;
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"
++          ))]
++pub use self::bsd::*;
+diff --git a/third_party/rust/nix-0.15.0/src/sys/quota.rs b/third_party/rust/nix-0.15.0/src/sys/quota.rs
+new file mode 100644
+index 0000000000000..8946fca2213c8
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/quota.rs
+@@ -0,0 +1,273 @@
++//! Set and configure disk quotas for users, groups, or projects.
++//!
++//! # Examples
++//!
++//! Enabling and setting a quota:
++//!
++//! ```rust,no_run
++//! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags};
++//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user");
++//! let mut dqblk: Dqblk = Default::default();
++//! dqblk.set_blocks_hard_limit(10000);
++//! dqblk.set_blocks_soft_limit(8000);
++//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS);
++//! ```
++use std::default::Default;
++use std::{mem, ptr};
++use libc::{self, c_int, c_char};
++use {Result, NixPath};
++use errno::Errno;
++
++struct QuotaCmd(QuotaSubCmd, QuotaType);
++
++impl QuotaCmd {
++    fn as_int(&self) -> c_int {
++        unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
++    }
++}
++
++// linux quota version >= 2
++libc_enum!{
++    #[repr(i32)]
++    enum QuotaSubCmd {
++        Q_SYNC,
++        Q_QUOTAON,
++        Q_QUOTAOFF,
++        Q_GETQUOTA,
++        Q_SETQUOTA,
++    }
++}
++
++libc_enum!{
++    /// The scope of the quota.
++    #[repr(i32)]
++    pub enum QuotaType {
++        /// Specify a user quota
++        USRQUOTA,
++        /// Specify a group quota
++        GRPQUOTA,
++    }
++}
++
++libc_enum!{
++    /// The type of quota format to use.
++    #[repr(i32)]
++    pub enum QuotaFmt {
++        /// Use the original quota format.
++        QFMT_VFS_OLD,
++        /// Use the standard VFS v0 quota format.
++        ///
++        /// Handles 32-bit UIDs/GIDs and quota limits up to 2<sup>32</sup> bytes/2<sup>32</sup> inodes.
++        QFMT_VFS_V0,
++        /// Use the VFS v1 quota format.
++        ///
++        /// Handles 32-bit UIDs/GIDs and quota limits of 2<sup>64</sup> bytes/2<sup>64</sup> inodes.
++        QFMT_VFS_V1,
++    }
++}
++
++libc_bitflags!(
++    /// Indicates the quota fields that are valid to read from.
++    #[derive(Default)]
++    pub struct QuotaValidFlags: u32 {
++        /// The block hard & soft limit fields.
++        QIF_BLIMITS;
++        /// The current space field.
++        QIF_SPACE;
++        /// The inode hard & soft limit fields.
++        QIF_ILIMITS;
++        /// The current inodes field.
++        QIF_INODES;
++        /// The disk use time limit field.
++        QIF_BTIME;
++        /// The file quote time limit field.
++        QIF_ITIME;
++        /// All block & inode limits.
++        QIF_LIMITS;
++        /// The space & inodes usage fields.
++        QIF_USAGE;
++        /// The time limit fields.
++        QIF_TIMES;
++        /// All fields.
++        QIF_ALL;
++    }
++);
++
++/// Wrapper type for `if_dqblk`
++// FIXME: Change to repr(transparent)
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct Dqblk(libc::dqblk);
++
++impl Default for Dqblk {
++    fn default() -> Dqblk {
++        Dqblk(libc::dqblk {
++            dqb_bhardlimit: 0,
++            dqb_bsoftlimit: 0,
++            dqb_curspace: 0,
++            dqb_ihardlimit: 0,
++            dqb_isoftlimit: 0,
++            dqb_curinodes: 0,
++            dqb_btime: 0,
++            dqb_itime: 0,
++            dqb_valid: 0,
++        })
++    }
++}
++
++impl Dqblk {
++    /// The absolute limit on disk quota blocks allocated.
++    pub fn blocks_hard_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
++            Some(self.0.dqb_bhardlimit)
++        } else {
++            None
++        }
++    }
++
++    /// Set the absolute limit on disk quota blocks allocated.
++    pub fn set_blocks_hard_limit(&mut self, limit: u64) {
++        self.0.dqb_bhardlimit = limit;
++    }
++
++    /// Preferred limit on disk quota blocks
++    pub fn blocks_soft_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
++            Some(self.0.dqb_bsoftlimit)
++        } else {
++            None
++        }
++    }
++
++    /// Set the preferred limit on disk quota blocks allocated.
++    pub fn set_blocks_soft_limit(&mut self, limit: u64) {
++        self.0.dqb_bsoftlimit = limit;
++    }
++
++    /// Current occupied space (bytes).
++    pub fn occupied_space(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_SPACE) {
++            Some(self.0.dqb_curspace)
++        } else {
++            None
++        }
++    }
++
++    /// Maximum number of allocated inodes.
++    pub fn inodes_hard_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
++            Some(self.0.dqb_ihardlimit)
++        } else {
++            None
++        }
++    }
++
++    /// Set the maximum number of allocated inodes.
++    pub fn set_inodes_hard_limit(&mut self, limit: u64) {
++        self.0.dqb_ihardlimit = limit;
++    }
++
++    /// Preferred inode limit
++    pub fn inodes_soft_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
++            Some(self.0.dqb_isoftlimit)
++        } else {
++            None
++        }
++    }
++
++    /// Set the preferred limit of allocated inodes.
++    pub fn set_inodes_soft_limit(&mut self, limit: u64) {
++        self.0.dqb_isoftlimit = limit;
++    }
++
++    /// Current number of allocated inodes.
++    pub fn allocated_inodes(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_INODES) {
++            Some(self.0.dqb_curinodes)
++        } else {
++            None
++        }
++    }
++
++    /// Time limit for excessive disk use.
++    pub fn block_time_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_BTIME) {
++            Some(self.0.dqb_btime)
++        } else {
++            None
++        }
++    }
++
++    /// Set the time limit for excessive disk use.
++    pub fn set_block_time_limit(&mut self, limit: u64) {
++        self.0.dqb_btime = limit;
++    }
++
++    /// Time limit for excessive files.
++    pub fn inode_time_limit(&self) -> Option<u64> {
++        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
++        if valid_fields.contains(QuotaValidFlags::QIF_ITIME) {
++            Some(self.0.dqb_itime)
++        } else {
++            None
++        }
++    }
++
++    /// Set the time limit for excessive files.
++    pub fn set_inode_time_limit(&mut self, limit: u64) {
++        self.0.dqb_itime = limit;
++    }
++}
++
++fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
++    unsafe {
++        Errno::clear();
++        let res = match special {
++            Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)),
++            None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)),
++        }?;
++
++        Errno::result(res).map(drop)
++    }
++}
++
++/// Turn on disk quotas for a block device.
++pub fn quotactl_on<P: ?Sized + NixPath>(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> {
++    quota_file.with_nix_path(|path| {
++        let mut path_copy = path.to_bytes_with_nul().to_owned();
++        let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
++        quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p)
++    })?
++}
++
++/// Disable disk quotas for a block device.
++pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Result<()> {
++    quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
++}
++
++/// Update the on-disk copy of quota usages for a filesystem.
++pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
++    quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
++}
++
++/// Get disk quota limits and current usage for the given user/group id.
++pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
++    let mut dqblk = unsafe { mem::uninitialized() };
++    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?;
++    dqblk
++}
++
++/// Configure quota values for the specified fields for a given user/group id.
++pub fn quotactl_set<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> {
++    let mut dqblk_copy = *dqblk;
++    dqblk_copy.0.dqb_valid = fields.bits();
++    quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/reboot.rs b/third_party/rust/nix-0.15.0/src/sys/reboot.rs
+new file mode 100644
+index 0000000000000..bafa8fc11996d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/reboot.rs
+@@ -0,0 +1,45 @@
++//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
++
++use {Error, Result};
++use errno::Errno;
++use libc;
++use void::Void;
++use std::mem::drop;
++
++libc_enum! {
++    /// How exactly should the system be rebooted.
++    ///
++    /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
++    /// enabling/disabling Ctrl-Alt-Delete.
++    #[repr(i32)]
++    pub enum RebootMode {
++        RB_HALT_SYSTEM,
++        RB_KEXEC,
++        RB_POWER_OFF,
++        RB_AUTOBOOT,
++        // we do not support Restart2,
++        RB_SW_SUSPEND,
++    }
++}
++
++pub fn reboot(how: RebootMode) -> Result<Void> {
++    unsafe {
++        libc::reboot(how as libc::c_int)
++    };
++    Err(Error::Sys(Errno::last()))
++}
++
++/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
++///
++/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
++pub fn set_cad_enabled(enable: bool) -> Result<()> {
++    let cmd = if enable {
++        libc::RB_ENABLE_CAD
++    } else {
++        libc::RB_DISABLE_CAD
++    };
++    let res = unsafe {
++        libc::reboot(cmd)
++    };
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/select.rs b/third_party/rust/nix-0.15.0/src/sys/select.rs
+new file mode 100644
+index 0000000000000..1b518e29f67a6
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/select.rs
+@@ -0,0 +1,334 @@
++use std::mem;
++use std::os::unix::io::RawFd;
++use std::ptr::{null, null_mut};
++use libc::{self, c_int};
++use Result;
++use errno::Errno;
++use sys::signal::SigSet;
++use sys::time::{TimeSpec, TimeVal};
++
++pub use libc::FD_SETSIZE;
++
++// FIXME: Change to repr(transparent) once it's stable
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct FdSet(libc::fd_set);
++
++impl FdSet {
++    pub fn new() -> FdSet {
++        let mut fdset = unsafe { mem::uninitialized() };
++        unsafe { libc::FD_ZERO(&mut fdset) };
++        FdSet(fdset)
++    }
++
++    pub fn insert(&mut self, fd: RawFd) {
++        unsafe { libc::FD_SET(fd, &mut self.0) };
++    }
++
++    pub fn remove(&mut self, fd: RawFd) {
++        unsafe { libc::FD_CLR(fd, &mut self.0) };
++    }
++
++    pub fn contains(&mut self, fd: RawFd) -> bool {
++        unsafe { libc::FD_ISSET(fd, &mut self.0) }
++    }
++
++    pub fn clear(&mut self) {
++        unsafe { libc::FD_ZERO(&mut self.0) };
++    }
++
++    /// Finds the highest file descriptor in the set.
++    ///
++    /// Returns `None` if the set is empty.
++    ///
++    /// This can be used to calculate the `nfds` parameter of the [`select`] function.
++    ///
++    /// # Example
++    ///
++    /// ```
++    /// # extern crate nix;
++    /// # use nix::sys::select::FdSet;
++    /// # fn main() {
++    /// let mut set = FdSet::new();
++    /// set.insert(4);
++    /// set.insert(9);
++    /// assert_eq!(set.highest(), Some(9));
++    /// # }
++    /// ```
++    ///
++    /// [`select`]: fn.select.html
++    pub fn highest(&mut self) -> Option<RawFd> {
++        for i in (0..FD_SETSIZE).rev() {
++            let i = i as RawFd;
++            if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
++                return Some(i)
++            }
++        }
++
++        None
++    }
++}
++
++/// Monitors file descriptors for readiness
++///
++/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
++/// file descriptors that are ready for the given operation are set.
++///
++/// When this function returns, `timeout` has an implementation-defined value.
++///
++/// # Parameters
++///
++/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
++///   is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
++///   to the maximum of that.
++/// * `readfds`: File descriptors to check for being ready to read.
++/// * `writefds`: File descriptors to check for being ready to write.
++/// * `errorfds`: File descriptors to check for pending error conditions.
++/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
++///   indefinitely).
++///
++/// # References
++///
++/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
++///
++/// [`FdSet::highest`]: struct.FdSet.html#method.highest
++pub fn select<'a, N, R, W, E, T>(nfds: N,
++                                 readfds: R,
++                                 writefds: W,
++                                 errorfds: E,
++                                 timeout: T) -> Result<c_int>
++where
++    N: Into<Option<c_int>>,
++    R: Into<Option<&'a mut FdSet>>,
++    W: Into<Option<&'a mut FdSet>>,
++    E: Into<Option<&'a mut FdSet>>,
++    T: Into<Option<&'a mut TimeVal>>,
++{
++    let mut readfds = readfds.into();
++    let mut writefds = writefds.into();
++    let mut errorfds = errorfds.into();
++    let timeout = timeout.into();
++
++    let nfds = nfds.into().unwrap_or_else(|| {
++        readfds.iter_mut()
++            .chain(writefds.iter_mut())
++            .chain(errorfds.iter_mut())
++            .map(|set| set.highest().unwrap_or(-1))
++            .max()
++            .unwrap_or(-1) + 1
++    });
++
++    let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
++                         .unwrap_or(null_mut());
++
++    let res = unsafe {
++        libc::select(nfds, readfds, writefds, errorfds, timeout)
++    };
++
++    Errno::result(res)
++}
++
++/// Monitors file descriptors for readiness with an altered signal mask.
++///
++/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
++/// file descriptors that are ready for the given operation are set.
++///
++/// When this function returns, the original signal mask is restored.
++///
++/// Unlike [`select`](#fn.select), `pselect` does not mutate the `timeout` value.
++///
++/// # Parameters
++///
++/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
++///   is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
++///   to the maximum of that.
++/// * `readfds`: File descriptors to check for read readiness
++/// * `writefds`: File descriptors to check for write readiness
++/// * `errorfds`: File descriptors to check for pending error conditions.
++/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
++///   indefinitely).
++/// * `sigmask`: Signal mask to activate while waiting for file descriptors to turn
++///    ready (`None` to set no alternative signal mask).
++///
++/// # References
++///
++/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
++///
++/// [The new pselect() system call](https://lwn.net/Articles/176911/)
++///
++/// [`FdSet::highest`]: struct.FdSet.html#method.highest
++pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
++                                     readfds: R,
++                                     writefds: W,
++                                     errorfds: E,
++                                     timeout: T,
++                                     sigmask: S) -> Result<c_int>
++where
++    N: Into<Option<c_int>>,
++    R: Into<Option<&'a mut FdSet>>,
++    W: Into<Option<&'a mut FdSet>>,
++    E: Into<Option<&'a mut FdSet>>,
++    T: Into<Option<&'a TimeSpec>>,
++    S: Into<Option<&'a SigSet>>,
++{
++    let mut readfds = readfds.into();
++    let mut writefds = writefds.into();
++    let mut errorfds = errorfds.into();
++    let sigmask = sigmask.into();
++    let timeout = timeout.into();
++
++    let nfds = nfds.into().unwrap_or_else(|| {
++        readfds.iter_mut()
++            .chain(writefds.iter_mut())
++            .chain(errorfds.iter_mut())
++            .map(|set| set.highest().unwrap_or(-1))
++            .max()
++            .unwrap_or(-1) + 1
++    });
++
++    let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
++    let timeout = timeout.map(|ts| ts.as_ref() as *const libc::timespec).unwrap_or(null());
++    let sigmask = sigmask.map(|sm| sm.as_ref() as *const libc::sigset_t).unwrap_or(null());
++
++    let res = unsafe {
++        libc::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask)
++    };
++
++    Errno::result(res)
++}
++
++
++#[cfg(test)]
++mod tests {
++    use super::*;
++    use std::os::unix::io::RawFd;
++    use sys::time::{TimeVal, TimeValLike};
++    use unistd::{write, pipe};
++
++    #[test]
++    fn fdset_insert() {
++        let mut fd_set = FdSet::new();
++
++        for i in 0..FD_SETSIZE {
++            assert!(!fd_set.contains(i as RawFd));
++        }
++
++        fd_set.insert(7);
++
++        assert!(fd_set.contains(7));
++    }
++
++    #[test]
++    fn fdset_remove() {
++        let mut fd_set = FdSet::new();
++
++        for i in 0..FD_SETSIZE {
++            assert!(!fd_set.contains(i as RawFd));
++        }
++
++        fd_set.insert(7);
++        fd_set.remove(7);
++
++        for i in 0..FD_SETSIZE {
++            assert!(!fd_set.contains(i as RawFd));
++        }
++    }
++
++    #[test]
++    fn fdset_clear() {
++        let mut fd_set = FdSet::new();
++        fd_set.insert(1);
++        fd_set.insert((FD_SETSIZE / 2) as RawFd);
++        fd_set.insert((FD_SETSIZE - 1) as RawFd);
++
++        fd_set.clear();
++
++        for i in 0..FD_SETSIZE {
++            assert!(!fd_set.contains(i as RawFd));
++        }
++    }
++
++    #[test]
++    fn fdset_highest() {
++        let mut set = FdSet::new();
++        assert_eq!(set.highest(), None);
++        set.insert(0);
++        assert_eq!(set.highest(), Some(0));
++        set.insert(90);
++        assert_eq!(set.highest(), Some(90));
++        set.remove(0);
++        assert_eq!(set.highest(), Some(90));
++        set.remove(90);
++        assert_eq!(set.highest(), None);
++
++        set.insert(4);
++        set.insert(5);
++        set.insert(7);
++        assert_eq!(set.highest(), Some(7));
++    }
++
++    #[test]
++    fn test_select() {
++        let (r1, w1) = pipe().unwrap();
++        write(w1, b"hi!").unwrap();
++        let (r2, _w2) = pipe().unwrap();
++
++        let mut fd_set = FdSet::new();
++        fd_set.insert(r1);
++        fd_set.insert(r2);
++
++        let mut timeout = TimeVal::seconds(10);
++        assert_eq!(1, select(None,
++                             &mut fd_set,
++                             None,
++                             None,
++                             &mut timeout).unwrap());
++        assert!(fd_set.contains(r1));
++        assert!(!fd_set.contains(r2));
++    }
++
++    #[test]
++    fn test_select_nfds() {
++        let (r1, w1) = pipe().unwrap();
++        write(w1, b"hi!").unwrap();
++        let (r2, _w2) = pipe().unwrap();
++
++        let mut fd_set = FdSet::new();
++        fd_set.insert(r1);
++        fd_set.insert(r2);
++
++        let mut timeout = TimeVal::seconds(10);
++        assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
++                             &mut fd_set,
++                             None,
++                             None,
++                             &mut timeout).unwrap());
++        assert!(fd_set.contains(r1));
++        assert!(!fd_set.contains(r2));
++    }
++
++    #[test]
++    fn test_select_nfds2() {
++        let (r1, w1) = pipe().unwrap();
++        write(w1, b"hi!").unwrap();
++        let (r2, _w2) = pipe().unwrap();
++
++        let mut fd_set = FdSet::new();
++        fd_set.insert(r1);
++        fd_set.insert(r2);
++
++        let mut timeout = TimeVal::seconds(10);
++        assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
++                             &mut fd_set,
++                             None,
++                             None,
++                             &mut timeout).unwrap());
++        assert!(fd_set.contains(r1));
++        assert!(!fd_set.contains(r2));
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/sendfile.rs b/third_party/rust/nix-0.15.0/src/sys/sendfile.rs
+new file mode 100644
+index 0000000000000..a47d8962f73fb
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/sendfile.rs
+@@ -0,0 +1,200 @@
++use std::os::unix::io::RawFd;
++use std::ptr;
++
++use libc::{self, off_t};
++
++use Result;
++use errno::Errno;
++
++/// 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.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub fn sendfile(
++    out_fd: RawFd,
++    in_fd: RawFd,
++    offset: Option<&mut off_t>,
++    count: usize,
++) -> Result<usize> {
++    let offset = offset
++        .map(|offset| offset as *mut _)
++        .unwrap_or(ptr::null_mut());
++    let ret = unsafe { libc::sendfile(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",
++                 target_os = "macos"))] {
++        use sys::uio::IoVec;
++
++        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
++        struct SendfileHeaderTrailer<'a>(
++            libc::sf_hdtr,
++            Option<Vec<IoVec<&'a [u8]>>>,
++            Option<Vec<IoVec<&'a [u8]>>>,
++        );
++
++        impl<'a> SendfileHeaderTrailer<'a> {
++            fn new(
++                headers: Option<&'a [&'a [u8]]>,
++                trailers: Option<&'a [&'a [u8]]>
++            ) -> SendfileHeaderTrailer<'a> {
++                let header_iovecs: Option<Vec<IoVec<&[u8]>>> =
++                    headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
++                let trailer_iovecs: Option<Vec<IoVec<&[u8]>>> =
++                    trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
++                SendfileHeaderTrailer(
++                    libc::sf_hdtr {
++                        headers: {
++                            header_iovecs
++                                .as_ref()
++                                .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
++                        },
++                        hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32,
++                        trailers: {
++                            trailer_iovecs
++                                .as_ref()
++                                .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
++                        },
++                        trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32
++                    },
++                    header_iovecs,
++                    trailer_iovecs,
++                )
++            }
++        }
++    }
++}
++
++cfg_if! {
++    if #[cfg(target_os = "freebsd")] {
++        use libc::c_int;
++
++        libc_bitflags!{
++            /// Configuration options for [`sendfile`.](fn.sendfile.html)
++            pub struct SfFlags: c_int {
++                /// Causes `sendfile` to return EBUSY instead of blocking when attempting to read a
++                /// busy page.
++                SF_NODISKIO;
++                /// Causes `sendfile` to sleep until the network stack releases its reference to the
++                /// VM pages read. When `sendfile` returns, the data is not guaranteed to have been
++                /// sent, but it is safe to modify the file.
++                SF_SYNC;
++                /// Causes `sendfile` to cache exactly the number of pages specified in the
++                /// `readahead` parameter, disabling caching heuristics.
++                SF_USER_READAHEAD;
++                /// Causes `sendfile` not to cache the data read.
++                SF_NOCACHE;
++            }
++        }
++
++        /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`.
++        ///
++        /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
++        /// an error occurs.
++        ///
++        /// `in_fd` must describe a regular file or shared memory object. `out_sock` must describe a
++        /// stream socket.
++        ///
++        /// If `offset` falls past the end of the file, the function returns success and zero bytes
++        /// written.
++        ///
++        /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
++        /// file (EOF).
++        ///
++        /// `headers` and `trailers` specify optional slices of byte slices to be sent before and
++        /// after the data read from `in_fd`, respectively. The length of headers and trailers sent
++        /// is included in the returned count of bytes written. The values of `offset` and `count`
++        /// do not apply to headers or trailers.
++        ///
++        /// `readahead` specifies the minimum number of pages to cache in memory ahead of the page
++        /// currently being sent.
++        ///
++        /// For more information, see
++        /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
++        pub fn sendfile(
++            in_fd: RawFd,
++            out_sock: RawFd,
++            offset: off_t,
++            count: Option<usize>,
++            headers: Option<&[&[u8]]>,
++            trailers: Option<&[&[u8]]>,
++            flags: SfFlags,
++            readahead: u16
++        ) -> (Result<()>, off_t) {
++            // Readahead goes in upper 16 bits
++            // Flags goes in lower 16 bits
++            // see `man 2 sendfile`
++            let flags: u32 = ((readahead as u32) << 16) | (flags.bits() as u32);
++            let mut bytes_sent: off_t = 0;
++            let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
++            let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
++            let return_code = unsafe {
++                libc::sendfile(in_fd,
++                               out_sock,
++                               offset,
++                               count.unwrap_or(0),
++                               hdtr_ptr as *mut libc::sf_hdtr,
++                               &mut bytes_sent as *mut off_t,
++                               flags as c_int)
++            };
++            (Errno::result(return_code).and(Ok(())), bytes_sent)
++        }
++    } else if #[cfg(any(target_os = "ios", target_os = "macos"))] {
++        /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to
++        /// `out_sock`.
++        ///
++        /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
++        /// an error occurs.
++        ///
++        /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket.
++        ///
++        /// If `offset` falls past the end of the file, the function returns success and zero bytes
++        /// written.
++        ///
++        /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
++        /// file (EOF).
++        ///
++        /// `hdtr` specifies an optional list of headers and trailers to be sent before and after
++        /// the data read from `in_fd`, respectively. The length of headers and trailers sent is
++        /// included in the returned count of bytes written. If any headers are specified and
++        /// `count` is non-zero, the length of the headers will be counted in the limit of total
++        /// bytes sent. Trailers do not count toward the limit of bytes sent and will always be sent
++        /// regardless. The value of `offset` does not affect headers or trailers.
++        ///
++        /// For more information, see
++        /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
++        pub fn sendfile(
++            in_fd: RawFd,
++            out_sock: RawFd,
++            offset: off_t,
++            count: Option<off_t>,
++            headers: Option<&[&[u8]]>,
++            trailers: Option<&[&[u8]]>
++        ) -> (Result<()>, off_t) {
++            let mut len = count.unwrap_or(0);
++            let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
++            let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
++            let return_code = unsafe {
++                libc::sendfile(in_fd,
++                               out_sock,
++                               offset,
++                               &mut len as *mut off_t,
++                               hdtr_ptr as *mut libc::sf_hdtr,
++                               0)
++            };
++            (Errno::result(return_code).and(Ok(())), len)
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/signal.rs b/third_party/rust/nix-0.15.0/src/sys/signal.rs
+new file mode 100644
+index 0000000000000..1013a77fd4b40
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/signal.rs
+@@ -0,0 +1,966 @@
++// Portions of this file are Copyright 2014 The Rust Project Developers.
++// See http://rust-lang.org/COPYRIGHT.
++
++///! Operating system signals.
++
++use libc;
++use {Error, Result};
++use errno::Errno;
++use std::mem;
++use std::fmt;
++use std::str::FromStr;
++#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++use std::os::unix::io::RawFd;
++use std::ptr;
++
++#[cfg(not(target_os = "openbsd"))]
++pub use self::sigevent::*;
++
++libc_enum!{
++    // Currently there is only one definition of c_int in libc, as well as only one
++    // type for signal constants.
++    // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
++    // this is not (yet) possible.
++    #[repr(i32)]
++    pub enum Signal {
++        SIGHUP,
++        SIGINT,
++        SIGQUIT,
++        SIGILL,
++        SIGTRAP,
++        SIGABRT,
++        SIGBUS,
++        SIGFPE,
++        SIGKILL,
++        SIGUSR1,
++        SIGSEGV,
++        SIGUSR2,
++        SIGPIPE,
++        SIGALRM,
++        SIGTERM,
++        #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
++                  not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++        SIGSTKFLT,
++        SIGCHLD,
++        SIGCONT,
++        SIGSTOP,
++        SIGTSTP,
++        SIGTTIN,
++        SIGTTOU,
++        SIGURG,
++        SIGXCPU,
++        SIGXFSZ,
++        SIGVTALRM,
++        SIGPROF,
++        SIGWINCH,
++        SIGIO,
++        #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++        SIGPWR,
++        SIGSYS,
++        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++        SIGEMT,
++        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++        SIGINFO,
++    }
++}
++
++impl FromStr for Signal {
++    type Err = Error;
++    fn from_str(s: &str) -> Result<Signal> {
++        Ok(match s {
++            "SIGHUP" => Signal::SIGHUP,
++            "SIGINT" => Signal::SIGINT,
++            "SIGQUIT" => Signal::SIGQUIT,
++            "SIGILL" => Signal::SIGILL,
++            "SIGTRAP" => Signal::SIGTRAP,
++            "SIGABRT" => Signal::SIGABRT,
++            "SIGBUS" => Signal::SIGBUS,
++            "SIGFPE" => Signal::SIGFPE,
++            "SIGKILL" => Signal::SIGKILL,
++            "SIGUSR1" => Signal::SIGUSR1,
++            "SIGSEGV" => Signal::SIGSEGV,
++            "SIGUSR2" => Signal::SIGUSR2,
++            "SIGPIPE" => Signal::SIGPIPE,
++            "SIGALRM" => Signal::SIGALRM,
++            "SIGTERM" => Signal::SIGTERM,
++            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
++                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++            "SIGSTKFLT" => Signal::SIGSTKFLT,
++            "SIGCHLD" => Signal::SIGCHLD,
++            "SIGCONT" => Signal::SIGCONT,
++            "SIGSTOP" => Signal::SIGSTOP,
++            "SIGTSTP" => Signal::SIGTSTP,
++            "SIGTTIN" => Signal::SIGTTIN,
++            "SIGTTOU" => Signal::SIGTTOU,
++            "SIGURG" => Signal::SIGURG,
++            "SIGXCPU" => Signal::SIGXCPU,
++            "SIGXFSZ" => Signal::SIGXFSZ,
++            "SIGVTALRM" => Signal::SIGVTALRM,
++            "SIGPROF" => Signal::SIGPROF,
++            "SIGWINCH" => Signal::SIGWINCH,
++            "SIGIO" => Signal::SIGIO,
++            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++            "SIGPWR" => Signal::SIGPWR,
++            "SIGSYS" => Signal::SIGSYS,
++            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            "SIGEMT" => Signal::SIGEMT,
++            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            "SIGINFO" => Signal::SIGINFO,
++            _ => return Err(Error::invalid_argument()),
++        })
++    }
++}
++
++impl AsRef<str> for Signal {
++    fn as_ref(&self) -> &str {
++        match *self {
++            Signal::SIGHUP => "SIGHUP",
++            Signal::SIGINT => "SIGINT",
++            Signal::SIGQUIT => "SIGQUIT",
++            Signal::SIGILL => "SIGILL",
++            Signal::SIGTRAP => "SIGTRAP",
++            Signal::SIGABRT => "SIGABRT",
++            Signal::SIGBUS => "SIGBUS",
++            Signal::SIGFPE => "SIGFPE",
++            Signal::SIGKILL => "SIGKILL",
++            Signal::SIGUSR1 => "SIGUSR1",
++            Signal::SIGSEGV => "SIGSEGV",
++            Signal::SIGUSR2 => "SIGUSR2",
++            Signal::SIGPIPE => "SIGPIPE",
++            Signal::SIGALRM => "SIGALRM",
++            Signal::SIGTERM => "SIGTERM",
++            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
++                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++            Signal::SIGSTKFLT => "SIGSTKFLT",
++            Signal::SIGCHLD => "SIGCHLD",
++            Signal::SIGCONT => "SIGCONT",
++            Signal::SIGSTOP => "SIGSTOP",
++            Signal::SIGTSTP => "SIGTSTP",
++            Signal::SIGTTIN => "SIGTTIN",
++            Signal::SIGTTOU => "SIGTTOU",
++            Signal::SIGURG => "SIGURG",
++            Signal::SIGXCPU => "SIGXCPU",
++            Signal::SIGXFSZ => "SIGXFSZ",
++            Signal::SIGVTALRM => "SIGVTALRM",
++            Signal::SIGPROF => "SIGPROF",
++            Signal::SIGWINCH => "SIGWINCH",
++            Signal::SIGIO => "SIGIO",
++            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++            Signal::SIGPWR => "SIGPWR",
++            Signal::SIGSYS => "SIGSYS",
++            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            Signal::SIGEMT => "SIGEMT",
++            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            Signal::SIGINFO => "SIGINFO",
++        }
++    }
++}
++
++impl fmt::Display for Signal {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        f.write_str(self.as_ref())
++    }
++}
++
++pub use self::Signal::*;
++
++#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++const SIGNALS: [Signal; 31] = [
++    SIGHUP,
++    SIGINT,
++    SIGQUIT,
++    SIGILL,
++    SIGTRAP,
++    SIGABRT,
++    SIGBUS,
++    SIGFPE,
++    SIGKILL,
++    SIGUSR1,
++    SIGSEGV,
++    SIGUSR2,
++    SIGPIPE,
++    SIGALRM,
++    SIGTERM,
++    SIGSTKFLT,
++    SIGCHLD,
++    SIGCONT,
++    SIGSTOP,
++    SIGTSTP,
++    SIGTTIN,
++    SIGTTOU,
++    SIGURG,
++    SIGXCPU,
++    SIGXFSZ,
++    SIGVTALRM,
++    SIGPROF,
++    SIGWINCH,
++    SIGIO,
++    SIGPWR,
++    SIGSYS];
++#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")))]
++const SIGNALS: [Signal; 30] = [
++    SIGHUP,
++    SIGINT,
++    SIGQUIT,
++    SIGILL,
++    SIGTRAP,
++    SIGABRT,
++    SIGBUS,
++    SIGFPE,
++    SIGKILL,
++    SIGUSR1,
++    SIGSEGV,
++    SIGUSR2,
++    SIGPIPE,
++    SIGALRM,
++    SIGTERM,
++    SIGCHLD,
++    SIGCONT,
++    SIGSTOP,
++    SIGTSTP,
++    SIGTTIN,
++    SIGTTOU,
++    SIGURG,
++    SIGXCPU,
++    SIGXFSZ,
++    SIGVTALRM,
++    SIGPROF,
++    SIGWINCH,
++    SIGIO,
++    SIGPWR,
++    SIGSYS];
++#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
++const SIGNALS: [Signal; 31] = [
++    SIGHUP,
++    SIGINT,
++    SIGQUIT,
++    SIGILL,
++    SIGTRAP,
++    SIGABRT,
++    SIGBUS,
++    SIGFPE,
++    SIGKILL,
++    SIGUSR1,
++    SIGSEGV,
++    SIGUSR2,
++    SIGPIPE,
++    SIGALRM,
++    SIGTERM,
++    SIGCHLD,
++    SIGCONT,
++    SIGSTOP,
++    SIGTSTP,
++    SIGTTIN,
++    SIGTTOU,
++    SIGURG,
++    SIGXCPU,
++    SIGXFSZ,
++    SIGVTALRM,
++    SIGPROF,
++    SIGWINCH,
++    SIGIO,
++    SIGSYS,
++    SIGEMT,
++    SIGINFO];
++
++pub const NSIG: libc::c_int = 32;
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct SignalIterator {
++    next: usize,
++}
++
++impl Iterator for SignalIterator {
++    type Item = Signal;
++
++    fn next(&mut self) -> Option<Signal> {
++        if self.next < SIGNALS.len() {
++            let next_signal = SIGNALS[self.next];
++            self.next += 1;
++            Some(next_signal)
++        } else {
++            None
++        }
++    }
++}
++
++impl Signal {
++    pub fn iterator() -> SignalIterator {
++        SignalIterator{next: 0}
++    }
++
++    // We do not implement the From trait, because it is supposed to be infallible.
++    // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
++    // implemented, we'll replace this function.
++    #[inline]
++    pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
++        if 0 < signum && signum < NSIG {
++            Ok(unsafe { mem::transmute(signum) })
++        } else {
++            Err(Error::invalid_argument())
++        }
++    }
++}
++
++pub const SIGIOT : Signal = SIGABRT;
++pub const SIGPOLL : Signal = SIGIO;
++pub const SIGUNUSED : Signal = SIGSYS;
++
++libc_bitflags!{
++    pub struct SaFlags: libc::c_int {
++        SA_NOCLDSTOP;
++        SA_NOCLDWAIT;
++        SA_NODEFER;
++        SA_ONSTACK;
++        SA_RESETHAND;
++        SA_RESTART;
++        SA_SIGINFO;
++    }
++}
++
++libc_enum! {
++    #[repr(i32)]
++    pub enum SigmaskHow {
++        SIG_BLOCK,
++        SIG_UNBLOCK,
++        SIG_SETMASK,
++    }
++}
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct SigSet {
++    sigset: libc::sigset_t
++}
++
++
++impl SigSet {
++    pub fn all() -> SigSet {
++        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
++        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };
++
++        SigSet { sigset: sigset }
++    }
++
++    pub fn empty() -> SigSet {
++        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
++        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
++
++        SigSet { sigset: sigset }
++    }
++
++    pub fn add(&mut self, signal: Signal) {
++        unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
++    }
++
++    pub fn clear(&mut self) {
++        unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
++    }
++
++    pub fn remove(&mut self, signal: Signal) {
++        unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
++    }
++
++    pub fn contains(&self, signal: Signal) -> bool {
++        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
++
++        match res {
++            1 => true,
++            0 => false,
++            _ => unreachable!("unexpected value from sigismember"),
++        }
++    }
++
++    pub fn extend(&mut self, other: &SigSet) {
++        for signal in Signal::iterator() {
++            if other.contains(signal) {
++                self.add(signal);
++            }
++        }
++    }
++
++    /// Gets the currently blocked (masked) set of signals for the calling thread.
++    pub fn thread_get_mask() -> Result<SigSet> {
++        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
++        pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?;
++        Ok(oldmask)
++    }
++
++    /// Sets the set of signals as the signal mask for the calling thread.
++    pub fn thread_set_mask(&self) -> Result<()> {
++        pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
++    }
++
++    /// Adds the set of signals to the signal mask for the calling thread.
++    pub fn thread_block(&self) -> Result<()> {
++        pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
++    }
++
++    /// Removes the set of signals from the signal mask for the calling thread.
++    pub fn thread_unblock(&self) -> Result<()> {
++        pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
++    }
++
++    /// Sets the set of signals as the signal mask, and returns the old mask.
++    pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
++        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
++        pthread_sigmask(how, Some(self), Some(&mut oldmask))?;
++        Ok(oldmask)
++    }
++
++    /// Suspends execution of the calling thread until one of the signals in the
++    /// signal mask becomes pending, and returns the accepted signal.
++    pub fn wait(&self) -> Result<Signal> {
++        let mut signum: libc::c_int = unsafe { mem::uninitialized() };
++        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
++
++        Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
++    }
++}
++
++impl AsRef<libc::sigset_t> for SigSet {
++    fn as_ref(&self) -> &libc::sigset_t {
++        &self.sigset
++    }
++}
++
++/// A signal handler.
++#[allow(unknown_lints)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum SigHandler {
++    /// Default signal handling.
++    SigDfl,
++    /// Request that the signal be ignored.
++    SigIgn,
++    /// Use the given signal-catching function, which takes in the signal.
++    Handler(extern fn(libc::c_int)),
++    /// Use the given signal-catching function, which takes in the signal, information about how
++    /// the signal was generated, and a pointer to the threads `ucontext_t`.
++    SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
++}
++
++/// Action to take on receipt of a signal. Corresponds to `sigaction`.
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct SigAction {
++    sigaction: libc::sigaction
++}
++
++impl SigAction {
++    /// Creates a new action.
++    ///
++    /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
++    /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
++    /// the signal-catching function.
++    pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
++        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
++        s.sa_sigaction = match handler {
++            SigHandler::SigDfl => libc::SIG_DFL,
++            SigHandler::SigIgn => libc::SIG_IGN,
++            SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
++            SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
++        };
++        s.sa_flags = match handler {
++            SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
++            _ => (flags - SaFlags::SA_SIGINFO).bits(),
++        };
++        s.sa_mask = mask.sigset;
++
++        SigAction { sigaction: s }
++    }
++
++    /// Returns the flags set on the action.
++    pub fn flags(&self) -> SaFlags {
++        SaFlags::from_bits_truncate(self.sigaction.sa_flags)
++    }
++
++    /// Returns the set of signals that are blocked during execution of the action's
++    /// signal-catching function.
++    pub fn mask(&self) -> SigSet {
++        SigSet { sigset: self.sigaction.sa_mask }
++    }
++
++    /// Returns the action's handler.
++    pub fn handler(&self) -> SigHandler {
++        match self.sigaction.sa_sigaction {
++            libc::SIG_DFL => SigHandler::SigDfl,
++            libc::SIG_IGN => SigHandler::SigIgn,
++            f if self.flags().contains(SaFlags::SA_SIGINFO) =>
++                SigHandler::SigAction( unsafe { mem::transmute(f) } ),
++            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
++        }
++    }
++}
++
++/// Changes the action taken by a process on receipt of a specific signal.
++///
++/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
++/// action for the given signal. If `sigaction` fails, no new signal handler is installed.
++///
++/// # Safety
++///
++/// Signal handlers may be called at any point during execution, which limits what is safe to do in
++/// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
++/// marked safe for signal handlers and only share global data using atomics.
++pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
++    let mut oldact = mem::uninitialized::<libc::sigaction>();
++
++    let res =
++        libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
++
++    Errno::result(res).map(|_| SigAction { sigaction: oldact })
++}
++
++/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
++///
++/// Installs `handler` for the given `signal`, returning the previous signal
++/// handler. `signal` should only be used following another call to `signal` or
++/// if the current handler is the default. The return value of `signal` is
++/// undefined after setting the handler with [`sigaction`][SigActionFn].
++///
++/// # Safety
++///
++/// If the pointer to the previous signal handler is invalid, undefined
++/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
++///
++/// # Examples
++///
++/// Ignore `SIGINT`:
++///
++/// ```no_run
++/// # use nix::sys::signal::{self, Signal, SigHandler};
++/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
++/// ```
++///
++/// Use a signal handler to set a flag variable:
++///
++/// ```no_run
++/// # #[macro_use] extern crate lazy_static;
++/// # extern crate libc;
++/// # extern crate nix;
++/// # use std::sync::atomic::{AtomicBool, Ordering};
++/// # use nix::sys::signal::{self, Signal, SigHandler};
++/// lazy_static! {
++///    static ref SIGNALED: AtomicBool = AtomicBool::new(false);
++/// }
++///
++/// extern fn handle_sigint(signal: libc::c_int) {
++///     let signal = Signal::from_c_int(signal).unwrap();
++///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
++/// }
++///
++/// fn main() {
++///     let handler = SigHandler::Handler(handle_sigint);
++///     unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
++/// }
++/// ```
++///
++/// # Errors
++///
++/// Returns [`Error::UnsupportedOperation`] if `handler` is
++/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
++///
++/// `signal` also returns any error from `libc::signal`, such as when an attempt
++/// is made to catch a signal that cannot be caught or to ignore a signal that
++/// cannot be ignored.
++///
++/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
++/// [SigActionStruct]: struct.SigAction.html
++/// [sigactionFn]: fn.sigaction.html
++pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
++    let signal = signal as libc::c_int;
++    let res = match handler {
++        SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
++        SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
++        SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
++        SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
++    };
++    Errno::result(res).map(|oldhandler| {
++        match oldhandler {
++            libc::SIG_DFL => SigHandler::SigDfl,
++            libc::SIG_IGN => SigHandler::SigIgn,
++            f => SigHandler::Handler(mem::transmute(f)),
++        }
++    })
++}
++
++/// Manages the signal mask (set of blocked signals) for the calling thread.
++///
++/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
++/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
++/// and no modification will take place.
++///
++/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
++///
++/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
++/// and then it will be updated with `set`.
++///
++/// 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.
++pub fn pthread_sigmask(how: SigmaskHow,
++                       set: Option<&SigSet>,
++                       oldset: Option<&mut SigSet>) -> Result<()> {
++    if set.is_none() && oldset.is_none() {
++        return Ok(())
++    }
++
++    let res = unsafe {
++        // if set or oldset is None, pass in null pointers instead
++        libc::pthread_sigmask(how as libc::c_int,
++                             set.map_or_else(ptr::null::<libc::sigset_t>,
++                                             |s| &s.sigset as *const libc::sigset_t),
++                             oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
++                                                |os| &mut os.sigset as *mut libc::sigset_t))
++    };
++
++    Errno::result(res).map(drop)
++}
++
++/// Examine and change blocked signals.
++///
++/// For more informations see the [`sigprocmask` man
++/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
++pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
++    if set.is_none() && oldset.is_none() {
++        return Ok(())
++    }
++
++    let res = unsafe {
++        // if set or oldset is None, pass in null pointers instead
++        libc::sigprocmask(how as libc::c_int,
++                          set.map_or_else(ptr::null::<libc::sigset_t>,
++                                          |s| &s.sigset as *const libc::sigset_t),
++                          oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
++                                             |os| &mut os.sigset as *mut libc::sigset_t))
++    };
++
++    Errno::result(res).map(drop)
++}
++
++pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
++    let res = unsafe { libc::kill(pid.into(),
++                                  match signal.into() {
++                                      Some(s) => s as libc::c_int,
++                                      None => 0,
++                                  }) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Send a signal to a process group [(see
++/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
++///
++/// If `pgrp` less then or equal 1, the behavior is platform-specific.
++/// If `signal` is `None`, `killpg` will only preform error checking and won't
++/// send any signal.
++pub fn killpg<T: Into<Option<Signal>>>(pgrp: ::unistd::Pid, signal: T) -> Result<()> {
++    let res = unsafe { libc::killpg(pgrp.into(),
++                                  match signal.into() {
++                                      Some(s) => s as libc::c_int,
++                                      None => 0,
++                                  }) };
++
++    Errno::result(res).map(drop)
++}
++
++pub fn raise(signal: Signal) -> Result<()> {
++    let res = unsafe { libc::raise(signal as libc::c_int) };
++
++    Errno::result(res).map(drop)
++}
++
++
++#[cfg(target_os = "freebsd")]
++pub type type_of_thread_id = libc::lwpid_t;
++#[cfg(target_os = "linux")]
++pub type type_of_thread_id = libc::pid_t;
++
++/// Used to request asynchronous notification of certain events, for example,
++/// with POSIX AIO, POSIX message queues, and POSIX timers.
++// sigval is actually a union of a int and a void*.  But it's never really used
++// as a pointer, because neither libc nor the kernel ever dereference it.  nix
++// therefore presents it as an intptr_t, which is how kevent uses it.
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum SigevNotify {
++    /// No notification will be delivered
++    SigevNone,
++    /// The signal given by `signal` will be delivered to the process.  The
++    /// value in `si_value` will be present in the `si_value` field of the
++    /// `siginfo_t` structure of the queued signal.
++    SigevSignal { signal: Signal, si_value: libc::intptr_t },
++    // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
++    // expose a way to set the union members needed by SIGEV_THREAD.
++    /// A new `kevent` is posted to the kqueue `kq`.  The `kevent`'s `udata`
++    /// field will contain the value in `udata`.
++    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++    SigevKevent { kq: RawFd, udata: libc::intptr_t },
++    /// The signal `signal` is queued to the thread whose LWP ID is given in
++    /// `thread_id`.  The value stored in `si_value` will be present in the
++    /// `si_value` of the `siginfo_t` structure of the queued signal.
++    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
++    SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
++                    si_value: libc::intptr_t },
++}
++
++#[cfg(not(target_os = "openbsd"))]
++mod sigevent {
++    use libc;
++    use std::mem;
++    use std::ptr;
++    use super::SigevNotify;
++    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
++    use super::type_of_thread_id;
++
++    /// Used to request asynchronous notification of the completion of certain
++    /// events, such as POSIX AIO and timers.
++    #[repr(C)]
++    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++    pub struct SigEvent {
++        sigevent: libc::sigevent
++    }
++
++    impl SigEvent {
++        /// **Note:** this constructor does not allow the user to set the
++        /// `sigev_notify_kevent_flags` field.  That's considered ok because on FreeBSD
++        /// at least those flags don't do anything useful.  That field is part of a
++        /// union that shares space with the more genuinely useful fields.
++        ///
++        /// **Note:** This constructor also doesn't allow the caller to set the
++        /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
++        /// required for `SIGEV_THREAD`.  That's considered ok because on no operating
++        /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
++        /// notification.  FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
++        /// 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`
++        pub fn new(sigev_notify: SigevNotify) -> SigEvent {
++            let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
++            sev.sigev_notify = match sigev_notify {
++                SigevNotify::SigevNone => libc::SIGEV_NONE,
++                SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
++                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++                SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
++                #[cfg(target_os = "freebsd")]
++                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
++                #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
++                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
++                #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
++                SigevNotify::SigevThreadId{..} => 4  // No SIGEV_THREAD_ID defined
++            };
++            sev.sigev_signo = match sigev_notify {
++                SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
++                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++                SigevNotify::SigevKevent{ kq, ..} => kq,
++                #[cfg(any(target_os = "linux", target_os = "freebsd"))]
++                SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
++                _ => 0
++            };
++            sev.sigev_value.sival_ptr = match sigev_notify {
++                SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
++                SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
++                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++                SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
++                #[cfg(any(target_os = "freebsd", target_os = "linux"))]
++                SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
++            };
++            SigEvent::set_tid(&mut sev, &sigev_notify);
++            SigEvent{sigevent: sev}
++        }
++
++        #[cfg(any(target_os = "freebsd", target_os = "linux"))]
++        fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
++            sev.sigev_notify_thread_id = match *sigev_notify {
++                SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
++                _ => 0 as type_of_thread_id
++            };
++        }
++
++        #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
++        fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
++        }
++
++        pub fn sigevent(&self) -> libc::sigevent {
++            self.sigevent
++        }
++    }
++
++    impl<'a> From<&'a libc::sigevent> for SigEvent {
++        fn from(sigevent: &libc::sigevent) -> Self {
++            SigEvent{ sigevent: *sigevent }
++        }
++    }
++}
++
++#[cfg(test)]
++mod tests {
++    use std::thread;
++    use super::*;
++
++    #[test]
++    fn test_contains() {
++        let mut mask = SigSet::empty();
++        mask.add(SIGUSR1);
++
++        assert!(mask.contains(SIGUSR1));
++        assert!(!mask.contains(SIGUSR2));
++
++        let all = SigSet::all();
++        assert!(all.contains(SIGUSR1));
++        assert!(all.contains(SIGUSR2));
++    }
++
++    #[test]
++    fn test_clear() {
++        let mut set = SigSet::all();
++        set.clear();
++        for signal in Signal::iterator() {
++            assert!(!set.contains(signal));
++        }
++    }
++
++    #[test]
++    fn test_from_str_round_trips() {
++        for signal in Signal::iterator() {
++            assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
++            assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
++        }
++    }
++
++    #[test]
++    fn test_from_str_invalid_value() {
++        let errval = Err(Error::Sys(Errno::EINVAL));
++        assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
++        assert_eq!("kill".parse::<Signal>(), errval);
++        assert_eq!("9".parse::<Signal>(), errval);
++    }
++
++    #[test]
++    fn test_extend() {
++        let mut one_signal = SigSet::empty();
++        one_signal.add(SIGUSR1);
++
++        let mut two_signals = SigSet::empty();
++        two_signals.add(SIGUSR2);
++        two_signals.extend(&one_signal);
++
++        assert!(two_signals.contains(SIGUSR1));
++        assert!(two_signals.contains(SIGUSR2));
++    }
++
++    #[test]
++    fn test_thread_signal_set_mask() {
++        thread::spawn(|| {
++            let prev_mask = SigSet::thread_get_mask()
++                .expect("Failed to get existing signal mask!");
++
++            let mut test_mask = prev_mask;
++            test_mask.add(SIGUSR1);
++
++            assert!(test_mask.thread_set_mask().is_ok());
++            let new_mask = SigSet::thread_get_mask()
++                .expect("Failed to get new mask!");
++
++            assert!(new_mask.contains(SIGUSR1));
++            assert!(!new_mask.contains(SIGUSR2));
++
++            prev_mask.thread_set_mask().expect("Failed to revert signal mask!");
++        }).join().unwrap();
++    }
++
++    #[test]
++    fn test_thread_signal_block() {
++        thread::spawn(|| {
++            let mut mask = SigSet::empty();
++            mask.add(SIGUSR1);
++
++            assert!(mask.thread_block().is_ok());
++
++            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
++        }).join().unwrap();
++    }
++
++    #[test]
++    fn test_thread_signal_unblock() {
++        thread::spawn(|| {
++            let mut mask = SigSet::empty();
++            mask.add(SIGUSR1);
++
++            assert!(mask.thread_unblock().is_ok());
++
++            assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
++        }).join().unwrap();
++    }
++
++    #[test]
++    fn test_thread_signal_swap() {
++        thread::spawn(|| {
++            let mut mask = SigSet::empty();
++            mask.add(SIGUSR1);
++            mask.thread_block().unwrap();
++
++            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
++
++            let mut mask2 = SigSet::empty();
++            mask2.add(SIGUSR2);
++
++            let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK)
++                .unwrap();
++
++            assert!(oldmask.contains(SIGUSR1));
++            assert!(!oldmask.contains(SIGUSR2));
++
++            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
++        }).join().unwrap();
++    }
++
++    #[test]
++    fn test_sigaction() {
++        use libc;
++        thread::spawn(|| {
++            extern fn test_sigaction_handler(_: libc::c_int) {}
++            extern fn test_sigaction_action(_: libc::c_int,
++                _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
++
++            let handler_sig = SigHandler::Handler(test_sigaction_handler);
++
++            let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART |
++                        SaFlags::SA_SIGINFO;
++
++            let mut mask = SigSet::empty();
++            mask.add(SIGUSR1);
++
++            let action_sig = SigAction::new(handler_sig, flags, mask);
++
++            assert_eq!(action_sig.flags(),
++                       SaFlags::SA_ONSTACK | SaFlags::SA_RESTART);
++            assert_eq!(action_sig.handler(), handler_sig);
++
++            mask = action_sig.mask();
++            assert!(mask.contains(SIGUSR1));
++            assert!(!mask.contains(SIGUSR2));
++
++            let handler_act = SigHandler::SigAction(test_sigaction_action);
++            let action_act = SigAction::new(handler_act, flags, mask);
++            assert_eq!(action_act.handler(), handler_act);
++
++            let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
++            assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
++
++            let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
++            assert_eq!(action_ign.handler(), SigHandler::SigIgn);
++        }).join().unwrap();
++    }
++
++    #[test]
++    fn test_sigwait() {
++        thread::spawn(|| {
++            let mut mask = SigSet::empty();
++            mask.add(SIGUSR1);
++            mask.add(SIGUSR2);
++            mask.thread_block().unwrap();
++
++            raise(SIGUSR1).unwrap();
++            assert_eq!(mask.wait().unwrap(), SIGUSR1);
++        }).join().unwrap();
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/signalfd.rs b/third_party/rust/nix-0.15.0/src/sys/signalfd.rs
+new file mode 100644
+index 0000000000000..5425a27be9e52
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/signalfd.rs
+@@ -0,0 +1,170 @@
++//! Interface for the `signalfd` syscall.
++//!
++//! # Signal discarding
++//! When a signal can't be delivered to a process (or thread), it will become a pending signal.
++//! Failure to deliver could happen if the signal is blocked by every thread in the process or if
++//! the signal handler is still handling a previous signal.
++//!
++//! If a signal is sent to a process (or thread) that already has a pending signal of the same
++//! type, it will be discarded. This means that if signals of the same type are received faster than
++//! they are processed, some of those signals will be dropped. Because of this limitation,
++//! `signalfd` in itself cannot be used for reliable communication between processes or threads.
++//!
++//! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending
++//! (ie. not consumed from a signalfd) it will be delivered to the signal handler.
++//!
++//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
++//! signal handlers.
++use libc;
++use unistd;
++use {Error, Result};
++use errno::Errno;
++pub use sys::signal::{self, SigSet};
++pub use libc::signalfd_siginfo as siginfo;
++
++use std::os::unix::io::{RawFd, AsRawFd};
++use std::mem;
++
++
++libc_bitflags!{
++    pub struct SfdFlags: libc::c_int {
++        SFD_NONBLOCK;
++        SFD_CLOEXEC;
++    }
++}
++
++pub const SIGNALFD_NEW: RawFd = -1;
++pub const SIGNALFD_SIGINFO_SIZE: usize = 128;
++
++/// Creates a new file descriptor for reading signals.
++///
++/// **Important:** please read the module level documentation about signal discarding before using
++/// this function!
++///
++/// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor.
++///
++/// 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)
++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()))
++    }
++}
++
++/// A helper struct for creating, reading and closing a `signalfd` instance.
++///
++/// **Important:** please read the module level documentation about signal discarding before using
++/// this struct!
++///
++/// # Examples
++///
++/// ```
++/// # use nix::sys::signalfd::*;
++/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used
++/// let mut mask = SigSet::empty();
++/// mask.add(signal::SIGUSR1);
++/// mask.thread_block().unwrap();
++///
++/// // Signals are queued up on the file descriptor
++/// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
++///
++/// match sfd.read_signal() {
++///     // we caught a signal
++///     Ok(Some(sig)) => (),
++///     // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set,
++///     // otherwise the read_signal call blocks)
++///     Ok(None) => (),
++///     Err(err) => (), // some error happend
++/// }
++/// ```
++#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++pub struct SignalFd(RawFd);
++
++impl SignalFd {
++    pub fn new(mask: &SigSet) -> Result<SignalFd> {
++        Self::with_flags(mask, SfdFlags::empty())
++    }
++
++    pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
++        let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
++
++        Ok(SignalFd(fd))
++    }
++
++    pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
++        signalfd(self.0, mask, SfdFlags::empty()).map(drop)
++    }
++
++    pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
++        let mut buffer: [u8; SIGNALFD_SIGINFO_SIZE] = unsafe { mem::uninitialized() };
++
++        match unistd::read(self.0, &mut buffer) {
++            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer) })),
++            Ok(_) => unreachable!("partial read on signalfd"),
++            Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
++            Err(error) => Err(error)
++        }
++    }
++}
++
++impl Drop for SignalFd {
++    fn drop(&mut self) {
++        let _ = unistd::close(self.0);
++    }
++}
++
++impl AsRawFd for SignalFd {
++    fn as_raw_fd(&self) -> RawFd {
++        self.0
++    }
++}
++
++impl Iterator for SignalFd {
++    type Item = siginfo;
++
++    fn next(&mut self) -> Option<Self::Item> {
++        match self.read_signal() {
++            Ok(Some(sig)) => Some(sig),
++            Ok(None) | Err(_) => None,
++        }
++    }
++}
++
++
++#[cfg(test)]
++mod tests {
++    use super::*;
++    use std::mem;
++    use libc;
++
++
++    #[test]
++    fn check_siginfo_size() {
++        assert_eq!(mem::size_of::<libc::signalfd_siginfo>(), SIGNALFD_SIGINFO_SIZE);
++    }
++
++    #[test]
++    fn create_signalfd() {
++        let mask = SigSet::empty();
++        let fd = SignalFd::new(&mask);
++        assert!(fd.is_ok());
++    }
++
++    #[test]
++    fn create_signalfd_with_opts() {
++        let mask = SigSet::empty();
++        let fd = SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK);
++        assert!(fd.is_ok());
++    }
++
++    #[test]
++    fn read_empty_signalfd() {
++        let mask = SigSet::empty();
++        let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
++
++        let res = fd.read_signal();
++        assert!(res.unwrap().is_none());
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs b/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
+new file mode 100644
+index 0000000000000..ed41441155361
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
+@@ -0,0 +1,1278 @@
++use super::sa_family_t;
++use {Error, Result, NixPath};
++use errno::Errno;
++use libc;
++use std::{fmt, mem, net, ptr, slice};
++use std::ffi::OsStr;
++use std::hash::{Hash, Hasher};
++use std::path::Path;
++use std::os::unix::ffi::OsStrExt;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use ::sys::socket::addr::netlink::NetlinkAddr;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use ::sys::socket::addr::alg::AlgAddr;
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++use std::os::unix::io::RawFd;
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++use ::sys::socket::addr::sys_control::SysControlAddr;
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub use self::datalink::LinkAddr;
++#[cfg(target_os = "linux")]
++pub use self::vsock::VsockAddr;
++
++/// These constants specify the protocol family to be used
++/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
++#[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))
++    Unix = libc::AF_UNIX,
++    /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
++    Inet = libc::AF_INET,
++    /// IPv6 Internet protocols (see [`ipv6(7)`](http://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))
++    #[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"))]
++    Packet = libc::AF_PACKET,
++    /// KEXT Controls and Notifications
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
++    System = libc::AF_SYSTEM,
++    /// Amateur radio AX.25 protocol
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Ax25 = libc::AF_AX25,
++    /// IPX - Novell protocols
++    Ipx = libc::AF_IPX,
++    /// AppleTalk
++    AppleTalk = libc::AF_APPLETALK,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetRom = libc::AF_NETROM,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Bridge = libc::AF_BRIDGE,
++    /// 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))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    X25 = libc::AF_X25,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Rose = libc::AF_ROSE,
++    Decnet = libc::AF_DECnet,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetBeui = libc::AF_NETBEUI,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Security = libc::AF_SECURITY,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Key = libc::AF_KEY,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Ash = libc::AF_ASH,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Econet = libc::AF_ECONET,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    AtmSvc = libc::AF_ATMSVC,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Rds = libc::AF_RDS,
++    Sna = libc::AF_SNA,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Irda = libc::AF_IRDA,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Pppox = libc::AF_PPPOX,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Wanpipe = libc::AF_WANPIPE,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Llc = libc::AF_LLC,
++    #[cfg(target_os = "linux")]
++    Ib = libc::AF_IB,
++    #[cfg(target_os = "linux")]
++    Mpls = libc::AF_MPLS,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    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")))]
++    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,
++    Isdn = libc::AF_ISDN,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Phonet = libc::AF_PHONET,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Ieee802154 = libc::AF_IEEE802154,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Caif = libc::AF_CAIF,
++    /// Interface to kernel crypto API
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Alg = libc::AF_ALG,
++    #[cfg(target_os = "linux")]
++    Nfc = libc::AF_NFC,
++    #[cfg(target_os = "linux")]
++    Vsock = libc::AF_VSOCK,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    ImpLink = libc::AF_IMPLINK,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Pup = libc::AF_PUP,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Chaos = libc::AF_CHAOS,
++    #[cfg(any(target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Ns = libc::AF_NS,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Iso = libc::AF_ISO,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Datakit = libc::AF_DATAKIT,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Ccitt = libc::AF_CCITT,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Dli = libc::AF_DLI,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Lat = libc::AF_LAT,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Hylink = libc::AF_HYLINK,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Link = libc::AF_LINK,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Coip = libc::AF_COIP,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Cnt = libc::AF_CNT,
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              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))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Unspec = libc::AF_UNSPEC,
++}
++
++impl AddressFamily {
++    /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
++    /// the `sa_family` field of a `sockaddr`.
++    ///
++    /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
++    /// and System. Returns None for unsupported or unknown address families.
++    pub fn from_i32(family: i32) -> Option<AddressFamily> {
++        match family {
++            libc::AF_UNIX => Some(AddressFamily::Unix),
++            libc::AF_INET => Some(AddressFamily::Inet),
++            libc::AF_INET6 => Some(AddressFamily::Inet6),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            libc::AF_NETLINK => Some(AddressFamily::Netlink),
++            #[cfg(any(target_os = "macos", target_os = "macos"))]
++            libc::AF_SYSTEM => Some(AddressFamily::System),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            libc::AF_PACKET => Some(AddressFamily::Packet),
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "ios",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            libc::AF_LINK => Some(AddressFamily::Link),
++            #[cfg(target_os = "linux")]
++            libc::AF_VSOCK => Some(AddressFamily::Vsock),
++            _ => None
++        }
++    }
++}
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum InetAddr {
++    V4(libc::sockaddr_in),
++    V6(libc::sockaddr_in6),
++}
++
++impl InetAddr {
++    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
++        match *std {
++            net::SocketAddr::V4(ref addr) => {
++                InetAddr::V4(libc::sockaddr_in {
++                    sin_family: AddressFamily::Inet as sa_family_t,
++                    sin_port: addr.port().to_be(),  // network byte order
++                    sin_addr: Ipv4Addr::from_std(addr.ip()).0,
++                    .. unsafe { mem::zeroed() }
++                })
++            }
++            net::SocketAddr::V6(ref addr) => {
++                InetAddr::V6(libc::sockaddr_in6 {
++                    sin6_family: AddressFamily::Inet6 as sa_family_t,
++                    sin6_port: addr.port().to_be(),  // network byte order
++                    sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
++                    sin6_flowinfo: addr.flowinfo(),  // host byte order
++                    sin6_scope_id: addr.scope_id(),  // host byte order
++                    .. unsafe { mem::zeroed() }
++                })
++            }
++        }
++    }
++
++    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
++        match ip {
++            IpAddr::V4(ref ip) => {
++                InetAddr::V4(libc::sockaddr_in {
++                    sin_family: AddressFamily::Inet as sa_family_t,
++                    sin_port: port.to_be(),
++                    sin_addr: ip.0,
++                    .. unsafe { mem::zeroed() }
++                })
++            }
++            IpAddr::V6(ref ip) => {
++                InetAddr::V6(libc::sockaddr_in6 {
++                    sin6_family: AddressFamily::Inet6 as sa_family_t,
++                    sin6_port: port.to_be(),
++                    sin6_addr: ip.0,
++                    .. unsafe { mem::zeroed() }
++                })
++            }
++        }
++    }
++    /// Gets the IP address associated with this socket address.
++    pub fn ip(&self) -> IpAddr {
++        match *self {
++            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
++            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
++        }
++    }
++
++    /// Gets the port number associated with this socket address
++    pub fn port(&self) -> u16 {
++        match *self {
++            InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
++            InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
++        }
++    }
++
++    pub fn to_std(&self) -> net::SocketAddr {
++        match *self {
++            InetAddr::V4(ref sa) => net::SocketAddr::V4(
++                net::SocketAddrV4::new(
++                    Ipv4Addr(sa.sin_addr).to_std(),
++                    self.port())),
++            InetAddr::V6(ref sa) => net::SocketAddr::V6(
++                net::SocketAddrV6::new(
++                    Ipv6Addr(sa.sin6_addr).to_std(),
++                    self.port(),
++                    sa.sin6_flowinfo,
++                    sa.sin6_scope_id)),
++        }
++    }
++
++    pub fn to_str(&self) -> String {
++        format!("{}", self)
++    }
++}
++
++impl fmt::Display for InetAddr {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        match *self {
++            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
++            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
++        }
++    }
++}
++
++/*
++ *
++ * ===== IpAddr =====
++ *
++ */
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum IpAddr {
++    V4(Ipv4Addr),
++    V6(Ipv6Addr),
++}
++
++impl IpAddr {
++    /// Create a new IpAddr that contains an IPv4 address.
++    ///
++    /// The result will represent the IP address a.b.c.d
++    pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
++        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
++    }
++
++    /// Create a new IpAddr that contains an IPv6 address.
++    ///
++    /// The result will represent the IP address a:b:c:d:e:f
++    pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
++        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
++    }
++
++    pub fn from_std(std: &net::IpAddr) -> IpAddr {
++        match *std {
++            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
++            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
++        }
++    }
++
++    pub fn to_std(&self) -> net::IpAddr {
++        match *self {
++            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
++            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
++        }
++    }
++}
++
++impl fmt::Display for IpAddr {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        match *self {
++            IpAddr::V4(ref v4) => v4.fmt(f),
++            IpAddr::V6(ref v6) => v6.fmt(f)
++        }
++    }
++}
++
++/*
++ *
++ * ===== Ipv4Addr =====
++ *
++ */
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct Ipv4Addr(pub libc::in_addr);
++
++impl Ipv4Addr {
++    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
++        let ip = (((a as u32) << 24) |
++                  ((b as u32) << 16) |
++                  ((c as u32) <<  8) |
++                  ((d as u32) <<  0)).to_be();
++
++        Ipv4Addr(libc::in_addr { s_addr: ip })
++    }
++
++    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
++        let bits = std.octets();
++        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
++    }
++
++    pub fn any() -> Ipv4Addr {
++        Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
++    }
++
++    pub fn octets(&self) -> [u8; 4] {
++        let bits = u32::from_be(self.0.s_addr);
++        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
++    }
++
++    pub fn to_std(&self) -> net::Ipv4Addr {
++        let bits = self.octets();
++        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
++    }
++}
++
++impl fmt::Display for Ipv4Addr {
++    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
++        let octets = self.octets();
++        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
++    }
++}
++
++/*
++ *
++ * ===== Ipv6Addr =====
++ *
++ */
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct Ipv6Addr(pub libc::in6_addr);
++
++// Note that IPv6 addresses are stored in big endian order on all architectures.
++// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
++// engine.
++
++macro_rules! to_u8_array {
++    ($($num:ident),*) => {
++        [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
++    }
++}
++
++macro_rules! to_u16_array {
++    ($slf:ident, $($first:expr, $second:expr),*) => {
++        [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
++    }
++}
++
++impl Ipv6Addr {
++    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
++        let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()};
++        in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h);
++        Ipv6Addr(in6_addr_var)
++    }
++
++    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
++        let s = std.segments();
++        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
++    }
++
++    /// Return the eight 16-bit segments that make up this address
++    pub fn segments(&self) -> [u16; 8] {
++        to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
++    }
++
++    pub fn to_std(&self) -> net::Ipv6Addr {
++        let s = self.segments();
++        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
++    }
++}
++
++impl fmt::Display for Ipv6Addr {
++    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
++        self.to_std().fmt(fmt)
++    }
++}
++
++/// A wrapper around `sockaddr_un`.
++///
++/// This also tracks the length of `sun_path` address (excluding
++/// a terminating null), because it may not be null-terminated.  For example,
++/// unconnected and Linux abstract sockets are never null-terminated, and POSIX
++/// does not require that `sun_len` include the terminating null even for normal
++/// sockets.  Note that the actual sockaddr length is greater by
++/// `offset_of!(libc::sockaddr_un, sun_path)`
++#[derive(Clone, Copy, Debug)]
++pub struct UnixAddr(pub libc::sockaddr_un, pub usize);
++
++impl UnixAddr {
++    /// Create a new sockaddr_un representing a filesystem path.
++    pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
++        path.with_nix_path(|cstr| {
++            unsafe {
++                let mut ret = libc::sockaddr_un {
++                    sun_family: AddressFamily::Unix as sa_family_t,
++                    .. mem::zeroed()
++                };
++
++                let bytes = cstr.to_bytes();
++
++                if bytes.len() > ret.sun_path.len() {
++                    return Err(Error::Sys(Errno::ENAMETOOLONG));
++                }
++
++                ptr::copy_nonoverlapping(bytes.as_ptr(),
++                                         ret.sun_path.as_mut_ptr() as *mut u8,
++                                         bytes.len());
++
++                Ok(UnixAddr(ret, bytes.len()))
++            }
++        })?
++    }
++
++    /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
++    ///
++    /// The leading null byte for the abstract namespace is automatically added;
++    /// thus the input `path` is expected to be the bare name, not null-prefixed.
++    /// This is a Linux-specific extension, primarily used to allow chrooted
++    /// processes to communicate with processes having a different filesystem view.
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
++        unsafe {
++            let mut ret = libc::sockaddr_un {
++                sun_family: AddressFamily::Unix as sa_family_t,
++                .. mem::zeroed()
++            };
++
++            if path.len() + 1 > ret.sun_path.len() {
++                return Err(Error::Sys(Errno::ENAMETOOLONG));
++            }
++
++            // Abstract addresses are represented by sun_path[0] ==
++            // b'\0', so copy starting one byte in.
++            ptr::copy_nonoverlapping(path.as_ptr(),
++                                     ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
++                                     path.len());
++
++            Ok(UnixAddr(ret, ret.sun_path.len()))
++        }
++    }
++
++    fn sun_path(&self) -> &[u8] {
++        unsafe { slice::from_raw_parts(self.0.sun_path.as_ptr() as *const u8, self.1) }
++    }
++
++    /// If this address represents a filesystem path, return that path.
++    pub fn path(&self) -> Option<&Path> {
++        if self.1 == 0 || self.0.sun_path[0] == 0 {
++            // unnamed or abstract
++            None
++        } else {
++            let p = self.sun_path();
++            // POSIX only requires that `sun_len` be at least long enough to
++            // contain the pathname, and it need not be null-terminated.  So we
++            // need to create a string that is the shorter of the
++            // null-terminated length or the full length.
++            let ptr = &self.0.sun_path as *const libc::c_char;
++            let reallen = unsafe { libc::strnlen(ptr, p.len()) };
++            Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
++        }
++    }
++
++    /// If this address represents an abstract socket, return its name.
++    ///
++    /// For abstract sockets only the bare name is returned, without the
++    /// leading null byte. `None` is returned for unnamed or path-backed sockets.
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    pub fn as_abstract(&self) -> Option<&[u8]> {
++        if self.1 >= 1 && self.0.sun_path[0] == 0 {
++            Some(&self.sun_path()[1..])
++        } else {
++            // unnamed or filesystem path
++            None
++        }
++    }
++}
++
++impl fmt::Display for UnixAddr {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        if self.1 == 0 {
++            f.write_str("<unbound UNIX socket>")
++        } else if let Some(path) = self.path() {
++            path.display().fmt(f)
++        } else {
++            let display = String::from_utf8_lossy(&self.sun_path()[1..]);
++            write!(f, "@{}", display)
++        }
++    }
++}
++
++impl PartialEq for UnixAddr {
++    fn eq(&self, other: &UnixAddr) -> bool {
++        self.sun_path() == other.sun_path()
++    }
++}
++
++impl Eq for UnixAddr {}
++
++impl Hash for UnixAddr {
++    fn hash<H: Hasher>(&self, s: &mut H) {
++        ( self.0.sun_family, self.sun_path() ).hash(s)
++    }
++}
++
++/// Represents a socket address
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum SockAddr {
++    Inet(InetAddr),
++    Unix(UnixAddr),
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Netlink(NetlinkAddr),
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Alg(AlgAddr),
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
++    SysControl(SysControlAddr),
++    /// Datalink address (MAC)
++    #[cfg(any(target_os = "android",
++              target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "linux",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    Link(LinkAddr),
++    #[cfg(target_os = "linux")]
++    Vsock(VsockAddr),
++}
++
++impl SockAddr {
++    pub fn new_inet(addr: InetAddr) -> SockAddr {
++        SockAddr::Inet(addr)
++    }
++
++    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
++        Ok(SockAddr::Unix(UnixAddr::new(path)?))
++    }
++
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
++        SockAddr::Netlink(NetlinkAddr::new(pid, groups))
++    }
++
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
++        SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
++    }
++
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
++    pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
++        SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
++    }
++
++    #[cfg(target_os = "linux")]
++    pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
++        SockAddr::Vsock(VsockAddr::new(cid, port))
++    }
++
++    pub fn family(&self) -> AddressFamily {
++        match *self {
++            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
++            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
++            SockAddr::Unix(..) => AddressFamily::Unix,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Netlink(..) => AddressFamily::Netlink,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Alg(..) => AddressFamily::Alg,
++            #[cfg(any(target_os = "ios", target_os = "macos"))]
++            SockAddr::SysControl(..) => AddressFamily::System,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Link(..) => AddressFamily::Packet,
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "ios",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            SockAddr::Link(..) => AddressFamily::Link,
++            #[cfg(target_os = "linux")]
++            SockAddr::Vsock(..) => AddressFamily::Vsock,
++        }
++    }
++
++    pub fn to_str(&self) -> String {
++        format!("{}", self)
++    }
++
++    /// Creates a `SockAddr` struct from libc's sockaddr.
++    ///
++    /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
++    /// Returns None for unsupported families.
++    pub unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
++        if addr.is_null() {
++            None
++        } else {
++            match AddressFamily::from_i32((*addr).sa_family as i32) {
++                Some(AddressFamily::Unix) => None,
++                Some(AddressFamily::Inet) => Some(SockAddr::Inet(
++                    InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
++                Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
++                    InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
++                #[cfg(any(target_os = "android", target_os = "linux"))]
++                Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
++                    NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
++                #[cfg(any(target_os = "ios", target_os = "macos"))]
++                Some(AddressFamily::System) => Some(SockAddr::SysControl(
++                    SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
++                #[cfg(any(target_os = "android", target_os = "linux"))]
++                Some(AddressFamily::Packet) => Some(SockAddr::Link(
++                    LinkAddr(*(addr as *const libc::sockaddr_ll)))),
++                #[cfg(any(target_os = "dragonfly",
++                          target_os = "freebsd",
++                          target_os = "ios",
++                          target_os = "macos",
++                          target_os = "netbsd",
++                          target_os = "openbsd"))]
++                Some(AddressFamily::Link) => {
++                    let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
++                    if ether_addr.is_empty() {
++                        None
++                    } else {
++                        Some(SockAddr::Link(ether_addr))
++                    }
++                },
++                #[cfg(target_os = "linux")]
++                Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
++                    VsockAddr(*(addr as *const libc::sockaddr_vm)))),
++                // Other address families are currently not supported and simply yield a None
++                // entry instead of a proper conversion to a `SockAddr`.
++                Some(_) | None => None,
++            }
++        }
++    }
++
++    /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
++    ///
++    /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
++    /// Returns a reference to the underlying data type (as a sockaddr reference) along
++    /// with the size of the actual data type. sockaddr is commonly used as a proxy for
++    /// a superclass as C doesn't support inheritance, so many functions that take
++    /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
++    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
++        match *self {
++            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
++            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
++            SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Alg(AlgAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t),
++            #[cfg(any(target_os = "ios", target_os = "macos"))]
++            SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t),
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "ios",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t),
++            #[cfg(target_os = "linux")]
++            SockAddr::Vsock(VsockAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t),
++        }
++    }
++}
++
++impl fmt::Display for SockAddr {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        match *self {
++            SockAddr::Inet(ref inet) => inet.fmt(f),
++            SockAddr::Unix(ref unix) => unix.fmt(f),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Netlink(ref nl) => nl.fmt(f),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Alg(ref nl) => nl.fmt(f),
++            #[cfg(any(target_os = "ios", target_os = "macos"))]
++            SockAddr::SysControl(ref sc) => sc.fmt(f),
++            #[cfg(any(target_os = "android",
++                      target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "ios",
++                      target_os = "linux",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
++            #[cfg(target_os = "linux")]
++            SockAddr::Vsock(ref svm) => svm.fmt(f),
++        }
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod netlink {
++    use ::sys::socket::addr::AddressFamily;
++    use libc::{sa_family_t, sockaddr_nl};
++    use std::{fmt, mem};
++
++    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++    pub struct NetlinkAddr(pub sockaddr_nl);
++
++    impl NetlinkAddr {
++        pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
++            let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
++            addr.nl_family = AddressFamily::Netlink as sa_family_t;
++            addr.nl_pid = pid;
++            addr.nl_groups = groups;
++
++            NetlinkAddr(addr)
++        }
++
++        pub fn pid(&self) -> u32 {
++            self.0.nl_pid
++        }
++
++        pub fn groups(&self) -> u32 {
++            self.0.nl_groups
++        }
++    }
++
++    impl fmt::Display for NetlinkAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            write!(f, "pid: {} groups: {}", self.pid(), self.groups())
++        }
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub mod alg {
++    use libc::{AF_ALG, sockaddr_alg, c_char};
++    use std::{fmt, mem, str};
++    use std::hash::{Hash, Hasher};
++    use std::ffi::CStr;
++
++    #[derive(Copy, Clone)]
++    pub struct AlgAddr(pub sockaddr_alg);
++
++    // , PartialEq, Eq, Debug, Hash
++    impl PartialEq for AlgAddr {
++        fn eq(&self, other: &Self) -> bool {
++            let (inner, other) = (self.0, other.0);
++            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
++            (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
++        }
++    }
++
++    impl Eq for AlgAddr {}
++
++    impl Hash for AlgAddr {
++        fn hash<H: Hasher>(&self, s: &mut H) {
++            let inner = self.0;
++            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
++        }
++    }
++
++    impl AlgAddr {
++        pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
++            let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
++            addr.salg_family = AF_ALG as u16;
++            addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
++            addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
++
++            AlgAddr(addr)
++        }
++
++
++        pub fn alg_type(&self) -> &CStr {
++            unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
++        }
++
++        pub fn alg_name(&self) -> &CStr {
++            unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
++        }
++    }
++
++    impl fmt::Display for AlgAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            write!(f, "type: {} alg: {}",
++                   self.alg_name().to_string_lossy(),
++                   self.alg_type().to_string_lossy())
++        }
++    }
++
++    impl fmt::Debug for AlgAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            fmt::Display::fmt(self, f)
++        }
++    }
++}
++
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++pub mod sys_control {
++    use ::sys::socket::addr::AddressFamily;
++    use libc::{self, c_uchar};
++    use std::{fmt, mem};
++    use std::os::unix::io::RawFd;
++    use {Errno, Error, Result};
++
++    // FIXME: Move type into `libc`
++    #[repr(C)]
++    #[derive(Clone, Copy)]
++    #[allow(missing_debug_implementations)]
++    pub struct ctl_ioc_info {
++        pub ctl_id: u32,
++        pub ctl_name: [c_uchar; MAX_KCTL_NAME],
++    }
++
++    const CTL_IOC_MAGIC: u8 = 'N' as u8;
++    const CTL_IOC_INFO: u8 = 3;
++    const MAX_KCTL_NAME: usize = 96;
++
++    ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
++
++    #[repr(C)]
++    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++    pub struct SysControlAddr(pub libc::sockaddr_ctl);
++
++    impl SysControlAddr {
++        pub fn new(id: u32, unit: u32) -> SysControlAddr {
++            let addr = libc::sockaddr_ctl {
++                sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
++                sc_family: AddressFamily::System as c_uchar,
++                ss_sysaddr: libc::AF_SYS_CONTROL as u16,
++                sc_id: id,
++                sc_unit: unit,
++                sc_reserved: [0; 5]
++            };
++
++            SysControlAddr(addr)
++        }
++
++        pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
++            if name.len() > MAX_KCTL_NAME {
++                return Err(Error::Sys(Errno::ENAMETOOLONG));
++            }
++
++            let mut ctl_name = [0; MAX_KCTL_NAME];
++            ctl_name[..name.len()].clone_from_slice(name.as_bytes());
++            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
++
++            unsafe { ctl_info(sockfd, &mut info)?; }
++
++            Ok(SysControlAddr::new(info.ctl_id, unit))
++        }
++
++        pub fn id(&self) -> u32 {
++            self.0.sc_id
++        }
++
++        pub fn unit(&self) -> u32 {
++            self.0.sc_unit
++        }
++    }
++
++    impl fmt::Display for SysControlAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            fmt::Debug::fmt(self, f)
++        }
++    }
++}
++
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod datalink {
++    use super::{libc, fmt, AddressFamily};
++
++    /// Hardware Address
++    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++    pub struct LinkAddr(pub libc::sockaddr_ll);
++
++    impl LinkAddr {
++        /// Always AF_PACKET
++        pub fn family(&self) -> AddressFamily {
++            assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
++            AddressFamily::Packet
++        }
++
++        /// Physical-layer protocol
++        pub fn protocol(&self) -> u16 {
++            self.0.sll_protocol
++        }
++
++        /// Interface number
++        pub fn ifindex(&self) -> usize {
++            self.0.sll_ifindex as usize
++        }
++
++        /// ARP hardware type
++        pub fn hatype(&self) -> u16 {
++            self.0.sll_hatype
++        }
++
++        /// Packet type
++        pub fn pkttype(&self) -> u8 {
++            self.0.sll_pkttype
++        }
++
++        /// Length of MAC address
++        pub fn halen(&self) -> usize {
++            self.0.sll_halen as usize
++        }
++
++        /// Physical-layer address (MAC)
++        pub fn addr(&self) -> [u8; 6] {
++            let a = self.0.sll_addr[0] as u8;
++            let b = self.0.sll_addr[1] as u8;
++            let c = self.0.sll_addr[2] as u8;
++            let d = self.0.sll_addr[3] as u8;
++            let e = self.0.sll_addr[4] as u8;
++            let f = self.0.sll_addr[5] as u8;
++
++            [a, b, c, d, e, f]
++        }
++    }
++
++    impl fmt::Display for LinkAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            let addr = self.addr();
++            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
++                addr[0],
++                addr[1],
++                addr[2],
++                addr[3],
++                addr[4],
++                addr[5])
++        }
++    }
++}
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++mod datalink {
++    use super::{libc, fmt, AddressFamily};
++
++    /// Hardware Address
++    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++    pub struct LinkAddr(pub libc::sockaddr_dl);
++
++    impl LinkAddr {
++        /// Total length of sockaddr
++        pub fn len(&self) -> usize {
++            self.0.sdl_len as usize
++        }
++
++        /// always == AF_LINK
++        pub fn family(&self) -> AddressFamily {
++            assert_eq!(self.0.sdl_family as i32, libc::AF_LINK);
++            AddressFamily::Link
++        }
++
++        /// interface index, if != 0, system given index for interface
++        pub fn ifindex(&self) -> usize {
++            self.0.sdl_index as usize
++        }
++
++        /// Datalink type
++        pub fn datalink_type(&self) -> u8 {
++            self.0.sdl_type
++        }
++
++        // MAC address start position
++        pub fn nlen(&self) -> usize {
++            self.0.sdl_nlen as usize
++        }
++
++        /// link level address length
++        pub fn alen(&self) -> usize {
++            self.0.sdl_alen as usize
++        }
++
++        /// link layer selector length
++        pub fn slen(&self) -> usize {
++            self.0.sdl_slen as usize
++        }
++
++        /// if link level address length == 0,
++        /// or `sdl_data` not be larger.
++        pub fn is_empty(&self) -> bool {
++            let nlen = self.nlen();
++            let alen = self.alen();
++            let data_len = self.0.sdl_data.len();
++
++            if alen > 0 && nlen + alen < data_len {
++                false
++            } else {
++                true
++            }
++        }
++
++        /// Physical-layer address (MAC)
++        pub fn addr(&self) -> [u8; 6] {
++            let nlen = self.nlen();
++            let data = self.0.sdl_data;
++
++            assert!(!self.is_empty());
++
++            let a = data[nlen] as u8;
++            let b = data[nlen + 1] as u8;
++            let c = data[nlen + 2] as u8;
++            let d = data[nlen + 3] as u8;
++            let e = data[nlen + 4] as u8;
++            let f = data[nlen + 5] as u8;
++
++            [a, b, c, d, e, f]
++        }
++    }
++
++    impl fmt::Display for LinkAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            let addr = self.addr();
++            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
++                addr[0],
++                addr[1],
++                addr[2],
++                addr[3],
++                addr[4],
++                addr[5])
++        }
++    }
++}
++
++#[cfg(target_os = "linux")]
++pub mod vsock {
++    use ::sys::socket::addr::AddressFamily;
++    use libc::{sa_family_t, sockaddr_vm};
++    use std::{fmt, mem};
++    use std::hash::{Hash, Hasher};
++
++    #[derive(Copy, Clone)]
++    pub struct VsockAddr(pub sockaddr_vm);
++
++    impl PartialEq for VsockAddr {
++        fn eq(&self, other: &Self) -> bool {
++            let (inner, other) = (self.0, other.0);
++            (inner.svm_family, inner.svm_cid, inner.svm_port) ==
++            (other.svm_family, other.svm_cid, other.svm_port)
++        }
++    }
++
++    impl Eq for VsockAddr {}
++
++    impl Hash for VsockAddr {
++        fn hash<H: Hasher>(&self, s: &mut H) {
++            let inner = self.0;
++            (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
++        }
++    }
++
++    /// VSOCK Address
++    ///
++    /// The address for AF_VSOCK socket is defined as a combination of a
++    /// 32-bit Context Identifier (CID) and a 32-bit port number.
++    impl VsockAddr {
++        pub fn new(cid: u32, port: u32) -> VsockAddr {
++            let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
++            addr.svm_family = AddressFamily::Vsock as sa_family_t;
++            addr.svm_cid = cid;
++            addr.svm_port = port;
++
++            VsockAddr(addr)
++        }
++
++        /// Context Identifier (CID)
++        pub fn cid(&self) -> u32 {
++            self.0.svm_cid
++        }
++
++        /// Port number
++        pub fn port(&self) -> u32 {
++            self.0.svm_port
++        }
++    }
++
++    impl fmt::Display for VsockAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            write!(f, "cid: {} port: {}", self.cid(), self.port())
++        }
++    }
++
++    impl fmt::Debug for VsockAddr {
++        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++            fmt::Display::fmt(self, f)
++        }
++    }
++}
++
++#[cfg(test)]
++mod tests {
++    #[cfg(any(target_os = "android",
++              target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "linux",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    use super::*;
++
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    #[test]
++    fn test_macos_loopback_datalink_addr() {
++        let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
++        let sa = bytes.as_ptr() as *const libc::sockaddr;
++        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
++        assert!(_sock_addr.is_none());
++    }
++
++    #[cfg(any(target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "openbsd"))]
++    #[test]
++    fn test_macos_tap_datalink_addr() {
++        let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
++        let ptr = bytes.as_ptr();
++        let sa = ptr as *const libc::sockaddr;
++        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
++
++        assert!(_sock_addr.is_some());
++
++        let sock_addr = _sock_addr.unwrap();
++
++        assert_eq!(sock_addr.family(), AddressFamily::Link);
++
++        match sock_addr {
++            SockAddr::Link(ether_addr) => {
++                assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
++            },
++            _ => { unreachable!() }
++        };
++    }
++
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    #[test]
++    fn test_abstract_sun_path() {
++        let name = String::from("nix\0abstract\0test");
++        let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
++
++        let sun_path1 = addr.sun_path();
++        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
++        assert_eq!(sun_path1.len(), sun_path2.len());
++        for i in 0..sun_path1.len() {
++            assert_eq!(sun_path1[i], sun_path2[i]);
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs b/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
+new file mode 100644
+index 0000000000000..1c12c5f851734
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
+@@ -0,0 +1,1294 @@
++//! Socket interface functions
++//!
++//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
++use {Error, Result};
++use errno::Errno;
++use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
++        CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
++use std::{mem, ptr, slice};
++use std::os::unix::io::RawFd;
++use sys::time::TimeVal;
++use sys::uio::IoVec;
++
++mod addr;
++pub mod sockopt;
++
++/*
++ *
++ * ===== Re-exports =====
++ *
++ */
++
++pub use self::addr::{
++    AddressFamily,
++    SockAddr,
++    InetAddr,
++    UnixAddr,
++    IpAddr,
++    Ipv4Addr,
++    Ipv6Addr,
++    LinkAddr,
++};
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use ::sys::socket::addr::netlink::NetlinkAddr;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use sys::socket::addr::alg::AlgAddr;
++#[cfg(target_os = "linux")]
++pub use sys::socket::addr::vsock::VsockAddr;
++
++pub use libc::{
++    cmsghdr,
++    msghdr,
++    sa_family_t,
++    sockaddr,
++    sockaddr_in,
++    sockaddr_in6,
++    sockaddr_storage,
++    sockaddr_un,
++};
++
++// Needed by the cmsg_space macro
++#[doc(hidden)]
++pub use libc::{c_uint, CMSG_SPACE};
++
++/// These constants are used to specify the communication semantics
++/// when creating a socket with [`socket()`](fn.socket.html)
++#[derive(Clone, Copy, PartialEq, Eq, Debug)]
++#[repr(i32)]
++pub enum SockType {
++    /// Provides sequenced, reliable, two-way, connection-
++    /// based byte streams.  An out-of-band data transmission
++    /// mechanism may be supported.
++    Stream = libc::SOCK_STREAM,
++    /// Supports datagrams (connectionless, unreliable
++    /// messages of a fixed maximum length).
++    Datagram = libc::SOCK_DGRAM,
++    /// Provides a sequenced, reliable, two-way connection-
++    /// based data transmission path for datagrams of fixed
++    /// maximum length; a consumer is required to read an
++    /// entire packet with each input system call.
++    SeqPacket = libc::SOCK_SEQPACKET,
++    /// Provides raw network protocol access.
++    Raw = libc::SOCK_RAW,
++    /// Provides a reliable datagram layer that does not
++    /// guarantee ordering.
++    Rdm = libc::SOCK_RDM,
++}
++
++/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
++/// to specify the protocol to use.
++#[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 = libc::IPPROTO_TCP,
++    /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
++    Udp = libc::IPPROTO_UDP,
++    /// Allows applications and other KEXTs to be notified when certain kernel events occur
++    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
++    KextEvent = libc::SYSPROTO_EVENT,
++    /// Allows applications to configure and control a KEXT
++    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
++    KextControl = libc::SYSPROTO_CONTROL,
++}
++
++libc_bitflags!{
++    /// Additional socket options
++    pub struct SockFlag: c_int {
++        /// Set non-blocking mode on the new socket
++        #[cfg(any(target_os = "android",
++                  target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        SOCK_NONBLOCK;
++        /// Set close-on-exec on the new descriptor
++        #[cfg(any(target_os = "android",
++                  target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        SOCK_CLOEXEC;
++        /// Return `EPIPE` instead of raising `SIGPIPE`
++        #[cfg(target_os = "netbsd")]
++        SOCK_NOSIGPIPE;
++        /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
++        /// to the DNS port (typically 53)
++        #[cfg(target_os = "openbsd")]
++        SOCK_DNS;
++    }
++}
++
++libc_bitflags!{
++    /// Flags for send/recv and their relatives
++    pub struct MsgFlags: c_int {
++        /// Sends or requests out-of-band data on sockets that support this notion
++        /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
++        /// support out-of-band data.
++        MSG_OOB;
++        /// Peeks at an incoming message. The data is treated as unread and the next
++        /// [`recv()`](fn.recv.html)
++        /// or similar function shall still return this data.
++        MSG_PEEK;
++        /// Receive operation blocks until the full amount of data can be
++        /// returned. The function may return smaller amount of data if a signal
++        /// is caught, an error or disconnect occurs.
++        MSG_WAITALL;
++        /// Enables nonblocking operation; if the operation would block,
++        /// `EAGAIN` or `EWOULDBLOCK` is returned.  This provides similar
++        /// behavior to setting the `O_NONBLOCK` flag
++        /// (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)),
++        /// 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.
++        MSG_DONTWAIT;
++        /// Receive flags: Control Data was discarded (buffer too small)
++        MSG_CTRUNC;
++        /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
++        /// (since Linux 2.4.27/2.6.8),
++        /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
++        /// sockets: return the real length of the packet or datagram, even
++        /// when it was longer than the passed buffer. Not implemented for UNIX
++        /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
++        ///
++        /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
++        MSG_TRUNC;
++        /// Terminates a record (when this notion is supported, as for
++        /// sockets of type [`SeqPacket`](enum.SockType.html)).
++        MSG_EOR;
++        /// This flag specifies that queued errors should be received from
++        /// the socket error queue. (For more details, see
++        /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        MSG_ERRQUEUE;
++        /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
++        /// 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).
++        ///
++        /// Only used in [`recvmsg`](fn.recvmsg.html) function.
++        #[cfg(any(target_os = "android",
++                  target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        MSG_CMSG_CLOEXEC;
++    }
++}
++
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        /// Unix credentials of the sending process.
++        ///
++        /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
++        #[repr(C)]
++        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
++        pub struct UnixCredentials(libc::ucred);
++
++        impl UnixCredentials {
++            /// Returns the process identifier
++            pub fn pid(&self) -> libc::pid_t {
++                self.0.pid
++            }
++
++            /// Returns the user identifier
++            pub fn uid(&self) -> libc::uid_t {
++                self.0.uid
++            }
++
++            /// Returns the group identifier
++            pub fn gid(&self) -> libc::gid_t {
++                self.0.gid
++            }
++        }
++
++        impl From<libc::ucred> for UnixCredentials {
++            fn from(cred: libc::ucred) -> Self {
++                UnixCredentials(cred)
++            }
++        }
++
++        impl Into<libc::ucred> for UnixCredentials {
++            fn into(self) -> libc::ucred {
++                self.0
++            }
++        }
++    }
++}
++
++/// Request for multicast socket operations
++///
++/// This is a wrapper type around `ip_mreq`.
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub struct IpMembershipRequest(libc::ip_mreq);
++
++impl IpMembershipRequest {
++    /// Instantiate a new `IpMembershipRequest`
++    ///
++    /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
++    pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
++        IpMembershipRequest(libc::ip_mreq {
++            imr_multiaddr: group.0,
++            imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
++        })
++    }
++}
++
++/// Request for ipv6 multicast socket operations
++///
++/// This is a wrapper type around `ipv6_mreq`.
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
++
++impl Ipv6MembershipRequest {
++    /// Instantiate a new `Ipv6MembershipRequest`
++    pub fn new(group: Ipv6Addr) -> Self {
++        Ipv6MembershipRequest(libc::ipv6_mreq {
++            ipv6mr_multiaddr: group.0,
++            ipv6mr_interface: 0,
++        })
++    }
++}
++
++cfg_if! {
++    // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
++    if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
++        type align_of_cmsg_data = u32;
++    } else {
++        type align_of_cmsg_data = size_t;
++    }
++}
++
++/// A type that can be used to store ancillary data received by
++/// [`recvmsg`](fn.recvmsg.html)
++pub trait CmsgBuffer {
++    fn as_bytes_mut(&mut self) -> &mut [u8];
++}
++
++/// Create a buffer large enough for storing some control messages as returned
++/// by [`recvmsg`](fn.recvmsg.html).
++///
++/// # Examples
++///
++/// ```
++/// # #[macro_use] extern crate nix;
++/// # use nix::sys::time::TimeVal;
++/// # use std::os::unix::io::RawFd;
++/// # fn main() {
++/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
++/// let _ = cmsg_space!(TimeVal);
++/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
++/// // with two file descriptors
++/// let _ = cmsg_space!([RawFd; 2]);
++/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
++/// // and a `ControlMessageOwned::ScmTimestamp` message
++/// let _ = cmsg_space!(RawFd, TimeVal);
++/// # }
++/// ```
++// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
++// stack-allocated array.
++#[macro_export]
++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)
++                } as usize;
++            )*
++            let mut v = Vec::<u8>::with_capacity(space);
++            // safe because any bit pattern is a valid u8
++            unsafe {v.set_len(space)};
++            v
++        }
++    }
++}
++
++/// A structure used to make room in a cmsghdr passed to recvmsg. The
++/// size and alignment match that of a cmsghdr followed by a T, but the
++/// fields are not accessible, as the actual types will change on a call
++/// to recvmsg.
++///
++/// To make room for multiple messages, nest the type parameter with
++/// tuples:
++///
++/// ```
++/// use std::os::unix::io::RawFd;
++/// use nix::sys::socket::CmsgSpace;
++/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
++/// ```
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub struct CmsgSpace<T> {
++    _hdr: cmsghdr,
++    _pad: [align_of_cmsg_data; 0],
++    _data: T,
++}
++
++impl<T> CmsgSpace<T> {
++    /// Create a CmsgSpace<T>. The structure is used only for space, so
++    /// the fields are uninitialized.
++    #[deprecated( since="0.14.0", note="Use the cmsg_space! macro instead")]
++    pub fn new() -> Self {
++        // Safe because the fields themselves aren't accessible.
++        unsafe { mem::uninitialized() }
++    }
++}
++
++impl<T> CmsgBuffer for CmsgSpace<T> {
++    fn as_bytes_mut(&mut self) -> &mut [u8] {
++        // Safe because nothing ever attempts to access CmsgSpace's fields
++        unsafe {
++            slice::from_raw_parts_mut(self as *mut CmsgSpace<T> as *mut u8,
++                                      mem::size_of::<Self>())
++        }
++    }
++}
++
++impl CmsgBuffer for Vec<u8> {
++    fn as_bytes_mut(&mut self) -> &mut [u8] {
++        &mut self[..]
++    }
++}
++
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub struct RecvMsg<'a> {
++    pub bytes: usize,
++    cmsghdr: Option<&'a cmsghdr>,
++    pub address: Option<SockAddr>,
++    pub flags: MsgFlags,
++    mhdr: msghdr,
++}
++
++impl<'a> RecvMsg<'a> {
++    /// Iterate over the valid control messages pointed to by this
++    /// msghdr.
++    pub fn cmsgs(&self) -> CmsgIterator {
++        CmsgIterator {
++            cmsghdr: self.cmsghdr,
++            mhdr: &self.mhdr
++        }
++    }
++}
++
++#[derive(Clone, Copy, Debug, Eq, PartialEq)]
++pub struct CmsgIterator<'a> {
++    /// Control message buffer to decode from. Must adhere to cmsg alignment.
++    cmsghdr: Option<&'a cmsghdr>,
++    mhdr: &'a msghdr
++}
++
++impl<'a> Iterator for CmsgIterator<'a> {
++    type Item = ControlMessageOwned;
++
++    fn next(&mut self) -> Option<ControlMessageOwned> {
++        match self.cmsghdr {
++            None => None,   // No more messages
++            Some(hdr) => {
++                // Get the data.
++                // Safe if cmsghdr points to valid data returned by recvmsg(2)
++                let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
++                // Advance the internal pointer.  Safe if mhdr and cmsghdr point
++                // to valid data returned by recvmsg(2)
++                self.cmsghdr = unsafe {
++                    let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
++                    p.as_ref()
++                };
++                cm
++            }
++        }
++    }
++}
++
++/// 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)
++//  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
++//  alignment issues.
++//
++//  See https://github.com/nix-rust/nix/issues/999
++#[derive(Clone, Debug, Eq, PartialEq)]
++pub enum ControlMessageOwned {
++    /// Received version of
++    /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
++    ScmRights(Vec<RawFd>),
++    /// Received version of
++    /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    ScmCredentials(libc::ucred),
++    /// A message of type `SCM_TIMESTAMP`, containing the time the
++    /// packet was received by the kernel.
++    ///
++    /// See the kernel's explanation in "SO_TIMESTAMP" of
++    /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
++    ///
++    /// # Examples
++    ///
++    // Disable this test on FreeBSD i386
++    // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
++    #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
++    #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
++    /// # #[macro_use] extern crate nix;
++    /// # use nix::sys::socket::*;
++    /// # use nix::sys::uio::IoVec;
++    /// # use nix::sys::time::*;
++    /// # use std::time::*;
++    /// # fn main() {
++    /// // Set up
++    /// let message = "Ohayō!".as_bytes();
++    /// let in_socket = socket(
++    ///     AddressFamily::Inet,
++    ///     SockType::Datagram,
++    ///     SockFlag::empty(),
++    ///     None).unwrap();
++    /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
++    /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
++    /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
++    /// let address = getsockname(in_socket).unwrap();
++    /// // Get initial time
++    /// let time0 = SystemTime::now();
++    /// // Send the message
++    /// let iov = [IoVec::from_slice(message)];
++    /// let flags = MsgFlags::empty();
++    /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
++    /// assert_eq!(message.len(), l);
++    /// // Receive the message
++    /// let mut buffer = vec![0u8; message.len()];
++    /// let mut cmsgspace = cmsg_space!(TimeVal);
++    /// let iov = [IoVec::from_mut_slice(&mut buffer)];
++    /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
++    /// let rtime = match r.cmsgs().next() {
++    ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
++    ///     Some(_) => panic!("Unexpected control message"),
++    ///     None => panic!("No control message")
++    /// };
++    /// // Check the final time
++    /// let time1 = SystemTime::now();
++    /// // the packet's received timestamp should lie in-between the two system
++    /// // times, unless the system clock was adjusted in the meantime.
++    /// let rduration = Duration::new(rtime.tv_sec() as u64,
++    ///                               rtime.tv_usec() as u32 * 1000);
++    /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
++    /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
++    /// // Close socket
++    /// nix::unistd::close(in_socket).unwrap();
++    /// # }
++    /// ```
++    ScmTimestamp(TimeVal),
++    #[cfg(any(
++        target_os = "android",
++        target_os = "ios",
++        target_os = "linux",
++        target_os = "macos",
++        target_os = "netbsd",
++    ))]
++    Ipv4PacketInfo(libc::in_pktinfo),
++    #[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 = "netbsd",
++    ))]
++    Ipv6PacketInfo(libc::in6_pktinfo),
++    #[cfg(any(
++        target_os = "freebsd",
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "netbsd",
++        target_os = "openbsd",
++    ))]
++    Ipv4RecvIf(libc::sockaddr_dl),
++    #[cfg(any(
++        target_os = "freebsd",
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "netbsd",
++        target_os = "openbsd",
++    ))]
++    Ipv4RecvDstAddr(libc::in_addr),
++    /// Catch-all variant for unimplemented cmsg types.
++    #[doc(hidden)]
++    Unknown(UnknownCmsg),
++}
++
++impl ControlMessageOwned {
++    /// Decodes a `ControlMessageOwned` from raw bytes.
++    ///
++    /// This is only safe to call if the data is correct for the message type
++    /// specified in the header. Normally, the kernel ensures that this is the
++    /// case. "Correct" in this case includes correct length, alignment and
++    /// actual content.
++    ///
++    /// Returns `None` if the data may be unaligned.  In that case use
++    /// `ControlMessageOwned::decode_from`.
++    unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
++    {
++        let p = CMSG_DATA(header);
++        let len = header as *const _ as usize + header.cmsg_len as usize
++            - p as usize;
++        match (header.cmsg_level, header.cmsg_type) {
++            (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
++                let n = len / mem::size_of::<RawFd>();
++                let mut fds = Vec::with_capacity(n);
++                for i in 0..n {
++                    let fdp = (p as *const RawFd).offset(i as isize);
++                    fds.push(ptr::read_unaligned(fdp));
++                }
++                let cmo = ControlMessageOwned::ScmRights(fds);
++                cmo
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
++                let cred: libc::ucred = ptr::read_unaligned(p as *const _);
++                ControlMessageOwned::ScmCredentials(cred)
++            }
++            (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
++                let tv: libc::timeval = ptr::read_unaligned(p as *const _);
++                ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
++            },
++            #[cfg(any(
++                target_os = "android",
++                target_os = "freebsd",
++                target_os = "ios",
++                target_os = "linux",
++                target_os = "macos"
++            ))]
++            (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
++                let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
++                ControlMessageOwned::Ipv6PacketInfo(info)
++            }
++            #[cfg(any(
++                target_os = "android",
++                target_os = "ios",
++                target_os = "linux",
++                target_os = "macos",
++                target_os = "netbsd",
++            ))]
++            (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
++                let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
++                ControlMessageOwned::Ipv4PacketInfo(info)
++            }
++            #[cfg(any(
++                target_os = "freebsd",
++                target_os = "ios",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd",
++            ))]
++            (libc::IPPROTO_IP, libc::IP_RECVIF) => {
++                let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
++                ControlMessageOwned::Ipv4RecvIf(dl)
++            },
++            #[cfg(any(
++                target_os = "freebsd",
++                target_os = "ios",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd",
++            ))]
++            (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
++                let dl = ptr::read_unaligned(p as *const libc::in_addr);
++                ControlMessageOwned::Ipv4RecvDstAddr(dl)
++            },
++            (_, _) => {
++                let sl = slice::from_raw_parts(p, len);
++                let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
++                ControlMessageOwned::Unknown(ucmsg)
++            }
++        }
++    }
++}
++
++/// A type-safe zero-copy wrapper around a single control message, as used wih
++/// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
++/// exhaustively pattern-match it.
++///
++/// [Further reading](http://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).
++    ///
++    /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
++    /// recommended since it causes platform-dependent behaviour: It might
++    /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
++    /// Instead, you can put all fds to be passed into a single `ScmRights`
++    /// message.
++    ScmRights(&'a [RawFd]),
++    /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
++    /// a process connected to the socket.
++    ///
++    /// This is similar to the socket option `SO_PEERCRED`, but requires a
++    /// process to explicitly send its credentials. A process running as root is
++    /// allowed to specify any credentials, while credentials sent by other
++    /// 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.
++    // FIXME: When `#[repr(transparent)]` is stable, use it on `UnixCredentials`
++    // and put that in here instead of a raw ucred.
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    ScmCredentials(&'a libc::ucred),
++
++    /// Set IV for `AF_ALG` crypto API.
++    ///
++    /// For further information, please refer to the
++    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
++    #[cfg(any(
++        target_os = "android",
++        target_os = "linux",
++    ))]
++    AlgSetIv(&'a [u8]),
++    /// Set crypto operation for `AF_ALG` crypto API. It may be one of
++    /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
++    ///
++    /// For further information, please refer to the
++    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
++    #[cfg(any(
++        target_os = "android",
++        target_os = "linux",
++    ))]
++    AlgSetOp(&'a libc::c_int),
++    /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
++    /// for `AF_ALG` crypto API.
++    ///
++    /// For further information, please refer to the
++    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
++    #[cfg(any(
++        target_os = "android",
++        target_os = "linux",
++    ))]
++    AlgSetAeadAssoclen(&'a u32),
++
++}
++
++// An opaque structure used to prevent cmsghdr from being a public type
++#[doc(hidden)]
++#[derive(Clone, Debug, Eq, PartialEq)]
++pub struct UnknownCmsg(cmsghdr, Vec<u8>);
++
++impl<'a> ControlMessage<'a> {
++    /// The value of CMSG_SPACE on this message.
++    /// Safe because CMSG_SPACE is always safe
++    fn space(&self) -> usize {
++        unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
++    }
++
++    /// The value of CMSG_LEN on this message.
++    /// Safe because CMSG_LEN is always safe
++    #[cfg(any(target_os = "android",
++              all(target_os = "linux", not(target_env = "musl"))))]
++    fn cmsg_len(&self) -> usize {
++        unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
++    }
++
++    #[cfg(not(any(target_os = "android",
++                  all(target_os = "linux", not(target_env = "musl")))))]
++    fn cmsg_len(&self) -> libc::c_uint {
++        unsafe{CMSG_LEN(self.len() as libc::c_uint)}
++    }
++
++    /// Return a reference to the payload data as a byte pointer
++    fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
++        let data_ptr = match self {
++            &ControlMessage::ScmRights(fds) => {
++                fds as *const _ as *const u8
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::ScmCredentials(creds) => {
++                creds as *const libc::ucred as *const u8
++            }
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetIv(iv) => {
++                unsafe {
++                    let alg_iv = cmsg_data as *mut libc::af_alg_iv;
++                    (*alg_iv).ivlen = iv.len() as u32;
++                    ptr::copy_nonoverlapping(
++                        iv.as_ptr(),
++                        (*alg_iv).iv.as_mut_ptr(),
++                        iv.len()
++                    );
++                };
++                return
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetOp(op) => {
++                op as *const _ as *const u8
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetAeadAssoclen(len) => {
++                len as *const _ as *const u8
++            },
++        };
++        unsafe {
++            ptr::copy_nonoverlapping(
++                data_ptr,
++                cmsg_data,
++                self.len()
++            )
++        };
++    }
++
++    /// The size of the payload, excluding its cmsghdr
++    fn len(&self) -> usize {
++        match self {
++            &ControlMessage::ScmRights(fds) => {
++                mem::size_of_val(fds)
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::ScmCredentials(creds) => {
++                mem::size_of_val(creds)
++            }
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetIv(iv) => {
++                mem::size_of::<libc::af_alg_iv>() + iv.len()
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetOp(op) => {
++                mem::size_of_val(op)
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetAeadAssoclen(len) => {
++                mem::size_of_val(len)
++            },
++        }
++    }
++
++    /// Returns the value to put into the `cmsg_level` field of the header.
++    fn cmsg_level(&self) -> libc::c_int {
++        match self {
++            &ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetIv(_) | &ControlMessage::AlgSetOp(_) | &ControlMessage::AlgSetAeadAssoclen(_) => {
++                libc::SOL_ALG
++            },
++        }
++    }
++
++    /// Returns the value to put into the `cmsg_type` field of the header.
++    fn cmsg_type(&self) -> libc::c_int {
++        match self {
++            &ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetIv(_) => {
++                libc::ALG_SET_IV
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetOp(_) => {
++                libc::ALG_SET_OP
++            },
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            &ControlMessage::AlgSetAeadAssoclen(_) => {
++                libc::ALG_SET_AEAD_ASSOCLEN
++            },
++        }
++    }
++
++    // Unsafe: cmsg must point to a valid cmsghdr with enough space to
++    // encode self.
++    unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
++        (*cmsg).cmsg_level = self.cmsg_level();
++        (*cmsg).cmsg_type = self.cmsg_type();
++        (*cmsg).cmsg_len = self.cmsg_len();
++        self.copy_to_cmsg_data(CMSG_DATA(cmsg));
++    }
++}
++
++
++/// Send data in scatter-gather vectors to a socket, possibly accompanied
++/// by ancillary data. Optionally direct the message at the given address,
++/// as with sendto.
++///
++/// Allocates if cmsgs is nonempty.
++pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
++               flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
++{
++    let capacity = cmsgs.iter().map(|c| c.space()).sum();
++
++    // First size the buffer needed to hold the cmsgs.  It must be zeroed,
++    // because subsequent code will not clear the padding bytes.
++    let cmsg_buffer = vec![0u8; capacity];
++
++    // Next encode the sending address, if provided
++    let (name, namelen) = match addr {
++        Some(addr) => {
++            let (x, y) = unsafe { addr.as_ffi_pair() };
++            (x as *const _, y)
++        },
++        None => (ptr::null(), 0),
++    };
++
++    // The message header must be initialized before the individual cmsgs.
++    let cmsg_ptr = if capacity > 0 {
++        cmsg_buffer.as_ptr() as *mut c_void
++    } else {
++        ptr::null_mut()
++    };
++
++    let mhdr = {
++        // Musl's msghdr has private fields, so this is the only way to
++        // initialize it.
++        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
++        mhdr.msg_name = name as *mut _;
++        mhdr.msg_namelen = namelen;
++        // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
++        // the buffer, but the standard says that it takes a mutable pointer
++        mhdr.msg_iov = iov.as_ptr() as *mut _;
++        mhdr.msg_iovlen = iov.len() as _;
++        mhdr.msg_control = cmsg_ptr;
++        mhdr.msg_controllen = capacity as _;
++        mhdr.msg_flags = 0;
++        mhdr
++    };
++
++    // Encode each cmsg.  This must happen after initializing the header because
++    // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
++    // CMSG_FIRSTHDR is always safe
++    let mut pmhdr: *mut cmsghdr = unsafe{CMSG_FIRSTHDR(&mhdr as *const msghdr)};
++    for cmsg in cmsgs {
++        assert_ne!(pmhdr, ptr::null_mut());
++        // Safe because we know that pmhdr is valid, and we initialized it with
++        // sufficient space
++        unsafe { cmsg.encode_into(pmhdr) };
++        // Safe because mhdr is valid
++        pmhdr = unsafe{CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr)};
++    }
++
++    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
++
++    Errno::result(ret).map(|r| r as usize)
++}
++
++/// Receive message in scatter-gather vectors from a socket, and
++/// optionally receive ancillary data into the provided buffer.
++/// If no ancillary data is desired, use () as the type parameter.
++///
++/// # References
++/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
++pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
++                   cmsg_buffer: Option<&'a mut dyn CmsgBuffer>,
++                   flags: MsgFlags) -> Result<RecvMsg<'a>>
++{
++    let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
++    let (msg_control, msg_controllen) = match cmsg_buffer {
++        Some(cmsgspace) => {
++            let msg_buf = cmsgspace.as_bytes_mut();
++            (msg_buf.as_mut_ptr(), msg_buf.len())
++        },
++        None => (ptr::null_mut(), 0),
++    };
++    let mut mhdr = {
++        // Musl's msghdr has private fields, so this is the only way to
++        // initialize it.
++        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
++        mhdr.msg_name = &mut address as *mut sockaddr_storage as *mut c_void;
++        mhdr.msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
++        mhdr.msg_iov = iov.as_ptr() as *mut iovec;
++        mhdr.msg_iovlen = iov.len() as _;
++        mhdr.msg_control = msg_control as *mut c_void;
++        mhdr.msg_controllen = msg_controllen as _;
++        mhdr.msg_flags = 0;
++        mhdr
++    };
++
++    let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
++
++    Errno::result(ret).map(|r| {
++        let cmsghdr = unsafe {
++            if mhdr.msg_controllen > 0 {
++                // got control message(s)
++                debug_assert!(!mhdr.msg_control.is_null());
++                debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
++                CMSG_FIRSTHDR(&mhdr as *const msghdr)
++            } else {
++                ptr::null()
++            }.as_ref()
++        };
++
++        let address = unsafe {
++            sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok()
++        };
++        RecvMsg {
++            bytes: r as usize,
++            cmsghdr,
++            address,
++            flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
++            mhdr,
++        }
++    })
++}
++
++
++/// Create an endpoint for communication
++///
++/// The `protocol` specifies a particular protocol to be used with the
++/// socket.  Normally only a single protocol exists to support a
++/// particular socket type within a given protocol family, in which case
++/// protocol can be specified as `None`.  However, it is possible that many
++/// 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)
++pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
++    let protocol = match protocol.into() {
++        None => 0,
++        Some(p) => p as c_int,
++    };
++
++    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
++    // little easier to understand by separating it out. So we have to merge these bitfields
++    // here.
++    let mut ty = ty as c_int;
++    ty |= flags.bits();
++
++    let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
++
++    Errno::result(res)
++}
++
++/// Create a pair of connected sockets
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
++pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
++                  flags: SockFlag) -> Result<(RawFd, RawFd)> {
++    let protocol = match protocol.into() {
++        None => 0,
++        Some(p) => p as c_int,
++    };
++
++    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
++    // little easier to understand by separating it out. So we have to merge these bitfields
++    // here.
++    let mut ty = ty as c_int;
++    ty |= flags.bits();
++
++    let mut fds = [-1, -1];
++
++    let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
++    Errno::result(res)?;
++
++    Ok((fds[0], fds[1]))
++}
++
++/// Listen for connections on a socket
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
++pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
++    let res = unsafe { libc::listen(sockfd, backlog as c_int) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Bind a name to a socket
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
++pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
++    let res = unsafe {
++        let (ptr, len) = addr.as_ffi_pair();
++        libc::bind(fd, ptr, len)
++    };
++
++    Errno::result(res).map(drop)
++}
++
++/// Accept a connection on a socket
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
++pub fn accept(sockfd: RawFd) -> Result<RawFd> {
++    let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
++
++    Errno::result(res)
++}
++
++/// Accept a connection on a socket
++///
++/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
++#[cfg(any(target_os = "android",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "openbsd"))]
++pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
++    let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
++
++    Errno::result(res)
++}
++
++/// Initiate a connection on a socket
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
++pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
++    let res = unsafe {
++        let (ptr, len) = addr.as_ffi_pair();
++        libc::connect(fd, ptr, len)
++    };
++
++    Errno::result(res).map(drop)
++}
++
++/// Receive data from a connection-oriented socket. Returns the number of
++/// bytes read
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
++pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
++    unsafe {
++        let ret = libc::recv(
++            sockfd,
++            buf.as_ptr() as *mut c_void,
++            buf.len() as size_t,
++            flags.bits());
++
++        Errno::result(ret).map(|r| r as usize)
++    }
++}
++
++/// Receive data from a connectionless or connection-oriented socket. Returns
++/// the number of bytes read and the socket address of the sender.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
++pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
++    unsafe {
++        let addr: sockaddr_storage = mem::zeroed();
++        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
++
++        let ret = Errno::result(libc::recvfrom(
++            sockfd,
++            buf.as_ptr() as *mut c_void,
++            buf.len() as size_t,
++            0,
++            mem::transmute(&addr),
++            &mut len as *mut socklen_t))?;
++
++        sockaddr_storage_to_addr(&addr, len as usize)
++            .map(|addr| (ret as usize, addr))
++    }
++}
++
++/// Send a message to a socket
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
++pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
++    let ret = unsafe {
++        let (ptr, len) = addr.as_ffi_pair();
++        libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
++    };
++
++    Errno::result(ret).map(|r| r as usize)
++}
++
++/// Send data to a connection-oriented socket. Returns the number of bytes read
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
++pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
++    let ret = unsafe {
++        libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
++    };
++
++    Errno::result(ret).map(|r| r as usize)
++}
++
++/*
++ *
++ * ===== Socket Options =====
++ *
++ */
++
++/// The protocol level at which to get / set socket options. Used as an
++/// argument to `getsockopt` and `setsockopt`.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
++#[repr(i32)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum SockLevel {
++    Socket = libc::SOL_SOCKET,
++    Tcp = libc::IPPROTO_TCP,
++    Ip = libc::IPPROTO_IP,
++    Ipv6 = libc::IPPROTO_IPV6,
++    Udp = libc::IPPROTO_UDP,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Netlink = libc::SOL_NETLINK,
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    Alg = libc::SOL_ALG,
++}
++
++/// Represents a socket option that can be accessed or set. Used as an argument
++/// to `getsockopt`
++pub trait GetSockOpt : Copy {
++    type Val;
++
++    #[doc(hidden)]
++    fn get(&self, fd: RawFd) -> Result<Self::Val>;
++}
++
++/// Represents a socket option that can be accessed or set. Used as an argument
++/// to `setsockopt`
++pub trait SetSockOpt : Clone {
++    type Val;
++
++    #[doc(hidden)]
++    fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
++}
++
++/// Get the current value for the requested socket option
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
++pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
++    opt.get(fd)
++}
++
++/// Sets the value for the requested socket option
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
++///
++/// # Examples
++///
++/// ```
++/// use nix::sys::socket::setsockopt;
++/// use nix::sys::socket::sockopt::KeepAlive;
++/// use std::net::TcpListener;
++/// use std::os::unix::io::AsRawFd;
++///
++/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
++/// let fd = listener.as_raw_fd();
++/// let res = setsockopt(fd, KeepAlive, &true);
++/// assert!(res.is_ok());
++/// ```
++pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
++    opt.set(fd, val)
++}
++
++/// Get the address of the peer connected to the socket `fd`.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
++pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
++    unsafe {
++        let addr: sockaddr_storage = mem::uninitialized();
++        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
++
++        let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
++
++        Errno::result(ret)?;
++
++        sockaddr_storage_to_addr(&addr, len as usize)
++    }
++}
++
++/// Get the current address to which the socket `fd` is bound.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
++pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
++    unsafe {
++        let addr: sockaddr_storage = mem::uninitialized();
++        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
++
++        let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
++
++        Errno::result(ret)?;
++
++        sockaddr_storage_to_addr(&addr, len as usize)
++    }
++}
++
++/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
++/// size.  In C this would usually be done by casting.  The `len` argument
++/// should be the number of bytes in the `sockaddr_storage` that are actually
++/// allocated and valid.  It must be at least as large as all the useful parts
++/// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
++/// include the terminating null.
++pub unsafe fn sockaddr_storage_to_addr(
++    addr: &sockaddr_storage,
++    len: usize) -> Result<SockAddr> {
++
++    if len < mem::size_of_val(&addr.ss_family) {
++        return Err(Error::Sys(Errno::ENOTCONN));
++    }
++
++    match addr.ss_family as c_int {
++        libc::AF_INET => {
++            assert!(len as usize == mem::size_of::<sockaddr_in>());
++            let ret = *(addr as *const _ as *const sockaddr_in);
++            Ok(SockAddr::Inet(InetAddr::V4(ret)))
++        }
++        libc::AF_INET6 => {
++            assert!(len as usize == mem::size_of::<sockaddr_in6>());
++            Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
++        }
++        libc::AF_UNIX => {
++            let sun = *(addr as *const _ as *const sockaddr_un);
++            let pathlen = len - offset_of!(sockaddr_un, sun_path);
++            Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
++        }
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        libc::AF_NETLINK => {
++            use libc::sockaddr_nl;
++            Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
++        }
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        libc::AF_ALG => {
++            use libc::sockaddr_alg;
++            Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
++        }
++        #[cfg(target_os = "linux")]
++        libc::AF_VSOCK => {
++            use libc::sockaddr_vm;
++            Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
++        }
++        af => panic!("unexpected address family {}", af),
++    }
++}
++
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum Shutdown {
++    /// Further receptions will be disallowed.
++    Read,
++    /// Further  transmissions will be disallowed.
++    Write,
++    /// Further receptions and transmissions will be disallowed.
++    Both,
++}
++
++/// Shut down part of a full-duplex connection.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
++pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
++    unsafe {
++        use libc::shutdown;
++
++        let how = match how {
++            Shutdown::Read  => libc::SHUT_RD,
++            Shutdown::Write => libc::SHUT_WR,
++            Shutdown::Both  => libc::SHUT_RDWR,
++        };
++
++        Errno::result(shutdown(df, how)).map(drop)
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs b/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
+new file mode 100644
+index 0000000000000..a996010018d5b
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
+@@ -0,0 +1,680 @@
++use super::{GetSockOpt, SetSockOpt};
++use Result;
++use errno::Errno;
++use sys::time::TimeVal;
++use libc::{self, c_int, c_void, socklen_t};
++use std::mem;
++use std::os::unix::io::RawFd;
++use std::ffi::{OsStr, OsString};
++#[cfg(target_family = "unix")]
++use std::os::unix::ffi::OsStrExt;
++
++// Constants
++// TCP_CA_NAME_MAX isn't defined in user space include files
++#[cfg(any(target_os = "freebsd", target_os = "linux"))] 
++const TCP_CA_NAME_MAX: usize = 16;
++
++/// Helper for implementing `SetSockOpt` for a given socket option. See
++/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
++///
++/// This macro aims to help implementing `SetSockOpt` for different socket options that accept
++/// different kinds of data to be used with `setsockopt`.
++///
++/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
++/// you are implementing represents a simple type.
++///
++/// # Arguments
++///
++/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
++/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
++///    (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
++///    and more. Please refer to your system manual for more options. Will be passed as the second
++///    argument (`level`) to the `setsockopt` call.
++/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
++///    `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
++///    to the `setsockopt` call.
++/// * Type of the value that you are going to set.
++/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
++///    `bool`, `SetUsize` for `usize`, etc.).
++macro_rules! setsockopt_impl {
++    ($name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
++        impl SetSockOpt for $name {
++            type Val = $ty;
++
++            fn set(&self, fd: RawFd, val: &$ty) -> Result<()> {
++                unsafe {
++                    let setter: $setter = Set::new(val);
++
++                    let res = libc::setsockopt(fd, $level, $flag,
++                                               setter.ffi_ptr(),
++                                               setter.ffi_len());
++                    Errno::result(res).map(drop)
++                }
++            }
++        }
++    }
++}
++
++/// Helper for implementing `GetSockOpt` for a given socket option. See
++/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html).
++///
++/// This macro aims to help implementing `GetSockOpt` for different socket options that accept
++/// different kinds of data to be use with `getsockopt`.
++///
++/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
++/// you are implementing represents a simple type.
++///
++/// # Arguments
++///
++/// * Name of the type you want to implement `GetSockOpt` for.
++/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`),  *ip
++///    protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),  and more. Please refer
++///    to your system manual for more options. Will be passed as the second argument (`level`) to
++///    the `getsockopt` call.
++/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
++///    `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
++///    the `getsockopt` call.
++/// * Type of the value that you are going to get.
++/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
++///    `bool`, `GetUsize` for `usize`, etc.).
++macro_rules! getsockopt_impl {
++    ($name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
++        impl GetSockOpt for $name {
++            type Val = $ty;
++
++            fn get(&self, fd: RawFd) -> Result<$ty> {
++                unsafe {
++                    let mut getter: $getter = Get::blank();
++
++                    let res = libc::getsockopt(fd, $level, $flag,
++                                               getter.ffi_ptr(),
++                                               getter.ffi_len());
++                    Errno::result(res)?;
++
++                    Ok(getter.unwrap())
++                }
++            }
++        }
++    }
++}
++
++/// Helper to generate the sockopt accessors. See
++/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and
++/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
++///
++/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options
++/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively.
++///
++/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and
++/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros.
++///
++/// # Arguments
++///
++/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
++///    both of them.
++/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
++/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
++///    (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
++///    and more. Please refer to your system manual for more options. Will be passed as the second
++///    argument (`level`) to the `getsockopt`/`setsockopt` call.
++/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
++///    `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
++///    to the `setsockopt`/`getsockopt` call.
++/// * `$ty:ty`: type of the value that will be get/set.
++/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
++/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
++macro_rules! sockopt_impl {
++    (GetOnly, $name:ident, $level:path, $flag:path, bool) => {
++        sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool);
++    };
++
++    (GetOnly, $name:ident, $level:path, $flag:path, u8) => {
++        sockopt_impl!(GetOnly, $name, $level, $flag, u8, GetU8);
++    };
++
++    (GetOnly, $name:ident, $level:path, $flag:path, usize) => {
++        sockopt_impl!(GetOnly, $name, $level, $flag, usize, GetUsize);
++    };
++
++    (SetOnly, $name:ident, $level:path, $flag:path, bool) => {
++        sockopt_impl!(SetOnly, $name, $level, $flag, bool, SetBool);
++    };
++
++    (SetOnly, $name:ident, $level:path, $flag:path, u8) => {
++        sockopt_impl!(SetOnly, $name, $level, $flag, u8, SetU8);
++    };
++
++    (SetOnly, $name:ident, $level:path, $flag:path, usize) => {
++        sockopt_impl!(SetOnly, $name, $level, $flag, usize, SetUsize);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, bool) => {
++        sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, u8) => {
++        sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, usize) => {
++        sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => {
++        sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString);
++    };
++
++    /*
++     * Matchers with generic getter types must be placed at the end, so
++     * they'll only match _after_ specialized matchers fail
++     */
++    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
++        sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
++    };
++
++    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
++        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++        pub struct $name;
++
++        getsockopt_impl!($name, $level, $flag, $ty, $getter);
++    };
++
++    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
++        sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
++    };
++
++    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
++        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++        pub struct $name;
++
++        setsockopt_impl!($name, $level, $flag, $ty, $setter);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
++        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++        pub struct $name;
++
++        setsockopt_impl!($name, $level, $flag, $ty, $setter);
++        getsockopt_impl!($name, $level, $flag, $ty, $getter);
++    };
++
++    (Both, $name:ident, $level:path, $flag:path, $ty:ty) => {
++        sockopt_impl!(Both, $name, $level, $flag, $ty, GetStruct<$ty>, SetStruct<$ty>);
++    };
++}
++
++/*
++ *
++ * ===== Define sockopts =====
++ *
++ */
++
++sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
++sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
++sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
++sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
++sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::IpMembershipRequest);
++sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::IpMembershipRequest);
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
++        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
++    } else if #[cfg(any(target_os = "dragonfly",
++                        target_os = "freebsd",
++                        target_os = "ios",
++                        target_os = "macos",
++                        target_os = "netbsd",
++                        target_os = "openbsd"))] {
++        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
++        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
++    }
++}
++sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
++sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
++sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
++sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
++sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
++sockopt_impl!(Both, OobInline, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
++sockopt_impl!(GetOnly, SocketError, libc::SOL_SOCKET, libc::SO_ERROR, i32);
++sockopt_impl!(Both, KeepAlive, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
++#[cfg(any(target_os = "ios",
++          target_os = "macos"))]
++sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "nacl"))]
++sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
++sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
++sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(SetOnly, RcvBufForce, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
++sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
++sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
++sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
++#[cfg(target_os = "openbsd")]
++sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
++#[cfg(target_os = "freebsd")]
++sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
++#[cfg(target_os = "linux")]
++sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
++#[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
++#[cfg(any(target_os = "freebsd", target_os = "linux"))] 
++sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
++#[cfg(any(
++    target_os = "android",
++    target_os = "ios",
++    target_os = "linux",
++    target_os = "macos",
++    target_os = "netbsd",
++))]
++sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
++#[cfg(any(
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "linux",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
++
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[derive(Copy, Clone, Debug)]
++pub struct AlgSetAeadAuthSize;
++
++// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
++// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
++#[cfg(any(target_os = "android", target_os = "linux"))]
++impl SetSockOpt for AlgSetAeadAuthSize {
++    type Val = usize;
++
++    fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
++        unsafe {
++            let res = libc::setsockopt(fd,
++                                       libc::SOL_ALG,
++                                       libc::ALG_SET_AEAD_AUTHSIZE,
++                                       ::std::ptr::null(),
++                                       *val as libc::socklen_t);
++            Errno::result(res).map(drop)
++        }
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[derive(Clone, Debug)]
++pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++impl<T> Default for AlgSetKey<T> {
++    fn default() -> Self {
++        AlgSetKey(Default::default())
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
++    type Val = T;
++
++    fn set(&self, fd: RawFd, val: &T) -> Result<()> {
++        unsafe {
++            let res = libc::setsockopt(fd,
++                                       libc::SOL_ALG,
++                                       libc::ALG_SET_KEY,
++                                       val.as_ref().as_ptr() as *const _,
++                                       val.as_ref().len() as libc::socklen_t);
++            Errno::result(res).map(drop)
++        }
++    }
++}
++
++/*
++ *
++ * ===== Accessor helpers =====
++ *
++ */
++
++/// Helper trait that describes what is expected from a `GetSockOpt` getter.
++unsafe trait Get<T> {
++    /// Returns an empty value.
++    unsafe fn blank() -> Self;
++    /// Returns a pointer to the stored value. This pointer will be passed to the system's
++    /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
++    fn ffi_ptr(&mut self) -> *mut c_void;
++    /// Returns length of the stored value. This pointer will be passed to the system's
++    /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
++    fn ffi_len(&mut self) -> *mut socklen_t;
++    /// Returns the stored value.
++    unsafe fn unwrap(self) -> T;
++}
++
++/// Helper trait that describes what is expected from a `SetSockOpt` setter.
++unsafe trait Set<'a, T> {
++    /// Initialize the setter with a given value.
++    fn new(val: &'a T) -> Self;
++    /// Returns a pointer to the stored value. This pointer will be passed to the system's
++    /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`).
++    fn ffi_ptr(&self) -> *const c_void;
++    /// Returns length of the stored value. This pointer will be passed to the system's
++    /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`).
++    fn ffi_len(&self) -> socklen_t;
++}
++
++/// Getter for an arbitrary `struct`.
++struct GetStruct<T> {
++    len: socklen_t,
++    val: T,
++}
++
++unsafe impl<T> Get<T> for GetStruct<T> {
++    unsafe fn blank() -> Self {
++        GetStruct {
++            len: mem::size_of::<T>() as socklen_t,
++            val: mem::zeroed(),
++        }
++    }
++
++    fn ffi_ptr(&mut self) -> *mut c_void {
++        &mut self.val as *mut T as *mut c_void
++    }
++
++    fn ffi_len(&mut self) -> *mut socklen_t {
++        &mut self.len
++    }
++
++    unsafe fn unwrap(self) -> T {
++        assert!(self.len as usize == mem::size_of::<T>(), "invalid getsockopt implementation");
++        self.val
++    }
++}
++
++/// Setter for an arbitrary `struct`.
++struct SetStruct<'a, T: 'static> {
++    ptr: &'a T,
++}
++
++unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
++    fn new(ptr: &'a T) -> SetStruct<'a, T> {
++        SetStruct { ptr: ptr }
++    }
++
++    fn ffi_ptr(&self) -> *const c_void {
++        self.ptr as *const T as *const c_void
++    }
++
++    fn ffi_len(&self) -> socklen_t {
++        mem::size_of::<T>() as socklen_t
++    }
++}
++
++/// Getter for a boolean value.
++struct GetBool {
++    len: socklen_t,
++    val: c_int,
++}
++
++unsafe impl Get<bool> for GetBool {
++    unsafe fn blank() -> Self {
++        GetBool {
++            len: mem::size_of::<c_int>() as socklen_t,
++            val: mem::zeroed(),
++        }
++    }
++
++    fn ffi_ptr(&mut self) -> *mut c_void {
++        &mut self.val as *mut c_int as *mut c_void
++    }
++
++    fn ffi_len(&mut self) -> *mut socklen_t {
++        &mut self.len
++    }
++
++    unsafe fn unwrap(self) -> bool {
++        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
++        self.val != 0
++    }
++}
++
++/// Setter for a boolean value.
++struct SetBool {
++    val: c_int,
++}
++
++unsafe impl<'a> Set<'a, bool> for SetBool {
++    fn new(val: &'a bool) -> SetBool {
++        SetBool { val: if *val { 1 } else { 0 } }
++    }
++
++    fn ffi_ptr(&self) -> *const c_void {
++        &self.val as *const c_int as *const c_void
++    }
++
++    fn ffi_len(&self) -> socklen_t {
++        mem::size_of::<c_int>() as socklen_t
++    }
++}
++
++/// Getter for an `u8` value.
++struct GetU8 {
++    len: socklen_t,
++    val: u8,
++}
++
++unsafe impl Get<u8> for GetU8 {
++    unsafe fn blank() -> Self {
++        GetU8 {
++            len: mem::size_of::<u8>() as socklen_t,
++            val: mem::zeroed(),
++        }
++    }
++
++    fn ffi_ptr(&mut self) -> *mut c_void {
++        &mut self.val as *mut u8 as *mut c_void
++    }
++
++    fn ffi_len(&mut self) -> *mut socklen_t {
++        &mut self.len
++    }
++
++    unsafe fn unwrap(self) -> u8 {
++        assert!(self.len as usize == mem::size_of::<u8>(), "invalid getsockopt implementation");
++        self.val as u8
++    }
++}
++
++/// Setter for an `u8` value.
++struct SetU8 {
++    val: u8,
++}
++
++unsafe impl<'a> Set<'a, u8> for SetU8 {
++    fn new(val: &'a u8) -> SetU8 {
++        SetU8 { val: *val as u8 }
++    }
++
++    fn ffi_ptr(&self) -> *const c_void {
++        &self.val as *const u8 as *const c_void
++    }
++
++    fn ffi_len(&self) -> socklen_t {
++        mem::size_of::<c_int>() as socklen_t
++    }
++}
++
++/// Getter for an `usize` value.
++struct GetUsize {
++    len: socklen_t,
++    val: c_int,
++}
++
++unsafe impl Get<usize> for GetUsize {
++    unsafe fn blank() -> Self {
++        GetUsize {
++            len: mem::size_of::<c_int>() as socklen_t,
++            val: mem::zeroed(),
++        }
++    }
++
++    fn ffi_ptr(&mut self) -> *mut c_void {
++        &mut self.val as *mut c_int as *mut c_void
++    }
++
++    fn ffi_len(&mut self) -> *mut socklen_t {
++        &mut self.len
++    }
++
++    unsafe fn unwrap(self) -> usize {
++        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
++        self.val as usize
++    }
++}
++
++/// Setter for an `usize` value.
++struct SetUsize {
++    val: c_int,
++}
++
++unsafe impl<'a> Set<'a, usize> for SetUsize {
++    fn new(val: &'a usize) -> SetUsize {
++        SetUsize { val: *val as c_int }
++    }
++
++    fn ffi_ptr(&self) -> *const c_void {
++        &self.val as *const c_int as *const c_void
++    }
++
++    fn ffi_len(&self) -> socklen_t {
++        mem::size_of::<c_int>() as socklen_t
++    }
++}
++
++/// Getter for a `OsString` value.
++struct GetOsString<T: AsMut<[u8]>> {
++    len: socklen_t,
++    val: T,
++}
++
++unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
++    unsafe fn blank() -> Self {
++        GetOsString {
++            len: mem::size_of::<T>() as socklen_t,
++            val: mem::zeroed(),
++        }
++    }
++
++    fn ffi_ptr(&mut self) -> *mut c_void {
++        &mut self.val as *mut T as *mut c_void
++    }
++
++    fn ffi_len(&mut self) -> *mut socklen_t {
++        &mut self.len
++    }
++
++    unsafe fn unwrap(mut self) -> OsString {
++        OsStr::from_bytes(self.val.as_mut()).to_owned()
++    }
++}
++
++/// Setter for a `OsString` value.
++struct SetOsString<'a> {
++    val: &'a OsStr,
++}
++
++unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> {
++    fn new(val: &'a OsString) -> SetOsString {
++        SetOsString { val: val.as_os_str() }
++    }
++
++    fn ffi_ptr(&self) -> *const c_void {
++        self.val.as_bytes().as_ptr() as *const c_void
++    }
++
++    fn ffi_len(&self) -> socklen_t {
++        self.val.len() as socklen_t
++    }
++}
++
++
++#[cfg(test)]
++mod test {
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    #[test]
++    fn can_get_peercred_on_unix_socket() {
++        use super::super::*;
++
++        let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
++        let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
++        let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
++        assert_eq!(a_cred, b_cred);
++        assert!(a_cred.pid() != 0);
++    }
++
++    #[test]
++    fn is_socket_type_unix() {
++        use super::super::*;
++        use ::unistd::close;
++
++        let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
++        let a_type = getsockopt(a, super::SockType).unwrap();
++        assert!(a_type == SockType::Stream);
++        close(a).unwrap();
++        close(b).unwrap();
++    }
++
++    #[test]
++    fn is_socket_type_dgram() {
++        use super::super::*;
++        use ::unistd::close;
++
++        let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
++        let s_type = getsockopt(s, super::SockType).unwrap();
++        assert!(s_type == SockType::Datagram);
++        close(s).unwrap();
++    }
++
++    #[cfg(any(target_os = "freebsd",
++              target_os = "linux",
++              target_os = "nacl"))]
++    #[test]
++    fn can_get_listen_on_tcp_socket() {
++        use super::super::*;
++        use ::unistd::close;
++
++        let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
++        let s_listening = getsockopt(s, super::AcceptConn).unwrap();
++        assert!(!s_listening);
++        listen(s, 10).unwrap();
++        let s_listening2 = getsockopt(s, super::AcceptConn).unwrap();
++        assert!(s_listening2);
++        close(s).unwrap();
++    }
++
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/stat.rs b/third_party/rust/nix-0.15.0/src/sys/stat.rs
+new file mode 100644
+index 0000000000000..66c8c9dd1b720
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/stat.rs
+@@ -0,0 +1,294 @@
++pub use libc::{dev_t, mode_t};
++pub use libc::stat as FileStat;
++
++use {Result, NixPath};
++use errno::Errno;
++use fcntl::{AtFlags, at_rawfd};
++use libc;
++use std::mem;
++use std::os::unix::io::RawFd;
++use sys::time::{TimeSpec, TimeVal};
++
++libc_bitflags!(
++    pub struct SFlag: mode_t {
++        S_IFIFO;
++        S_IFCHR;
++        S_IFDIR;
++        S_IFBLK;
++        S_IFREG;
++        S_IFLNK;
++        S_IFSOCK;
++        S_IFMT;
++    }
++);
++
++libc_bitflags! {
++    pub struct Mode: mode_t {
++        S_IRWXU;
++        S_IRUSR;
++        S_IWUSR;
++        S_IXUSR;
++        S_IRWXG;
++        S_IRGRP;
++        S_IWGRP;
++        S_IXGRP;
++        S_IRWXO;
++        S_IROTH;
++        S_IWOTH;
++        S_IXOTH;
++        S_ISUID as mode_t;
++        S_ISGID as mode_t;
++        S_ISVTX as mode_t;
++    }
++}
++
++pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
++        }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++#[cfg(target_os = "linux")]
++pub fn major(dev: dev_t) -> u64 {
++    ((dev >> 32) & 0xffff_f000) |
++    ((dev >>  8) & 0x0000_0fff)
++}
++
++#[cfg(target_os = "linux")]
++pub fn minor(dev: dev_t) -> u64 {
++    ((dev >> 12) & 0xffff_ff00) |
++    ((dev      ) & 0x0000_00ff)
++}
++
++#[cfg(target_os = "linux")]
++pub fn makedev(major: u64, minor: u64) -> dev_t {
++    ((major & 0xffff_f000) << 32) |
++    ((major & 0x0000_0fff) <<  8) |
++    ((minor & 0xffff_ff00) << 12) |
++     (minor & 0x0000_00ff)
++}
++
++pub fn umask(mode: Mode) -> Mode {
++    let prev = unsafe { libc::umask(mode.bits() as mode_t) };
++    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
++}
++
++pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
++    let mut dst = unsafe { mem::uninitialized() };
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
++        }
++    })?;
++
++    Errno::result(res)?;
++
++    Ok(dst)
++}
++
++pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
++    let mut dst = unsafe { mem::uninitialized() };
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
++        }
++    })?;
++
++    Errno::result(res)?;
++
++    Ok(dst)
++}
++
++pub fn fstat(fd: RawFd) -> Result<FileStat> {
++    let mut dst = unsafe { mem::uninitialized() };
++    let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) };
++
++    Errno::result(res)?;
++
++    Ok(dst)
++}
++
++pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
++    let mut dst = unsafe { mem::uninitialized() };
++    let res = pathname.with_nix_path(|cstr| {
++        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) }
++    })?;
++
++    Errno::result(res)?;
++
++    Ok(dst)
++}
++
++/// Change the file permission bits of the file specified by a file descriptor.
++///
++/// # References
++///
++/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
++pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
++    let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Flags for `fchmodat` function.
++#[derive(Clone, Copy, Debug)]
++pub enum FchmodatFlags {
++    FollowSymlink,
++    NoFollowSymlink,
++}
++
++/// Change the file permission bits.
++///
++/// The file to be changed is determined relative to the directory associated
++/// with the file descriptor `dirfd` or the current working directory
++/// if `dirfd` is `None`.
++///
++/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
++/// then the mode of the symbolic link is changed.
++///
++/// `fchmod(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
++/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
++/// in the `nix` crate.
++///
++/// # References
++///
++/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
++pub fn fchmodat<P: ?Sized + NixPath>(
++    dirfd: Option<RawFd>,
++    path: &P,
++    mode: Mode,
++    flag: FchmodatFlags,
++) -> Result<()> {
++    let atflag =
++        match flag {
++            FchmodatFlags::FollowSymlink => AtFlags::empty(),
++            FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
++        };
++    let res = path.with_nix_path(|cstr| unsafe {
++        libc::fchmodat(
++            at_rawfd(dirfd),
++            cstr.as_ptr(),
++            mode.bits() as mode_t,
++            atflag.bits() as libc::c_int,
++        )
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Change the access and modification times of a file.
++///
++/// `utimes(path, times)` is identical to
++/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
++/// is a deprecated API so prefer using the latter if the platforms you care
++/// about support it.
++///
++/// # References
++///
++/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
++pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
++    let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
++    let res = path.with_nix_path(|cstr| unsafe {
++        libc::utimes(cstr.as_ptr(), &times[0])
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Change the access and modification times of a file without following symlinks.
++///
++/// `lutimes(path, times)` is identical to
++/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former
++/// is a deprecated API so prefer using the latter if the platforms you care
++/// about support it.
++///
++/// # References
++///
++/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
++#[cfg(any(target_os = "linux",
++          target_os = "haiku",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "freebsd",
++          target_os = "netbsd"))]
++pub fn lutimes<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 {
++        libc::lutimes(cstr.as_ptr(), &times[0])
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Change the access and modification times of the file specified by a file descriptor.
++///
++/// # References
++///
++/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
++#[inline]
++pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
++    let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
++    let res = unsafe { libc::futimens(fd, &times[0]) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Flags for `utimensat` function.
++#[derive(Clone, Copy, Debug)]
++pub enum UtimensatFlags {
++    FollowSymlink,
++    NoFollowSymlink,
++}
++
++/// Change the access and modification times of a file.
++///
++/// The file to be changed is determined relative to the directory associated
++/// with the file descriptor `dirfd` or the current working directory
++/// if `dirfd` is `None`.
++///
++/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link,
++/// then the mode of the symbolic link is changed.
++///
++/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
++/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
++/// former if the platforms you care about support it.
++///
++/// # References
++///
++/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
++pub fn utimensat<P: ?Sized + NixPath>(
++    dirfd: Option<RawFd>,
++    path: &P,
++    atime: &TimeSpec,
++    mtime: &TimeSpec,
++    flag: UtimensatFlags
++) -> Result<()> {
++    let atflag =
++        match flag {
++            UtimensatFlags::FollowSymlink => AtFlags::empty(),
++            UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
++        };
++    let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
++    let res = path.with_nix_path(|cstr| unsafe {
++        libc::utimensat(
++            at_rawfd(dirfd),
++            cstr.as_ptr(),
++            &times[0],
++            atflag.bits() as libc::c_int,
++        )
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/statfs.rs b/third_party/rust/nix-0.15.0/src/sys/statfs.rs
+new file mode 100644
+index 0000000000000..d4596bf336958
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/statfs.rs
+@@ -0,0 +1,548 @@
++use std::fmt::{self, Debug};
++use std::mem;
++use std::os::unix::io::AsRawFd;
++#[cfg(not(any(target_os = "linux", target_os = "android")))]
++use std::ffi::CStr;
++
++use libc;
++
++use {NixPath, Result};
++use errno::Errno;
++
++#[cfg(target_os = "android")]
++pub type fsid_t = libc::__fsid_t;
++#[cfg(not(target_os = "android"))]
++pub type fsid_t = libc::fsid_t;
++
++#[derive(Clone, Copy)]
++pub struct Statfs(libc::statfs);
++
++#[cfg(target_os = "freebsd")]
++#[derive(Eq, Copy, Clone, PartialEq, Debug)]
++pub struct FsType(u32);
++#[cfg(target_os = "android")]
++#[derive(Eq, Copy, Clone, PartialEq, Debug)]
++pub struct FsType(libc::c_ulong);
++#[cfg(all(target_os = "linux", target_arch = "s390x"))]
++#[derive(Eq, Copy, Clone, PartialEq, Debug)]
++pub struct FsType(u32);
++#[cfg(all(target_os = "linux", target_env = "musl"))]
++#[derive(Eq, Copy, Clone, PartialEq, Debug)]
++pub struct FsType(libc::c_ulong);
++#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++#[derive(Eq, Copy, Clone, PartialEq, Debug)]
++pub struct FsType(libc::c_long);
++
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
++#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
++pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
++
++impl Statfs {
++    /// Magic code defining system type
++    #[cfg(not(any(
++        target_os = "openbsd",
++        target_os = "ios",
++        target_os = "macos"
++    )))]
++    pub fn filesystem_type(&self) -> FsType {
++        FsType(self.0.f_type)
++    }
++
++    /// Magic code defining system type
++    #[cfg(not(any(target_os = "linux", target_os = "android")))]
++    pub fn filesystem_type_name(&self) -> &str {
++        let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
++        c_str.to_str().unwrap()
++    }
++
++    /// Optimal transfer block size
++    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
++    pub fn optimal_transfer_size(&self) -> i32 {
++        self.0.f_iosize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
++    pub fn optimal_transfer_size(&self) -> u32 {
++        self.0.f_bsize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
++        self.0.f_bsize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++    pub fn optimal_transfer_size(&self) -> libc::c_long {
++        self.0.f_bsize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(target_os = "android")]
++    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
++        self.0.f_bsize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(target_os = "dragonfly")]
++    pub fn optimal_transfer_size(&self) -> libc::c_long {
++        self.0.f_iosize
++    }
++
++    /// Optimal transfer block size
++    #[cfg(target_os = "freebsd")]
++    pub fn optimal_transfer_size(&self) -> u64 {
++        self.0.f_iosize
++    }
++
++    /// Size of a block
++    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
++    pub fn block_size(&self) -> u32 {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
++    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
++    pub fn block_size(&self) -> u32 {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn block_size(&self) -> libc::c_ulong {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
++    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++    pub fn block_size(&self) -> libc::c_long {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    #[cfg(target_os = "freebsd")]
++    pub fn block_size(&self) -> u64 {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    #[cfg(target_os = "android")]
++    pub fn block_size(&self) -> libc::c_ulong {
++        self.0.f_bsize
++    }
++
++    /// Size of a block
++    #[cfg(target_os = "dragonfly")]
++    pub fn block_size(&self) -> libc::c_long {
++        self.0.f_bsize
++    }
++
++    /// Maximum length of filenames
++    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
++    pub fn maximum_name_length(&self) -> u32 {
++        self.0.f_namemax
++    }
++
++    /// Maximum length of filenames
++    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
++    pub fn maximum_name_length(&self) -> u32 {
++        self.0.f_namelen
++    }
++
++    /// Maximum length of filenames
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn maximum_name_length(&self) -> libc::c_ulong {
++        self.0.f_namelen
++    }
++
++    /// Maximum length of filenames
++    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++    pub fn maximum_name_length(&self) -> libc::c_long {
++        self.0.f_namelen
++    }
++
++    /// Maximum length of filenames
++    #[cfg(target_os = "android")]
++    pub fn maximum_name_length(&self) -> libc::c_ulong {
++        self.0.f_namelen
++    }
++
++    /// Total data blocks in filesystem
++    #[cfg(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++    ))]
++    pub fn blocks(&self) -> u64 {
++        self.0.f_blocks
++    }
++
++    /// Total data blocks in filesystem
++    #[cfg(target_os = "dragonfly")]
++    pub fn blocks(&self) -> libc::c_long {
++        self.0.f_blocks
++    }
++
++    /// Total data blocks in filesystem
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn blocks(&self) -> u64 {
++        self.0.f_blocks
++    }
++
++    /// Total data blocks in filesystem
++    #[cfg(not(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++        target_os = "dragonfly",
++        all(target_os = "linux", target_env = "musl")
++    )))]
++    pub fn blocks(&self) -> libc::c_ulong {
++        self.0.f_blocks
++    }
++
++    /// Free blocks in filesystem
++    #[cfg(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++    ))]
++    pub fn blocks_free(&self) -> u64 {
++        self.0.f_bfree
++    }
++
++    /// Free blocks in filesystem
++    #[cfg(target_os = "dragonfly")]
++    pub fn blocks_free(&self) -> libc::c_long {
++        self.0.f_bfree
++    }
++
++    /// Free blocks in filesystem
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn blocks_free(&self) -> u64 {
++        self.0.f_bfree
++    }
++
++    /// Free blocks in filesystem
++    #[cfg(not(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++        target_os = "dragonfly",
++        all(target_os = "linux", target_env = "musl")
++    )))]
++    pub fn blocks_free(&self) -> libc::c_ulong {
++        self.0.f_bfree
++    }
++
++    /// Free blocks available to unprivileged user
++    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
++    pub fn blocks_available(&self) -> u64 {
++        self.0.f_bavail
++    }
++
++    /// Free blocks available to unprivileged user
++    #[cfg(target_os = "dragonfly")]
++    pub fn blocks_available(&self) -> libc::c_long {
++        self.0.f_bavail
++    }
++
++    /// Free blocks available to unprivileged user
++    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
++    pub fn blocks_available(&self) -> i64 {
++        self.0.f_bavail
++    }
++
++    /// Free blocks available to unprivileged user
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn blocks_available(&self) -> u64 {
++        self.0.f_bavail
++    }
++
++    /// Free blocks available to unprivileged user
++    #[cfg(not(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++        target_os = "dragonfly",
++        all(target_os = "linux", target_env = "musl")
++    )))]
++    pub fn blocks_available(&self) -> libc::c_ulong {
++        self.0.f_bavail
++    }
++
++    /// Total file nodes in filesystem
++    #[cfg(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++    ))]
++    pub fn files(&self) -> u64 {
++        self.0.f_files
++    }
++
++    /// Total file nodes in filesystem
++    #[cfg(target_os = "dragonfly")]
++    pub fn files(&self) -> libc::c_long {
++        self.0.f_files
++    }
++
++    /// Total file nodes in filesystem
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn files(&self) -> u64 {
++        self.0.f_files
++    }
++
++    /// Total file nodes in filesystem
++    #[cfg(not(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++        target_os = "dragonfly",
++        all(target_os = "linux", target_env = "musl")
++    )))]
++    pub fn files(&self) -> libc::c_ulong {
++        self.0.f_files
++    }
++
++    /// Free file nodes in filesystem
++    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
++    pub fn files_free(&self) -> u64 {
++        self.0.f_ffree
++    }
++
++    /// Free file nodes in filesystem
++    #[cfg(target_os = "dragonfly")]
++    pub fn files_free(&self) -> libc::c_long {
++        self.0.f_ffree
++    }
++
++    /// Free file nodes in filesystem
++    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
++    pub fn files_free(&self) -> i64 {
++        self.0.f_ffree
++    }
++
++    /// Free file nodes in filesystem
++    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    pub fn files_free(&self) -> u64 {
++        self.0.f_ffree
++    }
++
++    /// Free file nodes in filesystem
++    #[cfg(not(any(
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "openbsd",
++        target_os = "dragonfly",
++        all(target_os = "linux", target_env = "musl")
++    )))]
++    pub fn files_free(&self) -> libc::c_ulong {
++        self.0.f_ffree
++    }
++
++    /// Filesystem ID
++    pub fn filesystem_id(&self) -> fsid_t {
++        self.0.f_fsid
++    }
++}
++
++impl Debug for Statfs {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        f.debug_struct("Statfs")
++            .field("optimal_transfer_size", &self.optimal_transfer_size())
++            .field("block_size", &self.block_size())
++            .field("blocks", &self.blocks())
++            .field("blocks_free", &self.blocks_free())
++            .field("blocks_available", &self.blocks_available())
++            .field("files", &self.files())
++            .field("files_free", &self.files_free())
++            .field("filesystem_id", &self.filesystem_id())
++            .finish()
++    }
++}
++
++pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
++    unsafe {
++        let mut stat: Statfs = mem::uninitialized();
++        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), &mut stat.0))?;
++        Errno::result(res).map(|_| stat)
++    }
++}
++
++pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
++    unsafe {
++        let mut stat: Statfs = mem::uninitialized();
++        Errno::result(libc::fstatfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
++    }
++}
++
++#[cfg(test)]
++mod test {
++    use std::fs::File;
++
++    use sys::statfs::*;
++    use sys::statvfs::*;
++    use std::path::Path;
++
++    #[test]
++    fn statfs_call() {
++        check_statfs("/tmp");
++        check_statfs("/dev");
++        check_statfs("/run");
++        check_statfs("/");
++    }
++
++    #[test]
++    fn fstatfs_call() {
++        check_fstatfs("/tmp");
++        check_fstatfs("/dev");
++        check_fstatfs("/run");
++        check_fstatfs("/");
++    }
++
++    fn check_fstatfs(path: &str) {
++        if !Path::new(path).exists() {
++            return;
++        }
++        let vfs = statvfs(path.as_bytes()).unwrap();
++        let file = File::open(path).unwrap();
++        let fs = fstatfs(&file).unwrap();
++        assert_fs_equals(fs, vfs);
++    }
++
++    fn check_statfs(path: &str) {
++        if !Path::new(path).exists() {
++            return;
++        }
++        let vfs = statvfs(path.as_bytes()).unwrap();
++        let fs = statfs(path.as_bytes()).unwrap();
++        assert_fs_equals(fs, vfs);
++    }
++
++    fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
++        assert_eq!(fs.files() as u64, vfs.files() as u64);
++        assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
++        assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
++    }
++
++    // This test is ignored because files_free/blocks_free can change after statvfs call and before
++    // statfs call.
++    #[test]
++    #[ignore]
++    fn statfs_call_strict() {
++        check_statfs_strict("/tmp");
++        check_statfs_strict("/dev");
++        check_statfs_strict("/run");
++        check_statfs_strict("/");
++    }
++
++    // This test is ignored because files_free/blocks_free can change after statvfs call and before
++    // fstatfs call.
++    #[test]
++    #[ignore]
++    fn fstatfs_call_strict() {
++        check_fstatfs_strict("/tmp");
++        check_fstatfs_strict("/dev");
++        check_fstatfs_strict("/run");
++        check_fstatfs_strict("/");
++    }
++
++    fn check_fstatfs_strict(path: &str) {
++        if !Path::new(path).exists() {
++            return;
++        }
++        let vfs = statvfs(path.as_bytes());
++        let file = File::open(path).unwrap();
++        let fs = fstatfs(&file);
++        assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
++    }
++
++    fn check_statfs_strict(path: &str) {
++        if !Path::new(path).exists() {
++            return;
++        }
++        let vfs = statvfs(path.as_bytes());
++        let fs = statfs(path.as_bytes());
++        assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
++    }
++
++    fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
++        assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
++        assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
++        assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
++        assert_eq!(fs.files() as u64, vfs.files() as u64);
++        assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
++        assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/statvfs.rs b/third_party/rust/nix-0.15.0/src/sys/statvfs.rs
+new file mode 100644
+index 0000000000000..e5980369d5119
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/statvfs.rs
+@@ -0,0 +1,160 @@
++//! Get filesystem statistics
++//!
++//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
++//! for more details.
++use std::mem;
++use std::os::unix::io::AsRawFd;
++
++use libc::{self, c_ulong};
++
++use {Result, NixPath};
++use errno::Errno;
++
++libc_bitflags!(
++    /// File system mount Flags
++    #[repr(C)]
++    #[derive(Default)]
++    pub struct FsFlags: c_ulong {
++        /// Read Only
++        ST_RDONLY;
++        /// Do not allow the set-uid bits to have an effect
++        ST_NOSUID;
++        /// Do not interpret character or block-special devices
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_NODEV;
++        /// Do not allow execution of binaries on the filesystem
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_NOEXEC;
++        /// All IO should be done synchronously
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_SYNCHRONOUS;
++        /// Allow mandatory locks on the filesystem
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_MANDLOCK;
++        /// Write on file/directory/symlink
++        #[cfg(target_os = "linux")]
++        ST_WRITE;
++        /// Append-only file
++        #[cfg(target_os = "linux")]
++        ST_APPEND;
++        /// Immutable file
++        #[cfg(target_os = "linux")]
++        ST_IMMUTABLE;
++        /// Do not update access times on files
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_NOATIME;
++        /// Do not update access times on files
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        ST_NODIRATIME;
++        /// Update access time relative to modify/change time
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
++        ST_RELATIME;
++    }
++);
++
++/// 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).
++// FIXME: Replace with repr(transparent)
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct Statvfs(libc::statvfs);
++
++impl Statvfs {
++    /// get the file system block size
++    pub fn block_size(&self) -> c_ulong {
++        self.0.f_bsize
++    }
++
++    /// Get the fundamental file system block size
++    pub fn fragment_size(&self) -> c_ulong {
++        self.0.f_frsize
++    }
++
++    /// Get the number of blocks.
++    ///
++    /// Units are in units of `fragment_size()`
++    pub fn blocks(&self) -> libc::fsblkcnt_t {
++        self.0.f_blocks
++    }
++
++    /// Get the number of free blocks in the file system
++    pub fn blocks_free(&self) -> libc::fsblkcnt_t {
++        self.0.f_bfree
++    }
++
++    /// Get the number of free blocks for unprivileged users
++    pub fn blocks_available(&self) -> libc::fsblkcnt_t {
++        self.0.f_bavail
++    }
++
++    /// Get the total number of file inodes
++    pub fn files(&self) -> libc::fsfilcnt_t {
++        self.0.f_files
++    }
++
++    /// Get the number of free file inodes
++    pub fn files_free(&self) -> libc::fsfilcnt_t {
++        self.0.f_ffree
++    }
++
++    /// Get the number of free file inodes for unprivileged users
++    pub fn files_available(&self) -> libc::fsfilcnt_t {
++        self.0.f_favail
++    }
++
++    /// Get the file system id
++    pub fn filesystem_id(&self) -> c_ulong {
++        self.0.f_fsid
++    }
++
++    /// Get the mount flags
++    pub fn flags(&self) -> FsFlags {
++        FsFlags::from_bits_truncate(self.0.f_flag)
++    }
++
++    /// Get the maximum filename length
++    pub fn name_max(&self) -> c_ulong {
++        self.0.f_namemax
++    }
++
++}
++
++/// Return a `Statvfs` object with information about the `path`
++pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
++    unsafe {
++        Errno::clear();
++        let mut stat: Statvfs = mem::uninitialized();
++        let res = path.with_nix_path(|path|
++            libc::statvfs(path.as_ptr(), &mut stat.0)
++        )?;
++
++        Errno::result(res).map(|_| stat)
++    }
++}
++
++/// Return a `Statvfs` object with information about `fd`
++pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
++    unsafe {
++        Errno::clear();
++        let mut stat: Statvfs = mem::uninitialized();
++        Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
++    }
++}
++
++#[cfg(test)]
++mod test {
++    use std::fs::File;
++    use sys::statvfs::*;
++
++    #[test]
++    fn statvfs_call() {
++        statvfs("/".as_bytes()).unwrap();
++    }
++
++    #[test]
++    fn fstatvfs_call() {
++        let root = File::open("/").unwrap();
++        fstatvfs(&root).unwrap();
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs b/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
+new file mode 100644
+index 0000000000000..4c8e38988886d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
+@@ -0,0 +1,72 @@
++use libc::{self, SI_LOAD_SHIFT};
++use std::{cmp, mem};
++use std::time::Duration;
++
++use Result;
++use errno::Errno;
++
++/// System info structure returned by `sysinfo`.
++#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++pub struct SysInfo(libc::sysinfo);
++
++impl SysInfo {
++    /// Returns the load average tuple.
++    ///
++    /// The returned values represent the load average over time intervals of
++    /// 1, 5, and 15 minutes, respectively.
++    pub fn load_average(&self) -> (f64, f64, f64) {
++        (
++            self.0.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64,
++            self.0.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64,
++            self.0.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64,
++        )
++    }
++
++    /// Returns the time since system boot.
++    pub fn uptime(&self) -> Duration {
++        // Truncate negative values to 0
++        Duration::from_secs(cmp::max(self.0.uptime, 0) as u64)
++    }
++
++    /// Current number of processes.
++    pub fn process_count(&self) -> u16 {
++        self.0.procs
++    }
++
++    /// Returns the amount of swap memory in Bytes.
++    pub fn swap_total(&self) -> u64 {
++        self.scale_mem(self.0.totalswap)
++    }
++
++    /// Returns the amount of unused swap memory in Bytes.
++    pub fn swap_free(&self) -> u64 {
++        self.scale_mem(self.0.freeswap)
++    }
++
++    /// Returns the total amount of installed RAM in Bytes.
++    pub fn ram_total(&self) -> u64 {
++        self.scale_mem(self.0.totalram)
++    }
++
++    /// Returns the amount of completely unused RAM in Bytes.
++    ///
++    /// "Unused" in this context means that the RAM in neither actively used by
++    /// programs, nor by the operating system as disk cache or buffer. It is
++    /// "wasted" RAM since it currently serves no purpose.
++    pub fn ram_unused(&self) -> u64 {
++        self.scale_mem(self.0.freeram)
++    }
++
++    fn scale_mem(&self, units: libc::c_ulong) -> u64 {
++        units as u64 * self.0.mem_unit as u64
++    }
++}
++
++/// Returns system information.
++///
++/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
++pub fn sysinfo() -> Result<SysInfo> {
++    let mut info: libc::sysinfo = unsafe { mem::uninitialized() };
++    let res = unsafe { libc::sysinfo(&mut info) };
++    Errno::result(res).map(|_| SysInfo(info))
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/termios.rs b/third_party/rust/nix-0.15.0/src/sys/termios.rs
+new file mode 100644
+index 0000000000000..c7cdf10b461c1
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/termios.rs
+@@ -0,0 +1,1107 @@
++//! An interface for controlling asynchronous communication ports
++//!
++//! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The
++//! underlying types are all implemented in libc for most platforms and either wrapped in safer
++//! 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
++//! 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.
++//! As this interface is not used with high-bandwidth information, this should be fine in most
++//! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the
++//! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields.
++//! This means that when crossing the FFI interface to the underlying C library, data is first
++//! copied into the underlying `termios` struct, then the operation is done, and the data is copied
++//! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is
++//! relatively small across all platforms (on the order of 32-64 bytes).
++//!
++//! The following examples highlight some of the API use cases such that users coming from using C
++//! or reading the standard documentation will understand how to use the safe API exposed here.
++//!
++//! Example disabling processing of the end-of-file control character:
++//!
++//! ```
++//! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
++//! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
++//! # let mut termios = unsafe { Termios::default_uninit() };
++//! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
++//! ```
++//!
++//! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides
++//! an interface for working with bitfields that is similar to working with the raw unsigned
++//! integer types but offers type safety because of the internal checking that values will always
++//! be a valid combination of the defined flags.
++//!
++//! An example showing some of the basic operations for interacting with the control flags:
++//!
++//! ```
++//! # use self::nix::sys::termios::{ControlFlags, Termios};
++//! # let mut termios = unsafe { Termios::default_uninit() };
++//! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
++//! termios.control_flags |= ControlFlags::CS5;
++//! ```
++//!
++//! # Baud rates
++//!
++//! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both
++//! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs
++//! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer
++//! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following
++//! conventions:
++//!
++//! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
++//! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
++//! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
++//! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
++//! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
++//!
++//! The most common use case of specifying a baud rate using the enum will work the same across
++//! platforms:
++//!
++//! ```rust
++//! # #[macro_use] extern crate nix;
++//! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! cfsetispeed(&mut t, BaudRate::B9600);
++//! cfsetospeed(&mut t, BaudRate::B9600);
++//! cfsetspeed(&mut t, BaudRate::B9600);
++//! # }
++//! ```
++//!
++//! Additionally round-tripping baud rates is consistent across platforms:
++//!
++//! ```rust
++//! # extern crate nix;
++//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! # cfsetspeed(&mut t, BaudRate::B9600);
++//! let speed = cfgetispeed(&t);
++//! assert!(speed == cfgetospeed(&t));
++//! cfsetispeed(&mut t, speed);
++//! # }
++//! ```
++//!
++//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
++//!
++// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
++#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
++            doc = " ```rust,ignore")]
++#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
++            doc = " ```rust")]
++//! # extern crate nix;
++//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! # cfsetspeed(&mut t, BaudRate::B9600);
++//! assert!(cfgetispeed(&t) == BaudRate::B9600);
++//! assert!(cfgetospeed(&t) == BaudRate::B9600);
++//! # }
++//! ```
++//!
++//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
++//!
++// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
++#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
++            doc = " ```rust")]
++#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
++            doc = " ```rust,ignore")]
++//! # extern crate nix;
++//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! # cfsetspeed(&mut t, 9600u32);
++//! assert!(cfgetispeed(&t) == 9600u32);
++//! assert!(cfgetospeed(&t) == 9600u32);
++//! # }
++//! ```
++//!
++//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
++//!
++// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
++#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
++            doc = " ```rust")]
++#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
++            doc = " ```rust,ignore")]
++//! # extern crate nix;
++//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! # cfsetspeed(&mut t, 9600u32);
++//! assert!(cfgetispeed(&t) == BaudRate::B9600.into());
++//! assert!(u32::from(BaudRate::B9600) == 9600u32);
++//! # }
++//! ```
++//!
++//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
++//! by specifying baud rates directly using `u32`s:
++//!
++// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
++#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
++            doc = " ```rust")]
++#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
++                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
++            doc = " ```rust,ignore")]
++//! # extern crate nix;
++//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
++//! # fn main() {
++//! # let mut t = unsafe { Termios::default_uninit() };
++//! cfsetispeed(&mut t, 9600u32);
++//! cfsetospeed(&mut t, 9600u32);
++//! cfsetspeed(&mut t, 9600u32);
++//! # }
++//! ```
++use Result;
++use errno::Errno;
++use libc::{self, c_int, tcflag_t};
++use std::cell::{Ref, RefCell};
++use std::convert::From;
++use std::mem;
++use std::os::unix::io::RawFd;
++
++use ::unistd::Pid;
++
++/// Stores settings for the termios API
++///
++/// This is a wrapper around the `libc::termios` struct that provides a safe interface for the
++/// standard fields. The only safe way to obtain an instance of this struct is to extract it from
++/// an open port using `tcgetattr()`.
++#[derive(Clone, Debug, Eq, PartialEq)]
++pub struct Termios {
++    inner: RefCell<libc::termios>,
++    /// Input mode flags (see `termios.c_iflag` documentation)
++    pub input_flags: InputFlags,
++    /// Output mode flags (see `termios.c_oflag` documentation)
++    pub output_flags: OutputFlags,
++    /// Control mode flags (see `termios.c_cflag` documentation)
++    pub control_flags: ControlFlags,
++    /// Local mode flags (see `termios.c_lflag` documentation)
++    pub local_flags: LocalFlags,
++    /// Control characters (see `termios.c_cc` documentation)
++    pub control_chars: [libc::cc_t; NCCS],
++}
++
++impl Termios {
++    /// Exposes an immutable reference to the underlying `libc::termios` data structure.
++    ///
++    /// This can be used for interfacing with other FFI functions like:
++    ///
++    /// ```rust
++    /// # extern crate libc;
++    /// # extern crate nix;
++    /// # fn main() {
++    /// # use nix::sys::termios::Termios;
++    /// # let mut termios = unsafe { Termios::default_uninit() };
++    /// let inner_termios = termios.get_libc_termios();
++    /// unsafe { libc::cfgetispeed(&*inner_termios) };
++    /// # }
++    /// ```
++    ///
++    /// There is no public API exposed for functions that modify the underlying `libc::termios`
++    /// data because it requires additional work to maintain type safety.
++    // FIXME: Switch this over to use pub(crate)
++    #[doc(hidden)]
++    pub fn get_libc_termios(&self) -> Ref<libc::termios> {
++        {
++            let mut termios = self.inner.borrow_mut();
++            termios.c_iflag = self.input_flags.bits();
++            termios.c_oflag = self.output_flags.bits();
++            termios.c_cflag = self.control_flags.bits();
++            termios.c_lflag = self.local_flags.bits();
++            termios.c_cc = self.control_chars;
++        }
++        self.inner.borrow()
++    }
++
++    /// Exposes the inner `libc::termios` datastore within `Termios`.
++    ///
++    /// This is unsafe because if this is used to modify the inner libc::termios struct, it will not
++    /// automatically update the safe wrapper type around it. Therefore we disable docs to
++    /// effectively limit its use to nix internals. In this case it should also be paired with a
++    /// call to `update_wrapper()` so that the wrapper-type and internal representation stay
++    /// consistent.
++    unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
++        {
++            let mut termios = self.inner.borrow_mut();
++            termios.c_iflag = self.input_flags.bits();
++            termios.c_oflag = self.output_flags.bits();
++            termios.c_cflag = self.control_flags.bits();
++            termios.c_lflag = self.local_flags.bits();
++            termios.c_cc = self.control_chars;
++        }
++        self.inner.as_ptr()
++    }
++
++    /// Allows for easily creating new `Termios` structs that will be overwritten with real data.
++    ///
++    /// This should only be used when the inner libc::termios struct will be overwritten before it's
++    /// read.
++    // FIXME: Switch this over to use pub(crate)
++    #[doc(hidden)]
++    pub unsafe fn default_uninit() -> Self {
++        Termios {
++            inner: RefCell::new(mem::uninitialized()),
++            input_flags: InputFlags::empty(),
++            output_flags: OutputFlags::empty(),
++            control_flags: ControlFlags::empty(),
++            local_flags: LocalFlags::empty(),
++            control_chars: [0 as libc::cc_t; NCCS],
++        }
++    }
++
++    /// Updates the wrapper values from the internal `libc::termios` data structure.
++    #[doc(hidden)]
++    pub fn update_wrapper(&mut self) {
++        let termios = *self.inner.borrow_mut();
++        self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
++        self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
++        self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
++        self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
++        self.control_chars = termios.c_cc;
++    }
++}
++
++impl From<libc::termios> for Termios {
++    fn from(termios: libc::termios) -> Self {
++        Termios {
++            inner: RefCell::new(termios),
++            input_flags: InputFlags::from_bits_truncate(termios.c_iflag),
++            output_flags: OutputFlags::from_bits_truncate(termios.c_oflag),
++            control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
++            local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
++            control_chars: termios.c_cc,
++        }
++    }
++}
++
++impl From<Termios> for libc::termios {
++    fn from(termios: Termios) -> Self {
++        termios.inner.into_inner()
++    }
++}
++
++libc_enum!{
++    /// Baud rates supported by the system.
++    ///
++    /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this
++    /// enum.
++    ///
++    /// B0 is special and will disable the port.
++    #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
++    #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), repr(u32))]
++    pub enum BaudRate {
++        B0,
++        B50,
++        B75,
++        B110,
++        B134,
++        B150,
++        B200,
++        B300,
++        B600,
++        B1200,
++        B1800,
++        B2400,
++        B4800,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        B7200,
++        B9600,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        B14400,
++        B19200,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        B28800,
++        B38400,
++        B57600,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        B76800,
++        B115200,
++        B230400,
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd"))]
++        B460800,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B500000,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B576000,
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd"))]
++        B921600,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B1000000,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B1152000,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B1500000,
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        B2000000,
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++        B2500000,
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++        B3000000,
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++        B3500000,
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++        B4000000,
++    }
++}
++
++impl From<libc::speed_t> for BaudRate {
++    fn from(s: libc::speed_t) -> BaudRate {
++
++        use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
++                   B9600, B19200, B38400, B57600, B115200, B230400};
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++        use libc::{B2500000, B3000000, B3500000, B4000000};
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        use libc::{B7200, B14400, B28800, B76800};
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "linux",
++                  target_os = "netbsd"))]
++        use libc::{B460800, B921600};
++
++        match s {
++            B0 => BaudRate::B0,
++            B50 => BaudRate::B50,
++            B75 => BaudRate::B75,
++            B110 => BaudRate::B110,
++            B134 => BaudRate::B134,
++            B150 => BaudRate::B150,
++            B200 => BaudRate::B200,
++            B300 => BaudRate::B300,
++            B600 => BaudRate::B600,
++            B1200 => BaudRate::B1200,
++            B1800 => BaudRate::B1800,
++            B2400 => BaudRate::B2400,
++            B4800 => BaudRate::B4800,
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            B7200 => BaudRate::B7200,
++            B9600 => BaudRate::B9600,
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            B14400 => BaudRate::B14400,
++            B19200 => BaudRate::B19200,
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            B28800 => BaudRate::B28800,
++            B38400 => BaudRate::B38400,
++            B57600 => BaudRate::B57600,
++            #[cfg(any(target_os = "dragonfly",
++                      target_os = "freebsd",
++                      target_os = "macos",
++                      target_os = "netbsd",
++                      target_os = "openbsd"))]
++            B76800 => BaudRate::B76800,
++            B115200 => BaudRate::B115200,
++            B230400 => BaudRate::B230400,
++            #[cfg(any(target_os = "android",
++                      target_os = "freebsd",
++                      target_os = "linux",
++                      target_os = "netbsd"))]
++            B460800 => BaudRate::B460800,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B500000 => BaudRate::B500000,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B576000 => BaudRate::B576000,
++            #[cfg(any(target_os = "android",
++                      target_os = "freebsd",
++                      target_os = "linux",
++                      target_os = "netbsd"))]
++            B921600 => BaudRate::B921600,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B1000000 => BaudRate::B1000000,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B1152000 => BaudRate::B1152000,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B1500000 => BaudRate::B1500000,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            B2000000 => BaudRate::B2000000,
++            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++            B2500000 => BaudRate::B2500000,
++            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++            B3000000 => BaudRate::B3000000,
++            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++            B3500000 => BaudRate::B3500000,
++            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
++            B4000000 => BaudRate::B4000000,
++            b => unreachable!("Invalid baud constant: {}", b),
++        }
++    }
++}
++
++// TODO: Include `TryFrom<u32> for BaudRate` once that API stabilizes
++#[cfg(any(target_os = "freebsd",
++          target_os = "dragonfly",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++impl From<BaudRate> for u32 {
++    fn from(b: BaudRate) -> u32 {
++        b as u32
++    }
++}
++
++// TODO: Add TCSASOFT, which will require treating this as a bitfield.
++libc_enum! {
++    /// Specify when a port configuration change should occur.
++    ///
++    /// Used as an argument to `tcsetattr()`
++    #[repr(i32)]
++    pub enum SetArg {
++        /// The change will occur immediately
++        TCSANOW,
++        /// The change occurs after all output has been written
++        TCSADRAIN,
++        /// Same as `TCSADRAIN`, but will also flush the input buffer
++        TCSAFLUSH,
++    }
++}
++
++libc_enum! {
++    /// Specify a combination of the input and output buffers to flush
++    ///
++    /// Used as an argument to `tcflush()`.
++    #[repr(i32)]
++    pub enum FlushArg {
++        /// Flush data that was received but not read
++        TCIFLUSH,
++        /// Flush data written but not transmitted
++        TCOFLUSH,
++        /// Flush both received data not read and written data not transmitted
++        TCIOFLUSH,
++    }
++}
++
++libc_enum! {
++    /// Specify how transmission flow should be altered
++    ///
++    /// Used as an argument to `tcflow()`.
++    #[repr(i32)]
++    pub enum FlowArg {
++        /// Suspend transmission
++        TCOOFF,
++        /// Resume transmission
++        TCOON,
++        /// Transmit a STOP character, which should disable a connected terminal device
++        TCIOFF,
++        /// Transmit a START character, which should re-enable a connected terminal device
++        TCION,
++    }
++}
++
++// TODO: Make this usable directly as a slice index.
++libc_enum! {
++    /// Indices into the `termios.c_cc` array for special characters.
++    #[repr(usize)]
++    pub enum SpecialCharacterIndices {
++        VDISCARD,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        VDSUSP,
++        VEOF,
++        VEOL,
++        VEOL2,
++        VERASE,
++        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++        VERASE2,
++        VINTR,
++        VKILL,
++        VLNEXT,
++        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
++        VMIN,
++        VQUIT,
++        VREPRINT,
++        VSTART,
++        #[cfg(any(target_os = "dragonfly",
++                target_os = "freebsd",
++                target_os = "macos",
++                target_os = "netbsd",
++                target_os = "openbsd"))]
++        VSTATUS,
++        VSTOP,
++        VSUSP,
++        #[cfg(target_os = "linux")]
++        VSWTC,
++        #[cfg(target_os = "haiku")]
++        VSWTCH,
++        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
++        VTIME,
++        VWERASE,
++        #[cfg(target_os = "dragonfly")]
++        VCHECKPT,
++    }
++}
++
++pub use libc::NCCS;
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub use libc::_POSIX_VDISABLE;
++
++libc_bitflags! {
++    /// Flags for configuring the input mode of a terminal
++    pub struct InputFlags: tcflag_t {
++        IGNBRK;
++        BRKINT;
++        IGNPAR;
++        PARMRK;
++        INPCK;
++        ISTRIP;
++        INLCR;
++        IGNCR;
++        ICRNL;
++        IXON;
++        IXOFF;
++        IXANY;
++        IMAXBEL;
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
++        IUTF8;
++    }
++}
++
++libc_bitflags! {
++    /// Flags for configuring the output mode of a terminal
++    pub struct OutputFlags: tcflag_t {
++        OPOST;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "linux",
++                  target_os = "openbsd"))]
++        OLCUC;
++        ONLCR;
++        OCRNL as tcflag_t;
++        ONOCR as tcflag_t;
++        ONLRET as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        OFILL as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        OFDEL as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        NL0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        NL1 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        CR0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        CR1 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        CR2 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        CR3 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        TAB0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        TAB1 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        TAB2 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        TAB3 as tcflag_t;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        XTABS;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        BS0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        BS1 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        VT0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        VT1 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        FF0 as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        FF1 as tcflag_t;
++        #[cfg(any(target_os = "freebsd",
++                  target_os = "dragonfly",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        OXTABS;
++        #[cfg(any(target_os = "freebsd",
++                  target_os = "dragonfly",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        ONOEOT as tcflag_t;
++
++        // Bitmasks for use with OutputFlags to select specific settings
++        // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
++        // is resolved.
++
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        CRDLY as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        TABDLY as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        BSDLY as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        VTDLY as tcflag_t;
++        #[cfg(any(target_os = "android",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos"))]
++        FFDLY as tcflag_t;
++    }
++}
++
++libc_bitflags! {
++    /// Flags for setting the control mode of a terminal
++    pub struct ControlFlags: tcflag_t {
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        CIGNORE;
++        CS5;
++        CS6;
++        CS7;
++        CS8;
++        CSTOPB;
++        CREAD;
++        PARENB;
++        PARODD;
++        HUPCL;
++        CLOCAL;
++        CRTSCTS;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        CBAUD;
++        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))]
++        CMSPAR;
++        #[cfg(any(target_os = "android",
++                  all(target_os = "linux",
++                      not(any(target_arch = "powerpc", target_arch = "powerpc64")))))]
++        CIBAUD;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        CBAUDEX;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        MDMBUF;
++        #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
++        CHWFLOW;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        CCTS_OFLOW;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        CRTS_IFLOW;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd"))]
++        CDTR_IFLOW;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd"))]
++        CDSR_OFLOW;
++        #[cfg(any(target_os = "dragonfly",
++                  target_os = "freebsd"))]
++        CCAR_OFLOW;
++
++        // Bitmasks for use with ControlFlags to select specific settings
++        // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
++        // is resolved.
++
++        CSIZE;
++    }
++}
++
++libc_bitflags! {
++    /// Flags for setting any local modes
++    pub struct LocalFlags: tcflag_t {
++        ECHOKE;
++        ECHOE;
++        ECHOK;
++        ECHO;
++        ECHONL;
++        ECHOPRT;
++        ECHOCTL;
++        ISIG;
++        ICANON;
++        #[cfg(any(target_os = "freebsd",
++                  target_os = "dragonfly",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        ALTWERASE;
++        IEXTEN;
++        EXTPROC;
++        TOSTOP;
++        FLUSHO;
++        #[cfg(any(target_os = "freebsd",
++                  target_os = "dragonfly",
++                  target_os = "ios",
++                  target_os = "macos",
++                  target_os = "netbsd",
++                  target_os = "openbsd"))]
++        NOKERNINFO;
++        PENDIN;
++        NOFLSH;
++    }
++}
++
++cfg_if!{
++    if #[cfg(any(target_os = "freebsd",
++                 target_os = "dragonfly",
++                 target_os = "ios",
++                 target_os = "macos",
++                 target_os = "netbsd",
++                 target_os = "openbsd"))] {
++        /// Get input baud rate (see
++        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
++        ///
++        /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
++        pub fn cfgetispeed(termios: &Termios) -> u32 {
++            let inner_termios = termios.get_libc_termios();
++            unsafe { libc::cfgetispeed(&*inner_termios) as u32 }
++        }
++
++        /// Get output baud rate (see
++        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
++        ///
++        /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
++        pub fn cfgetospeed(termios: &Termios) -> u32 {
++            let inner_termios = termios.get_libc_termios();
++            unsafe { libc::cfgetospeed(&*inner_termios) as u32 }
++        }
++
++        /// Set input baud rate (see
++        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
++        ///
++        /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
++        pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++
++        /// Set output baud rate (see
++        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
++        ///
++        /// `cfsetospeed()` sets the output baud rate in the given termios structure.
++        pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++
++        /// Set both the input and output baud rates (see
++        /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
++        ///
++        /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that
++        /// this is part of the 4.4BSD standard and not part of POSIX.
++        pub fn cfsetspeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++    } else {
++        /// Get input baud rate (see
++        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
++        ///
++        /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
++        pub fn cfgetispeed(termios: &Termios) -> BaudRate {
++            let inner_termios = termios.get_libc_termios();
++            unsafe { libc::cfgetispeed(&*inner_termios) }.into()
++        }
++
++        /// Get output baud rate (see
++        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
++        ///
++        /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
++        pub fn cfgetospeed(termios: &Termios) -> BaudRate {
++            let inner_termios = termios.get_libc_termios();
++            unsafe { libc::cfgetospeed(&*inner_termios) }.into()
++        }
++
++        /// Set input baud rate (see
++        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
++        ///
++        /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
++        pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++
++        /// Set output baud rate (see
++        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
++        ///
++        /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
++        pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++
++        /// Set both the input and output baud rates (see
++        /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
++        ///
++        /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that
++        /// this is part of the 4.4BSD standard and not part of POSIX.
++        pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
++            let inner_termios = unsafe { termios.get_libc_termios_mut() };
++            let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) };
++            termios.update_wrapper();
++            Errno::result(res).map(drop)
++        }
++    }
++}
++
++/// 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)).
++///
++/// `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
++/// that this is a non-standard function, but is available on Linux and BSDs.
++pub fn cfmakeraw(termios: &mut Termios) {
++    let inner_termios = unsafe { termios.get_libc_termios_mut() };
++    unsafe {
++        libc::cfmakeraw(inner_termios);
++    }
++    termios.update_wrapper();
++}
++
++/// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see
++/// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)).
++///
++/// Note that this is a non-standard function, available on FreeBSD.
++#[cfg(target_os = "freebsd")]
++pub fn cfmakesane(termios: &mut Termios) {
++    let inner_termios = unsafe { termios.get_libc_termios_mut() };
++    unsafe {
++        libc::cfmakesane(inner_termios);
++    }
++    termios.update_wrapper();
++}
++
++/// Return the configuration of a port
++/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
++///
++/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
++/// this structure *will not* reconfigure the port, instead the modifications should be done to
++/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
++pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
++    let mut termios: libc::termios = unsafe { mem::uninitialized() };
++
++    let res = unsafe { libc::tcgetattr(fd, &mut termios) };
++
++    Errno::result(res)?;
++
++    Ok(termios.into())
++}
++
++/// Set the configuration for a terminal (see
++/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
++///
++/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
++/// takes affect at a time specified by `actions`. Note that this function may return success if
++/// *any* of the parameters were successfully set, not only if all were set successfully.
++pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
++    let inner_termios = termios.get_libc_termios();
++    Errno::result(unsafe { libc::tcsetattr(fd, actions as c_int, &*inner_termios) }).map(drop)
++}
++
++/// Block until all output data is written (see
++/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
++pub fn tcdrain(fd: RawFd) -> Result<()> {
++    Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
++}
++
++/// Suspend or resume the transmission or reception of data (see
++/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
++///
++/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
++/// depending on the value of `action`.
++pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
++    Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
++}
++
++/// Discard data in the output or input queue (see
++/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
++///
++/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
++/// depending on the value of `action`.
++pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
++    Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
++}
++
++/// Send a break for a specific duration (see
++/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
++///
++/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
++/// of zero-valued bits for an implementation-defined duration.
++pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
++    Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
++}
++
++/// Get the session controlled by the given terminal (see
++/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
++pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
++    let res = unsafe { libc::tcgetsid(fd) };
++
++    Errno::result(res).map(Pid::from_raw)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/time.rs b/third_party/rust/nix-0.15.0/src/sys/time.rs
+new file mode 100644
+index 0000000000000..3ad57543b18a7
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/time.rs
+@@ -0,0 +1,542 @@
++use std::{cmp, fmt, ops};
++use std::convert::From;
++use libc::{c_long, timespec, timeval};
++pub use libc::{time_t, suseconds_t};
++
++pub trait TimeValLike: Sized {
++    #[inline]
++    fn zero() -> Self {
++        Self::seconds(0)
++    }
++
++    #[inline]
++    fn hours(hours: i64) -> Self {
++        let secs = hours.checked_mul(SECS_PER_HOUR)
++            .expect("TimeValLike::hours ouf of bounds");
++        Self::seconds(secs)
++    }
++
++    #[inline]
++    fn minutes(minutes: i64) -> Self {
++        let secs = minutes.checked_mul(SECS_PER_MINUTE)
++            .expect("TimeValLike::minutes out of bounds");
++        Self::seconds(secs)
++    }
++
++    fn seconds(seconds: i64) -> Self;
++    fn milliseconds(milliseconds: i64) -> Self;
++    fn microseconds(microseconds: i64) -> Self;
++    fn nanoseconds(nanoseconds: i64) -> Self;
++
++    #[inline]
++    fn num_hours(&self) -> i64 {
++        self.num_seconds() / 3600
++    }
++
++    #[inline]
++    fn num_minutes(&self) -> i64 {
++        self.num_seconds() / 60
++    }
++
++    fn num_seconds(&self) -> i64;
++    fn num_milliseconds(&self) -> i64;
++    fn num_microseconds(&self) -> i64;
++    fn num_nanoseconds(&self) -> i64;
++}
++
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct TimeSpec(timespec);
++
++const NANOS_PER_SEC: i64 = 1_000_000_000;
++const SECS_PER_MINUTE: i64 = 60;
++const SECS_PER_HOUR: i64 = 3600;
++
++#[cfg(target_pointer_width = "64")]
++const TS_MAX_SECONDS: i64 = (::std::i64::MAX / NANOS_PER_SEC) - 1;
++
++#[cfg(target_pointer_width = "32")]
++const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
++
++const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
++
++
++impl AsRef<timespec> for TimeSpec {
++    fn as_ref(&self) -> &timespec {
++        &self.0
++    }
++}
++
++impl Ord for TimeSpec {
++    // The implementation of cmp is simplified by assuming that the struct is
++    // normalized.  That is, tv_nsec must always be within [0, 1_000_000_000)
++    fn cmp(&self, other: &TimeSpec) -> cmp::Ordering {
++        if self.tv_sec() == other.tv_sec() {
++            self.tv_nsec().cmp(&other.tv_nsec())
++        } else {
++            self.tv_sec().cmp(&other.tv_sec())
++        }
++    }
++}
++
++impl PartialOrd for TimeSpec {
++    fn partial_cmp(&self, other: &TimeSpec) -> Option<cmp::Ordering> {
++        Some(self.cmp(other))
++    }
++}
++
++impl TimeValLike for TimeSpec {
++    #[inline]
++    fn seconds(seconds: i64) -> TimeSpec {
++        assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
++                "TimeSpec out of bounds; seconds={}", seconds);
++        TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
++    }
++
++    #[inline]
++    fn milliseconds(milliseconds: i64) -> TimeSpec {
++        let nanoseconds = milliseconds.checked_mul(1_000_000)
++            .expect("TimeSpec::milliseconds out of bounds");
++
++        TimeSpec::nanoseconds(nanoseconds)
++    }
++
++    /// Makes a new `TimeSpec` with given number of microseconds.
++    #[inline]
++    fn microseconds(microseconds: i64) -> TimeSpec {
++        let nanoseconds = microseconds.checked_mul(1_000)
++            .expect("TimeSpec::milliseconds out of bounds");
++
++        TimeSpec::nanoseconds(nanoseconds)
++    }
++
++    /// Makes a new `TimeSpec` with given number of nanoseconds.
++    #[inline]
++    fn nanoseconds(nanoseconds: i64) -> TimeSpec {
++        let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
++        assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
++                "TimeSpec out of bounds");
++        TimeSpec(timespec {tv_sec: secs as time_t,
++                           tv_nsec: nanos as c_long })
++    }
++
++    fn num_seconds(&self) -> i64 {
++        if self.tv_sec() < 0 && self.tv_nsec() > 0 {
++            (self.tv_sec() + 1) as i64
++        } else {
++            self.tv_sec() as i64
++        }
++    }
++
++    fn num_milliseconds(&self) -> i64 {
++        self.num_nanoseconds() / 1_000_000
++    }
++
++    fn num_microseconds(&self) -> i64 {
++        self.num_nanoseconds() / 1_000_000_000
++    }
++
++    fn num_nanoseconds(&self) -> i64 {
++        let secs = self.num_seconds() * 1_000_000_000;
++        let nsec = self.nanos_mod_sec();
++        secs + nsec as i64
++    }
++}
++
++impl TimeSpec {
++    fn nanos_mod_sec(&self) -> c_long {
++        if self.tv_sec() < 0 && self.tv_nsec() > 0 {
++            self.tv_nsec() - NANOS_PER_SEC as c_long
++        } else {
++            self.tv_nsec()
++        }
++    }
++
++    pub fn tv_sec(&self) -> time_t {
++        self.0.tv_sec
++    }
++
++    pub fn tv_nsec(&self) -> c_long {
++        self.0.tv_nsec
++    }
++}
++
++impl ops::Neg for TimeSpec {
++    type Output = TimeSpec;
++
++    fn neg(self) -> TimeSpec {
++        TimeSpec::nanoseconds(-self.num_nanoseconds())
++    }
++}
++
++impl ops::Add for TimeSpec {
++    type Output = TimeSpec;
++
++    fn add(self, rhs: TimeSpec) -> TimeSpec {
++        TimeSpec::nanoseconds(
++            self.num_nanoseconds() + rhs.num_nanoseconds())
++    }
++}
++
++impl ops::Sub for TimeSpec {
++    type Output = TimeSpec;
++
++    fn sub(self, rhs: TimeSpec) -> TimeSpec {
++        TimeSpec::nanoseconds(
++            self.num_nanoseconds() - rhs.num_nanoseconds())
++    }
++}
++
++impl ops::Mul<i32> for TimeSpec {
++    type Output = TimeSpec;
++
++    fn mul(self, rhs: i32) -> TimeSpec {
++        let usec = self.num_nanoseconds().checked_mul(rhs as i64)
++            .expect("TimeSpec multiply out of bounds");
++
++        TimeSpec::nanoseconds(usec)
++    }
++}
++
++impl ops::Div<i32> for TimeSpec {
++    type Output = TimeSpec;
++
++    fn div(self, rhs: i32) -> TimeSpec {
++        let usec = self.num_nanoseconds() / rhs as i64;
++        TimeSpec::nanoseconds(usec)
++    }
++}
++
++impl fmt::Display for TimeSpec {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        let (abs, sign) = if self.tv_sec() < 0 {
++            (-*self, "-")
++        } else {
++            (*self, "")
++        };
++
++        let sec = abs.tv_sec();
++
++        write!(f, "{}", sign)?;
++
++        if abs.tv_nsec() == 0 {
++            if abs.tv_sec() == 1 {
++                write!(f, "{} second", sec)?;
++            } else {
++                write!(f, "{} seconds", sec)?;
++            }
++        } else if abs.tv_nsec() % 1_000_000 == 0 {
++            write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?;
++        } else if abs.tv_nsec() % 1_000 == 0 {
++            write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?;
++        } else {
++            write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?;
++        }
++
++        Ok(())
++    }
++}
++
++
++
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct TimeVal(timeval);
++
++const MICROS_PER_SEC: i64 = 1_000_000;
++
++#[cfg(target_pointer_width = "64")]
++const TV_MAX_SECONDS: i64 = (::std::i64::MAX / MICROS_PER_SEC) - 1;
++
++#[cfg(target_pointer_width = "32")]
++const TV_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
++
++const TV_MIN_SECONDS: i64 = -TV_MAX_SECONDS;
++
++impl AsRef<timeval> for TimeVal {
++    fn as_ref(&self) -> &timeval {
++        &self.0
++    }
++}
++
++impl Ord for TimeVal {
++    // The implementation of cmp is simplified by assuming that the struct is
++    // normalized.  That is, tv_usec must always be within [0, 1_000_000)
++    fn cmp(&self, other: &TimeVal) -> cmp::Ordering {
++        if self.tv_sec() == other.tv_sec() {
++            self.tv_usec().cmp(&other.tv_usec())
++        } else {
++            self.tv_sec().cmp(&other.tv_sec())
++        }
++    }
++}
++
++impl PartialOrd for TimeVal {
++    fn partial_cmp(&self, other: &TimeVal) -> Option<cmp::Ordering> {
++        Some(self.cmp(other))
++    }
++}
++
++impl TimeValLike for TimeVal {
++    #[inline]
++    fn seconds(seconds: i64) -> TimeVal {
++        assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
++                "TimeVal out of bounds; seconds={}", seconds);
++        TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
++    }
++
++    #[inline]
++    fn milliseconds(milliseconds: i64) -> TimeVal {
++        let microseconds = milliseconds.checked_mul(1_000)
++            .expect("TimeVal::milliseconds out of bounds");
++
++        TimeVal::microseconds(microseconds)
++    }
++
++    /// Makes a new `TimeVal` with given number of microseconds.
++    #[inline]
++    fn microseconds(microseconds: i64) -> TimeVal {
++        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
++        assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
++                "TimeVal out of bounds");
++        TimeVal(timeval {tv_sec: secs as time_t,
++                           tv_usec: micros as suseconds_t })
++    }
++
++    /// Makes a new `TimeVal` with given number of nanoseconds.  Some precision
++    /// will be lost
++    #[inline]
++    fn nanoseconds(nanoseconds: i64) -> TimeVal {
++        let microseconds = nanoseconds / 1000;
++        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
++        assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
++                "TimeVal out of bounds");
++        TimeVal(timeval {tv_sec: secs as time_t,
++                           tv_usec: micros as suseconds_t })
++    }
++
++    fn num_seconds(&self) -> i64 {
++        if self.tv_sec() < 0 && self.tv_usec() > 0 {
++            (self.tv_sec() + 1) as i64
++        } else {
++            self.tv_sec() as i64
++        }
++    }
++
++    fn num_milliseconds(&self) -> i64 {
++        self.num_microseconds() / 1_000
++    }
++
++    fn num_microseconds(&self) -> i64 {
++        let secs = self.num_seconds() * 1_000_000;
++        let usec = self.micros_mod_sec();
++        secs + usec as i64
++    }
++
++    fn num_nanoseconds(&self) -> i64 {
++        self.num_microseconds() * 1_000
++    }
++}
++
++impl TimeVal {
++    fn micros_mod_sec(&self) -> suseconds_t {
++        if self.tv_sec() < 0 && self.tv_usec() > 0 {
++            self.tv_usec() - MICROS_PER_SEC as suseconds_t
++        } else {
++            self.tv_usec()
++        }
++    }
++
++    pub fn tv_sec(&self) -> time_t {
++        self.0.tv_sec
++    }
++
++    pub fn tv_usec(&self) -> suseconds_t {
++        self.0.tv_usec
++    }
++}
++
++impl ops::Neg for TimeVal {
++    type Output = TimeVal;
++
++    fn neg(self) -> TimeVal {
++        TimeVal::microseconds(-self.num_microseconds())
++    }
++}
++
++impl ops::Add for TimeVal {
++    type Output = TimeVal;
++
++    fn add(self, rhs: TimeVal) -> TimeVal {
++        TimeVal::microseconds(
++            self.num_microseconds() + rhs.num_microseconds())
++    }
++}
++
++impl ops::Sub for TimeVal {
++    type Output = TimeVal;
++
++    fn sub(self, rhs: TimeVal) -> TimeVal {
++        TimeVal::microseconds(
++            self.num_microseconds() - rhs.num_microseconds())
++    }
++}
++
++impl ops::Mul<i32> for TimeVal {
++    type Output = TimeVal;
++
++    fn mul(self, rhs: i32) -> TimeVal {
++        let usec = self.num_microseconds().checked_mul(rhs as i64)
++            .expect("TimeVal multiply out of bounds");
++
++        TimeVal::microseconds(usec)
++    }
++}
++
++impl ops::Div<i32> for TimeVal {
++    type Output = TimeVal;
++
++    fn div(self, rhs: i32) -> TimeVal {
++        let usec = self.num_microseconds() / rhs as i64;
++        TimeVal::microseconds(usec)
++    }
++}
++
++impl fmt::Display for TimeVal {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        let (abs, sign) = if self.tv_sec() < 0 {
++            (-*self, "-")
++        } else {
++            (*self, "")
++        };
++
++        let sec = abs.tv_sec();
++
++        write!(f, "{}", sign)?;
++
++        if abs.tv_usec() == 0 {
++            if abs.tv_sec() == 1 {
++                write!(f, "{} second", sec)?;
++            } else {
++                write!(f, "{} seconds", sec)?;
++            }
++        } else if abs.tv_usec() % 1000 == 0 {
++            write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?;
++        } else {
++            write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?;
++        }
++
++        Ok(())
++    }
++}
++
++impl From<timeval> for TimeVal {
++    fn from(tv: timeval) -> Self {
++        TimeVal(tv)
++    }
++}
++
++#[inline]
++fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
++    (div_floor_64(this, other), mod_floor_64(this, other))
++}
++
++#[inline]
++fn div_floor_64(this: i64, other: i64) -> i64 {
++    match div_rem_64(this, other) {
++        (d, r) if (r > 0 && other < 0)
++               || (r < 0 && other > 0) => d - 1,
++        (d, _)                         => d,
++    }
++}
++
++#[inline]
++fn mod_floor_64(this: i64, other: i64) -> i64 {
++    match this % other {
++        r if (r > 0 && other < 0)
++          || (r < 0 && other > 0) => r + other,
++        r                         => r,
++    }
++}
++
++#[inline]
++fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
++    (this / other, this % other)
++}
++
++#[cfg(test)]
++mod test {
++    use super::{TimeSpec, TimeVal, TimeValLike};
++
++    #[test]
++    pub fn test_timespec() {
++        assert!(TimeSpec::seconds(1) != TimeSpec::zero());
++        assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2),
++                   TimeSpec::seconds(3));
++        assert_eq!(TimeSpec::minutes(3) + TimeSpec::seconds(2),
++                   TimeSpec::seconds(182));
++    }
++
++    #[test]
++    pub fn test_timespec_neg() {
++        let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
++        let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
++
++        assert_eq!(a, -b);
++    }
++
++    #[test]
++    pub fn test_timespec_ord() {
++        assert!(TimeSpec::seconds(1) == TimeSpec::nanoseconds(1_000_000_000));
++        assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
++        assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
++        assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
++        assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
++    }
++
++    #[test]
++    pub fn test_timespec_fmt() {
++        assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
++        assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
++        assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
++        assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
++        assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds");
++        assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
++    }
++
++    #[test]
++    pub fn test_timeval() {
++        assert!(TimeVal::seconds(1) != TimeVal::zero());
++        assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2),
++                   TimeVal::seconds(3));
++        assert_eq!(TimeVal::minutes(3) + TimeVal::seconds(2),
++                   TimeVal::seconds(182));
++    }
++
++    #[test]
++    pub fn test_timeval_ord() {
++        assert!(TimeVal::seconds(1) == TimeVal::microseconds(1_000_000));
++        assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
++        assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
++        assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
++        assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
++    }
++
++    #[test]
++    pub fn test_timeval_neg() {
++        let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
++        let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
++
++        assert_eq!(a, -b);
++    }
++
++    #[test]
++    pub fn test_timeval_fmt() {
++        assert_eq!(TimeVal::zero().to_string(), "0 seconds");
++        assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
++        assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
++        assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
++        assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
++        assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/uio.rs b/third_party/rust/nix-0.15.0/src/sys/uio.rs
+new file mode 100644
+index 0000000000000..d089084eed711
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/uio.rs
+@@ -0,0 +1,194 @@
++// Silence invalid warnings due to rust-lang/rust#16719
++#![allow(improper_ctypes)]
++
++use Result;
++use errno::Errno;
++use libc::{self, c_int, c_void, size_t, off_t};
++use std::marker::PhantomData;
++use std::os::unix::io::RawFd;
++
++pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize> {
++    let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
++    let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Write to `fd` at `offset` from buffers in `iov`.
++///
++/// Buffers in `iov` will be written in order until all buffers have been written
++/// or an error occurs. The file offset is not changed.
++///
++/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
++               offset: off_t) -> Result<usize> {
++    let res = unsafe {
++        libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Read from `fd` at `offset` filling buffers in `iov`.
++///
++/// Buffers in `iov` will be filled in order until all buffers have been filled,
++/// no more bytes are available, or an error occurs. The file offset is not
++/// changed.
++///
++/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
++              offset: off_t) -> Result<usize> {
++    let res = unsafe {
++        libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
++    let res = unsafe {
++        libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
++                    offset)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
++    let res = unsafe {
++        libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
++                   offset)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// A slice of memory in a remote process, starting at address `base`
++/// and consisting of `len` bytes.
++///
++/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html),
++/// except that it refers to memory in some other process, and is
++/// therefore not represented in Rust by an actual slice as `IoVec` is. It
++/// is used with [`process_vm_readv`](fn.process_vm_readv.html)
++/// and [`process_vm_writev`](fn.process_vm_writev.html).
++#[cfg(target_os = "linux")]
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct RemoteIoVec {
++    /// The starting address of this slice (`iov_base`).
++    pub base: usize,
++    /// The number of bytes in this slice (`iov_len`).
++    pub len: usize,
++}
++
++/// Write data directly to another process's virtual memory
++/// (see [`process_vm_writev`(2)]).
++///
++/// `local_iov` is a list of [`IoVec`]s containing the data to be written,
++/// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the
++/// data should be written in the target process. On success, returns the
++/// number of bytes written, which will always be a whole
++/// number of `remote_iov` chunks.
++///
++/// This requires the same permissions as debugging the process using
++/// [ptrace]: you must either be a privileged process (with
++/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
++/// target process and the OS must have unprivileged debugging enabled.
++///
++/// This function is only available on Linux.
++///
++/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
++/// [ptrace]: ../ptrace/index.html
++/// [`IoVec`]: struct.IoVec.html
++/// [`RemoteIoVec`]: struct.RemoteIoVec.html
++#[cfg(target_os = "linux")]
++pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
++    let res = unsafe {
++        libc::process_vm_writev(pid.into(),
++                                local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
++                                remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Read data directly from another process's virtual memory
++/// (see [`process_vm_readv`(2)]).
++///
++/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy
++/// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying
++/// where the source data is in the target process. On success,
++/// returns the number of bytes written, which will always be a whole
++/// number of `remote_iov` chunks.
++///
++/// This requires the same permissions as debugging the process using
++/// [`ptrace`]: you must either be a privileged process (with
++/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
++/// target process and the OS must have unprivileged debugging enabled.
++///
++/// This function is only available on Linux.
++///
++/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
++/// [`ptrace`]: ../ptrace/index.html
++/// [`IoVec`]: struct.IoVec.html
++/// [`RemoteIoVec`]: struct.RemoteIoVec.html
++#[cfg(any(target_os = "linux"))]
++pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
++    let res = unsafe {
++        libc::process_vm_readv(pid.into(),
++                               local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
++                               remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
++    };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct IoVec<T>(libc::iovec, PhantomData<T>);
++
++impl<T> IoVec<T> {
++    #[inline]
++    pub fn as_slice(&self) -> &[u8] {
++        use std::slice;
++
++        unsafe {
++            slice::from_raw_parts(
++                self.0.iov_base as *const u8,
++                self.0.iov_len as usize)
++        }
++    }
++}
++
++impl<'a> IoVec<&'a [u8]> {
++    pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
++        IoVec(libc::iovec {
++            iov_base: buf.as_ptr() as *mut c_void,
++            iov_len: buf.len() as size_t,
++        }, PhantomData)
++    }
++}
++
++impl<'a> IoVec<&'a mut [u8]> {
++    pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
++        IoVec(libc::iovec {
++            iov_base: buf.as_ptr() as *mut c_void,
++            iov_len: buf.len() as size_t,
++        }, PhantomData)
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/utsname.rs b/third_party/rust/nix-0.15.0/src/sys/utsname.rs
+new file mode 100644
+index 0000000000000..ab09c7d23232a
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/utsname.rs
+@@ -0,0 +1,67 @@
++use std::mem;
++use libc::{self, c_char};
++use std::ffi::CStr;
++use std::str::from_utf8_unchecked;
++
++#[repr(C)]
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct UtsName(libc::utsname);
++
++impl UtsName {
++    pub fn sysname(&self) -> &str {
++        to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char)
++    }
++
++    pub fn nodename(&self) -> &str {
++        to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char)
++    }
++
++    pub fn release(&self) -> &str {
++        to_str(&(&self.0.release as *const c_char ) as *const *const c_char)
++    }
++
++    pub fn version(&self) -> &str {
++        to_str(&(&self.0.version as *const c_char ) as *const *const c_char)
++    }
++
++    pub fn machine(&self) -> &str {
++        to_str(&(&self.0.machine as *const c_char ) as *const *const c_char)
++    }
++}
++
++pub fn uname() -> UtsName {
++    unsafe {
++        let mut ret: UtsName = mem::uninitialized();
++        libc::uname(&mut ret.0);
++        ret
++    }
++}
++
++#[inline]
++fn to_str<'a>(s: *const *const c_char) -> &'a str {
++    unsafe {
++        let res = CStr::from_ptr(*s).to_bytes();
++        from_utf8_unchecked(res)
++    }
++}
++
++#[cfg(test)]
++mod test {
++    #[cfg(target_os = "linux")]
++    #[test]
++    pub fn test_uname_linux() {
++        assert_eq!(super::uname().sysname(), "Linux");
++    }
++
++    #[cfg(any(target_os = "macos", target_os = "ios"))]
++    #[test]
++    pub fn test_uname_darwin() {
++        assert_eq!(super::uname().sysname(), "Darwin");
++    }
++
++    #[cfg(target_os = "freebsd")]
++    #[test]
++    pub fn test_uname_freebsd() {
++        assert_eq!(super::uname().sysname(), "FreeBSD");
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/sys/wait.rs b/third_party/rust/nix-0.15.0/src/sys/wait.rs
+new file mode 100644
+index 0000000000000..c54f7ec579667
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/sys/wait.rs
+@@ -0,0 +1,239 @@
++use libc::{self, c_int};
++use Result;
++use errno::Errno;
++use unistd::Pid;
++
++use sys::signal::Signal;
++
++libc_bitflags!(
++    pub struct WaitPidFlag: c_int {
++        WNOHANG;
++        WUNTRACED;
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd"))]
++        WEXITED;
++        WCONTINUED;
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd"))]
++        WSTOPPED;
++        /// Don't reap, just poll status.
++        #[cfg(any(target_os = "android",
++                  target_os = "freebsd",
++                  target_os = "haiku",
++                  target_os = "ios",
++                  target_os = "linux",
++                  target_os = "macos",
++                  target_os = "netbsd"))]
++        WNOWAIT;
++        /// Don't wait on children of other threads in this group
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        __WNOTHREAD;
++        /// Wait on all children, regardless of type
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        __WALL;
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        __WCLONE;
++    }
++);
++
++/// Possible return values from `wait()` or `waitpid()`.
++///
++/// Each status (other than `StillAlive`) describes a state transition
++/// in a child process `Pid`, such as the process exiting or stopping,
++/// plus additional data about the transition if any.
++///
++/// Note that there are two Linux-specific enum variants, `PtraceEvent`
++/// and `PtraceSyscall`. Portable code should avoid exhaustively
++/// matching on `WaitStatus`.
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub enum WaitStatus {
++    /// The process exited normally (as with `exit()` or returning from
++    /// `main`) with the given exit code. This case matches the C macro
++    /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
++    Exited(Pid, i32),
++    /// The process was killed by the given signal. The third field
++    /// indicates whether the signal generated a core dump. This case
++    /// matches the C macro `WIFSIGNALED(status)`; the last two fields
++    /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
++    Signaled(Pid, Signal, bool),
++    /// The process is alive, but was stopped by the given signal. This
++    /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
++    /// case matches the C macro `WIFSTOPPED(status)`; the second field
++    /// is `WSTOPSIG(status)`.
++    Stopped(Pid, Signal),
++    /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
++    /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
++    /// currently-defined events use `SIGTRAP` as the signal; the third
++    /// 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
++    #[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
++    #[cfg(any(target_os = "linux", target_os = "android"))]
++    PtraceSyscall(Pid),
++    /// The process was previously stopped but has resumed execution
++    /// after receiving a `SIGCONT` signal. This is only reported if
++    /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
++    /// macro `WIFCONTINUED(status)`.
++    Continued(Pid),
++    /// There are currently no state changes to report in any awaited
++    /// child process. This is only returned if `WaitPidFlag::WNOHANG`
++    /// was used (otherwise `wait()` or `waitpid()` would block until
++    /// there was something to report).
++    StillAlive,
++}
++
++impl WaitStatus {
++    /// Extracts the PID from the WaitStatus unless it equals StillAlive.
++    pub fn pid(&self) -> Option<Pid> {
++        use self::WaitStatus::*;
++        match *self {
++            Exited(p, _)  | Signaled(p, _, _) |
++                Stopped(p, _) | Continued(p) => Some(p),
++            StillAlive => None,
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
++        }
++    }
++}
++
++fn exited(status: i32) -> bool {
++    unsafe { libc::WIFEXITED(status) }
++}
++
++fn exit_status(status: i32) -> i32 {
++    unsafe { libc::WEXITSTATUS(status) }
++}
++
++fn signaled(status: i32) -> bool {
++    unsafe { libc::WIFSIGNALED(status) }
++}
++
++fn term_signal(status: i32) -> Result<Signal> {
++    Signal::from_c_int(unsafe { libc::WTERMSIG(status) })
++}
++
++fn dumped_core(status: i32) -> bool {
++    unsafe { libc::WCOREDUMP(status) }
++}
++
++fn stopped(status: i32) -> bool {
++    unsafe { libc::WIFSTOPPED(status) }
++}
++
++fn stop_signal(status: i32) -> Result<Signal> {
++    Signal::from_c_int(unsafe { libc::WSTOPSIG(status) })
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn syscall_stop(status: i32) -> bool {
++    // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
++    // of delivering SIGTRAP | 0x80 as the signal number for syscall
++    // stops. This allows easily distinguishing syscall stops from
++    // genuine SIGTRAP signals.
++    unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn stop_additional(status: i32) -> c_int {
++    (status >> 16) as c_int
++}
++
++fn continued(status: i32) -> bool {
++    unsafe { libc::WIFCONTINUED(status) }
++}
++
++impl WaitStatus {
++    /// Convert a raw `wstatus` as returned by `waitpid`/`wait` into a `WaitStatus`
++    ///
++    /// # Errors
++    ///
++    /// Returns an `Error` corresponding to `EINVAL` for invalid status values.
++    ///
++    /// # Examples
++    ///
++    /// Convert a `wstatus` obtained from `libc::waitpid` into a `WaitStatus`:
++    ///
++    /// ```
++    /// use nix::sys::wait::WaitStatus;
++    /// use nix::sys::signal::Signal;
++    /// let pid = nix::unistd::Pid::from_raw(1);
++    /// let status = WaitStatus::from_raw(pid, 0x0002);
++    /// assert_eq!(status, Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
++    /// ```
++    pub fn from_raw(pid: Pid, status: i32) -> Result<WaitStatus> {
++        Ok(if exited(status) {
++            WaitStatus::Exited(pid, exit_status(status))
++        } else if signaled(status) {
++            WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status))
++        } else if stopped(status) {
++            cfg_if! {
++                if #[cfg(any(target_os = "android", target_os = "linux"))] {
++                    fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
++                        let status_additional = stop_additional(status);
++                        Ok(if syscall_stop(status) {
++                            WaitStatus::PtraceSyscall(pid)
++                        } else if status_additional == 0 {
++                            WaitStatus::Stopped(pid, stop_signal(status)?)
++                        } else {
++                            WaitStatus::PtraceEvent(pid, stop_signal(status)?,
++                                                    stop_additional(status))
++                        })
++                    }
++                } else {
++                    fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
++                        Ok(WaitStatus::Stopped(pid, stop_signal(status)?))
++                    }
++                }
++            }
++            return decode_stopped(pid, status);
++        } else {
++            assert!(continued(status));
++            WaitStatus::Continued(pid)
++        })
++    }
++}
++
++pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
++    use self::WaitStatus::*;
++
++    let mut status: i32 = 0;
++
++    let option_bits = match options {
++        Some(bits) => bits.bits(),
++        None => 0,
++    };
++
++    let res = unsafe {
++        libc::waitpid(
++            pid.into().unwrap_or(Pid::from_raw(-1)).into(),
++            &mut status as *mut c_int,
++            option_bits,
++        )
++    };
++
++    match Errno::result(res)? {
++        0 => Ok(StillAlive),
++        res => WaitStatus::from_raw(Pid::from_raw(res), status),
++    }
++}
++
++pub fn wait() -> Result<WaitStatus> {
++    waitpid(None, None)
++}
+diff --git a/third_party/rust/nix-0.15.0/src/ucontext.rs b/third_party/rust/nix-0.15.0/src/ucontext.rs
+new file mode 100644
+index 0000000000000..5e10e7d1f8934
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/ucontext.rs
+@@ -0,0 +1,39 @@
++use libc;
++#[cfg(not(target_env = "musl"))]
++use Result;
++#[cfg(not(target_env = "musl"))]
++use errno::Errno;
++use std::mem;
++use sys::signal::SigSet;
++
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++pub struct UContext {
++    context: libc::ucontext_t,
++}
++
++impl UContext {
++    #[cfg(not(target_env = "musl"))]
++    pub fn get() -> Result<UContext> {
++        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
++        let res = unsafe {
++            libc::getcontext(&mut context as *mut libc::ucontext_t)
++        };
++        Errno::result(res).map(|_| UContext { context: context })
++    }
++
++    #[cfg(not(target_env = "musl"))]
++    pub fn set(&self) -> Result<()> {
++        let res = unsafe {
++            libc::setcontext(&self.context as *const libc::ucontext_t)
++        };
++        Errno::result(res).map(drop)
++    }
++
++    pub fn sigmask_mut(&mut self) -> &mut SigSet {
++        unsafe { mem::transmute(&mut self.context.uc_sigmask) }
++    }
++
++    pub fn sigmask(&self) -> &SigSet {
++        unsafe { mem::transmute(&self.context.uc_sigmask) }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/src/unistd.rs b/third_party/rust/nix-0.15.0/src/unistd.rs
+new file mode 100644
+index 0000000000000..f422f09198655
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/src/unistd.rs
+@@ -0,0 +1,2394 @@
++//! Safe wrappers around functions found in libc "unistd.h" header
++
++use errno::{self, Errno};
++use {Error, Result, NixPath};
++use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag};
++use fcntl::FcntlArg::F_SETFD;
++use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
++           uid_t, gid_t, mode_t};
++use std::{fmt, mem, ptr};
++use std::ffi::{CString, CStr, OsString, OsStr};
++use std::os::unix::ffi::{OsStringExt, OsStrExt};
++use std::os::unix::io::RawFd;
++use std::path::PathBuf;
++use void::Void;
++use sys::stat::Mode;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use self::pivot_root::*;
++
++#[cfg(any(target_os = "android", target_os = "freebsd",
++          target_os = "linux", target_os = "openbsd"))]
++pub use self::setres::*;
++
++/// User identifier
++///
++/// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
++/// passing wrong value.
++#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
++pub struct Uid(uid_t);
++
++impl Uid {
++    /// Creates `Uid` from raw `uid_t`.
++    pub fn from_raw(uid: uid_t) -> Self {
++        Uid(uid)
++    }
++
++    /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
++    pub fn current() -> Self {
++        getuid()
++    }
++
++    /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
++    pub fn effective() -> Self {
++        geteuid()
++    }
++
++    /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
++    pub fn is_root(&self) -> bool {
++        *self == ROOT
++    }
++
++    /// Get the raw `uid_t` wrapped by `self`.
++    pub fn as_raw(&self) -> uid_t {
++        self.0
++    }
++}
++
++impl From<Uid> for uid_t {
++    fn from(uid: Uid) -> Self {
++        uid.0
++    }
++}
++
++impl fmt::Display for Uid {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        fmt::Display::fmt(&self.0, f)
++    }
++}
++
++/// Constant for UID = 0
++pub const ROOT: Uid = Uid(0);
++
++/// Group identifier
++///
++/// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally
++/// passing wrong value.
++#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
++pub struct Gid(gid_t);
++
++impl Gid {
++    /// Creates `Gid` from raw `gid_t`.
++    pub fn from_raw(gid: gid_t) -> Self {
++        Gid(gid)
++    }
++
++    /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
++    pub fn current() -> Self {
++        getgid()
++    }
++
++    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getgid`.
++    pub fn effective() -> Self {
++        getegid()
++    }
++
++    /// Get the raw `gid_t` wrapped by `self`.
++    pub fn as_raw(&self) -> gid_t {
++        self.0
++    }
++}
++
++impl From<Gid> for gid_t {
++    fn from(gid: Gid) -> Self {
++        gid.0
++    }
++}
++
++impl fmt::Display for Gid {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        fmt::Display::fmt(&self.0, f)
++    }
++}
++
++/// Process identifier
++///
++/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
++/// passing wrong value.
++#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
++pub struct Pid(pid_t);
++
++impl Pid {
++    /// Creates `Pid` from raw `pid_t`.
++    pub fn from_raw(pid: pid_t) -> Self {
++        Pid(pid)
++    }
++
++    /// Returns PID of calling process
++    pub fn this() -> Self {
++        getpid()
++    }
++
++    /// Returns PID of parent of calling process
++    pub fn parent() -> Self {
++        getppid()
++    }
++
++    /// Get the raw `pid_t` wrapped by `self`.
++    pub fn as_raw(&self) -> pid_t {
++        self.0
++    }
++}
++
++impl From<Pid> for pid_t {
++    fn from(pid: Pid) -> Self {
++        pid.0
++    }
++}
++
++impl fmt::Display for Pid {
++    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
++        fmt::Display::fmt(&self.0, f)
++    }
++}
++
++
++/// Represents the successful result of calling `fork`
++///
++/// When `fork` is called, the process continues execution in the parent process
++/// and in the new child.  This return type can be examined to determine whether
++/// you are now executing in the parent process or in the child.
++#[derive(Clone, Copy, Debug)]
++pub enum ForkResult {
++    Parent { child: Pid },
++    Child,
++}
++
++impl ForkResult {
++
++    /// Return `true` if this is the child process of the `fork()`
++    #[inline]
++    pub fn is_child(&self) -> bool {
++        match *self {
++            ForkResult::Child => true,
++            _ => false
++        }
++    }
++
++    /// Returns `true` if this is the parent process of the `fork()`
++    #[inline]
++    pub fn is_parent(&self) -> bool {
++        !self.is_child()
++    }
++}
++
++/// Create a new child process duplicating the parent process ([see
++/// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
++///
++/// After calling the fork system call (successfully) two processes will
++/// be created that are identical with the exception of their pid and the
++/// return value of this function.  As an example:
++///
++/// ```no_run
++/// use nix::unistd::{fork, ForkResult};
++///
++/// match fork() {
++///    Ok(ForkResult::Parent { child, .. }) => {
++///        println!("Continuing execution in parent process, new child has pid: {}", child);
++///    }
++///    Ok(ForkResult::Child) => println!("I'm a new child process"),
++///    Err(_) => println!("Fork failed"),
++/// }
++/// ```
++///
++/// This will print something like the following (order indeterministic).  The
++/// thing to note is that you end up with two processes continuing execution
++/// immediately after the fork call but with different match arms.
++///
++/// ```text
++/// Continuing execution in parent process, new child has pid: 1234
++/// I'm a new child process
++/// ```
++///
++/// # 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]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
++#[inline]
++pub fn fork() -> Result<ForkResult> {
++    use self::ForkResult::*;
++    let res = unsafe { libc::fork() };
++
++    Errno::result(res).map(|res| match res {
++        0 => Child,
++        res => Parent { child: Pid(res) },
++    })
++}
++
++/// Get the pid of this process (see
++/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
++///
++/// Since you are running code, there is always a pid to return, so there
++/// is no error case that needs to be handled.
++#[inline]
++pub fn getpid() -> Pid {
++    Pid(unsafe { libc::getpid() })
++}
++
++/// Get the pid of this processes' parent (see
++/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
++///
++/// There is always a parent pid to return, so there is no error case that needs
++/// to be handled.
++#[inline]
++pub fn getppid() -> Pid {
++    Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful."
++}
++
++/// Set a process group ID (see
++/// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
++///
++/// Set the process group id (PGID) of a particular process.  If a pid of zero
++/// is specified, then the pid of the calling process is used.  Process groups
++/// may be used to group together a set of processes in order for the OS to
++/// apply some operations across the group.
++///
++/// `setsid()` may be used to create a new process group.
++#[inline]
++pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
++    let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
++    Errno::result(res).map(drop)
++}
++#[inline]
++pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
++    let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
++    Errno::result(res).map(Pid)
++}
++
++/// Create new session and set process group id (see
++/// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
++#[inline]
++pub fn setsid() -> Result<Pid> {
++    Errno::result(unsafe { libc::setsid() }).map(Pid)
++}
++
++/// Get the process group ID of a session leader
++/// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
++///
++/// Obtain the process group ID of the process that is the session leader of the process specified
++/// by pid. If pid is zero, it specifies the calling process.
++#[inline]
++pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
++    let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
++    Errno::result(res).map(Pid)
++}
++
++
++/// Get the terminal foreground process group (see
++/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
++///
++/// Get the group process id (GPID) of the foreground process group on the
++/// terminal associated to file descriptor (FD).
++#[inline]
++pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
++    let res = unsafe { libc::tcgetpgrp(fd) };
++    Errno::result(res).map(Pid)
++}
++/// Set the terminal foreground process group (see
++/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
++///
++/// Get the group process id (PGID) to the foreground process group on the
++/// terminal associated to file descriptor (FD).
++#[inline]
++pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
++    let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) };
++    Errno::result(res).map(drop)
++}
++
++
++/// Get the group id of the calling process (see
++///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
++///
++/// Get the process group id (PGID) of the calling process.
++/// According to the man page it is always successful.
++#[inline]
++pub fn getpgrp() -> Pid {
++    Pid(unsafe { libc::getpgrp() })
++}
++
++/// Get the caller's thread ID (see
++/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
++///
++/// This function is only available on Linux based systems.  In a single
++/// threaded process, the main thread will have the same ID as the process.  In
++/// a multithreaded process, each thread will have a unique thread id but the
++/// same process ID.
++///
++/// No error handling is required as a thread id should always exist for any
++/// process, even if threads are not being used.
++#[cfg(any(target_os = "linux", target_os = "android"))]
++#[inline]
++pub fn gettid() -> Pid {
++    Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
++}
++
++/// Create a copy of the specified file descriptor (see
++/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
++///
++/// The new file descriptor will be have a new index but refer to the same
++/// resource as the old file descriptor and the old and new file descriptors may
++/// be used interchangeably.  The new and old file descriptor share the same
++/// underlying resource, offset, and file status flags.  The actual index used
++/// for the file descriptor will be the lowest fd index that is available.
++///
++/// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`).
++#[inline]
++pub fn dup(oldfd: RawFd) -> Result<RawFd> {
++    let res = unsafe { libc::dup(oldfd) };
++
++    Errno::result(res)
++}
++
++/// Create a copy of the specified file descriptor using the specified fd (see
++/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
++///
++/// This function behaves similar to `dup()` except that it will try to use the
++/// specified fd instead of allocating a new one.  See the man pages for more
++/// detail on the exact behavior of this function.
++#[inline]
++pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
++    let res = unsafe { libc::dup2(oldfd, newfd) };
++
++    Errno::result(res)
++}
++
++/// 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)).
++///
++/// This function behaves similar to `dup2()` but allows for flags to be
++/// specified.
++pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
++    dup3_polyfill(oldfd, newfd, flags)
++}
++
++#[inline]
++fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
++    if oldfd == newfd {
++        return Err(Error::Sys(Errno::EINVAL));
++    }
++
++    let fd = dup2(oldfd, newfd)?;
++
++    if flags.contains(OFlag::O_CLOEXEC) {
++        if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
++            let _ = close(fd);
++            return Err(e);
++        }
++    }
++
++    Ok(fd)
++}
++
++/// Change the current working directory of the calling process (see
++/// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
++///
++/// This function may fail in a number of different scenarios.  See the man
++/// pages for additional details on possible failure cases.
++#[inline]
++pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::chdir(cstr.as_ptr()) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// 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)).
++///
++/// This function may fail in a number of different scenarios.  See the man
++/// pages for additional details on possible failure cases.
++#[inline]
++pub fn fchdir(dirfd: RawFd) -> Result<()> {
++    let res = unsafe { libc::fchdir(dirfd) };
++
++    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))
++///
++/// # Errors
++///
++/// There are several situations where mkdir might fail:
++///
++/// - current user has insufficient rights in the parent directory
++/// - the path already exists
++/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
++///
++/// # Example
++///
++/// ```rust
++/// extern crate tempfile;
++/// extern crate nix;
++///
++/// use nix::unistd;
++/// use nix::sys::stat;
++/// use tempfile::tempdir;
++///
++/// fn main() {
++///     let tmp_dir1 = tempdir().unwrap();
++///     let tmp_dir2 = tmp_dir1.path().join("new_dir");
++///
++///     // create new directory and give read, write and execute rights to the owner
++///     match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
++///        Ok(_) => println!("created {:?}", tmp_dir2),
++///        Err(err) => println!("Error creating directory: {}", err),
++///     }
++/// }
++/// ```
++#[inline]
++pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
++///
++/// # Errors
++///
++/// There are several situations where mkfifo might fail:
++///
++/// - current user has insufficient rights in the parent directory
++/// - the path already exists
++/// - 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)
++///
++/// # Example
++///
++/// ```rust
++/// extern crate tempfile;
++/// extern crate nix;
++///
++/// use nix::unistd;
++/// use nix::sys::stat;
++/// use tempfile::tempdir;
++///
++/// fn main() {
++///     let tmp_dir = tempdir().unwrap();
++///     let fifo_path = tmp_dir.path().join("foo.pipe");
++///
++///     // create new fifo and give read, write and execute rights to the owner
++///     match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
++///        Ok(_) => println!("created {:?}", fifo_path),
++///        Err(err) => println!("Error creating fifo: {}", err),
++///     }
++/// }
++/// ```
++#[inline]
++pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Creates a symbolic link at `path2` which points to `path1`.
++///
++/// If `dirfd` has a value, then `path2` is relative to directory associated
++/// with the file descriptor.
++///
++/// 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).
++pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
++    path1: &P1,
++    dirfd: Option<RawFd>,
++    path2: &P2) -> Result<()> {
++    let res =
++        path1.with_nix_path(|path1| {
++            path2.with_nix_path(|path2| {
++                unsafe {
++                    libc::symlinkat(
++                        path1.as_ptr(),
++                        dirfd.unwrap_or(libc::AT_FDCWD),
++                        path2.as_ptr()
++                    )
++                }
++            })
++        })??;
++    Errno::result(res).map(drop)
++}
++
++/// Returns the current directory as a `PathBuf`
++///
++/// Err is returned if the current user doesn't have the permission to read or search a component
++/// of the current path.
++///
++/// # Example
++///
++/// ```rust
++/// extern crate nix;
++///
++/// 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);
++/// }
++/// ```
++#[inline]
++pub fn getcwd() -> Result<PathBuf> {
++    let mut buf = Vec::with_capacity(512);
++    loop {
++        unsafe {
++            let ptr = buf.as_mut_ptr() as *mut c_char;
++
++            // The buffer must be large enough to store the absolute pathname plus
++            // a terminating null byte, or else null is returned.
++            // To safely handle this we start with a reasonable size (512 bytes)
++            // and double the buffer size upon every error
++            if !libc::getcwd(ptr, buf.capacity()).is_null() {
++                let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
++                buf.set_len(len);
++                buf.shrink_to_fit();
++                return Ok(PathBuf::from(OsString::from_vec(buf)));
++            } else {
++                let error = Errno::last();
++                // ERANGE means buffer was too small to store directory name
++                if error != Errno::ERANGE {
++                    return Err(Error::Sys(error));
++                }
++            }
++
++            // Trigger the internal buffer resizing logic of `Vec` by requiring
++            // more space than the current capacity.
++            let cap = buf.capacity();
++            buf.set_len(cap);
++            buf.reserve(1);
++        }
++    }
++}
++
++/// Computes the raw UID and GID values to pass to a `*chown` call.
++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
++    // around to get -1.
++    let uid = owner.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1));
++    let gid = group.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1));
++    (uid, gid)
++}
++
++/// 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)).
++///
++/// 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
++/// only if `Some` owner/group is provided.
++#[inline]
++pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        let (uid, gid) = chown_raw_ids(owner, group);
++        unsafe { libc::chown(cstr.as_ptr(), uid, gid) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Flags for `fchownat` function.
++#[derive(Clone, Copy, Debug)]
++pub enum FchownatFlags {
++    FollowSymlink,
++    NoFollowSymlink,
++}
++
++/// Change the ownership of the file at `path` to be owned by the specified
++/// `owner` (user) and `group`.
++///
++/// 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
++/// only if `Some` owner/group is provided.
++///
++/// The file to be changed is determined relative to the directory associated
++/// with the file descriptor `dirfd` or the current working directory
++/// if `dirfd` is `None`.
++///
++/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
++/// then the mode of the symbolic link is changed.
++///
++/// `fchownat(None, path, mode, FchownatFlags::NoFollowSymlink)` is identical to
++/// a call `libc::lchown(path, mode)`.  That's why `lchmod` is unimplemented in
++/// the `nix` crate.
++///
++/// # References
++///
++/// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
++pub fn fchownat<P: ?Sized + NixPath>(
++    dirfd: Option<RawFd>,
++    path: &P,
++    owner: Option<Uid>,
++    group: Option<Gid>,
++    flag: FchownatFlags,
++) -> Result<()> {
++    let atflag =
++        match flag {
++            FchownatFlags::FollowSymlink => AtFlags::empty(),
++            FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
++        };
++    let res = path.with_nix_path(|cstr| unsafe {
++        let (uid, gid) = chown_raw_ids(owner, group);
++        libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid,
++                       atflag.bits() as libc::c_int)
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
++    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
++    args_p.push(ptr::null());
++    args_p
++}
++
++/// Replace the current process image with a new one (see
++/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
++///
++/// See the `::nix::unistd::execve` system call for additional details.  `execv`
++/// performs the same action but does not allow for customization of the
++/// environment for the new process.
++#[inline]
++pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
++    let args_p = to_exec_array(argv);
++
++    unsafe {
++        libc::execv(path.as_ptr(), args_p.as_ptr())
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++
++/// Replace the current process image with a new one (see
++/// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
++///
++/// The execve system call allows for another process to be "called" which will
++/// replace the current process image.  That is, this process becomes the new
++/// command that is run. On success, this function will not return. Instead,
++/// the new program will run until it exits.
++///
++/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
++/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
++/// in the `args` list is an argument to the new process. Each element in the
++/// `env` list should be a string in the form "key=value".
++#[inline]
++pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
++    let args_p = to_exec_array(args);
++    let env_p = to_exec_array(env);
++
++    unsafe {
++        libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++/// 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)).
++///
++/// See `::nix::unistd::execve` for additional details.  `execvp` behaves the
++/// same as execv except that it will examine the `PATH` environment variables
++/// for file names not specified with a leading slash.  For example, `execv`
++/// would not work if "bash" was specified for the path argument, but `execvp`
++/// would assuming that a bash executable was on the system `PATH`.
++#[inline]
++pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
++    let args_p = to_exec_array(args);
++
++    unsafe {
++        libc::execvp(filename.as_ptr(), args_p.as_ptr())
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++/// 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)).
++///
++/// 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
++/// information.
++#[cfg(any(target_os = "haiku",
++          target_os = "linux",
++          target_os = "openbsd"))]
++pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
++    let args_p = to_exec_array(args);
++    let env_p = to_exec_array(env);
++
++    unsafe {
++        libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++/// Replace the current process image with a new one (see
++/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
++///
++/// The `fexecve` function allows for another process to be "called" which will
++/// replace the current process image.  That is, this process becomes the new
++/// command that is run. On success, this function will not return. Instead,
++/// the new program will run until it exits.
++///
++/// This function is similar to `execve`, except that the program to be executed
++/// is referenced as a file descriptor instead of a path.
++// Note for NetBSD and OpenBSD: although rust-lang/libc includes it (under
++// unix/bsd/netbsdlike/) fexecve is not currently implemented on NetBSD nor on
++// OpenBSD.
++#[cfg(any(target_os = "android",
++          target_os = "linux",
++          target_os = "freebsd"))]
++#[inline]
++pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
++    let args_p = to_exec_array(args);
++    let env_p = to_exec_array(env);
++
++    unsafe {
++        libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++/// Execute program relative to a directory file descriptor (see
++/// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
++///
++/// The `execveat` function allows for another process to be "called" which will
++/// replace the current process image.  That is, this process becomes the new
++/// command that is run. On success, this function will not return. Instead,
++/// the new program will run until it exits.
++///
++/// This function is similar to `execve`, except that the program to be executed
++/// is referenced as a file descriptor to the base directory plus a path.
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[inline]
++pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
++                env: &[CString], flags: super::fcntl::AtFlags) -> Result<Void> {
++    let args_p = to_exec_array(args);
++    let env_p = to_exec_array(env);
++
++    unsafe {
++        libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(),
++                      args_p.as_ptr(), env_p.as_ptr(), flags);
++    };
++
++    Err(Error::Sys(Errno::last()))
++}
++
++/// Daemonize this process by detaching from the controlling terminal (see
++/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
++///
++/// When a process is launched it is typically associated with a parent and it,
++/// in turn, by its controlling terminal/process.  In order for a process to run
++/// in the "background" it must daemonize itself by detaching itself.  Under
++/// posix, this is done by doing the following:
++///
++/// 1. Parent process (this one) forks
++/// 2. Parent process exits
++/// 3. Child process continues to run.
++///
++/// `nochdir`:
++///
++/// * `nochdir = true`: The current working directory after daemonizing will
++///    be the current working directory.
++/// *  `nochdir = false`: The current working directory after daemonizing will
++///    be the root direcory, `/`.
++///
++/// `noclose`:
++///
++/// * `noclose = true`: The process' current stdin, stdout, and stderr file
++///   descriptors will remain identical after daemonizing.
++/// * `noclose = false`: The process' stdin, stdout, and stderr will point to
++///   `/dev/null` after daemonizing.
++#[cfg_attr(any(target_os = "macos", target_os = "ios"), deprecated(
++    since="0.14.0",
++    note="Deprecated in MacOSX 10.5"
++))]
++#[cfg_attr(any(target_os = "macos", target_os = "ios"), allow(deprecated))]
++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)).
++///
++/// 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
++/// will be return if the name is not valid or the current process does not have
++/// permissions to update the host name.
++pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
++    // Handle some differences in type of the len arg across platforms.
++    cfg_if! {
++        if #[cfg(any(target_os = "dragonfly",
++                     target_os = "freebsd",
++                     target_os = "ios",
++                     target_os = "macos", ))] {
++            type sethostname_len_t = c_int;
++        } else {
++            type sethostname_len_t = size_t;
++        }
++    }
++    let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
++    let len = name.as_ref().len() as sethostname_len_t;
++
++    let res = unsafe { libc::sethostname(ptr, len) };
++    Errno::result(res).map(drop)
++}
++
++/// 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)).
++///
++/// 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
++/// to the length of the provided slice including a NUL terminating byte.  If
++/// the hostname is longer than the length provided, no error will be provided.
++/// The posix specification does not specify whether implementations will
++/// null-terminate in this case, but the nix implementation will ensure that the
++/// buffer is null terminated in this case.
++///
++/// ```no_run
++/// use nix::unistd;
++///
++/// let mut buf = [0u8; 64];
++/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
++/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
++/// println!("Hostname: {}", hostname);
++/// ```
++pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
++    let ptr = buffer.as_mut_ptr() as *mut c_char;
++    let len = buffer.len() as size_t;
++
++    let res = unsafe { libc::gethostname(ptr, len) };
++    Errno::result(res).map(|_| {
++        buffer[len - 1] = 0; // ensure always null-terminated
++        unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
++    })
++}
++
++/// Close a raw file descriptor
++///
++/// Be aware that many Rust types implicitly close-on-drop, including
++/// `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).
++///
++/// # Examples
++///
++/// ```no_run
++/// extern crate tempfile;
++/// extern crate nix;
++///
++/// 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!
++/// }
++/// ```
++///
++/// ```rust
++/// extern crate tempfile;
++/// extern crate nix;
++///
++/// 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
++/// }
++/// ```
++pub fn close(fd: RawFd) -> Result<()> {
++    let res = unsafe { libc::close(fd) };
++    Errno::result(res).map(drop)
++}
++
++/// Read from a raw file descriptor.
++///
++/// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
++pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
++    let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Write to a raw file descriptor.
++///
++/// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
++pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
++    let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
++
++    Errno::result(res).map(|r| r as usize)
++}
++
++/// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to.
++///
++/// [`lseek`]: ./fn.lseek.html
++/// [`lseek64`]: ./fn.lseek64.html
++#[repr(i32)]
++#[derive(Clone, Copy, Debug)]
++pub enum Whence {
++    /// Specify an offset relative to the start of the file.
++    SeekSet = libc::SEEK_SET,
++    /// Specify an offset relative to the current file location.
++    SeekCur = libc::SEEK_CUR,
++    /// Specify an offset relative to the end of the file.
++    SeekEnd = libc::SEEK_END,
++    /// 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",
++          all(target_os = "linux", not(any(target_env = "musl",
++                                           target_arch = "mips",
++                                           target_arch = "mips64")))))]
++    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",
++          all(target_os = "linux", not(any(target_env = "musl",
++                                           target_arch = "mips",
++                                           target_arch = "mips64")))))]
++    SeekHole = libc::SEEK_HOLE
++}
++
++/// Move the read/write file offset.
++///
++/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
++pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
++    let res = unsafe { libc::lseek(fd, offset, whence as i32) };
++
++    Errno::result(res).map(|r| r as off_t)
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t> {
++    let res = unsafe { libc::lseek64(fd, offset, whence as i32) };
++
++    Errno::result(res).map(|r| r as libc::off64_t)
++}
++
++/// Create an interprocess channel.
++///
++/// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
++pub fn pipe() -> Result<(RawFd, RawFd)> {
++    unsafe {
++        let mut fds: [c_int; 2] = mem::uninitialized();
++
++        let res = libc::pipe(fds.as_mut_ptr());
++
++        Errno::result(res)?;
++
++        Ok((fds[0], fds[1]))
++    }
++}
++
++/// Like `pipe`, but allows setting certain file descriptor flags.
++///
++/// 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_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)
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "emscripten",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
++    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
++
++    let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) };
++
++    Errno::result(res)?;
++
++    Ok((fds[0], fds[1]))
++}
++
++/// Like `pipe`, but allows setting certain file descriptor flags.
++///
++/// The following flags are supported, and will be set after the pipe is
++/// created:
++///
++/// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
++/// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++#[deprecated(
++    since="0.10.0",
++    note="pipe2(2) is not actually atomic on these platforms.  Use pipe(2) and fcntl(2) instead"
++)]
++pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
++    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
++
++    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
++
++    Errno::result(res)?;
++
++    pipe2_setflags(fds[0], fds[1], flags)?;
++
++    Ok((fds[0], fds[1]))
++}
++
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
++    use fcntl::FcntlArg::F_SETFL;
++
++    let mut res = Ok(0);
++
++    if flags.contains(OFlag::O_CLOEXEC) {
++        res = res
++            .and_then(|_| fcntl(fd1, F_SETFD(FdFlag::FD_CLOEXEC)))
++            .and_then(|_| fcntl(fd2, F_SETFD(FdFlag::FD_CLOEXEC)));
++    }
++
++    if flags.contains(OFlag::O_NONBLOCK) {
++        res = res
++            .and_then(|_| fcntl(fd1, F_SETFL(OFlag::O_NONBLOCK)))
++            .and_then(|_| fcntl(fd2, F_SETFL(OFlag::O_NONBLOCK)));
++    }
++
++    match res {
++        Ok(_) => Ok(()),
++        Err(e) => {
++            let _ = close(fd1);
++            let _ = close(fd2);
++            Err(e)
++        }
++    }
++}
++
++/// Truncate a file to a specified length
++///
++/// See also
++/// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
++pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::truncate(cstr.as_ptr(), len)
++        }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Truncate a file to a specified length
++///
++/// See also
++/// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
++pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
++    Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
++}
++
++pub fn isatty(fd: RawFd) -> Result<bool> {
++    unsafe {
++        // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
++        // we return `Ok(false)`
++        if libc::isatty(fd) == 1 {
++            Ok(true)
++        } else {
++            match Errno::last() {
++                Errno::ENOTTY => Ok(false),
++                err => Err(Error::Sys(err)),
++            }
++        }
++    }
++}
++
++/// Remove a directory entry
++///
++/// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
++pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::unlink(cstr.as_ptr())
++        }
++    })?;
++    Errno::result(res).map(drop)
++}
++
++/// Flags for `unlinkat` function.
++#[derive(Clone, Copy, Debug)]
++pub enum UnlinkatFlags {
++    RemoveDir,
++    NoRemoveDir,
++}
++
++/// Remove a directory entry
++///
++/// In the case of a relative path, the directory entry to be removed is determined relative to
++/// the directory associated with the file descriptor `dirfd` or the current working directory
++/// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is
++/// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path`
++/// is performed.
++///
++/// # References
++/// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
++pub fn unlinkat<P: ?Sized + NixPath>(
++    dirfd: Option<RawFd>,
++    path: &P,
++    flag: UnlinkatFlags,
++) -> Result<()> {
++    let atflag =
++        match flag {
++            UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR,
++            UnlinkatFlags::NoRemoveDir => AtFlags::empty(),
++        };
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int)
++        }
++    })?;
++    Errno::result(res).map(drop)
++}
++
++
++#[inline]
++pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe { libc::chroot(cstr.as_ptr()) }
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
++/// Commit filesystem caches to disk
++///
++/// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
++#[cfg(any(
++    target_os = "dragonfly",
++    target_os = "freebsd",
++    target_os = "linux",
++    target_os = "netbsd",
++    target_os = "openbsd"
++))]
++pub fn sync() -> () {
++    unsafe { libc::sync() };
++}
++
++/// Synchronize changes to a file
++///
++/// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
++#[inline]
++pub fn fsync(fd: RawFd) -> Result<()> {
++    let res = unsafe { libc::fsync(fd) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Synchronize the data of a file
++///
++/// See also
++/// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
++// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
++// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
++#[cfg(any(target_os = "linux",
++          target_os = "android",
++          target_os = "emscripten"))]
++#[inline]
++pub fn fdatasync(fd: RawFd) -> Result<()> {
++    let res = unsafe { libc::fdatasync(fd) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Get a real user ID
++///
++/// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
++// POSIX requires that getuid is always successful, so no need to check return
++// value or errno.
++#[inline]
++pub fn getuid() -> Uid {
++    Uid(unsafe { libc::getuid() })
++}
++
++/// Get the effective user ID
++///
++/// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
++// POSIX requires that geteuid is always successful, so no need to check return
++// value or errno.
++#[inline]
++pub fn geteuid() -> Uid {
++    Uid(unsafe { libc::geteuid() })
++}
++
++/// Get the real group ID
++///
++/// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
++// POSIX requires that getgid is always successful, so no need to check return
++// value or errno.
++#[inline]
++pub fn getgid() -> Gid {
++    Gid(unsafe { libc::getgid() })
++}
++
++/// Get the effective group ID
++///
++/// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
++// POSIX requires that getegid is always successful, so no need to check return
++// value or errno.
++#[inline]
++pub fn getegid() -> Gid {
++    Gid(unsafe { libc::getegid() })
++}
++
++/// Set the effective user ID
++///
++/// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
++#[inline]
++pub fn seteuid(euid: Uid) -> Result<()> {
++    let res = unsafe { libc::seteuid(euid.into()) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Set the effective group ID
++///
++/// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
++#[inline]
++pub fn setegid(egid: Gid) -> Result<()> {
++    let res = unsafe { libc::setegid(egid.into()) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Set the user ID
++///
++/// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
++#[inline]
++pub fn setuid(uid: Uid) -> Result<()> {
++    let res = unsafe { libc::setuid(uid.into()) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Set the group ID
++///
++/// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
++#[inline]
++pub fn setgid(gid: Gid) -> Result<()> {
++    let res = unsafe { libc::setgid(gid.into()) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Get the list of supplementary group IDs of the calling process.
++///
++/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
++///
++/// **Note:** This function is not available for Apple platforms. On those
++/// platforms, checking group membership should be achieved via communication
++/// with the `opendirectoryd` service.
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++pub fn getgroups() -> Result<Vec<Gid>> {
++    // First get the number of groups so we can size our Vec
++    let ret = unsafe { libc::getgroups(0, ptr::null_mut()) };
++
++    // Now actually get the groups. We try multiple times in case the number of
++    // groups has changed since the first call to getgroups() and the buffer is
++    // now too small.
++    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ret)? as usize);
++    loop {
++        // FIXME: On the platforms we currently support, the `Gid` struct has
++        // the same representation in memory as a bare `gid_t`. This is not
++        // necessarily the case on all Rust platforms, though. See RFC 1785.
++        let ret = unsafe {
++            libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
++        };
++
++        match Errno::result(ret) {
++            Ok(s) => {
++                unsafe { groups.set_len(s as usize) };
++                return Ok(groups);
++            },
++            Err(Error::Sys(Errno::EINVAL)) => {
++                // EINVAL indicates that the buffer size was too small. Trigger
++                // the internal buffer resizing logic of `Vec` by requiring
++                // more space than the current capacity.
++                let cap = groups.capacity();
++                unsafe { groups.set_len(cap) };
++                groups.reserve(1);
++            },
++            Err(e) => return Err(e)
++        }
++    }
++}
++
++/// Set the list of supplementary group IDs for the calling process.
++///
++/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
++///
++/// **Note:** This function is not available for Apple platforms. On those
++/// platforms, group membership management should be achieved via communication
++/// with the `opendirectoryd` service.
++///
++/// # Examples
++///
++/// `setgroups` can be used when dropping privileges from the root user to a
++/// specific user and group. For example, given the user `www-data` with UID
++/// `33` and the group `backup` with the GID `34`, one could switch the user as
++/// follows:
++///
++/// ```rust,no_run
++/// # use std::error::Error;
++/// # use nix::unistd::*;
++/// #
++/// # fn try_main() -> Result<(), Box<Error>> {
++/// let uid = Uid::from_raw(33);
++/// let gid = Gid::from_raw(34);
++/// setgroups(&[gid])?;
++/// setgid(gid)?;
++/// setuid(uid)?;
++/// #
++/// #     Ok(())
++/// # }
++/// #
++/// # fn main() {
++/// #     try_main().unwrap();
++/// # }
++/// ```
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++pub fn setgroups(groups: &[Gid]) -> Result<()> {
++    cfg_if! {
++        if #[cfg(any(target_os = "dragonfly",
++                     target_os = "freebsd",
++                     target_os = "ios",
++                     target_os = "macos",
++                     target_os = "netbsd",
++                     target_os = "openbsd"))] {
++            type setgroups_ngroups_t = c_int;
++        } else {
++            type setgroups_ngroups_t = size_t;
++        }
++    }
++    // FIXME: On the platforms we currently support, the `Gid` struct has the
++    // same representation in memory as a bare `gid_t`. This is not necessarily
++    // the case on all Rust platforms, though. See RFC 1785.
++    let res = unsafe {
++        libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t)
++    };
++
++    Errno::result(res).map(drop)
++}
++
++/// Calculate the supplementary group access list.
++///
++/// 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)
++///
++/// **Note:** This function is not available for Apple platforms. On those
++/// platforms, checking group membership should be achieved via communication
++/// with the `opendirectoryd` service.
++///
++/// # Errors
++///
++/// Although the `getgrouplist()` call does not return any specific
++/// errors on any known platforms, this implementation will return a system
++/// error of `EINVAL` if the number of groups to be fetched exceeds the
++/// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()`
++/// 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")))]
++pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
++    let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
++        Ok(Some(n)) => n as c_int,
++        Ok(None) | Err(_) => <c_int>::max_value(),
++    };
++    use std::cmp::min;
++    let mut ngroups = min(ngroups_max, 8);
++    let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
++    cfg_if! {
++        if #[cfg(any(target_os = "ios", target_os = "macos"))] {
++            type getgrouplist_group_t = c_int;
++        } else {
++            type getgrouplist_group_t = gid_t;
++        }
++    }
++    let gid: gid_t = group.into();
++    loop {
++        let ret = unsafe {
++            libc::getgrouplist(user.as_ptr(),
++                               gid as getgrouplist_group_t,
++                               groups.as_mut_ptr() as *mut getgrouplist_group_t,
++                               &mut ngroups)
++        };
++
++        // BSD systems only return 0 or -1, Linux returns ngroups on success.
++        if ret >= 0 {
++            unsafe { groups.set_len(ngroups as usize) };
++            return Ok(groups);
++        } else if ret == -1 {
++            // Returns -1 if ngroups is too small, but does not set errno.
++            // BSD systems will still fill the groups buffer with as many
++            // groups as possible, but Linux manpages do not mention this
++            // behavior.
++
++            let cap = groups.capacity();
++            if cap >= ngroups_max as usize {
++                // We already have the largest capacity we can, give up
++                return Err(Error::invalid_argument());
++            }
++
++            // Reserve space for at least ngroups
++            groups.reserve(ngroups as usize);
++
++            // Even if the buffer gets resized to bigger than ngroups_max,
++            // don't ever ask for more than ngroups_max groups
++            ngroups = min(ngroups_max, groups.capacity() as c_int);
++        }
++    }
++}
++
++/// Initialize the supplementary group access list.
++///
++/// Sets the supplementary group IDs for the calling process using 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/initgroups.3.html)
++///
++/// **Note:** This function is not available for Apple platforms. On those
++/// platforms, group membership management should be achieved via communication
++/// with the `opendirectoryd` service.
++///
++/// # Examples
++///
++/// `initgroups` can be used when dropping privileges from the root user to
++/// another user. For example, given the user `www-data`, we could look up the
++/// UID and GID for the user in the system's password database (usually found
++/// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`,
++/// respectively, one could switch the user as follows:
++///
++/// ```rust,no_run
++/// # use std::error::Error;
++/// # use std::ffi::CString;
++/// # use nix::unistd::*;
++/// #
++/// # fn try_main() -> Result<(), Box<Error>> {
++/// let user = CString::new("www-data").unwrap();
++/// let uid = Uid::from_raw(33);
++/// let gid = Gid::from_raw(33);
++/// initgroups(&user, gid)?;
++/// setgid(gid)?;
++/// setuid(uid)?;
++/// #
++/// #     Ok(())
++/// # }
++/// #
++/// # fn main() {
++/// #     try_main().unwrap();
++/// # }
++/// ```
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
++    cfg_if! {
++        if #[cfg(any(target_os = "ios", target_os = "macos"))] {
++            type initgroups_group_t = c_int;
++        } else {
++            type initgroups_group_t = gid_t;
++        }
++    }
++    let gid: gid_t = group.into();
++    let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) };
++
++    Errno::result(res).map(drop)
++}
++
++/// Suspend the thread until a signal is received.
++///
++/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
++#[inline]
++pub fn pause() {
++    unsafe { libc::pause() };
++}
++
++pub mod alarm {
++    //! Alarm signal scheduling.
++    //!
++    //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
++    //! elapsed, which has to be caught, because the default action for the
++    //! signal is to terminate the program. This signal also can't be ignored
++    //! because the system calls like `pause` will not be interrupted, see the
++    //! second example below.
++    //!
++    //! # Examples
++    //!
++    //! Canceling an alarm:
++    //!
++    //! ```
++    //! use nix::unistd::alarm;
++    //!
++    //! // Set an alarm for 60 seconds from now.
++    //! alarm::set(60);
++    //!
++    //! // Cancel the above set alarm, which returns the number of seconds left
++    //! // of the previously set alarm.
++    //! assert_eq!(alarm::cancel(), Some(60));
++    //! ```
++    //!
++    //! Scheduling an alarm and waiting for the signal:
++    //!
++    //! ```
++    //! use std::time::{Duration, Instant};
++    //!
++    //! use nix::unistd::{alarm, pause};
++    //! use nix::sys::signal::*;
++    //!
++    //! // We need to setup an empty signal handler to catch the alarm signal,
++    //! // otherwise the program will be terminated once the signal is delivered.
++    //! extern fn signal_handler(_: nix::libc::c_int) { }
++    //! unsafe { sigaction(Signal::SIGALRM, &SigAction::new(SigHandler::Handler(signal_handler), SaFlags::empty(), SigSet::empty())); }
++    //!
++    //! // Set an alarm for 1 second from now.
++    //! alarm::set(1);
++    //!
++    //! let start = Instant::now();
++    //! // Pause the process until the alarm signal is received.
++    //! pause();
++    //!
++    //! assert!(start.elapsed() >= Duration::from_secs(1));
++    //! ```
++    //!
++    //! # References
++    //!
++    //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
++
++    use libc;
++
++    /// Schedule an alarm signal.
++    ///
++    /// This will cause the system to generate a `SIGALRM` signal for the
++    /// process after the specified number of seconds have elapsed.
++    ///
++    /// Returns the leftover time of a previously set alarm if there was one.
++    pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
++        assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
++        alarm(secs)
++    }
++
++    /// Cancel an previously set alarm signal.
++    ///
++    /// Returns the leftover time of a previously set alarm if there was one.
++    pub fn cancel() -> Option<libc::c_uint> {
++        alarm(0)
++    }
++
++    fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
++        match unsafe { libc::alarm(secs) } {
++            0 => None,
++            secs => Some(secs),
++        }
++    }
++}
++
++/// Suspend execution for an interval of time
++///
++/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
++// Per POSIX, does not fail
++#[inline]
++pub fn sleep(seconds: c_uint) -> c_uint {
++    unsafe { libc::sleep(seconds) }
++}
++
++pub mod acct {
++    use libc;
++    use {Result, NixPath};
++    use errno::Errno;
++    use std::ptr;
++
++    /// Enable process accounting
++    ///
++    /// See also [acct(2)](https://linux.die.net/man/2/acct)
++    pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> {
++        let res = filename.with_nix_path(|cstr| {
++            unsafe { libc::acct(cstr.as_ptr()) }
++        })?;
++
++        Errno::result(res).map(drop)
++    }
++
++    /// Disable process accounting
++    pub fn disable() -> Result<()> {
++        let res = unsafe { libc::acct(ptr::null()) };
++
++        Errno::result(res).map(drop)
++    }
++}
++
++/// Creates a regular file which persists even after process termination
++///
++/// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX`
++/// * returns: tuple of file descriptor and filename
++///
++/// 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)
++///
++/// # Example
++///
++/// ```rust
++/// use nix::unistd;
++///
++/// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
++///     Ok((fd, path)) => {
++///         unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
++///         fd
++///     }
++///     Err(e) => panic!("mkstemp failed: {}", e)
++/// };
++/// // do something with fd
++/// ```
++#[inline]
++pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
++    let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
++    let p = path.as_mut_ptr() as *mut _;
++    let fd = unsafe { libc::mkstemp(p) };
++    let last = path.pop(); // drop the trailing nul
++    debug_assert!(last == Some(b'\0'));
++    let pathname = OsString::from_vec(path);
++    Errno::result(fd)?;
++    Ok((fd, PathBuf::from(pathname)))
++}
++
++/// 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.
++/// 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_`.
++///
++/// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose
++/// not to implement variables that cannot change at runtime.
++///
++/// # 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)
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++#[repr(i32)]
++pub enum PathconfVar {
++    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
++              target_os = "netbsd", target_os = "openbsd"))]
++    /// Minimum number of bits needed to represent, as a signed integer value,
++    /// the maximum size of a regular file allowed in the specified directory.
++    FILESIZEBITS = libc::_PC_FILESIZEBITS,
++    /// Maximum number of links to a single file.
++    LINK_MAX = libc::_PC_LINK_MAX,
++    /// Maximum number of bytes in a terminal canonical input line.
++    MAX_CANON = libc::_PC_MAX_CANON,
++    /// Minimum number of bytes for which space is available in a terminal input
++    /// queue; therefore, the maximum number of bytes a conforming application
++    /// may require to be typed as input before reading them.
++    MAX_INPUT = libc::_PC_MAX_INPUT,
++    /// Maximum number of bytes in a filename (not including the terminating
++    /// null of a filename string).
++    NAME_MAX = libc::_PC_NAME_MAX,
++    /// Maximum number of bytes the implementation will store as a pathname in a
++    /// user-supplied buffer of unspecified size, including the terminating null
++    /// character. Minimum number the implementation will accept as the maximum
++    /// number of bytes in a pathname.
++    PATH_MAX = libc::_PC_PATH_MAX,
++    /// 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"))]
++    /// Symbolic links can be created.
++    POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
++    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
++              target_os = "linux", target_os = "openbsd"))]
++    /// Minimum number of bytes of storage actually allocated for any portion of
++    /// a file.
++    POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
++    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
++              target_os = "linux", target_os = "openbsd"))]
++    /// Recommended increment for file transfer sizes between the
++    /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
++    POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
++    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
++              target_os = "linux", target_os = "openbsd"))]
++    /// Maximum recommended file transfer size.
++    POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
++    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
++              target_os = "linux", target_os = "openbsd"))]
++    /// Minimum recommended file transfer size.
++    POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
++    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
++              target_os = "linux", target_os = "openbsd"))]
++    ///  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"))]
++    /// 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
++    /// appropriate privileges, and to changing the group ID of a file only to
++    /// the effective group ID of the process or to one of its supplementary
++    /// group IDs.
++    _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED,
++    /// Pathname components longer than {NAME_MAX} generate an error.
++    _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC,
++    /// This symbol shall be defined to be the value of a character that shall
++    /// 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"))]
++    /// 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"))]
++    /// 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"))]
++    /// Synchronized input or output operations may be performed for the
++    /// associated file.
++    _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
++    #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
++    /// The resolution in nanoseconds for all file timestamps.
++    _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION
++}
++
++/// Like `pathconf`, but works with file descriptors instead of paths (see
++/// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
++///
++/// # Parameters
++///
++/// - `fd`:   The file descriptor whose variable should be interrogated
++/// - `var`:  The pathconf variable to lookup
++///
++/// # Returns
++///
++/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
++///     implementation level (for option variables).  Implementation levels are
++///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
++/// - `Ok(None)`: the variable has no limit (for limit variables) or is
++///     unsupported (for option variables)
++/// - `Err(x)`: an error occurred
++pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> {
++    let raw = unsafe {
++        Errno::clear();
++        libc::fpathconf(fd, var as c_int)
++    };
++    if raw == -1 {
++        if errno::errno() == 0 {
++            Ok(None)
++        } else {
++            Err(Error::Sys(Errno::last()))
++        }
++    } else {
++        Ok(Some(raw))
++    }
++}
++
++/// Get path-dependent configurable system variables (see
++/// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
++///
++/// Returns the value of a path-dependent configurable system variable.  Most
++/// supported variables also have associated compile-time constants, but POSIX
++/// allows their values to change at runtime.  There are generally two types of
++/// `pathconf` variables: options and limits.  See [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
++///
++/// # Parameters
++///
++/// - `path`: Lookup the value of `var` for this file or directory
++/// - `var`:  The `pathconf` variable to lookup
++///
++/// # Returns
++///
++/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
++///     implementation level (for option variables).  Implementation levels are
++///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
++/// - `Ok(None)`: the variable has no limit (for limit variables) or is
++///     unsupported (for option variables)
++/// - `Err(x)`: an error occurred
++pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>> {
++    let raw = path.with_nix_path(|cstr| {
++        unsafe {
++            Errno::clear();
++            libc::pathconf(cstr.as_ptr(), var as c_int)
++        }
++    })?;
++    if raw == -1 {
++        if errno::errno() == 0 {
++            Ok(None)
++        } else {
++            Err(Error::Sys(Errno::last()))
++        }
++    } else {
++        Ok(Some(raw))
++    }
++}
++
++/// 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.
++/// 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_`.
++///
++/// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been
++/// implemented by all platforms.
++///
++/// # 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)
++#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++#[repr(i32)]
++pub enum SysconfVar {
++    /// Maximum number of I/O operations in a single list I/O call supported by
++    /// the implementation.
++    AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
++    /// Maximum number of outstanding asynchronous I/O operations supported by
++    /// the implementation.
++    AIO_MAX = libc::_SC_AIO_MAX,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The maximum amount by which a process can decrease its asynchronous I/O
++    /// priority level from its own scheduling priority.
++    AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
++    /// Maximum length of argument to the exec functions including environment data.
++    ARG_MAX = libc::_SC_ARG_MAX,
++    /// Maximum number of functions that may be registered with `atexit`.
++    ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
++    /// Maximum obase values allowed by the bc utility.
++    BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
++    /// Maximum number of elements permitted in an array by the bc utility.
++    BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
++    /// Maximum scale value allowed by the bc utility.
++    BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
++    /// Maximum length of a string constant accepted by the bc utility.
++    BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
++    /// Maximum number of simultaneous processes per real user ID.
++    CHILD_MAX = libc::_SC_CHILD_MAX,
++    // _SC_CLK_TCK is obsolete
++    /// Maximum number of weights that can be assigned to an entry of the
++    /// LC_COLLATE order keyword in the locale definition file
++    COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
++    /// Maximum number of timer expiration overruns.
++    DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
++    /// Maximum number of expressions that can be nested within parentheses by
++    /// the expr utility.
++    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"))]
++    /// 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,
++    /// Maximum number of iovec structures that one process has available for
++    /// use with `readv` or `writev`.
++    IOV_MAX = libc::_SC_IOV_MAX,
++    /// Unless otherwise noted, the maximum length, in bytes, of a utility's
++    /// input line (either standard input or another file), when the utility is
++    /// described as processing text files. The length includes room for the
++    /// trailing <newline>.
++    LINE_MAX = libc::_SC_LINE_MAX,
++    /// Maximum length of a login name.
++    LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
++    /// Maximum number of simultaneous supplementary group IDs per process.
++    NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
++    /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
++    GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
++    /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
++    GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
++    /// The maximum number of open message queue descriptors a process may hold.
++    MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
++    /// The maximum number of message priorities supported by the implementation.
++    MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
++    /// A value one greater than the maximum value that the system may assign to
++    /// a newly-created file descriptor.
++    OPEN_MAX = libc::_SC_OPEN_MAX,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              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"))]
++    /// The implementation supports barriers.
++    _POSIX_BARRIERS = libc::_SC_BARRIERS,
++    /// The implementation supports asynchronous input and output.
++    _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"))]
++    /// 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"))]
++    /// The implementation supports the Process CPU-Time Clocks option.
++    _POSIX_CPUTIME = libc::_SC_CPUTIME,
++    /// The implementation supports the File Synchronization option.
++    _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"))]
++    /// The implementation supports the IPv6 option.
++    _POSIX_IPV6 = libc::_SC_IPV6,
++    /// The implementation supports job control.
++    _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
++    /// The implementation supports memory mapped Files.
++    _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
++    /// The implementation supports the Process Memory Locking option.
++    _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
++    /// The implementation supports the Range Memory Locking option.
++    _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
++    /// The implementation supports memory protection.
++    _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
++    /// The implementation supports the Message Passing option.
++    _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
++    /// The implementation supports the Monotonic Clock option.
++    _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"))]
++    /// The implementation supports the Prioritized Input and Output option.
++    _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
++    /// The implementation supports the Process Scheduling option.
++    _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"))]
++    /// 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"))]
++    /// 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",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              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"))]
++    /// 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.
++    _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
++    /// The implementation supports semaphores.
++    _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
++    /// The implementation supports the Shared Memory Objects option.
++    _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the POSIX shell.
++    _POSIX_SHELL = libc::_SC_SHELL,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Spawn option.
++    _POSIX_SPAWN = libc::_SC_SPAWN,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports spin locks.
++    _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Process Sporadic Server option.
++    _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
++    /// The implementation supports the Synchronized Input and Output option.
++    _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
++    /// The implementation supports the Thread Stack Address Attribute option.
++    _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
++    /// The implementation supports the Thread Stack Size Attribute option.
++    _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="netbsd", target_os="openbsd"))]
++    /// The implementation supports the Thread CPU-Time Clocks option.
++    _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
++    /// The implementation supports the Non-Robust Mutex Priority Inheritance
++    /// option.
++    _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
++    /// The implementation supports the Non-Robust Mutex Priority Protection option.
++    _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
++    /// The implementation supports the Thread Execution Scheduling option.
++    _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Thread Process-Shared Synchronization
++    /// option.
++    _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
++    #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
++    /// The implementation supports the Robust Mutex Priority Inheritance option.
++    _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
++    #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
++    /// The implementation supports the Robust Mutex Priority Protection option.
++    _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
++    /// The implementation supports thread-safe functions.
++    _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Thread Sporadic Server option.
++    _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
++    /// The implementation supports threads.
++    _POSIX_THREADS = libc::_SC_THREADS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports timeouts.
++    _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
++    /// The implementation supports timers.
++    _POSIX_TIMERS = libc::_SC_TIMERS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Trace option.
++    _POSIX_TRACE = libc::_SC_TRACE,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Trace Event Filter option.
++    _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Trace Inherit option.
++    _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Trace Log option.
++    _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
++    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the Typed Memory Objects option.
++    _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
++    /// Integer value indicating version of this standard (C-language binding)
++    /// to which the implementation conforms. For implementations conforming to
++    /// POSIX.1-2008, the value shall be 200809L.
++    _POSIX_VERSION = libc::_SC_VERSION,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation provides a C-language compilation environment with
++    /// 32-bit `int`, `long`, `pointer`, and `off_t` types.
++    _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation provides a C-language compilation environment with
++    /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
++    /// least 64 bits.
++    _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation provides a C-language compilation environment with
++    /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
++    _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation provides a C-language compilation environment with an
++    /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
++    /// using at least 64 bits.
++    _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
++    /// The implementation supports the C-Language Binding option.
++    _POSIX2_C_BIND = libc::_SC_2_C_BIND,
++    /// The implementation supports the C-Language Development Utilities option.
++    _POSIX2_C_DEV = libc::_SC_2_C_DEV,
++    /// The implementation supports the Terminal Characteristics option.
++    _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
++    /// The implementation supports the FORTRAN Development Utilities option.
++    _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
++    /// The implementation supports the FORTRAN Runtime Utilities option.
++    _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
++    /// The implementation supports the creation of locales by the localedef
++    /// utility.
++    _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Batch Environment Services and Utilities
++    /// option.
++    _POSIX2_PBS = libc::_SC_2_PBS,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Batch Accounting option.
++    _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Batch Checkpoint/Restart option.
++    _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Locate Batch Job Request option.
++    _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Batch Job Message Request option.
++    _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    /// The implementation supports the Track Batch Job Request option.
++    _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
++    /// The implementation supports the Software Development Utilities option.
++    _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
++    /// The implementation supports the User Portability Utilities option.
++    _POSIX2_UPE = libc::_SC_2_UPE,
++    /// Integer value indicating version of the Shell and Utilities volume of
++    /// POSIX.1 to which the implementation conforms.
++    _POSIX2_VERSION = libc::_SC_2_VERSION,
++    /// The size of a system page in bytes.
++    ///
++    /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
++    /// enum constants to have the same value, so nix omits `PAGESIZE`.
++    PAGE_SIZE = libc::_SC_PAGE_SIZE,
++    PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
++    PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
++    PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
++    PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
++    RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    RTSIG_MAX = libc::_SC_RTSIG_MAX,
++    SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
++    #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os = "openbsd"))]
++    SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
++    STREAM_MAX = libc::_SC_STREAM_MAX,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="netbsd",
++              target_os="openbsd"))]
++    SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
++    TIMER_MAX = libc::_SC_TIMER_MAX,
++    TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
++    TZNAME_MAX = libc::_SC_TZNAME_MAX,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The implementation supports the X/Open Encryption Option Group.
++    _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The implementation supports the Issue 4, Version 2 Enhanced
++    /// Internationalization Option Group.
++    _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The implementation supports the X/Open Realtime Option Group.
++    _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The implementation supports the X/Open Realtime Threads Option Group.
++    _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
++    /// The implementation supports the Issue 4, Version 2 Shared Memory Option
++    /// Group.
++    _XOPEN_SHM = libc::_SC_XOPEN_SHM,
++    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
++              target_os="linux", target_os = "macos", target_os="openbsd"))]
++    /// The implementation supports the XSI STREAMS Option Group.
++    _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// The implementation supports the XSI option
++    _XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
++    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
++              target_os = "ios", target_os="linux", target_os = "macos",
++              target_os="openbsd"))]
++    /// Integer value indicating version of the X/Open Portability Guide to
++    /// which the implementation conforms.
++    _XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
++}
++
++/// Get configurable system variables (see
++/// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
++///
++/// Returns the value of a configurable system variable.  Most supported
++/// variables also have associated compile-time constants, but POSIX
++/// allows their values to change at runtime.  There are generally two types of
++/// sysconf variables: options and limits.  See sysconf(3) for more details.
++///
++/// # Returns
++///
++/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
++///     implementation level (for option variables).  Implementation levels are
++///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
++/// - `Ok(None)`: the variable has no limit (for limit variables) or is
++///     unsupported (for option variables)
++/// - `Err(x)`: an error occurred
++pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
++    let raw = unsafe {
++        Errno::clear();
++        libc::sysconf(var as c_int)
++    };
++    if raw == -1 {
++        if errno::errno() == 0 {
++            Ok(None)
++        } else {
++            Err(Error::Sys(Errno::last()))
++        }
++    } else {
++        Ok(Some(raw))
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod pivot_root {
++    use libc;
++    use {Result, NixPath};
++    use errno::Errno;
++
++    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
++            new_root: &P1, put_old: &P2) -> Result<()> {
++        let res = new_root.with_nix_path(|new_root| {
++            put_old.with_nix_path(|put_old| {
++                unsafe {
++                    libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr())
++                }
++            })
++        })??;
++
++        Errno::result(res).map(drop)
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "freebsd",
++          target_os = "linux", target_os = "openbsd"))]
++mod setres {
++    use libc;
++    use Result;
++    use errno::Errno;
++    use super::{Uid, Gid};
++
++    /// Sets the real, effective, and saved uid.
++    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
++    ///
++    /// * `ruid`: real user id
++    /// * `euid`: effective user id
++    /// * `suid`: saved user id
++    /// * returns: Ok or libc error code.
++    ///
++    /// Err is returned if the user doesn't have permission to set this UID.
++    #[inline]
++    pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
++        let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
++
++        Errno::result(res).map(drop)
++    }
++
++    /// Sets the real, effective, and saved gid.
++    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
++    ///
++    /// * `rgid`: real group id
++    /// * `egid`: effective group id
++    /// * `sgid`: saved group id
++    /// * returns: Ok or libc error code.
++    ///
++    /// Err is returned if the user doesn't have permission to set this GID.
++    #[inline]
++    pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
++        let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
++
++        Errno::result(res).map(drop)
++    }
++}
++
++libc_bitflags!{
++    /// Options for access()
++    pub struct AccessFlags : c_int {
++        /// Test for existence of file.
++        F_OK;
++        /// Test for read permission.
++        R_OK;
++        /// Test for write permission.
++        W_OK;
++        /// Test for execute (search) permission.
++        X_OK;
++    }
++}
++
++/// 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)
++pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
++    let res = path.with_nix_path(|cstr| {
++        unsafe {
++            libc::access(cstr.as_ptr(), amode.bits)
++        }
++    })?;
++    Errno::result(res).map(drop)
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/mod.rs b/third_party/rust/nix-0.15.0/test/sys/mod.rs
+new file mode 100644
+index 0000000000000..60a58dd106f19
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/mod.rs
+@@ -0,0 +1,38 @@
++mod test_signal;
++
++// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of
++// this writing. There is an user-level implementation, but whether aio
++// works or not heavily depends on which pthread implementation is chosen
++// by the user at link time. For this reason we do not want to run aio test
++// cases on DragonFly.
++#[cfg(any(target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd"))]
++mod test_aio;
++#[cfg(target_os = "linux")]
++mod test_signalfd;
++mod test_socket;
++mod test_sockopt;
++mod test_select;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod test_sysinfo;
++mod test_termios;
++mod test_ioctl;
++mod test_wait;
++mod test_uio;
++
++#[cfg(target_os = "linux")]
++mod test_epoll;
++#[cfg(target_os = "linux")]
++mod test_inotify;
++mod test_pthread;
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++mod test_ptrace;
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_aio.rs b/third_party/rust/nix-0.15.0/test/sys/test_aio.rs
+new file mode 100644
+index 0000000000000..d4b09b0b81905
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_aio.rs
+@@ -0,0 +1,654 @@
++use bytes::{Bytes, BytesMut};
++use libc::{c_int, c_void};
++use nix::{Error, Result};
++use nix::errno::*;
++use nix::sys::aio::*;
++use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet};
++use nix::sys::time::{TimeSpec, TimeValLike};
++use std::io::{Write, Read, Seek, SeekFrom};
++use std::ops::Deref;
++use std::os::unix::io::AsRawFd;
++use std::sync::atomic::{AtomicBool, Ordering};
++use std::{thread, time};
++use tempfile::tempfile;
++
++// Helper that polls an AioCb for completion or error
++fn poll_aio(aiocb: &mut AioCb) -> Result<()> {
++    loop {
++        let err = aiocb.error();
++        if err != Err(Error::from(Errno::EINPROGRESS)) { return err; };
++        thread::sleep(time::Duration::from_millis(10));
++    }
++}
++
++#[test]
++fn test_accessors() {
++    let mut rbuf = vec![0; 4];
++    let aiocb = AioCb::from_mut_slice( 1001,
++                           2,   //offset
++                           &mut rbuf,
++                           42,   //priority
++                           SigevNotify::SigevSignal {
++                               signal: Signal::SIGUSR2,
++                               si_value: 99
++                           },
++                           LioOpcode::LIO_NOP);
++    assert_eq!(1001, aiocb.fd());
++    assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode());
++    assert_eq!(4, aiocb.nbytes());
++    assert_eq!(2, aiocb.offset());
++    assert_eq!(42, aiocb.priority());
++    let sev = aiocb.sigevent().sigevent();
++    assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo);
++    assert_eq!(99, sev.sigev_value.sival_ptr as i64);
++}
++
++// Tests AioCb.cancel.  We aren't trying to test the OS's implementation, only
++// our bindings.  So it's sufficient to check that AioCb.cancel returned any
++// AioCancelStat value.
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_cancel() {
++    let wbuf: &[u8] = b"CDEF";
++
++    let f = tempfile().unwrap();
++    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++                            0,   //offset
++                            wbuf,
++                            0,   //priority
++                            SigevNotify::SigevNone,
++                            LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++    let err = aiocb.error();
++    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
++
++    let cancelstat = aiocb.cancel();
++    assert!(cancelstat.is_ok());
++
++    // Wait for aiocb to complete, but don't care whether it succeeded
++    let _ = poll_aio(&mut aiocb);
++    let _ = aiocb.aio_return();
++}
++
++// Tests using aio_cancel_all for all outstanding IOs.
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_aio_cancel_all() {
++    let wbuf: &[u8] = b"CDEF";
++
++    let f = tempfile().unwrap();
++    let mut aiocb = AioCb::from_slice(f.as_raw_fd(),
++                            0,   //offset
++                            wbuf,
++                            0,   //priority
++                            SigevNotify::SigevNone,
++                            LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++    let err = aiocb.error();
++    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
++
++    let cancelstat = aio_cancel_all(f.as_raw_fd());
++    assert!(cancelstat.is_ok());
++
++    // Wait for aiocb to complete, but don't care whether it succeeded
++    let _ = poll_aio(&mut aiocb);
++    let _ = aiocb.aio_return();
++}
++
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_fsync() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
++                            0,   //priority
++                            SigevNotify::SigevNone);
++    let err = aiocb.fsync(AioFsyncMode::O_SYNC);
++    assert!(err.is_ok());
++    poll_aio(&mut aiocb).unwrap();
++    aiocb.aio_return().unwrap();
++}
++
++/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns
++/// an error
++// Skip on Linux, because Linux's AIO implementation can't detect errors
++// synchronously
++#[test]
++#[cfg(any(target_os = "freebsd", target_os = "macos"))]
++fn test_fsync_error() {
++    use std::mem;
++
++    const INITIAL: &[u8] = b"abcdef123456";
++    // Create an invalid AioFsyncMode
++    let mode = unsafe { mem::transmute(666) };
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
++                            0,   //priority
++                            SigevNotify::SigevNone);
++    let err = aiocb.fsync(mode);
++    assert!(err.is_err());
++}
++
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_aio_suspend() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    const WBUF: &[u8] = b"CDEFG";
++    let timeout = TimeSpec::seconds(10);
++    let mut rbuf = vec![0; 4];
++    let rlen = rbuf.len();
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++
++    let mut wcb = AioCb::from_slice( f.as_raw_fd(),
++                           2,   //offset
++                           WBUF,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_WRITE);
++
++    let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
++                            8,   //offset
++                            &mut rbuf,
++                            0,   //priority
++                            SigevNotify::SigevNone,
++                            LioOpcode::LIO_READ);
++    wcb.write().unwrap();
++    rcb.read().unwrap();
++    loop {
++        {
++            let cbbuf = [&wcb, &rcb];
++            assert!(aio_suspend(&cbbuf[..], Some(timeout)).is_ok());
++        }
++        if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
++           wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
++            break
++        }
++    }
++
++    assert!(wcb.aio_return().unwrap() as usize == WBUF.len());
++    assert!(rcb.aio_return().unwrap() as usize == rlen);
++}
++
++// Test a simple aio operation with no completion notification.  We must poll
++// for completion
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_read() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let mut rbuf = vec![0; 4];
++    const EXPECT: &[u8] = b"cdef";
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    {
++        let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
++                               2,   //offset
++                               &mut rbuf,
++                               0,   //priority
++                               SigevNotify::SigevNone,
++                               LioOpcode::LIO_NOP);
++        aiocb.read().unwrap();
++
++        let err = poll_aio(&mut aiocb);
++        assert!(err == Ok(()));
++        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++    }
++
++    assert!(EXPECT == rbuf.deref().deref());
++}
++
++/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
++/// returns an error
++// Skip on Linux, because Linux's AIO implementation can't detect errors
++// synchronously
++#[test]
++#[cfg(any(target_os = "freebsd", target_os = "macos"))]
++fn test_read_error() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let mut rbuf = vec![0; 4];
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
++                           -1,   //an invalid offset
++                           &mut rbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    assert!(aiocb.read().is_err());
++}
++
++// Tests from_mut_slice
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_read_into_mut_slice() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let mut rbuf = vec![0; 4];
++    const EXPECT: &[u8] = b"cdef";
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    {
++        let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
++                               2,   //offset
++                               &mut rbuf,
++                               0,   //priority
++                               SigevNotify::SigevNone,
++                               LioOpcode::LIO_NOP);
++        aiocb.read().unwrap();
++
++        let err = poll_aio(&mut aiocb);
++        assert!(err == Ok(()));
++        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++    }
++
++    assert!(rbuf == EXPECT);
++}
++
++// Tests from_ptr
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_read_into_pointer() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let mut rbuf = vec![0; 4];
++    const EXPECT: &[u8] = b"cdef";
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    {
++        // Safety: ok because rbuf lives until after poll_aio
++        let mut aiocb = unsafe {
++            AioCb::from_mut_ptr( f.as_raw_fd(),
++                                 2,   //offset
++                                 rbuf.as_mut_ptr() as *mut c_void,
++                                 rbuf.len(),
++                                 0,   //priority
++                                 SigevNotify::SigevNone,
++                                 LioOpcode::LIO_NOP)
++        };
++        aiocb.read().unwrap();
++
++        let err = poll_aio(&mut aiocb);
++        assert!(err == Ok(()));
++        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++    }
++
++    assert!(rbuf == EXPECT);
++}
++
++// Test reading into an immutable buffer.  It should fail
++// FIXME: This test fails to panic on Linux/musl
++#[test]
++#[should_panic(expected = "Can't read into an immutable buffer")]
++#[cfg_attr(target_env = "musl", ignore)]
++fn test_read_immutable_buffer() {
++    let rbuf: &[u8] = b"CDEF";
++    let f = tempfile().unwrap();
++    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++                           2,   //offset
++                           rbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    aiocb.read().unwrap();
++}
++
++
++// Test a simple aio operation with no completion notification.  We must poll
++// for completion.  Unlike test_aio_read, this test uses AioCb::from_slice
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_write() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let wbuf = "CDEF".to_string().into_bytes();
++    let mut rbuf = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++                           2,   //offset
++                           &wbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++
++    let err = poll_aio(&mut aiocb);
++    assert!(err == Ok(()));
++    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf == EXPECT);
++}
++
++// Tests `AioCb::from_boxed_slice` with `Bytes`
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_write_bytes() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
++    let mut rbuf = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++    let expected_len = wbuf.len();
++
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
++                           2,   //offset
++                           wbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++
++    let err = poll_aio(&mut aiocb);
++    assert!(err == Ok(()));
++    assert!(aiocb.aio_return().unwrap() as usize == expected_len);
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf == EXPECT);
++}
++
++// Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_read_bytes_mut_small() {
++    const INITIAL: &[u8] = b"abcdef";
++    let rbuf = Box::new(BytesMut::from(vec![0; 4]));
++    const EXPECT: &[u8] = b"cdef";
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++
++    let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
++                           2,   //offset
++                           rbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    aiocb.read().unwrap();
++
++    let err = poll_aio(&mut aiocb);
++    assert_eq!(err, Ok(()));
++    assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
++    let buffer = aiocb.boxed_mut_slice().unwrap();
++    assert_eq!(buffer.borrow(), EXPECT);
++}
++
++// Tests `AioCb::from_ptr`
++#[test]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_write_from_pointer() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    let wbuf = "CDEF".to_string().into_bytes();
++    let mut rbuf = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    // Safety: ok because aiocb outlives poll_aio
++    let mut aiocb = unsafe {
++        AioCb::from_ptr( f.as_raw_fd(),
++                         2,   //offset
++                         wbuf.as_ptr() as *const c_void,
++                         wbuf.len(),
++                         0,   //priority
++                         SigevNotify::SigevNone,
++                         LioOpcode::LIO_NOP)
++    };
++    aiocb.write().unwrap();
++
++    let err = poll_aio(&mut aiocb);
++    assert!(err == Ok(()));
++    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf == EXPECT);
++}
++
++/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
++/// returns an error
++// Skip on Linux, because Linux's AIO implementation can't detect errors
++// synchronously
++#[test]
++#[cfg(any(target_os = "freebsd", target_os = "macos"))]
++fn test_write_error() {
++    let wbuf = "CDEF".to_string().into_bytes();
++    let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor
++                           0,   //offset
++                           &wbuf,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    assert!(aiocb.write().is_err());
++}
++
++lazy_static! {
++    pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
++}
++
++extern fn sigfunc(_: c_int) {
++    SIGNALED.store(true, Ordering::Relaxed);
++}
++
++// Test an aio operation with completion delivered by a signal
++// FIXME: This test is ignored on mips because of failures in qemu in CI
++#[test]
++#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
++fn test_write_sigev_signal() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let sa = SigAction::new(SigHandler::Handler(sigfunc),
++                            SaFlags::SA_RESETHAND,
++                            SigSet::empty());
++    SIGNALED.store(false, Ordering::Relaxed);
++    unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
++
++    const INITIAL: &[u8] = b"abcdef123456";
++    const WBUF: &[u8] = b"CDEF";
++    let mut rbuf = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++
++    let mut f = tempfile().unwrap();
++    f.write_all(INITIAL).unwrap();
++    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++                           2,   //offset
++                           WBUF,
++                           0,   //priority
++                           SigevNotify::SigevSignal {
++                               signal: Signal::SIGUSR2,
++                               si_value: 0  //TODO: validate in sigfunc
++                           },
++                           LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++    while !SIGNALED.load(Ordering::Relaxed) {
++        thread::sleep(time::Duration::from_millis(10));
++    }
++
++    assert!(aiocb.aio_return().unwrap() as usize == WBUF.len());
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf == EXPECT);
++}
++
++// Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
++// time listio returns.
++#[test]
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_liocb_listio_wait() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    const WBUF: &[u8] = b"CDEF";
++    let mut rbuf = vec![0; 4];
++    let rlen = rbuf.len();
++    let mut rbuf2 = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++    let mut f = tempfile().unwrap();
++
++    f.write_all(INITIAL).unwrap();
++
++    {
++        let wcb = AioCb::from_slice( f.as_raw_fd(),
++                               2,   //offset
++                               WBUF,
++                               0,   //priority
++                               SigevNotify::SigevNone,
++                               LioOpcode::LIO_WRITE);
++
++        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
++                                8,   //offset
++                                &mut rbuf,
++                                0,   //priority
++                                SigevNotify::SigevNone,
++                                LioOpcode::LIO_READ);
++        let mut liocb = LioCb::with_capacity(2);
++        liocb.aiocbs.push(wcb);
++        liocb.aiocbs.push(rcb);
++        let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
++        err.expect("lio_listio");
++
++        assert!(liocb.aio_return(0).unwrap() as usize == WBUF.len());
++        assert!(liocb.aio_return(1).unwrap() as usize == rlen);
++    }
++    assert!(rbuf.deref().deref() == b"3456");
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf2).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf2 == EXPECT);
++}
++
++// Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
++// mechanism to check for the individual AioCb's completion.
++#[test]
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++fn test_liocb_listio_nowait() {
++    const INITIAL: &[u8] = b"abcdef123456";
++    const WBUF: &[u8] = b"CDEF";
++    let mut rbuf = vec![0; 4];
++    let rlen = rbuf.len();
++    let mut rbuf2 = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++    let mut f = tempfile().unwrap();
++
++    f.write_all(INITIAL).unwrap();
++
++    {
++        let wcb = AioCb::from_slice( f.as_raw_fd(),
++                               2,   //offset
++                               WBUF,
++                               0,   //priority
++                               SigevNotify::SigevNone,
++                               LioOpcode::LIO_WRITE);
++
++        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
++                                8,   //offset
++                                &mut rbuf,
++                                0,   //priority
++                                SigevNotify::SigevNone,
++                                LioOpcode::LIO_READ);
++        let mut liocb = LioCb::with_capacity(2);
++        liocb.aiocbs.push(wcb);
++        liocb.aiocbs.push(rcb);
++        let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
++        err.expect("lio_listio");
++
++        poll_aio(&mut liocb.aiocbs[0]).unwrap();
++        poll_aio(&mut liocb.aiocbs[1]).unwrap();
++        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
++        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
++    }
++    assert!(rbuf.deref().deref() == b"3456");
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf2).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf2 == EXPECT);
++}
++
++// Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
++// AioCb's are complete.
++// FIXME: This test is ignored on mips/mips64 because of failures in qemu in CI.
++#[test]
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
++fn test_liocb_listio_signal() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    const INITIAL: &[u8] = b"abcdef123456";
++    const WBUF: &[u8] = b"CDEF";
++    let mut rbuf = vec![0; 4];
++    let rlen = rbuf.len();
++    let mut rbuf2 = Vec::new();
++    const EXPECT: &[u8] = b"abCDEF123456";
++    let mut f = tempfile().unwrap();
++    let sa = SigAction::new(SigHandler::Handler(sigfunc),
++                            SaFlags::SA_RESETHAND,
++                            SigSet::empty());
++    let sigev_notify = SigevNotify::SigevSignal { signal: Signal::SIGUSR2,
++                                                  si_value: 0 };
++
++    f.write_all(INITIAL).unwrap();
++
++    {
++        let wcb = AioCb::from_slice( f.as_raw_fd(),
++                               2,   //offset
++                               WBUF,
++                               0,   //priority
++                               SigevNotify::SigevNone,
++                               LioOpcode::LIO_WRITE);
++
++        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
++                                8,   //offset
++                                &mut rbuf,
++                                0,   //priority
++                                SigevNotify::SigevNone,
++                                LioOpcode::LIO_READ);
++        let mut liocb = LioCb::with_capacity(2);
++        liocb.aiocbs.push(wcb);
++        liocb.aiocbs.push(rcb);
++        SIGNALED.store(false, Ordering::Relaxed);
++        unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
++        let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify);
++        err.expect("lio_listio");
++        while !SIGNALED.load(Ordering::Relaxed) {
++            thread::sleep(time::Duration::from_millis(10));
++        }
++
++        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
++        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
++    }
++    assert!(rbuf.deref().deref() == b"3456");
++
++    f.seek(SeekFrom::Start(0)).unwrap();
++    let len = f.read_to_end(&mut rbuf2).unwrap();
++    assert!(len == EXPECT.len());
++    assert!(rbuf2 == EXPECT);
++}
++
++// Try to use LioCb::listio to read into an immutable buffer.  It should fail
++// FIXME: This test fails to panic on Linux/musl
++#[test]
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[should_panic(expected = "Can't read into an immutable buffer")]
++#[cfg_attr(target_env = "musl", ignore)]
++fn test_liocb_listio_read_immutable() {
++    let rbuf: &[u8] = b"abcd";
++    let f = tempfile().unwrap();
++
++
++    let mut liocb = LioCb::from(vec![
++        AioCb::from_slice( f.as_raw_fd(),
++            2,   //offset
++            rbuf,
++            0,   //priority
++            SigevNotify::SigevNone,
++            LioOpcode::LIO_READ)
++    ]);
++    let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs b/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
+new file mode 100644
+index 0000000000000..492da401ef726
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
+@@ -0,0 +1,32 @@
++extern crate nix;
++extern crate tempfile;
++
++// Test dropping an AioCb that hasn't yet finished.
++// This must happen in its own process, because on OSX this test seems to hose
++// the AIO subsystem and causes subsequent tests to fail
++#[test]
++#[should_panic(expected = "Dropped an in-progress AioCb")]
++#[cfg(all(not(target_env = "musl"),
++          any(target_os = "linux",
++              target_os = "ios",
++              target_os = "macos",
++              target_os = "freebsd",
++              target_os = "netbsd")))]
++fn test_drop() {
++    use nix::sys::aio::*;
++    use nix::sys::signal::*;
++    use std::os::unix::io::AsRawFd;
++    use tempfile::tempfile;
++
++    const WBUF: &[u8] = b"CDEF";
++
++    let f = tempfile().unwrap();
++    f.set_len(6).unwrap();
++    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
++                           2,   //offset
++                           WBUF,
++                           0,   //priority
++                           SigevNotify::SigevNone,
++                           LioOpcode::LIO_NOP);
++    aiocb.write().unwrap();
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs b/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
+new file mode 100644
+index 0000000000000..e0dc5131defe0
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
+@@ -0,0 +1,24 @@
++use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent};
++use nix::sys::epoll::{epoll_create1, epoll_ctl};
++use nix::Error;
++use nix::errno::Errno;
++
++#[test]
++pub fn test_epoll_errno() {
++    let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
++    let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
++    assert!(result.is_err());
++    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
++
++    let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
++    assert!(result.is_err());
++    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
++}
++
++#[test]
++pub fn test_epoll_ctl() {
++    let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
++    let mut event = EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1);
++    epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap();
++    epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap();
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs b/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
+new file mode 100644
+index 0000000000000..a8ead46d487ba
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
+@@ -0,0 +1,65 @@
++use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
++use nix::Error;
++use nix::errno::Errno;
++use tempfile;
++use std::ffi::OsString;
++use std::fs::{rename, File};
++
++#[test]
++pub fn test_inotify() {
++    let instance = Inotify::init(InitFlags::IN_NONBLOCK)
++        .unwrap();
++    let tempdir = tempfile::tempdir().unwrap();
++
++    instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
++
++    let events = instance.read_events();
++    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
++
++    File::create(tempdir.path().join("test")).unwrap();
++
++    let events = instance.read_events().unwrap();
++    assert_eq!(events[0].name, Some(OsString::from("test")));
++}
++
++#[test]
++pub fn test_inotify_multi_events() {
++    let instance = Inotify::init(InitFlags::IN_NONBLOCK)
++        .unwrap();
++    let tempdir = tempfile::tempdir().unwrap();
++
++    instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
++
++    let events = instance.read_events();
++    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
++
++    File::create(tempdir.path().join("test")).unwrap();
++    rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
++
++    // Now there should be 5 events in queue:
++    //   - IN_CREATE on test
++    //   - IN_OPEN on test
++    //   - IN_CLOSE_WRITE on test
++    //   - IN_MOVED_FROM on test with a cookie
++    //   - IN_MOVED_TO on test2 with the same cookie
++
++    let events = instance.read_events().unwrap();
++    assert_eq!(events.len(), 5);
++
++    assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE);
++    assert_eq!(events[0].name, Some(OsString::from("test")));
++
++    assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN);
++    assert_eq!(events[1].name, Some(OsString::from("test")));
++
++    assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE);
++    assert_eq!(events[2].name, Some(OsString::from("test")));
++
++    assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM);
++    assert_eq!(events[3].name, Some(OsString::from("test")));
++
++    assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO);
++    assert_eq!(events[4].name, Some(OsString::from("test2")));
++
++    assert_eq!(events[3].cookie, events[4].cookie);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs b/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
+new file mode 100644
+index 0000000000000..0a439b3346f53
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
+@@ -0,0 +1,334 @@
++#![allow(dead_code)]
++
++// Simple tests to ensure macro generated fns compile
++ioctl_none_bad!(do_bad, 0x1234);
++ioctl_read_bad!(do_bad_read, 0x1234, u16);
++ioctl_write_int_bad!(do_bad_write_int, 0x1234);
++ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
++ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
++ioctl_none!(do_none, 0, 0);
++ioctl_read!(read_test, 0, 0, u32);
++ioctl_write_int!(write_ptr_int, 0, 0);
++ioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
++ioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
++ioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
++ioctl_readwrite!(readwrite_test, 0, 0, u64);
++ioctl_read_buf!(readbuf_test, 0, 0, u32);
++const SPI_IOC_MAGIC: u8 = b'k';
++const SPI_IOC_MESSAGE: u8 = 0;
++ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
++ioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
++ioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
++ioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
++ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
++
++// See C code for source of values for op calculations (does NOT work for mips/powerpc):
++// https://gist.github.com/posborne/83ea6880770a1aef332e
++//
++// TODO:  Need a way to compute these constants at test time.  Using precomputed
++// values is fragile and needs to be maintained.
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++mod linux {
++    #[test]
++    fn test_op_none() {
++        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
++            assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
++            assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
++        } else {
++            assert_eq!(request_code_none!(b'q', 10), 0x0000_710A);
++            assert_eq!(request_code_none!(b'a', 255), 0x0000_61FF);
++        }
++    }
++
++    #[test]
++    fn test_op_write() {
++        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
++            assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
++        } else {
++            assert_eq!(request_code_write!(b'z', 10, 1), 0x4001_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 512), 0x4200_7A0A);
++        }
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_write_64() {
++        if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
++            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
++        } else {
++            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
++        }
++
++    }
++
++    #[test]
++    fn test_op_read() {
++        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
++            assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
++        } else {
++            assert_eq!(request_code_read!(b'z', 10, 1), 0x8001_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 512), 0x8200_7A0A);
++        }
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_read_64() {
++        if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
++            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
++        } else {
++            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
++        }
++    }
++
++    #[test]
++    fn test_op_read_write() {
++        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
++        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_read_write_64() {
++        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
++    }
++}
++
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
++mod bsd {
++    #[test]
++    fn test_op_none() {
++        assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
++        assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
++    }
++
++    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
++    #[test]
++    fn test_op_write_int() {
++        assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
++        assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
++    }
++
++    #[test]
++    fn test_op_write() {
++        assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
++        assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_write_64() {
++        assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
++    }
++
++    #[test]
++    fn test_op_read() {
++        assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
++        assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_read_64() {
++        assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
++    }
++
++    #[test]
++    fn test_op_read_write() {
++        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
++        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
++    }
++
++    #[cfg(target_pointer_width = "64")]
++    #[test]
++    fn test_op_read_write_64() {
++        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod linux_ioctls {
++    use std::mem;
++    use std::os::unix::io::AsRawFd;
++
++    use tempfile::tempfile;
++    use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
++
++    use nix::Error::Sys;
++    use nix::errno::Errno::{ENOTTY, ENOSYS};
++
++    ioctl_none_bad!(tiocnxcl, TIOCNXCL);
++    #[test]
++    fn test_ioctl_none_bad() {
++        let file = tempfile().unwrap();
++        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    ioctl_read_bad!(tcgets, TCGETS, termios);
++    #[test]
++    fn test_ioctl_read_bad() {
++        let file = tempfile().unwrap();
++        let mut termios = unsafe { mem::uninitialized() };
++        let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    ioctl_write_int_bad!(tcsbrk, TCSBRK);
++    #[test]
++    fn test_ioctl_write_int_bad() {
++        let file = tempfile().unwrap();
++        let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
++    #[test]
++    fn test_ioctl_write_ptr_bad() {
++        let file = tempfile().unwrap();
++        let termios: termios = unsafe { mem::uninitialized() };
++        let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    // FIXME: Find a suitable example for `ioctl_readwrite_bad`
++
++    // From linux/videodev2.h
++    ioctl_none!(log_status, b'V', 70);
++    #[test]
++    fn test_ioctl_none() {
++        let file = tempfile().unwrap();
++        let res = unsafe { log_status(file.as_raw_fd()) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    #[repr(C)]
++    pub struct v4l2_audio {
++        index: u32,
++        name: [u8; 32],
++        capability: u32,
++        mode: u32,
++        reserved: [u32; 2],
++    }
++
++    // From linux/videodev2.h
++    ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
++    #[test]
++    fn test_ioctl_write_ptr() {
++        let file = tempfile().unwrap();
++        let data: v4l2_audio = unsafe { mem::zeroed() };
++        let res = unsafe { s_audio(file.as_raw_fd(), &data) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    // From linux/net/bluetooth/hci_sock.h
++    const HCI_IOC_MAGIC: u8 = b'H';
++    const HCI_IOC_HCIDEVUP: u8 = 201;
++    ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
++    #[test]
++    fn test_ioctl_write_int() {
++        let file = tempfile().unwrap();
++        let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    // From linux/videodev2.h
++    ioctl_read!(g_audio, b'V', 33, v4l2_audio);
++    #[test]
++    fn test_ioctl_read() {
++        let file = tempfile().unwrap();
++        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
++        let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    // From linux/videodev2.h
++    ioctl_readwrite!(enum_audio,  b'V', 65, v4l2_audio);
++    #[test]
++    fn test_ioctl_readwrite() {
++        let file = tempfile().unwrap();
++        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
++        let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    // FIXME: Find a suitable example for `ioctl_read_buf`.
++
++    #[repr(C)]
++    pub struct spi_ioc_transfer {
++        tx_buf: u64,
++        rx_buf: u64,
++        len: u32,
++        speed_hz: u32,
++        delay_usecs: u16,
++        bits_per_word: u8,
++        cs_change: u8,
++        tx_nbits: u8,
++        rx_nbits: u8,
++        pad: u16,
++    }
++
++    // From linux/spi/spidev.h
++    ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer);
++    #[test]
++    fn test_ioctl_write_buf() {
++        let file = tempfile().unwrap();
++        let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
++        let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
++        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
++    }
++
++    // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
++}
++
++#[cfg(target_os = "freebsd")]
++mod freebsd_ioctls {
++    use std::mem;
++    use std::os::unix::io::AsRawFd;
++
++    use tempfile::tempfile;
++    use libc::termios;
++
++    use nix::Error::Sys;
++    use nix::errno::Errno::ENOTTY;
++
++    // From sys/sys/ttycom.h
++    const TTY_IOC_MAGIC: u8 = b't';
++    const TTY_IOC_TYPE_NXCL: u8 = 14;
++    const TTY_IOC_TYPE_GETA: u8 = 19;
++    const TTY_IOC_TYPE_SETA: u8 = 20;
++
++    ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
++    #[test]
++    fn test_ioctl_none() {
++        let file = tempfile().unwrap();
++        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
++    #[test]
++    fn test_ioctl_read() {
++        let file = tempfile().unwrap();
++        let mut termios = unsafe { mem::uninitialized() };
++        let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++
++    ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
++    #[test]
++    fn test_ioctl_write_ptr() {
++        let file = tempfile().unwrap();
++        let termios: termios = unsafe { mem::uninitialized() };
++        let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
++        assert_eq!(res, Err(Sys(ENOTTY)));
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs b/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
+new file mode 100644
+index 0000000000000..19ee3facf87d7
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
+@@ -0,0 +1,111 @@
++// vim: tw=80
++
++// Annoyingly, Cargo is unable to conditionally build an entire test binary.  So
++// we must disable the test here rather than in Cargo.toml
++#![cfg(target_os = "freebsd")]
++
++extern crate nix;
++extern crate sysctl;
++extern crate tempfile;
++
++use nix::Error;
++use nix::errno::*;
++use nix::libc::off_t;
++use nix::sys::aio::*;
++use nix::sys::signal::SigevNotify;
++use nix::unistd::{SysconfVar, sysconf};
++use std::os::unix::io::AsRawFd;
++use std::{thread, time};
++use sysctl::CtlValue;
++use tempfile::tempfile;
++
++const BYTES_PER_OP: usize = 512;
++
++/// Attempt to collect final status for all of `liocb`'s operations, freeing
++/// system resources
++fn finish_liocb(liocb: &mut LioCb) {
++    for j in 0..liocb.aiocbs.len() {
++        loop {
++            let e = liocb.error(j);
++            match e {
++                Ok(()) => break,
++                Err(Error::Sys(Errno::EINPROGRESS)) =>
++                    thread::sleep(time::Duration::from_millis(10)),
++                Err(x) => panic!("aio_error({:?})", x)
++            }
++        }
++        assert_eq!(liocb.aio_return(j).unwrap(), BYTES_PER_OP as isize);
++    }
++}
++
++// Deliberately exceed system resource limits, causing lio_listio to return EIO.
++// This test must run in its own process since it deliberately uses all AIO
++// resources.  ATM it is only enabled on FreeBSD, because I don't know how to
++// check system AIO limits on other operating systems.
++#[test]
++fn test_lio_listio_resubmit() {
++    let mut resubmit_count = 0;
++
++    // Lookup system resource limits
++    let alm = sysconf(SysconfVar::AIO_LISTIO_MAX)
++        .expect("sysconf").unwrap() as usize;
++    let maqpp = if let CtlValue::Int(x) = sysctl::value(
++            "vfs.aio.max_aio_queue_per_proc").unwrap(){
++        x as usize
++    } else {
++        panic!("unknown sysctl");
++    };
++
++    // Find lio_listio sizes that satisfy the AIO_LISTIO_MAX constraint and also
++    // result in a final lio_listio call that can only partially be queued
++    let target_ops = maqpp + alm / 2;
++    let num_listios = (target_ops + alm - 3) / (alm - 2);
++    let ops_per_listio = (target_ops + num_listios - 1) / num_listios;
++    assert!((num_listios - 1) * ops_per_listio < maqpp,
++        "the last lio_listio won't make any progress; fix the algorithm");
++    println!("Using {:?} LioCbs of {:?} operations apiece", num_listios,
++             ops_per_listio);
++
++    let f = tempfile().unwrap();
++    let buffer_set = (0..num_listios).map(|_| {
++        (0..ops_per_listio).map(|_| {
++            vec![0u8; BYTES_PER_OP]
++        }).collect::<Vec<_>>()
++    }).collect::<Vec<_>>();
++
++    let mut liocbs = (0..num_listios).map(|i| {
++        let mut liocb = LioCb::with_capacity(ops_per_listio);
++        for j in 0..ops_per_listio {
++            let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t;
++            let wcb = AioCb::from_slice( f.as_raw_fd(),
++                                   offset,
++                                   &buffer_set[i][j][..],
++                                   0,   //priority
++                                   SigevNotify::SigevNone,
++                                   LioOpcode::LIO_WRITE);
++            liocb.aiocbs.push(wcb);
++        }
++        let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
++        while err == Err(Error::Sys(Errno::EIO)) ||
++              err == Err(Error::Sys(Errno::EAGAIN)) ||
++              err == Err(Error::Sys(Errno::EINTR)) {
++            // 
++            thread::sleep(time::Duration::from_millis(10));
++            resubmit_count += 1;
++            err = liocb.listio_resubmit(LioMode::LIO_NOWAIT,
++                                        SigevNotify::SigevNone);
++        }
++        liocb
++    }).collect::<Vec<_>>();
++
++    // Ensure that every AioCb completed
++    for liocb in liocbs.iter_mut() {
++        finish_liocb(liocb);
++    }
++
++    if resubmit_count > 0 {
++        println!("Resubmitted {:?} times, test passed", resubmit_count);
++    } else {
++        println!("Never resubmitted.  Test ambiguous");
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs b/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
+new file mode 100644
+index 0000000000000..8928010087a13
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
+@@ -0,0 +1,15 @@
++use nix::sys::pthread::*;
++
++#[cfg(target_env = "musl")]
++#[test]
++fn test_pthread_self() {
++    let tid = pthread_self();
++    assert!(tid != ::std::ptr::null_mut());
++}
++
++#[cfg(not(target_env = "musl"))]
++#[test]
++fn test_pthread_self() {
++    let tid = pthread_self();
++    assert!(tid != 0);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs b/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
+new file mode 100644
+index 0000000000000..24d9b522ee4e5
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
+@@ -0,0 +1,107 @@
++use nix::Error;
++use nix::errno::Errno;
++use nix::unistd::getpid;
++use nix::sys::ptrace;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use nix::sys::ptrace::Options;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use std::mem;
++
++#[test]
++fn test_ptrace() {
++    // Just make sure ptrace can be called at all, for now.
++    // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
++    let err = ptrace::attach(getpid()).unwrap_err();
++    assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
++            err == Error::Sys(Errno::ENOSYS));
++}
++
++// Just make sure ptrace_setoptions can be called at all, for now.
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptrace_setoptions() {
++    let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
++    assert!(err != Error::UnsupportedOperation);
++}
++
++// Just make sure ptrace_getevent can be called at all, for now.
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptrace_getevent() {
++    let err = ptrace::getevent(getpid()).unwrap_err();
++    assert!(err != Error::UnsupportedOperation);
++}
++
++// Just make sure ptrace_getsiginfo can be called at all, for now.
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptrace_getsiginfo() {
++    if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
++        panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
++    }
++}
++
++// Just make sure ptrace_setsiginfo can be called at all, for now.
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptrace_setsiginfo() {
++    let siginfo = unsafe { mem::uninitialized() };
++    if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
++        panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
++    }
++}
++
++
++#[test]
++fn test_ptrace_cont() {
++    use nix::sys::ptrace;
++    use nix::sys::signal::{raise, Signal};
++    use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
++    use nix::unistd::fork;
++    use nix::unistd::ForkResult::*;
++
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // FIXME: qemu-user doesn't implement ptrace on all architectures
++    // and retunrs ENOSYS in this case.
++    // We (ab)use this behavior to detect the affected platforms
++    // and skip the test then.
++    // On valid platforms the ptrace call should return Errno::EPERM, this
++    // is already tested by `test_ptrace`.
++    let err = ptrace::attach(getpid()).unwrap_err();
++    if err == Error::Sys(Errno::ENOSYS) {
++        return;
++    }
++
++    match fork().expect("Error: Fork Failed") {
++        Child => {
++            ptrace::traceme().unwrap();
++            // As recommended by ptrace(2), raise SIGTRAP to pause the child
++            // until the parent is ready to continue
++            loop {
++                raise(Signal::SIGTRAP).unwrap();
++            }
++
++        },
++        Parent { child } => {
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
++            ptrace::cont(child, None).unwrap();
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
++            ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
++            match waitpid(child, None) {
++                Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
++                    // FIXME It's been observed on some systems (apple) the 
++                    // tracee may not be killed but remain as a zombie process
++                    // affecting other wait based tests. Add an extra kill just
++                    // to make sure there are no zombies.
++                    let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
++                    while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
++                        let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
++                    }
++                }
++                _ => panic!("The process should have been killed"),
++            }
++        },
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_select.rs b/third_party/rust/nix-0.15.0/test/sys/test_select.rs
+new file mode 100644
+index 0000000000000..cf68700c5e16f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_select.rs
+@@ -0,0 +1,54 @@
++use nix::sys::select::*;
++use nix::unistd::{pipe, write};
++use nix::sys::signal::SigSet;
++use nix::sys::time::{TimeSpec, TimeValLike};
++
++#[test]
++pub fn test_pselect() {
++    let _mtx = ::SIGNAL_MTX
++        .lock()
++        .expect("Mutex got poisoned by another test");
++
++    let (r1, w1) = pipe().unwrap();
++    write(w1, b"hi!").unwrap();
++    let (r2, _w2) = pipe().unwrap();
++
++    let mut fd_set = FdSet::new();
++    fd_set.insert(r1);
++    fd_set.insert(r2);
++
++    let timeout = TimeSpec::seconds(10);
++    let sigmask = SigSet::empty();
++    assert_eq!(
++        1,
++        pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
++    );
++    assert!(fd_set.contains(r1));
++    assert!(!fd_set.contains(r2));
++}
++
++#[test]
++pub fn test_pselect_nfds2() {
++    let (r1, w1) = pipe().unwrap();
++    write(w1, b"hi!").unwrap();
++    let (r2, _w2) = pipe().unwrap();
++
++    let mut fd_set = FdSet::new();
++    fd_set.insert(r1);
++    fd_set.insert(r2);
++
++    let timeout = TimeSpec::seconds(10);
++    assert_eq!(
++        1,
++        pselect(
++            ::std::cmp::max(r1, r2) + 1,
++            &mut fd_set,
++            None,
++            None,
++            &timeout,
++            None
++        ).unwrap()
++    );
++    assert!(fd_set.contains(r1));
++    assert!(!fd_set.contains(r2));
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_signal.rs b/third_party/rust/nix-0.15.0/test/sys/test_signal.rs
+new file mode 100644
+index 0000000000000..8780763f773ef
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_signal.rs
+@@ -0,0 +1,104 @@
++use libc;
++use nix::Error;
++use nix::sys::signal::*;
++use nix::unistd::*;
++use std::sync::atomic::{AtomicBool, Ordering};
++
++#[test]
++fn test_kill_none() {
++    kill(getpid(), None).expect("Should be able to send signal to myself.");
++}
++
++#[test]
++fn test_killpg_none() {
++    killpg(getpgrp(), None)
++        .expect("Should be able to send signal to my process group.");
++}
++
++#[test]
++fn test_old_sigaction_flags() {
++    extern "C" fn handler(_: ::libc::c_int) {}
++    let act = SigAction::new(
++        SigHandler::Handler(handler),
++        SaFlags::empty(),
++        SigSet::empty(),
++    );
++    let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
++    let _flags = oact.flags();
++    let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
++    let _flags = oact.flags();
++}
++
++#[test]
++fn test_sigprocmask_noop() {
++    sigprocmask(SigmaskHow::SIG_BLOCK, None, None)
++        .expect("this should be an effective noop");
++}
++
++#[test]
++fn test_sigprocmask() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // This needs to be a signal that rust doesn't use in the test harness.
++    const SIGNAL: Signal = Signal::SIGCHLD;
++
++    let mut old_signal_set = SigSet::empty();
++    sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
++        .expect("expect to be able to retrieve old signals");
++
++    // Make sure the old set doesn't contain the signal, otherwise the following
++    // test don't make sense.
++    assert_eq!(old_signal_set.contains(SIGNAL), false,
++               "the {:?} signal is already blocked, please change to a \
++                different one", SIGNAL);
++
++    // Now block the signal.
++    let mut signal_set = SigSet::empty();
++    signal_set.add(SIGNAL);
++    sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None)
++        .expect("expect to be able to block signals");
++
++    // And test it again, to make sure the change was effective.
++    old_signal_set.clear();
++    sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
++        .expect("expect to be able to retrieve old signals");
++    assert_eq!(old_signal_set.contains(SIGNAL), true,
++               "expected the {:?} to be blocked", SIGNAL);
++
++    // Reset the signal.
++    sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
++        .expect("expect to be able to block signals");
++}
++
++lazy_static! {
++    static ref SIGNALED: AtomicBool = AtomicBool::new(false);
++}
++
++extern fn test_sigaction_handler(signal: libc::c_int) {
++    let signal = Signal::from_c_int(signal).unwrap();
++    SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
++}
++
++extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {
++}
++
++#[test]
++fn test_signal() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
++    raise(Signal::SIGINT).unwrap();
++    assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigIgn);
++
++    let handler = SigHandler::Handler(test_sigaction_handler);
++    assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl);
++    raise(Signal::SIGINT).unwrap();
++    assert!(SIGNALED.load(Ordering::Relaxed));
++    assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
++
++    let action_handler = SigHandler::SigAction(test_sigaction_action);
++    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
++
++    // Restore default signal handler
++    unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs b/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
+new file mode 100644
+index 0000000000000..a3b6098841f1c
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
+@@ -0,0 +1,25 @@
++#[test]
++fn test_signalfd() {
++    use nix::sys::signalfd::SignalFd;
++    use nix::sys::signal::{self, raise, Signal, SigSet};
++
++    // Grab the mutex for altering signals so we don't interfere with other tests.
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Block the SIGUSR1 signal from automatic processing for this thread
++    let mut mask = SigSet::empty();
++    mask.add(signal::SIGUSR1);
++    mask.thread_block().unwrap();
++
++    let mut fd = SignalFd::new(&mask).unwrap();
++
++    // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
++    // because `kill` with `getpid` isn't correct during multi-threaded execution like during a
++    // cargo test session. Instead use `raise` which does the correct thing by default.
++    raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");
++
++    // And now catch that same signal.
++    let res = fd.read_signal().unwrap().unwrap();
++    let signo = Signal::from_c_int(res.ssi_signo as i32).unwrap();
++    assert_eq!(signo, signal::SIGUSR1);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_socket.rs b/third_party/rust/nix-0.15.0/test/sys/test_socket.rs
+new file mode 100644
+index 0000000000000..7e64d2b77f071
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_socket.rs
+@@ -0,0 +1,1066 @@
++use nix::ifaddrs::InterfaceAddress;
++use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
++use std::collections::hash_map::DefaultHasher;
++use std::hash::{Hash, Hasher};
++use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
++use std::os::unix::io::RawFd;
++use std::path::Path;
++use std::slice;
++use std::str::FromStr;
++use libc::c_char;
++use tempfile;
++
++#[test]
++pub fn test_inetv4_addr_to_sock_addr() {
++    let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
++    let addr = InetAddr::from_std(&actual);
++
++    match addr {
++        InetAddr::V4(addr) => {
++            let ip: u32 = 0x7f00_0001;
++            let port: u16 = 3000;
++            let saddr = addr.sin_addr.s_addr;
++
++            assert_eq!(saddr, ip.to_be());
++            assert_eq!(addr.sin_port, port.to_be());
++        }
++        _ => panic!("nope"),
++    }
++
++    assert_eq!(addr.to_str(), "127.0.0.1:3000");
++
++    let inet = addr.to_std();
++    assert_eq!(actual, inet);
++}
++
++#[test]
++pub fn test_inetv6_addr_to_sock_addr() {
++    let port: u16 = 3000;
++    let flowinfo: u32 = 1;
++    let scope_id: u32 = 2;
++    let ip: Ipv6Addr = "fe80::1".parse().unwrap();
++
++    let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
++    let addr = InetAddr::from_std(&actual);
++
++    match addr {
++        InetAddr::V6(addr) => {
++            assert_eq!(addr.sin6_port, port.to_be());
++            assert_eq!(addr.sin6_flowinfo, flowinfo);
++            assert_eq!(addr.sin6_scope_id, scope_id);
++        }
++        _ => panic!("nope"),
++    }
++
++    assert_eq!(actual, addr.to_std());
++}
++
++#[test]
++pub fn test_path_to_sock_addr() {
++    let path = "/foo/bar";
++    let actual = Path::new(path);
++    let addr = UnixAddr::new(actual).unwrap();
++
++    let expect: &[c_char] = unsafe {
++        slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
++    };
++    assert_eq!(&addr.0.sun_path[..8], expect);
++
++    assert_eq!(addr.path(), Some(actual));
++}
++
++fn calculate_hash<T: Hash>(t: &T) -> u64 {
++    let mut s = DefaultHasher::new();
++    t.hash(&mut s);
++    s.finish()
++}
++
++#[test]
++pub fn test_addr_equality_path() {
++    let path = "/foo/bar";
++    let actual = Path::new(path);
++    let addr1 = UnixAddr::new(actual).unwrap();
++    let mut addr2 = addr1.clone();
++
++    addr2.0.sun_path[10] = 127;
++
++    assert_eq!(addr1, addr2);
++    assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[test]
++pub fn test_abstract_sun_path_too_long() {
++    let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough");
++    let addr = UnixAddr::new_abstract(name.as_bytes());
++    assert!(addr.is_err());
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[test]
++pub fn test_addr_equality_abstract() {
++    let name = String::from("nix\0abstract\0test");
++    let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap();
++    let mut addr2 = addr1.clone();
++
++    assert_eq!(addr1, addr2);
++    assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
++
++    addr2.0.sun_path[18] = 127;
++    assert_ne!(addr1, addr2);
++    assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
++}
++
++// Test getting/setting abstract addresses (without unix socket creation)
++#[cfg(target_os = "linux")]
++#[test]
++pub fn test_abstract_uds_addr() {
++    let empty = String::new();
++    let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
++    let sun_path = [0u8; 107];
++    assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
++
++    let name = String::from("nix\0abstract\0test");
++    let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
++    let sun_path = [
++        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++    ];
++    assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
++    assert_eq!(addr.path(), None);
++
++    // Internally, name is null-prefixed (abstract namespace)
++    assert_eq!(addr.0.sun_path[0], 0);
++}
++
++#[test]
++pub fn test_getsockname() {
++    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
++    use nix::sys::socket::{bind, SockAddr};
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let sockname = tempdir.path().join("sock");
++    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
++               .expect("socket failed");
++    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
++    bind(sock, &sockaddr).expect("bind failed");
++    assert_eq!(sockaddr.to_str(),
++               getsockname(sock).expect("getsockname failed").to_str());
++}
++
++#[test]
++pub fn test_socketpair() {
++    use nix::unistd::{read, write};
++    use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};
++
++    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
++                     .unwrap();
++    write(fd1, b"hello").unwrap();
++    let mut buf = [0;5];
++    read(fd2, &mut buf).unwrap();
++
++    assert_eq!(&buf[..], b"hello");
++}
++
++// Test error handling of our recvmsg wrapper
++#[test]
++pub fn test_recvmsg_ebadf() {
++    use nix::Error;
++    use nix::errno::Errno;
++    use nix::sys::socket::{MsgFlags, recvmsg};
++    use nix::sys::uio::IoVec;
++
++    let mut buf = [0u8; 5];
++    let iov = [IoVec::from_mut_slice(&mut buf[..])];
++    let fd = -1;    // Bad file descriptor
++    let r = recvmsg(fd, &iov, None, MsgFlags::empty());
++    assert_eq!(r.err().unwrap(), Error::Sys(Errno::EBADF));
++}
++
++// Disable the test on emulated platforms due to a bug in QEMU versions <
++// 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
++#[test]
++pub fn test_scm_rights() {
++    use nix::sys::uio::IoVec;
++    use nix::unistd::{pipe, read, write, close};
++    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
++                           AddressFamily, SockType, SockFlag,
++                           ControlMessage, ControlMessageOwned, MsgFlags};
++
++    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
++                     .unwrap();
++    let (r, w) = pipe().unwrap();
++    let mut received_r: Option<RawFd> = None;
++
++    {
++        let iov = [IoVec::from_slice(b"hello")];
++        let fds = [r];
++        let cmsg = ControlMessage::ScmRights(&fds);
++        assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
++        close(r).unwrap();
++        close(fd1).unwrap();
++    }
++
++    {
++        let mut buf = [0u8; 5];
++        let iov = [IoVec::from_mut_slice(&mut buf[..])];
++        let mut cmsgspace = cmsg_space!([RawFd; 1]);
++        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
++
++        for cmsg in msg.cmsgs() {
++            if let ControlMessageOwned::ScmRights(fd) = cmsg {
++                assert_eq!(received_r, None);
++                assert_eq!(fd.len(), 1);
++                received_r = Some(fd[0]);
++            } else {
++                panic!("unexpected cmsg");
++            }
++        }
++        assert_eq!(msg.bytes, 5);
++        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
++        close(fd2).unwrap();
++    }
++
++    let received_r = received_r.expect("Did not receive passed fd");
++    // Ensure that the received file descriptor works
++    write(w, b"world").unwrap();
++    let mut buf = [0u8; 5];
++    read(received_r, &mut buf).unwrap();
++    assert_eq!(&buf[..], b"world");
++    close(received_r).unwrap();
++    close(w).unwrap();
++}
++
++// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
++#[cfg(any(target_os = "linux", target_os= "android"))]
++#[test]
++pub fn test_af_alg_cipher() {
++    use libc;
++    use nix::sys::uio::IoVec;
++    use nix::unistd::read;
++    use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
++                           AddressFamily, SockType, SockFlag, SockAddr,
++                           ControlMessage, MsgFlags};
++    use nix::sys::socket::sockopt::AlgSetKey;
++
++    let alg_type = "skcipher";
++    let alg_name = "ctr(aes)";
++    // 256-bits secret key
++    let key = vec![0u8; 32];
++    // 16-bytes IV
++    let iv_len = 16;
++    let iv = vec![1u8; iv_len];
++    // 256-bytes plain payload
++    let payload_len = 256;
++    let payload = vec![2u8; payload_len];
++
++    let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
++        .expect("socket failed");
++
++    let sockaddr = SockAddr::new_alg(alg_type, alg_name);
++    bind(sock, &sockaddr).expect("bind failed");
++
++    if let SockAddr::Alg(alg) = sockaddr {
++        assert_eq!(alg.alg_name().to_string_lossy(), alg_name);
++        assert_eq!(alg.alg_type().to_string_lossy(), alg_type);
++    } else {
++        panic!("unexpected SockAddr");
++    }
++
++    setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt");
++    let session_socket = accept(sock).expect("accept failed");
++
++    let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
++    let iov = IoVec::from_slice(&payload);
++    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
++
++    // allocate buffer for encrypted data
++    let mut encrypted = vec![0u8; payload_len];
++    let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
++    assert_eq!(num_bytes, payload_len);
++
++    let iov = IoVec::from_slice(&encrypted);
++
++    let iv = vec![1u8; iv_len];
++
++    let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
++    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
++
++    // allocate buffer for decrypted data
++    let mut decrypted = vec![0u8; payload_len];
++    let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
++
++    assert_eq!(num_bytes, payload_len);
++    assert_eq!(decrypted, payload);
++}
++
++// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
++#[cfg(any(target_os = "linux", target_os= "android"))]
++#[test]
++pub fn test_af_alg_aead() {
++    use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
++    use nix::sys::uio::IoVec;
++    use nix::unistd::{read, close};
++    use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
++                           AddressFamily, SockType, SockFlag, SockAddr,
++                           ControlMessage, MsgFlags};
++    use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
++
++    let auth_size = 4usize;
++    let assoc_size = 16u32;
++
++    let alg_type = "aead";
++    let alg_name = "gcm(aes)";
++    // 256-bits secret key
++    let key = vec![0u8; 32];
++    // 12-bytes IV
++    let iv_len = 12;
++    let iv = vec![1u8; iv_len];
++    // 256-bytes plain payload
++    let payload_len = 256;
++    let mut payload = vec![2u8; payload_len + (assoc_size as usize) + auth_size];
++
++    for i in 0..assoc_size {
++        payload[i as usize] = 10;
++    }
++
++    let len = payload.len();
++
++    for i in 0..auth_size {
++        payload[len - 1 - i] = 0;
++    }
++
++    let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
++        .expect("socket failed");
++
++    let sockaddr = SockAddr::new_alg(alg_type, alg_name);
++    bind(sock, &sockaddr).expect("bind failed");
++
++    setsockopt(sock, AlgSetAeadAuthSize, &auth_size).expect("setsockopt AlgSetAeadAuthSize");
++    setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey");
++    let session_socket = accept(sock).expect("accept failed");
++
++    let msgs = [
++        ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT),
++        ControlMessage::AlgSetIv(iv.as_slice()),
++        ControlMessage::AlgSetAeadAssoclen(&assoc_size)];
++    let iov = IoVec::from_slice(&payload);
++    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
++
++    // allocate buffer for encrypted data
++    let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size];
++    let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
++    assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize));
++    close(session_socket).expect("close");
++
++    for i in 0..assoc_size {
++        encrypted[i as usize] = 10;
++    }
++
++    let iov = IoVec::from_slice(&encrypted);
++
++    let iv = vec![1u8; iv_len];
++
++    let session_socket = accept(sock).expect("accept failed");
++
++    let msgs = [
++        ControlMessage::AlgSetOp(&ALG_OP_DECRYPT),
++        ControlMessage::AlgSetIv(iv.as_slice()),
++        ControlMessage::AlgSetAeadAssoclen(&assoc_size),
++    ];
++    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
++
++    // allocate buffer for decrypted data
++    let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
++    let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
++
++    assert!(num_bytes >= payload_len + (assoc_size as usize));
++    assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]);
++}
++
++/// Tests that passing multiple fds using a single `ControlMessage` works.
++// Disable the test on emulated platforms due to a bug in QEMU versions <
++// 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
++#[test]
++fn test_scm_rights_single_cmsg_multiple_fds() {
++    use std::os::unix::net::UnixDatagram;
++    use std::os::unix::io::{RawFd, AsRawFd};
++    use std::thread;
++    use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags,
++        sendmsg, recvmsg};
++    use nix::sys::uio::IoVec;
++    use libc;
++
++    let (send, receive) = UnixDatagram::pair().unwrap();
++    let thread = thread::spawn(move || {
++        let mut buf = [0u8; 8];
++        let iovec = [IoVec::from_mut_slice(&mut buf)];
++        let mut space = cmsg_space!([RawFd; 2]);
++        let msg = recvmsg(
++            receive.as_raw_fd(),
++            &iovec,
++            Some(&mut space),
++            MsgFlags::empty()
++        ).unwrap();
++        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
++
++        let mut cmsgs = msg.cmsgs();
++        match cmsgs.next() {
++            Some(ControlMessageOwned::ScmRights(fds)) => {
++                assert_eq!(fds.len(), 2,
++                           "unexpected fd count (expected 2 fds, got {})",
++                           fds.len());
++            },
++            _ => panic!(),
++        }
++        assert!(cmsgs.next().is_none(), "unexpected control msg");
++
++        assert_eq!(msg.bytes, 8);
++        assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]);
++    });
++
++    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++    let iov = [IoVec::from_slice(&slice)];
++    let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO];    // pass stdin and stdout
++    let cmsg = [ControlMessage::ScmRights(&fds)];
++    sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
++    thread.join().unwrap();
++}
++
++// Verify `sendmsg` builds a valid `msghdr` when passing an empty
++// `cmsgs` argument.  This should result in a msghdr with a nullptr
++// msg_control field and a msg_controllen of 0 when calling into the
++// raw `sendmsg`.
++#[test]
++pub fn test_sendmsg_empty_cmsgs() {
++    use nix::sys::uio::IoVec;
++    use nix::unistd::close;
++    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
++                           AddressFamily, SockType, SockFlag, MsgFlags};
++
++    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
++                     .unwrap();
++
++    {
++        let iov = [IoVec::from_slice(b"hello")];
++        assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
++        close(fd1).unwrap();
++    }
++
++    {
++        let mut buf = [0u8; 5];
++        let iov = [IoVec::from_mut_slice(&mut buf[..])];
++        let mut cmsgspace = cmsg_space!([RawFd; 1]);
++        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
++
++        for _ in msg.cmsgs() {
++            panic!("unexpected cmsg");
++        }
++        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
++        assert_eq!(msg.bytes, 5);
++        close(fd2).unwrap();
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[test]
++fn test_scm_credentials() {
++    use libc;
++    use nix::sys::uio::IoVec;
++    use nix::unistd::{close, getpid, getuid, getgid};
++    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
++                           AddressFamily, SockType, SockFlag,
++                           ControlMessage, ControlMessageOwned, MsgFlags};
++    use nix::sys::socket::sockopt::PassCred;
++
++    let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
++        .unwrap();
++    setsockopt(recv, PassCred, &true).unwrap();
++
++    {
++        let iov = [IoVec::from_slice(b"hello")];
++        let cred = libc::ucred {
++            pid: getpid().as_raw(),
++            uid: getuid().as_raw(),
++            gid: getgid().as_raw(),
++        };
++        let cmsg = ControlMessage::ScmCredentials(&cred);
++        assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
++        close(send).unwrap();
++    }
++
++    {
++        let mut buf = [0u8; 5];
++        let iov = [IoVec::from_mut_slice(&mut buf[..])];
++        let mut cmsgspace = cmsg_space!(libc::ucred);
++        let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
++        let mut received_cred = None;
++
++        for cmsg in msg.cmsgs() {
++            if let ControlMessageOwned::ScmCredentials(cred) = cmsg {
++                assert!(received_cred.is_none());
++                assert_eq!(cred.pid, getpid().as_raw());
++                assert_eq!(cred.uid, getuid().as_raw());
++                assert_eq!(cred.gid, getgid().as_raw());
++                received_cred = Some(cred);
++            } else {
++                panic!("unexpected cmsg");
++            }
++        }
++        received_cred.expect("no creds received");
++        assert_eq!(msg.bytes, 5);
++        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
++        close(recv).unwrap();
++    }
++}
++
++/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
++/// `sendmsg` call.
++#[cfg(any(target_os = "android", target_os = "linux"))]
++// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
++// see https://bugs.launchpad.net/qemu/+bug/1781280
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
++#[test]
++fn test_scm_credentials_and_rights() {
++    use libc;
++
++    let space = cmsg_space!(libc::ucred, RawFd);
++    test_impl_scm_credentials_and_rights(space);
++}
++
++/// Ensure that passing a an oversized control message buffer to recvmsg
++/// still works.
++#[cfg(any(target_os = "android", target_os = "linux"))]
++// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
++// see https://bugs.launchpad.net/qemu/+bug/1781280
++#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
++#[test]
++fn test_too_large_cmsgspace() {
++    let space = vec![0u8; 1024];
++    test_impl_scm_credentials_and_rights(space);
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
++    use libc::ucred;
++    use nix::sys::uio::IoVec;
++    use nix::unistd::{pipe, read, write, close, getpid, getuid, getgid};
++    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
++                           SockType, SockFlag,
++                           ControlMessage, ControlMessageOwned, MsgFlags};
++    use nix::sys::socket::sockopt::PassCred;
++
++    let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
++        .unwrap();
++    setsockopt(recv, PassCred, &true).unwrap();
++
++    let (r, w) = pipe().unwrap();
++    let mut received_r: Option<RawFd> = None;
++
++    {
++        let iov = [IoVec::from_slice(b"hello")];
++        let cred = ucred {
++            pid: getpid().as_raw(),
++            uid: getuid().as_raw(),
++            gid: getgid().as_raw(),
++        };
++        let fds = [r];
++        let cmsgs = [
++            ControlMessage::ScmCredentials(&cred),
++            ControlMessage::ScmRights(&fds),
++        ];
++        assert_eq!(sendmsg(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5);
++        close(r).unwrap();
++        close(send).unwrap();
++    }
++
++    {
++        let mut buf = [0u8; 5];
++        let iov = [IoVec::from_mut_slice(&mut buf[..])];
++        let msg = recvmsg(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap();
++        let mut received_cred = None;
++
++        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
++
++        for cmsg in msg.cmsgs() {
++            match cmsg {
++                ControlMessageOwned::ScmRights(fds) => {
++                    assert_eq!(received_r, None, "already received fd");
++                    assert_eq!(fds.len(), 1);
++                    received_r = Some(fds[0]);
++                }
++                ControlMessageOwned::ScmCredentials(cred) => {
++                    assert!(received_cred.is_none());
++                    assert_eq!(cred.pid, getpid().as_raw());
++                    assert_eq!(cred.uid, getuid().as_raw());
++                    assert_eq!(cred.gid, getgid().as_raw());
++                    received_cred = Some(cred);
++                }
++                _ => panic!("unexpected cmsg"),
++            }
++        }
++        received_cred.expect("no creds received");
++        assert_eq!(msg.bytes, 5);
++        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
++        close(recv).unwrap();
++    }
++
++    let received_r = received_r.expect("Did not receive passed fd");
++    // Ensure that the received file descriptor works
++    write(w, b"world").unwrap();
++    let mut buf = [0u8; 5];
++    read(received_r, &mut buf).unwrap();
++    assert_eq!(&buf[..], b"world");
++    close(received_r).unwrap();
++    close(w).unwrap();
++}
++
++// Test creating and using named unix domain sockets
++#[test]
++pub fn test_unixdomain() {
++    use nix::sys::socket::{SockType, SockFlag};
++    use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
++    use nix::unistd::{read, write, close};
++    use std::thread;
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let sockname = tempdir.path().join("sock");
++    let s1 = socket(AddressFamily::Unix, SockType::Stream,
++                    SockFlag::empty(), None).expect("socket failed");
++    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
++    bind(s1, &sockaddr).expect("bind failed");
++    listen(s1, 10).expect("listen failed");
++
++    let thr = thread::spawn(move || {
++        let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
++                 .expect("socket failed");
++        connect(s2, &sockaddr).expect("connect failed");
++        write(s2, b"hello").expect("write failed");
++        close(s2).unwrap();
++    });
++
++    let s3 = accept(s1).expect("accept failed");
++
++    let mut buf = [0;5];
++    read(s3, &mut buf).unwrap();
++    close(s3).unwrap();
++    close(s1).unwrap();
++    thr.join().unwrap();
++
++    assert_eq!(&buf[..], b"hello");
++}
++
++// Test creating and using named system control sockets
++#[cfg(any(target_os = "macos", target_os = "ios"))]
++#[test]
++pub fn test_syscontrol() {
++    use nix::Error;
++    use nix::errno::Errno;
++    use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol};
++
++    let fd = socket(AddressFamily::System, SockType::Datagram,
++                    SockFlag::empty(), SockProtocol::KextControl)
++             .expect("socket failed");
++    let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
++    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));
++
++    // requires root privileges
++    // connect(fd, &sockaddr).expect("connect failed");
++}
++
++#[cfg(any(
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "linux",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++fn loopback_address(family: AddressFamily) -> Option<InterfaceAddress> {
++    use std::io;
++    use std::io::Write;
++    use nix::ifaddrs::getifaddrs;
++    use nix::sys::socket::SockAddr;
++    use nix::net::if_::*;
++
++    let addrs = match getifaddrs() {
++        Ok(iter) => iter,
++        Err(e) => {
++            let stdioerr = io::stderr();
++            let mut handle = stdioerr.lock();
++            writeln!(handle, "getifaddrs: {:?}", e).unwrap();
++            return None;
++        },
++    };
++    // return first address matching family
++    for ifaddr in addrs {
++        if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) {
++            match ifaddr.address {
++                Some(SockAddr::Inet(InetAddr::V4(..))) => {
++                    match family {
++                        AddressFamily::Inet => return Some(ifaddr),
++                        _ => continue
++                    }
++                },
++                Some(SockAddr::Inet(InetAddr::V6(..))) => {
++                    match family {
++                        AddressFamily::Inet6 => return Some(ifaddr),
++                        _ => continue
++                    }
++                },
++                _ => continue,
++            }
++        }
++    }
++    None
++}
++
++#[cfg(any(
++    target_os = "android",
++    target_os = "ios",
++    target_os = "linux",
++    target_os = "macos",
++    target_os = "netbsd",
++))]
++// qemu doesn't seem to be emulating this correctly in these architectures
++#[cfg_attr(any(
++    target_arch = "mips",
++    target_arch = "mips64",
++    target_arch = "powerpc64",
++), ignore)]
++#[test]
++pub fn test_recv_ipv4pktinfo() {
++    use libc;
++    use nix::sys::socket::sockopt::Ipv4PacketInfo;
++    use nix::sys::socket::{bind, SockFlag, SockType};
++    use nix::sys::socket::{getsockname, setsockopt, socket};
++    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
++    use nix::sys::uio::IoVec;
++    use nix::net::if_::*;
++
++    let lo_ifaddr = loopback_address(AddressFamily::Inet);
++    let (lo_name, lo) = match lo_ifaddr {
++        Some(ifaddr) => (ifaddr.interface_name,
++                         ifaddr.address.expect("Expect IPv4 address on interface")),
++        None => return,
++    };
++    let receive = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("receive socket failed");
++    bind(receive, &lo).expect("bind failed");
++    let sa = getsockname(receive).expect("getsockname failed");
++    setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
++
++    {
++        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++        let iov = [IoVec::from_slice(&slice)];
++
++        let send = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
++    }
++
++    {
++        let mut buf = [0u8; 8];
++        let iovec = [IoVec::from_mut_slice(&mut buf)];
++        let mut space = cmsg_space!(libc::in_pktinfo);
++        let msg = recvmsg(
++            receive,
++            &iovec,
++            Some(&mut space),
++            MsgFlags::empty(),
++        ).expect("recvmsg failed");
++        assert!(
++            !msg.flags
++                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
++        );
++
++        let mut cmsgs = msg.cmsgs();
++        match cmsgs.next() {
++            Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) => {
++                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
++                assert_eq!(
++                    pktinfo.ipi_ifindex as libc::c_uint,
++                    i,
++                    "unexpected ifindex (expected {}, got {})",
++                    i,
++                    pktinfo.ipi_ifindex
++                );
++            }
++            _ => (),
++        }
++        assert!(cmsgs.next().is_none(), "unexpected additional control msg");
++        assert_eq!(msg.bytes, 8);
++        assert_eq!(
++            iovec[0].as_slice(),
++            [1u8, 2, 3, 4, 5, 6, 7, 8]
++        );
++    }
++}
++
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++// qemu doesn't seem to be emulating this correctly in these architectures
++#[cfg_attr(any(
++    target_arch = "mips",
++    target_arch = "mips64",
++    target_arch = "powerpc64",
++), ignore)]
++#[test]
++pub fn test_recvif() {
++    use libc;
++    use nix::net::if_::*;
++    use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr};
++    use nix::sys::socket::{bind, SockFlag, SockType};
++    use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr};
++    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
++    use nix::sys::uio::IoVec;
++
++    let lo_ifaddr = loopback_address(AddressFamily::Inet);
++    let (lo_name, lo) = match lo_ifaddr {
++        Some(ifaddr) => (ifaddr.interface_name,
++                         ifaddr.address.expect("Expect IPv4 address on interface")),
++        None => return,
++    };
++    let receive = socket(
++        AddressFamily::Inet,
++        SockType::Datagram,
++        SockFlag::empty(),
++        None,
++    ).expect("receive socket failed");
++    bind(receive, &lo).expect("bind failed");
++    let sa = getsockname(receive).expect("getsockname failed");
++    setsockopt(receive, Ipv4RecvIf, &true).expect("setsockopt IP_RECVIF failed");
++    setsockopt(receive, Ipv4RecvDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
++
++    {
++        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++        let iov = [IoVec::from_slice(&slice)];
++
++        let send = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
++    }
++
++    {
++        let mut buf = [0u8; 8];
++        let iovec = [IoVec::from_mut_slice(&mut buf)];
++        let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
++        let msg = recvmsg(
++            receive,
++            &iovec,
++            Some(&mut space),
++            MsgFlags::empty(),
++        ).expect("recvmsg failed");
++        assert!(
++            !msg.flags
++                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
++        );
++        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
++
++        let mut rx_recvif = false;
++        let mut rx_recvdstaddr = false;
++        for cmsg in msg.cmsgs() {
++            match cmsg {
++                ControlMessageOwned::Ipv4RecvIf(dl) => {
++                    rx_recvif = true;
++                    let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
++                    assert_eq!(
++                        dl.sdl_index as libc::c_uint,
++                        i,
++                        "unexpected ifindex (expected {}, got {})",
++                        i,
++                        dl.sdl_index
++                    );
++                },
++                ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
++                    rx_recvdstaddr = true;
++                    if let SockAddr::Inet(InetAddr::V4(a)) = lo {
++                        assert_eq!(a.sin_addr.s_addr,
++                                   addr.s_addr,
++                                   "unexpected destination address (expected {}, got {})",
++                                   a.sin_addr.s_addr,
++                                   addr.s_addr);
++                    } else {
++                        panic!("unexpected Sockaddr");
++                    }
++                },
++                _ => panic!("unexpected additional control msg"),
++            }
++        }
++        assert_eq!(rx_recvif, true);
++        assert_eq!(rx_recvdstaddr, true);
++        assert_eq!(msg.bytes, 8);
++        assert_eq!(
++            iovec[0].as_slice(),
++            [1u8, 2, 3, 4, 5, 6, 7, 8]
++        );
++    }
++}
++
++#[cfg(any(
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "ios",
++    target_os = "linux",
++    target_os = "macos",
++    target_os = "netbsd",
++    target_os = "openbsd",
++))]
++// qemu doesn't seem to be emulating this correctly in these architectures
++#[cfg_attr(any(
++    target_arch = "mips",
++    target_arch = "mips64",
++    target_arch = "powerpc64",
++), ignore)]
++#[test]
++pub fn test_recv_ipv6pktinfo() {
++    use libc;
++    use nix::net::if_::*;
++    use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
++    use nix::sys::socket::{bind, SockFlag, SockType};
++    use nix::sys::socket::{getsockname, setsockopt, socket};
++    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
++    use nix::sys::uio::IoVec;
++
++    let lo_ifaddr = loopback_address(AddressFamily::Inet6);
++    let (lo_name, lo) = match lo_ifaddr {
++        Some(ifaddr) => (ifaddr.interface_name,
++                         ifaddr.address.expect("Expect IPv4 address on interface")),
++        None => return,
++    };
++    let receive = socket(
++        AddressFamily::Inet6,
++        SockType::Datagram,
++        SockFlag::empty(),
++        None,
++    ).expect("receive socket failed");
++    bind(receive, &lo).expect("bind failed");
++    let sa = getsockname(receive).expect("getsockname failed");
++    setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
++
++    {
++        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++        let iov = [IoVec::from_slice(&slice)];
++
++        let send = socket(
++            AddressFamily::Inet6,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
++    }
++
++    {
++        let mut buf = [0u8; 8];
++        let iovec = [IoVec::from_mut_slice(&mut buf)];
++        let mut space = cmsg_space!(libc::in6_pktinfo);
++        let msg = recvmsg(
++            receive,
++            &iovec,
++            Some(&mut space),
++            MsgFlags::empty(),
++        ).expect("recvmsg failed");
++        assert!(
++            !msg.flags
++                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
++        );
++
++        let mut cmsgs = msg.cmsgs();
++        match cmsgs.next() {
++            Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) => {
++                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
++                assert_eq!(
++                    pktinfo.ipi6_ifindex,
++                    i,
++                    "unexpected ifindex (expected {}, got {})",
++                    i,
++                    pktinfo.ipi6_ifindex
++                );
++            }
++            _ => (),
++        }
++        assert!(cmsgs.next().is_none(), "unexpected additional control msg");
++        assert_eq!(msg.bytes, 8);
++        assert_eq!(
++            iovec[0].as_slice(),
++            [1u8, 2, 3, 4, 5, 6, 7, 8]
++        );
++    }
++}
++
++#[cfg(target_os = "linux")]
++#[test]
++pub fn test_vsock() {
++    use libc;
++    use nix::Error;
++    use nix::errno::Errno;
++    use nix::sys::socket::{AddressFamily, socket, bind, connect, listen,
++                           SockAddr, SockType, SockFlag};
++    use nix::unistd::{close};
++    use std::thread;
++
++    let port: u32 = 3000;
++
++    let s1 = socket(AddressFamily::Vsock,  SockType::Stream,
++                    SockFlag::empty(), None)
++             .expect("socket failed");
++
++    // VMADDR_CID_HYPERVISOR and VMADDR_CID_RESERVED are reserved, so we expect
++    // an EADDRNOTAVAIL error.
++    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
++    assert_eq!(bind(s1, &sockaddr).err(),
++               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
++
++    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_RESERVED, port);
++    assert_eq!(bind(s1, &sockaddr).err(),
++               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
++
++
++    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
++    assert_eq!(bind(s1, &sockaddr), Ok(()));
++    listen(s1, 10).expect("listen failed");
++
++    let thr = thread::spawn(move || {
++        let cid: u32 = libc::VMADDR_CID_HOST;
++
++        let s2 = socket(AddressFamily::Vsock, SockType::Stream,
++                        SockFlag::empty(), None)
++                 .expect("socket failed");
++
++        let sockaddr = SockAddr::new_vsock(cid, port);
++
++        // The current implementation does not support loopback devices, so,
++        // for now, we expect a failure on the connect.
++        assert_ne!(connect(s2, &sockaddr), Ok(()));
++
++        close(s2).unwrap();
++    });
++
++    close(s1).unwrap();
++    thr.join().unwrap();
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs b/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
+new file mode 100644
+index 0000000000000..c4860c0d61d3d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
+@@ -0,0 +1,53 @@
++use rand::{thread_rng, Rng};
++use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
++
++#[cfg(target_os = "linux")]
++#[test]
++fn is_so_mark_functional() {
++    use nix::sys::socket::sockopt;
++
++    require_capability!(CAP_NET_ADMIN);
++
++    let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
++    setsockopt(s, sockopt::Mark, &1337).unwrap();
++    let mark = getsockopt(s, sockopt::Mark).unwrap();
++    assert_eq!(mark, 1337);
++}
++
++#[test]
++fn test_so_buf() {
++    let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
++             .unwrap();
++    let bufsize: usize = thread_rng().gen_range(4096, 131_072);
++    setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
++    let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
++    assert!(actual >= bufsize);
++    setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
++    let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
++    assert!(actual >= bufsize);
++}
++
++// The CI doesn't supported getsockopt and setsockopt on emulated processors.
++// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
++// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
++// So the syscall doesn't work properly unless the kernel is also emulated.
++#[test]
++#[cfg(all(
++    any(target_arch = "x86", target_arch = "x86_64"),
++    any(target_os = "freebsd", target_os = "linux")
++))]
++fn test_tcp_congestion() {
++    use std::ffi::OsString;
++
++    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
++
++    let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
++    setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
++
++    setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();
++
++    assert_eq!(
++        getsockopt(fd, sockopt::TcpCongestion).unwrap(),
++        val
++    );
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs b/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
+new file mode 100644
+index 0000000000000..73e6586f6223e
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
+@@ -0,0 +1,18 @@
++use nix::sys::sysinfo::*;
++
++#[test]
++fn sysinfo_works() {
++    let info = sysinfo().unwrap();
++
++    let (l1, l5, l15) = info.load_average();
++    assert!(l1 >= 0.0);
++    assert!(l5 >= 0.0);
++    assert!(l15 >= 0.0);
++
++    info.uptime();  // just test Duration construction
++
++    assert!(info.swap_free() <= info.swap_total(),
++            "more swap available than installed (free: {}, total: {})",
++            info.swap_free(),
++            info.swap_total());
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_termios.rs b/third_party/rust/nix-0.15.0/test/sys/test_termios.rs
+new file mode 100644
+index 0000000000000..a14b8ce1a23cb
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_termios.rs
+@@ -0,0 +1,136 @@
++use std::os::unix::prelude::*;
++use tempfile::tempfile;
++
++use nix::{Error, fcntl};
++use nix::errno::Errno;
++use nix::pty::openpty;
++use nix::sys::termios::{self, LocalFlags, OutputFlags, Termios, tcgetattr};
++use nix::unistd::{read, write, close};
++
++/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
++fn write_all(f: RawFd, buf: &[u8]) {
++    let mut len = 0;
++    while len < buf.len() {
++        len += write(f, &buf[len..]).unwrap();
++    }
++}
++
++// Test tcgetattr on a terminal
++#[test]
++fn test_tcgetattr_pty() {
++    // openpty uses ptname(3) internally
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    let pty = openpty(None, None).expect("openpty failed");
++    assert!(termios::tcgetattr(pty.master).is_ok());
++    close(pty.master).expect("closing the master failed");
++    close(pty.slave).expect("closing the slave failed");
++}
++
++// Test tcgetattr on something that isn't a terminal
++#[test]
++fn test_tcgetattr_enotty() {
++    let file = tempfile().unwrap();
++    assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(),
++               Some(Error::Sys(Errno::ENOTTY)));
++}
++
++// Test tcgetattr on an invalid file descriptor
++#[test]
++fn test_tcgetattr_ebadf() {
++    assert_eq!(termios::tcgetattr(-1).err(),
++               Some(Error::Sys(Errno::EBADF)));
++}
++
++// Test modifying output flags
++#[test]
++fn test_output_flags() {
++    // openpty uses ptname(3) internally
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open one pty to get attributes for the second one
++    let mut termios = {
++        let pty = openpty(None, None).expect("openpty failed");
++        assert!(pty.master > 0);
++        assert!(pty.slave > 0);
++        let termios = tcgetattr(pty.master).expect("tcgetattr failed");
++        close(pty.master).unwrap();
++        close(pty.slave).unwrap();
++        termios
++    };
++
++    // Make sure postprocessing '\r' isn't specified by default or this test is useless.
++    assert!(!termios.output_flags.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
++
++    // Specify that '\r' characters should be transformed to '\n'
++    // OPOST is specified to enable post-processing
++    termios.output_flags.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
++
++    // Open a pty
++    let pty = openpty(None, &termios).unwrap();
++    assert!(pty.master > 0);
++    assert!(pty.slave > 0);
++
++    // Write into the master
++    let string = "foofoofoo\r";
++    write_all(pty.master, string.as_bytes());
++
++    // Read from the slave verifying that the output has been properly transformed
++    let mut buf = [0u8; 10];
++    ::read_exact(pty.slave, &mut buf);
++    let transformed_string = "foofoofoo\n";
++    close(pty.master).unwrap();
++    close(pty.slave).unwrap();
++    assert_eq!(&buf, transformed_string.as_bytes());
++}
++
++// Test modifying local flags
++#[test]
++fn test_local_flags() {
++    // openpty uses ptname(3) internally
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open one pty to get attributes for the second one
++    let mut termios = {
++        let pty = openpty(None, None).unwrap();
++        assert!(pty.master > 0);
++        assert!(pty.slave > 0);
++        let termios = tcgetattr(pty.master).unwrap();
++        close(pty.master).unwrap();
++        close(pty.slave).unwrap();
++        termios
++    };
++
++    // Make sure echo is specified by default or this test is useless.
++    assert!(termios.local_flags.contains(LocalFlags::ECHO));
++
++    // Disable local echo
++    termios.local_flags.remove(LocalFlags::ECHO);
++
++    // Open a new pty with our modified termios settings
++    let pty = openpty(None, &termios).unwrap();
++    assert!(pty.master > 0);
++    assert!(pty.slave > 0);
++
++    // Set the master is in nonblocking mode or reading will never return.
++    let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
++    let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
++    fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
++
++    // Write into the master
++    let string = "foofoofoo\r";
++    write_all(pty.master, string.as_bytes());
++
++    // Try to read from the master, which should not have anything as echoing was disabled.
++    let mut buf = [0u8; 10];
++    let read = read(pty.master, &mut buf).unwrap_err();
++    close(pty.master).unwrap();
++    close(pty.slave).unwrap();
++    assert_eq!(read, Error::Sys(Errno::EAGAIN));
++}
++
++#[test]
++fn test_cfmakeraw() {
++    let mut termios = unsafe { Termios::default_uninit() };
++    termios::cfmakeraw(&mut termios);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_uio.rs b/third_party/rust/nix-0.15.0/test/sys/test_uio.rs
+new file mode 100644
+index 0000000000000..3e4fc28ceb0e4
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_uio.rs
+@@ -0,0 +1,241 @@
++use nix::sys::uio::*;
++use nix::unistd::*;
++use rand::{thread_rng, Rng};
++use rand::distributions::Alphanumeric;
++use std::{cmp, iter};
++use std::fs::{OpenOptions};
++use std::os::unix::io::AsRawFd;
++
++use tempfile::{tempfile, tempdir};
++
++#[test]
++fn test_writev() {
++    let mut to_write = Vec::with_capacity(16 * 128);
++    for _ in 0..16 {
++        let s: String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
++        let b = s.as_bytes();
++        to_write.extend(b.iter().cloned());
++    }
++    // Allocate and fill iovecs
++    let mut iovecs = Vec::new();
++    let mut consumed = 0;
++    while consumed < to_write.len() {
++        let left = to_write.len() - consumed;
++        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
++        let b = &to_write[consumed..consumed+slice_len];
++        iovecs.push(IoVec::from_slice(b));
++        consumed += slice_len;
++    }
++    let pipe_res = pipe();
++    assert!(pipe_res.is_ok());
++    let (reader, writer) = pipe_res.ok().unwrap();
++    // FileDesc will close its filedesc (reader).
++    let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
++    // Blocking io, should write all data.
++    let write_res = writev(writer, &iovecs);
++    // Successful write
++    assert!(write_res.is_ok());
++    let written = write_res.ok().unwrap();
++    // Check whether we written all data
++    assert_eq!(to_write.len(), written);
++    let read_res = read(reader, &mut read_buf[..]);
++    // Successful read
++    assert!(read_res.is_ok());
++    let read = read_res.ok().unwrap() as usize;
++    // Check we have read as much as we written
++    assert_eq!(read, written);
++    // Check equality of written and read data
++    assert_eq!(&to_write, &read_buf);
++    let close_res = close(writer);
++    assert!(close_res.is_ok());
++    let close_res = close(reader);
++    assert!(close_res.is_ok());
++}
++
++#[test]
++fn test_readv() {
++    let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
++    let to_write = s.as_bytes().to_vec();
++    let mut storage = Vec::new();
++    let mut allocated = 0;
++    while allocated < to_write.len() {
++        let left = to_write.len() - allocated;
++        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
++        let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
++        storage.push(v);
++        allocated += vec_len;
++    }
++    let mut iovecs = Vec::with_capacity(storage.len());
++    for v in &mut storage {
++        iovecs.push(IoVec::from_mut_slice(&mut v[..]));
++    }
++    let pipe_res = pipe();
++    assert!(pipe_res.is_ok());
++    let (reader, writer) = pipe_res.ok().unwrap();
++    // Blocking io, should write all data.
++    let write_res = write(writer, &to_write);
++    // Successful write
++    assert!(write_res.is_ok());
++    let read_res = readv(reader, &mut iovecs[..]);
++    assert!(read_res.is_ok());
++    let read = read_res.ok().unwrap();
++    // Check whether we've read all data
++    assert_eq!(to_write.len(), read);
++    // Cccumulate data from iovecs
++    let mut read_buf = Vec::with_capacity(to_write.len());
++    for iovec in &iovecs {
++        read_buf.extend(iovec.as_slice().iter().cloned());
++    }
++    // Check whether iovecs contain all written data
++    assert_eq!(read_buf.len(), to_write.len());
++    // Check equality of written and read data
++    assert_eq!(&read_buf, &to_write);
++    let close_res = close(reader);
++    assert!(close_res.is_ok());
++    let close_res = close(writer);
++    assert!(close_res.is_ok());
++}
++
++#[test]
++fn test_pwrite() {
++    use std::io::Read;
++
++    let mut file = tempfile().unwrap();
++    let buf = [1u8;8];
++    assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
++    let mut file_content = Vec::new();
++    file.read_to_end(&mut file_content).unwrap();
++    let mut expected = vec![0u8;8];
++    expected.extend(vec![1;8]);
++    assert_eq!(file_content, expected);
++}
++
++#[test]
++fn test_pread() {
++    use std::io::Write;
++
++    let tempdir = tempdir().unwrap();
++
++    let path = tempdir.path().join("pread_test_file");
++    let mut file = OpenOptions::new().write(true).read(true).create(true)
++                                    .truncate(true).open(path).unwrap();
++    let file_content: Vec<u8> = (0..64).collect();
++    file.write_all(&file_content).unwrap();
++
++    let mut buf = [0u8;16];
++    assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
++    let expected: Vec<_> = (16..32).collect();
++    assert_eq!(&buf[..], &expected[..]);
++}
++
++#[test]
++#[cfg(target_os = "linux")]
++fn test_pwritev() {
++    use std::io::Read;
++
++    let to_write: Vec<u8> = (0..128).collect();
++    let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();
++
++    let iovecs = [
++        IoVec::from_slice(&to_write[0..17]),
++        IoVec::from_slice(&to_write[17..64]),
++        IoVec::from_slice(&to_write[64..128]),
++    ];
++
++    let tempdir = tempdir().unwrap();
++
++    // pwritev them into a temporary file
++    let path = tempdir.path().join("pwritev_test_file");
++    let mut file = OpenOptions::new().write(true).read(true).create(true)
++                                    .truncate(true).open(path).unwrap();
++
++    let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
++    assert_eq!(written, to_write.len());
++
++    // Read the data back and make sure it matches
++    let mut contents = Vec::new();
++    file.read_to_end(&mut contents).unwrap();
++    assert_eq!(contents, expected);
++}
++
++#[test]
++#[cfg(target_os = "linux")]
++fn test_preadv() {
++    use std::io::Write;
++
++    let to_write: Vec<u8> = (0..200).collect();
++    let expected: Vec<u8> = (100..200).collect();
++
++    let tempdir = tempdir().unwrap();
++
++    let path = tempdir.path().join("preadv_test_file");
++
++    let mut file = OpenOptions::new().read(true).write(true).create(true)
++                                    .truncate(true).open(path).unwrap();
++    file.write_all(&to_write).unwrap();
++
++    let mut buffers: Vec<Vec<u8>> = vec![
++        vec![0; 24],
++        vec![0; 1],
++        vec![0; 75],
++    ];
++
++    {
++        // Borrow the buffers into IoVecs and preadv into them
++        let iovecs: Vec<_> = buffers.iter_mut().map(
++            |buf| IoVec::from_mut_slice(&mut buf[..])).collect();
++        assert_eq!(Ok(100), preadv(file.as_raw_fd(), &iovecs, 100));
++    }
++
++    let all = buffers.concat();
++    assert_eq!(all, expected);
++}
++
++#[test]
++#[cfg(target_os = "linux")]
++// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
++#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
++fn test_process_vm_readv() {
++    use nix::unistd::ForkResult::*;
++    use nix::sys::signal::*;
++    use nix::sys::wait::*;
++
++    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Pre-allocate memory in the child, since allocation isn't safe
++    // post-fork (~= async-signal-safe)
++    let mut vector = vec![1u8, 2, 3, 4, 5];
++
++    let (r, w) = pipe().unwrap();
++    match fork().expect("Error: Fork Failed") {
++        Parent { child } => {
++            close(w).unwrap();
++            // wait for child
++            read(r, &mut [0u8]).unwrap();
++            close(r).unwrap();
++
++            let ptr = vector.as_ptr() as usize;
++            let remote_iov = RemoteIoVec { base: ptr, len: 5 };
++            let mut buf = vec![0u8; 5];
++
++            let ret = process_vm_readv(child,
++                                       &[IoVec::from_mut_slice(&mut buf)],
++                                       &[remote_iov]);
++
++            kill(child, SIGTERM).unwrap();
++            waitpid(child, None).unwrap();
++
++            assert_eq!(Ok(5), ret);
++            assert_eq!(20u8, buf.iter().sum());
++        },
++        Child => {
++            let _ = close(r);
++            for i in &mut vector {
++                *i += 1;
++            }
++            let _ = write(w, b"\0");
++            let _ = close(w);
++            loop { let _ = pause(); }
++        },
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/sys/test_wait.rs b/third_party/rust/nix-0.15.0/test/sys/test_wait.rs
+new file mode 100644
+index 0000000000000..d07d82f0d9075
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/sys/test_wait.rs
+@@ -0,0 +1,104 @@
++use nix::Error;
++use nix::unistd::*;
++use nix::unistd::ForkResult::*;
++use nix::sys::signal::*;
++use nix::sys::wait::*;
++use libc::_exit;
++
++#[test]
++fn test_wait_signal() {
++    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
++    match fork().expect("Error: Fork Failed") {
++      Child => {
++          pause();
++          unsafe { _exit(123) }
++      },
++      Parent { child } => {
++          kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
++          assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, SIGKILL, false)));
++      },
++    }
++}
++
++#[test]
++fn test_wait_exit() {
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Safe: Child only calls `_exit`, which is async-signal-safe.
++    match fork().expect("Error: Fork Failed") {
++      Child => unsafe { _exit(12); },
++      Parent { child } => {
++          assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
++      },
++    }
++}
++
++#[test]
++fn test_waitstatus_from_raw() {
++    let pid = Pid::from_raw(1);
++    assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
++    assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2)));
++    assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Error::invalid_argument()));
++}
++
++#[test]
++fn test_waitstatus_pid() {
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    match fork().unwrap() {
++        Child => unsafe { _exit(0) },
++        Parent { child } => {
++            let status = waitpid(child, None).unwrap();
++            assert_eq!(status.pid(), Some(child));
++        }
++    }
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++// FIXME: qemu-user doesn't implement ptrace on most arches
++#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
++mod ptrace {
++    use nix::sys::ptrace::{self, Options, Event};
++    use nix::sys::signal::*;
++    use nix::sys::wait::*;
++    use nix::unistd::*;
++    use nix::unistd::ForkResult::*;
++    use libc::_exit;
++
++    fn ptrace_child() -> ! {
++        ptrace::traceme().unwrap();
++        // As recommended by ptrace(2), raise SIGTRAP to pause the child
++        // until the parent is ready to continue
++        raise(SIGTRAP).unwrap();
++        unsafe { _exit(0) }
++    }
++
++    fn ptrace_parent(child: Pid) {
++        // Wait for the raised SIGTRAP
++        assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, SIGTRAP)));
++        // We want to test a syscall stop and a PTRACE_EVENT stop
++        assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
++
++        // First, stop on the next system call, which will be exit()
++        assert!(ptrace::syscall(child).is_ok());
++        assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
++        // Then get the ptrace event for the process exiting
++        assert!(ptrace::cont(child, None).is_ok());
++        assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)));
++        // Finally get the normal wait() result, now that the process has exited
++        assert!(ptrace::cont(child, None).is_ok());
++        assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));
++    }
++
++    #[test]
++    fn test_wait_ptrace() {
++        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++        match fork().expect("Error: Fork Failed") {
++            Child => ptrace_child(),
++            Parent { child } => ptrace_parent(child),
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test.rs b/third_party/rust/nix-0.15.0/test/test.rs
+new file mode 100644
+index 0000000000000..6a71d261b5712
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test.rs
+@@ -0,0 +1,149 @@
++// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
++#![allow(deprecated)]
++extern crate bytes;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++extern crate caps;
++#[macro_use]
++extern crate cfg_if;
++#[macro_use]
++extern crate nix;
++#[macro_use]
++extern crate lazy_static;
++extern crate libc;
++extern crate rand;
++#[cfg(target_os = "freebsd")]
++extern crate sysctl;
++extern crate tempfile;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++macro_rules! require_capability {
++    ($capname:ident) => {
++        use ::caps::{Capability, CapSet, has_cap};
++        use ::std::io::{self, Write};
++
++        if !has_cap(None, CapSet::Effective, Capability::$capname).unwrap() {
++            let stderr = io::stderr();
++            let mut handle = stderr.lock();
++            writeln!(handle, "Insufficient capabilities. Skipping test.")
++                .unwrap();
++            return;
++        }
++    }
++}
++
++#[cfg(target_os = "freebsd")]
++macro_rules! skip_if_jailed {
++    ($name:expr) => {
++        use ::sysctl::CtlValue;
++
++        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
++            .unwrap()
++        {
++            use ::std::io::Write;
++            let stderr = ::std::io::stderr();
++            let mut handle = stderr.lock();
++            writeln!(handle, "{} cannot run in a jail. Skipping test.", $name)
++                .unwrap();
++            return;
++        }
++    }
++}
++
++macro_rules! skip_if_not_root {
++    ($name:expr) => {
++        use nix::unistd::Uid;
++
++        if !Uid::current().is_root() {
++            use ::std::io::Write;
++            let stderr = ::std::io::stderr();
++            let mut handle = stderr.lock();
++            writeln!(handle, "{} requires root privileges. Skipping test.", $name).unwrap();
++            return;
++        }
++    };
++}
++
++mod sys;
++mod test_dir;
++mod test_fcntl;
++#[cfg(any(target_os = "android",
++          target_os = "linux"))]
++mod test_kmod;
++#[cfg(any(target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "fushsia",
++          target_os = "linux",
++          target_os = "netbsd"))]
++mod test_mq;
++mod test_net;
++mod test_nix_path;
++mod test_poll;
++mod test_pty;
++#[cfg(any(target_os = "android",
++          target_os = "freebsd",
++          target_os = "ios",
++          target_os = "linux",
++          target_os = "macos"))]
++mod test_sendfile;
++mod test_stat;
++mod test_unistd;
++
++use std::os::unix::io::RawFd;
++use std::path::PathBuf;
++use std::sync::{Mutex, RwLock, RwLockWriteGuard};
++use nix::unistd::{chdir, getcwd, read};
++
++/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
++fn read_exact(f: RawFd, buf: &mut  [u8]) {
++    let mut len = 0;
++    while len < buf.len() {
++        // get_mut would be better than split_at_mut, but it requires nightly
++        let (_, remaining) = buf.split_at_mut(len);
++        len += read(f, remaining).unwrap();
++    }
++}
++
++lazy_static! {
++    /// Any test that changes the process's current working directory must grab
++    /// the RwLock exclusively.  Any process that cares about the current
++    /// working directory must grab it shared.
++    pub static ref CWD_LOCK: RwLock<()> = RwLock::new(());
++    /// Any test that creates child processes must grab this mutex, regardless
++    /// of what it does with those children.
++    pub static ref FORK_MTX: Mutex<()> = Mutex::new(());
++    /// Any test that changes the process's supplementary groups must grab this
++    /// mutex
++    pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(());
++    /// Any tests that loads or unloads kernel modules must grab this mutex
++    pub static ref KMOD_MTX: Mutex<()> = Mutex::new(());
++    /// Any test that calls ptsname(3) must grab this mutex.
++    pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(());
++    /// Any test that alters signal handling must grab this mutex.
++    pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(());
++}
++
++/// RAII object that restores a test's original directory on drop
++struct DirRestore<'a> {
++    d: PathBuf,
++    _g: RwLockWriteGuard<'a, ()>
++}
++
++impl<'a> DirRestore<'a> {
++    fn new() -> Self {
++        let guard = ::CWD_LOCK.write()
++            .expect("Lock got poisoned by another test");
++        DirRestore{
++            _g: guard,
++            d: getcwd().unwrap(),
++        }
++    }
++}
++
++impl<'a> Drop for DirRestore<'a> {
++    fn drop(&mut self) {
++        let r = chdir(&self.d);
++        if std::thread::panicking() {
++            r.unwrap();
++        }
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_dir.rs b/third_party/rust/nix-0.15.0/test/test_dir.rs
+new file mode 100644
+index 0000000000000..c42fbcd18a29d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_dir.rs
+@@ -0,0 +1,46 @@
++extern crate nix;
++extern crate tempfile;
++
++use nix::dir::{Dir, Type};
++use nix::fcntl::OFlag;
++use nix::sys::stat::Mode;
++use std::fs::File;
++use self::tempfile::tempdir;
++
++#[test]
++fn read() {
++    let tmp = tempdir().unwrap();
++    File::create(&tmp.path().join("foo")).unwrap();
++    ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap();
++    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
++                            Mode::empty()).unwrap();
++    let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect();
++    entries.sort_by(|a, b| a.file_name().cmp(b.file_name()));
++    let entry_names: Vec<_> = entries
++        .iter()
++        .map(|e| e.file_name().to_str().unwrap().to_owned())
++        .collect();
++    assert_eq!(&entry_names[..], &[".", "..", "bar", "foo"]);
++
++    // Check file types. The system is allowed to return DT_UNKNOWN (aka None here) but if it does
++    // return a type, ensure it's correct.
++    assert!(&[Some(Type::Directory), None].contains(&entries[0].file_type())); // .: dir
++    assert!(&[Some(Type::Directory), None].contains(&entries[1].file_type())); // ..: dir
++    assert!(&[Some(Type::Symlink), None].contains(&entries[2].file_type())); // bar: symlink
++    assert!(&[Some(Type::File), None].contains(&entries[3].file_type())); // foo: regular file
++}
++
++#[test]
++fn rewind() {
++    let tmp = tempdir().unwrap();
++    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
++                            Mode::empty()).unwrap();
++    let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
++    let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
++    assert_eq!(entries1, entries2);
++}
++
++#[test]
++fn ebadf() {
++    assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::Sys(nix::errno::Errno::EBADF));
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_fcntl.rs b/third_party/rust/nix-0.15.0/test/test_fcntl.rs
+new file mode 100644
+index 0000000000000..6b2bbd679fc31
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_fcntl.rs
+@@ -0,0 +1,234 @@
++use nix::Error;
++use nix::errno::*;
++use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
++use nix::sys::stat::Mode;
++use nix::unistd::{close, read};
++use tempfile::{self, NamedTempFile};
++use std::fs::File;
++use std::io::prelude::*;
++use std::os::unix::fs;
++
++#[test]
++fn test_openat() {
++    const CONTENTS: &[u8] = b"abcd";
++    let mut tmp = NamedTempFile::new().unwrap();
++    tmp.write_all(CONTENTS).unwrap();
++
++    let dirfd = open(tmp.path().parent().unwrap(),
++                     OFlag::empty(),
++                     Mode::empty()).unwrap();
++    let fd = openat(dirfd,
++                    tmp.path().file_name().unwrap(),
++                    OFlag::O_RDONLY,
++                    Mode::empty()).unwrap();
++
++    let mut buf = [0u8; 1024];
++    assert_eq!(4, read(fd, &mut buf).unwrap());
++    assert_eq!(CONTENTS, &buf[0..4]);
++
++    close(fd).unwrap();
++    close(dirfd).unwrap();
++}
++
++#[test]
++fn test_renameat() {
++    let old_dir = tempfile::tempdir().unwrap();
++    let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
++    let old_path = old_dir.path().join("old");
++    File::create(&old_path).unwrap();
++    let new_dir = tempfile::tempdir().unwrap();
++    let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
++    renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
++    assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
++               Error::Sys(Errno::ENOENT));
++    close(old_dirfd).unwrap();
++    close(new_dirfd).unwrap();
++    assert!(new_dir.path().join("new").exists());
++}
++
++#[test]
++fn test_readlink() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let src = tempdir.path().join("a");
++    let dst = tempdir.path().join("b");
++    println!("a: {:?}, b: {:?}", &src, &dst);
++    fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
++    let dirfd = open(tempdir.path(),
++                     OFlag::empty(),
++                     Mode::empty()).unwrap();
++
++    let mut buf = vec![0; src.to_str().unwrap().len() + 1];
++    assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
++               src.to_str().unwrap());
++    assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
++               src.to_str().unwrap());
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++mod linux_android {
++    use std::io::prelude::*;
++    use std::io::SeekFrom;
++    use std::os::unix::prelude::*;
++
++    use libc::loff_t;
++
++    use nix::fcntl::*;
++    use nix::sys::uio::IoVec;
++    use nix::unistd::{close, pipe, read, write};
++
++    use tempfile::{tempfile, NamedTempFile};
++
++    /// This test creates a temporary file containing the contents
++    /// 'foobarbaz' and uses the `copy_file_range` call to transfer
++    /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
++    /// resulting file is read and should contain the contents `bar`.
++    /// The from_offset should be updated by the call to reflect
++    /// the 3 bytes read (6).
++    ///
++    /// FIXME: This test is disabled for linux based builds, because Travis
++    /// Linux version is too old for `copy_file_range`.
++    #[test]
++    #[ignore]
++    fn test_copy_file_range() {
++        const CONTENTS: &[u8] = b"foobarbaz";
++
++        let mut tmp1 = tempfile().unwrap();
++        let mut tmp2 = tempfile().unwrap();
++
++        tmp1.write_all(CONTENTS).unwrap();
++        tmp1.flush().unwrap();
++
++        let mut from_offset: i64 = 3;
++        copy_file_range(
++            tmp1.as_raw_fd(),
++            Some(&mut from_offset),
++            tmp2.as_raw_fd(),
++            None,
++            3,
++        )
++        .unwrap();
++
++        let mut res: String = String::new();
++        tmp2.seek(SeekFrom::Start(0)).unwrap();
++        tmp2.read_to_string(&mut res).unwrap();
++
++        assert_eq!(res, String::from("bar"));
++        assert_eq!(from_offset, 6);
++    }
++
++    #[test]
++    fn test_splice() {
++        const CONTENTS: &[u8] = b"abcdef123456";
++        let mut tmp = tempfile().unwrap();
++        tmp.write_all(CONTENTS).unwrap();
++
++        let (rd, wr) = pipe().unwrap();
++        let mut offset: loff_t = 5;
++        let res = splice(tmp.as_raw_fd(), Some(&mut offset),
++            wr, None, 2, SpliceFFlags::empty()).unwrap();
++
++        assert_eq!(2, res);
++
++        let mut buf = [0u8; 1024];
++        assert_eq!(2, read(rd, &mut buf).unwrap());
++        assert_eq!(b"f1", &buf[0..2]);
++        assert_eq!(7, offset);
++
++        close(rd).unwrap();
++        close(wr).unwrap();
++    }
++
++    #[test]
++    fn test_tee() {
++        let (rd1, wr1) = pipe().unwrap();
++        let (rd2, wr2) = pipe().unwrap();
++
++        write(wr1, b"abc").unwrap();
++        let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
++
++        assert_eq!(2, res);
++
++        let mut buf = [0u8; 1024];
++
++        // Check the tee'd bytes are at rd2.
++        assert_eq!(2, read(rd2, &mut buf).unwrap());
++        assert_eq!(b"ab", &buf[0..2]);
++
++        // Check all the bytes are still at rd1.
++        assert_eq!(3, read(rd1, &mut buf).unwrap());
++        assert_eq!(b"abc", &buf[0..3]);
++
++        close(rd1).unwrap();
++        close(wr1).unwrap();
++        close(rd2).unwrap();
++        close(wr2).unwrap();
++    }
++
++    #[test]
++    fn test_vmsplice() {
++        let (rd, wr) = pipe().unwrap();
++
++        let buf1 = b"abcdef";
++        let buf2 = b"defghi";
++        let mut iovecs = Vec::with_capacity(2);
++        iovecs.push(IoVec::from_slice(&buf1[0..3]));
++        iovecs.push(IoVec::from_slice(&buf2[0..3]));
++
++        let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
++
++        assert_eq!(6, res);
++
++        // Check the bytes can be read at rd.
++        let mut buf = [0u8; 32];
++        assert_eq!(6, read(rd, &mut buf).unwrap());
++        assert_eq!(b"abcdef", &buf[0..6]);
++
++        close(rd).unwrap();
++        close(wr).unwrap();
++    }
++
++    #[test]
++    fn test_fallocate() {
++        let tmp = NamedTempFile::new().unwrap();
++
++        let fd = tmp.as_raw_fd();
++        fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
++
++        // Check if we read exactly 100 bytes
++        let mut buf = [0u8; 200];
++        assert_eq!(100, read(fd, &mut buf).unwrap());
++    }
++}
++
++#[cfg(any(target_os = "linux",
++          target_os = "android",
++          target_os = "emscripten",
++          target_os = "fuchsia",
++          any(target_os = "wasi", target_env = "wasi"),
++          target_env = "uclibc",
++          target_env = "freebsd"))]
++mod test_posix_fadvise {
++
++    use tempfile::NamedTempFile;
++    use std::os::unix::io::{RawFd, AsRawFd};
++    use nix::errno::Errno;
++    use nix::fcntl::*;
++    use nix::unistd::pipe;
++
++    #[test]
++    fn test_success() {
++        let tmp = NamedTempFile::new().unwrap();
++        let fd = tmp.as_raw_fd();
++        let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED).unwrap();
++
++        assert_eq!(res, 0);
++    }
++
++    #[test]
++    fn test_errno() {
++        let (rd, _wr) = pipe().unwrap();
++        let errno = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
++                                 .unwrap();
++        assert_eq!(errno, Errno::ESPIPE as i32);
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
+new file mode 100644
+index 0000000000000..74c99b77e96e1
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
+@@ -0,0 +1,7 @@
++obj-m += hello.o
++
++all:
++	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
++
++clean:
++	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
+diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
+new file mode 100644
+index 0000000000000..1c34987d2ac39
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
+@@ -0,0 +1,26 @@
++/*
++ *  SPDX-License-Identifier: GPL-2.0+ or MIT
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++
++static int number= 1;
++static char *who = "World";
++
++module_param(number, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
++MODULE_PARM_DESC(myint, "Just some number");
++module_param(who, charp, 0000);
++MODULE_PARM_DESC(who, "Whot to greet");
++
++int init_module(void)
++{
++	printk(KERN_INFO "Hello %s (%d)!\n", who, number);
++	return 0;
++}
++
++void cleanup_module(void)
++{
++	printk(KERN_INFO "Goodbye %s (%d)!\n", who, number);
++}
++
++MODULE_LICENSE("Dual MIT/GPL");
+diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs b/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
+new file mode 100644
+index 0000000000000..ad406357b06d2
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
+@@ -0,0 +1,166 @@
++use std::fs::copy;
++use std::path::PathBuf;
++use std::process::Command;
++use tempfile::{tempdir, TempDir};
++
++fn compile_kernel_module() -> (PathBuf, String, TempDir) {
++    let _m = ::FORK_MTX
++        .lock()
++        .expect("Mutex got poisoned by another test");
++
++    let tmp_dir = tempdir().expect("unable to create temporary build directory");
++
++    copy(
++        "test/test_kmod/hello_mod/hello.c",
++        &tmp_dir.path().join("hello.c"),
++    ).expect("unable to copy hello.c to temporary build directory");
++    copy(
++        "test/test_kmod/hello_mod/Makefile",
++        &tmp_dir.path().join("Makefile"),
++    ).expect("unable to copy Makefile to temporary build directory");
++
++    let status = Command::new("make")
++        .current_dir(tmp_dir.path())
++        .status()
++        .expect("failed to run make");
++
++    assert!(status.success());
++
++    // Return the relative path of the build kernel module
++    (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir)
++}
++
++use nix::errno::Errno;
++use nix::kmod::{delete_module, DeleteModuleFlags};
++use nix::kmod::{finit_module, init_module, ModuleInitFlags};
++use nix::Error;
++use std::ffi::CString;
++use std::fs::File;
++use std::io::Read;
++
++#[test]
++fn test_finit_and_delete_module() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
++
++    let f = File::open(kmod_path).expect("unable to open kernel module");
++    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
++        .expect("unable to load kernel module");
++
++    delete_module(
++        &CString::new(kmod_name).unwrap(),
++        DeleteModuleFlags::empty(),
++    ).expect("unable to unload kernel module");
++}
++
++#[test]
++fn test_finit_and_delete_modul_with_params() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
++
++    let f = File::open(kmod_path).expect("unable to open kernel module");
++    finit_module(
++        &f,
++        &CString::new("who=Rust number=2018").unwrap(),
++        ModuleInitFlags::empty(),
++    ).expect("unable to load kernel module");
++
++    delete_module(
++        &CString::new(kmod_name).unwrap(),
++        DeleteModuleFlags::empty(),
++    ).expect("unable to unload kernel module");
++}
++
++#[test]
++fn test_init_and_delete_module() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
++
++    let mut f = File::open(kmod_path).expect("unable to open kernel module");
++    let mut contents: Vec<u8> = Vec::new();
++    f.read_to_end(&mut contents)
++        .expect("unable to read kernel module content to buffer");
++    init_module(&mut contents, &CString::new("").unwrap()).expect("unable to load kernel module");
++
++    delete_module(
++        &CString::new(kmod_name).unwrap(),
++        DeleteModuleFlags::empty(),
++    ).expect("unable to unload kernel module");
++}
++
++#[test]
++fn test_init_and_delete_module_with_params() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
++
++    let mut f = File::open(kmod_path).expect("unable to open kernel module");
++    let mut contents: Vec<u8> = Vec::new();
++    f.read_to_end(&mut contents)
++        .expect("unable to read kernel module content to buffer");
++    init_module(&mut contents, &CString::new("who=Nix number=2015").unwrap())
++        .expect("unable to load kernel module");
++
++    delete_module(
++        &CString::new(kmod_name).unwrap(),
++        DeleteModuleFlags::empty(),
++    ).expect("unable to unload kernel module");
++}
++
++#[test]
++fn test_finit_module_invalid() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let kmod_path = "/dev/zero";
++
++    let f = File::open(kmod_path).expect("unable to open kernel module");
++    let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
++
++    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
++}
++
++#[test]
++fn test_finit_module_twice_and_delete_module() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
++
++    let f = File::open(kmod_path).expect("unable to open kernel module");
++    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
++        .expect("unable to load kernel module");
++
++    let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
++
++    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EEXIST));
++
++    delete_module(
++        &CString::new(kmod_name).unwrap(),
++        DeleteModuleFlags::empty(),
++    ).expect("unable to unload kernel module");
++}
++
++#[test]
++fn test_delete_module_not_loaded() {
++    require_capability!(CAP_SYS_MODULE);
++    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
++
++    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_mount.rs b/third_party/rust/nix-0.15.0/test/test_mount.rs
+new file mode 100644
+index 0000000000000..d2e08bc42855d
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_mount.rs
+@@ -0,0 +1,238 @@
++// Impelmentation note: to allow unprivileged users to run it, this test makes
++// use of user and mount namespaces. On systems that allow unprivileged user
++// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
++// without root.
++
++extern crate libc;
++extern crate nix;
++extern crate tempfile;
++
++#[cfg(target_os = "linux")]
++mod test_mount {
++    use std::fs::{self, File};
++    use std::io::{self, Read, Write};
++    use std::os::unix::fs::OpenOptionsExt;
++    use std::os::unix::fs::PermissionsExt;
++    use std::process::{self, Command};
++
++    use libc::{EACCES, EROFS};
++
++    use nix::errno::Errno;
++    use nix::mount::{mount, umount, MsFlags};
++    use nix::sched::{unshare, CloneFlags};
++    use nix::sys::stat::{self, Mode};
++    use nix::unistd::getuid;
++
++    use tempfile;
++
++    static SCRIPT_CONTENTS: &'static [u8] = b"#!/bin/sh
++exit 23";
++
++    const EXPECTED_STATUS: i32 = 23;
++
++    const NONE: Option<&'static [u8]> = None;
++    pub fn test_mount_tmpfs_without_flags_allows_rwx() {
++        let tempdir = tempfile::tempdir().unwrap();
++
++        mount(NONE,
++              tempdir.path(),
++              Some(b"tmpfs".as_ref()),
++              MsFlags::empty(),
++              NONE)
++            .unwrap_or_else(|e| panic!("mount failed: {}", e));
++
++        let test_path = tempdir.path().join("test");
++
++        // Verify write.
++        fs::OpenOptions::new()
++            .create(true)
++            .write(true)
++            .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
++            .open(&test_path)
++            .or_else(|e|
++                if Errno::from_i32(e.raw_os_error().unwrap()) == Errno::EOVERFLOW {
++                    // Skip tests on certain Linux kernels which have a bug
++                    // regarding tmpfs in namespaces.
++                    // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is
++                    // not.  There is no legitimate reason for open(2) to return
++                    // EOVERFLOW here.
++                    // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087
++                    let stderr = io::stderr();
++                    let mut handle = stderr.lock();
++                    writeln!(handle, "Buggy Linux kernel detected.  Skipping test.")
++                    .unwrap();
++                    process::exit(0);
++               } else {
++                   panic!("open failed: {}", e);
++               }
++            )
++            .and_then(|mut f| f.write(SCRIPT_CONTENTS))
++            .unwrap_or_else(|e| panic!("write failed: {}", e));
++
++        // Verify read.
++        let mut buf = Vec::new();
++        File::open(&test_path)
++            .and_then(|mut f| f.read_to_end(&mut buf))
++            .unwrap_or_else(|e| panic!("read failed: {}", e));
++        assert_eq!(buf, SCRIPT_CONTENTS);
++
++        // Verify execute.
++        assert_eq!(EXPECTED_STATUS,
++                   Command::new(&test_path)
++                       .status()
++                       .unwrap_or_else(|e| panic!("exec failed: {}", e))
++                       .code()
++                       .unwrap_or_else(|| panic!("child killed by signal")));
++
++        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
++    }
++
++    pub fn test_mount_rdonly_disallows_write() {
++        let tempdir = tempfile::tempdir().unwrap();
++
++        mount(NONE,
++              tempdir.path(),
++              Some(b"tmpfs".as_ref()),
++              MsFlags::MS_RDONLY,
++              NONE)
++            .unwrap_or_else(|e| panic!("mount failed: {}", e));
++
++        // EROFS: Read-only file system
++        assert_eq!(EROFS as i32,
++                   File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap());
++
++        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
++    }
++
++    pub fn test_mount_noexec_disallows_exec() {
++        let tempdir = tempfile::tempdir().unwrap();
++
++        mount(NONE,
++              tempdir.path(),
++              Some(b"tmpfs".as_ref()),
++              MsFlags::MS_NOEXEC,
++              NONE)
++            .unwrap_or_else(|e| panic!("mount failed: {}", e));
++
++        let test_path = tempdir.path().join("test");
++
++        fs::OpenOptions::new()
++            .create(true)
++            .write(true)
++            .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
++            .open(&test_path)
++            .and_then(|mut f| f.write(SCRIPT_CONTENTS))
++            .unwrap_or_else(|e| panic!("write failed: {}", e));
++
++        // Verify that we cannot execute despite a+x permissions being set.
++        let mode = stat::Mode::from_bits_truncate(fs::metadata(&test_path)
++                                                      .map(|md| md.permissions().mode())
++                                                      .unwrap_or_else(|e| {
++                                                          panic!("metadata failed: {}", e)
++                                                      }));
++
++        assert!(mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH),
++                "{:?} did not have execute permissions",
++                &test_path);
++
++        // EACCES: Permission denied
++        assert_eq!(EACCES as i32,
++                   Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap());
++
++        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
++    }
++
++    pub fn test_mount_bind() {
++        let tempdir = tempfile::tempdir().unwrap();
++        let file_name = "test";
++
++        {
++            let mount_point = tempfile::tempdir().unwrap();
++
++            mount(Some(tempdir.path()),
++                  mount_point.path(),
++                  NONE,
++                  MsFlags::MS_BIND,
++                  NONE)
++                .unwrap_or_else(|e| panic!("mount failed: {}", e));
++
++            fs::OpenOptions::new()
++                .create(true)
++                .write(true)
++                .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
++                .open(mount_point.path().join(file_name))
++                .and_then(|mut f| f.write(SCRIPT_CONTENTS))
++                .unwrap_or_else(|e| panic!("write failed: {}", e));
++
++            umount(mount_point.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
++        }
++
++        // Verify the file written in the mount shows up in source directory, even
++        // after unmounting.
++
++        let mut buf = Vec::new();
++        File::open(tempdir.path().join(file_name))
++            .and_then(|mut f| f.read_to_end(&mut buf))
++            .unwrap_or_else(|e| panic!("read failed: {}", e));
++        assert_eq!(buf, SCRIPT_CONTENTS);
++    }
++
++    pub fn setup_namespaces() {
++        // Hold on to the uid in the parent namespace.
++        let uid = getuid();
++
++        unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| {
++            let stderr = io::stderr();
++            let mut handle = stderr.lock();
++            writeln!(handle,
++                     "unshare failed: {}. Are unprivileged user namespaces available?",
++                     e).unwrap();
++            writeln!(handle, "mount is not being tested").unwrap();
++            // Exit with success because not all systems support unprivileged user namespaces, and
++            // that's not what we're testing for.
++            process::exit(0);
++        });
++
++        // Map user as uid 1000.
++        fs::OpenOptions::new()
++            .write(true)
++            .open("/proc/self/uid_map")
++            .and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes()))
++            .unwrap_or_else(|e| panic!("could not write uid map: {}", e));
++    }
++}
++
++
++// Test runner
++
++/// Mimic normal test output (hackishly).
++#[cfg(target_os = "linux")]
++macro_rules! run_tests {
++    ( $($test_fn:ident),* ) => {{
++        println!();
++
++        $(
++            print!("test test_mount::{} ... ", stringify!($test_fn));
++            $test_fn();
++            println!("ok");
++        )*
++
++        println!();
++    }}
++}
++
++#[cfg(target_os = "linux")]
++fn main() {
++    use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx,
++                     test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec,
++                     test_mount_bind};
++    setup_namespaces();
++
++    run_tests!(test_mount_tmpfs_without_flags_allows_rwx,
++               test_mount_rdonly_disallows_write,
++               test_mount_noexec_disallows_exec,
++               test_mount_bind);
++}
++
++#[cfg(not(target_os = "linux"))]
++fn main() {}
+diff --git a/third_party/rust/nix-0.15.0/test/test_mq.rs b/third_party/rust/nix-0.15.0/test/test_mq.rs
+new file mode 100644
+index 0000000000000..caac4fc261cd6
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_mq.rs
+@@ -0,0 +1,152 @@
++use libc::c_long;
++
++use std::ffi::CString;
++use std::str;
++
++use nix::errno::Errno::*;
++use nix::Error::Sys;
++use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive};
++use nix::mqueue::{MqAttr, MQ_OFlag};
++use nix::sys::stat::Mode;
++
++#[test]
++fn test_mq_send_and_receive() {
++    const MSG_SIZE: c_long =  32;
++    let attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
++    let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
++
++    let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
++    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
++    let r0 = mq_open(mq_name, oflag0, mode, Some(&attr));
++    if let Err(Sys(ENOSYS)) = r0 {
++        println!("message queues not supported or module not loaded?");
++        return;
++    };
++    let mqd0 = r0.unwrap();
++    let msg_to_send = "msg_1";
++    mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap();
++
++    let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
++    let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap();
++    let mut buf = [0u8; 32];
++    let mut prio = 0u32;
++    let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
++    assert!(prio == 1);
++
++    mq_close(mqd1).unwrap();
++    mq_close(mqd0).unwrap();
++    assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap());
++}
++
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_mq_getattr() {
++    use nix::mqueue::mq_getattr;
++    const MSG_SIZE: c_long =  32;
++    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
++    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
++    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
++    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
++    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
++    if let Err(Sys(ENOSYS)) = r {
++        println!("message queues not supported or module not loaded?");
++        return;
++    };
++    let mqd = r.unwrap();
++
++    let read_attr = mq_getattr(mqd).unwrap();
++    assert_eq!(read_attr, initial_attr);
++    mq_close(mqd).unwrap();
++}
++
++// FIXME: Fix failures for mips in QEMU
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
++fn test_mq_setattr() {
++    use nix::mqueue::{mq_getattr, mq_setattr};
++    const MSG_SIZE: c_long =  32;
++    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
++    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
++    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
++    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
++    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
++    if let Err(Sys(ENOSYS)) = r {
++        println!("message queues not supported or module not loaded?");
++        return;
++    };
++    let mqd = r.unwrap();
++
++    let new_attr =  MqAttr::new(0, 20, MSG_SIZE * 2, 100);
++    let old_attr = mq_setattr(mqd, &new_attr).unwrap();
++    assert_eq!(old_attr, initial_attr);
++
++    let new_attr_get = mq_getattr(mqd).unwrap();
++    // The following tests make sense. No changes here because according to the Linux man page only
++    // O_NONBLOCK can be set (see tests below)
++    assert_ne!(new_attr_get, new_attr);
++
++    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0);
++    mq_setattr(mqd, &new_attr_non_blocking).unwrap();
++    let new_attr_get = mq_getattr(mqd).unwrap();
++
++    // now the O_NONBLOCK flag has been set
++    assert_ne!(new_attr_get, initial_attr);
++    assert_eq!(new_attr_get, new_attr_non_blocking);
++    mq_close(mqd).unwrap();
++}
++
++// FIXME: Fix failures for mips in QEMU
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
++fn test_mq_set_nonblocking() {
++    use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
++    const MSG_SIZE: c_long =  32;
++    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
++    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
++    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
++    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
++    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
++    if let Err(Sys(ENOSYS)) = r {
++        println!("message queues not supported or module not loaded?");
++        return;
++    };
++    let mqd = r.unwrap();
++    mq_set_nonblock(mqd).unwrap();
++    let new_attr = mq_getattr(mqd);
++    assert!(new_attr.unwrap().flags() == MQ_OFlag::O_NONBLOCK.bits() as c_long);
++    mq_remove_nonblock(mqd).unwrap();
++    let new_attr = mq_getattr(mqd);
++    assert!(new_attr.unwrap().flags() == 0);
++    mq_close(mqd).unwrap();
++}
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_mq_unlink() {
++    use nix::mqueue::mq_unlink;
++    const MSG_SIZE: c_long =  32;
++    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
++    let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
++    let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
++    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
++    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
++    let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr));
++    if let Err(Sys(ENOSYS)) = r {
++        println!("message queues not supported or module not loaded?");
++        return;
++    };
++    let mqd = r.unwrap();
++
++    let res_unlink = mq_unlink(mq_name_opened);
++    assert!(res_unlink == Ok(()) );
++
++    let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
++    assert!(res_unlink_not_opened == Err(Sys(ENOENT)) );
++
++    mq_close(mqd).unwrap();
++    let res_unlink_after_close = mq_unlink(mq_name_opened);
++    assert!(res_unlink_after_close == Err(Sys(ENOENT)) );
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_net.rs b/third_party/rust/nix-0.15.0/test/test_net.rs
+new file mode 100644
+index 0000000000000..b8940e718bdf3
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_net.rs
+@@ -0,0 +1,12 @@
++use nix::net::if_::*;
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++const LOOPBACK: &[u8] = b"lo";
++
++#[cfg(not(any(target_os = "android", target_os = "linux")))]
++const LOOPBACK: &[u8] = b"lo0";
++
++#[test]
++fn test_if_nametoindex() {
++    assert!(if_nametoindex(&LOOPBACK[..]).is_ok());
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_nix_path.rs b/third_party/rust/nix-0.15.0/test/test_nix_path.rs
+new file mode 100644
+index 0000000000000..e69de29bb2d1d
+diff --git a/third_party/rust/nix-0.15.0/test/test_poll.rs b/third_party/rust/nix-0.15.0/test/test_poll.rs
+new file mode 100644
+index 0000000000000..aef40e4792b5a
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_poll.rs
+@@ -0,0 +1,50 @@
++use nix::poll::{PollFlags, poll, PollFd};
++use nix::unistd::{write, pipe};
++
++#[test]
++fn test_poll() {
++    let (r, w) = pipe().unwrap();
++    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
++
++    // Poll an idle pipe.  Should timeout
++    let nfds = poll(&mut fds, 100).unwrap();
++    assert_eq!(nfds, 0);
++    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
++
++    write(w, b".").unwrap();
++
++    // Poll a readable pipe.  Should return an event.
++    let nfds = poll(&mut fds, 100).unwrap();
++    assert_eq!(nfds, 1);
++    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
++}
++
++// ppoll(2) is the same as poll except for how it handles timeouts and signals.
++// Repeating the test for poll(2) should be sufficient to check that our
++// bindings are correct.
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux"))]
++#[test]
++fn test_ppoll() {
++    use nix::poll::ppoll;
++    use nix::sys::signal::SigSet;
++    use nix::sys::time::{TimeSpec, TimeValLike};
++
++    let timeout = TimeSpec::milliseconds(1);
++    let (r, w) = pipe().unwrap();
++    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
++
++    // Poll an idle pipe.  Should timeout
++    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
++    assert_eq!(nfds, 0);
++    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
++
++    write(w, b".").unwrap();
++
++    // Poll a readable pipe.  Should return an event.
++    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
++    assert_eq!(nfds, 1);
++    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_pty.rs b/third_party/rust/nix-0.15.0/test/test_pty.rs
+new file mode 100644
+index 0000000000000..476b15c10128c
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_pty.rs
+@@ -0,0 +1,235 @@
++use std::io::Write;
++use std::path::Path;
++use std::os::unix::prelude::*;
++use tempfile::tempfile;
++
++use libc::{_exit, STDOUT_FILENO};
++use nix::fcntl::{OFlag, open};
++use nix::pty::*;
++use nix::sys::stat;
++use nix::sys::termios::*;
++use nix::unistd::{write, close, pause};
++
++/// Regression test for Issue #659
++/// This is the correct way to explicitly close a `PtyMaster`
++#[test]
++fn test_explicit_close() {
++    let mut f = {
++        let m = posix_openpt(OFlag::O_RDWR).unwrap();
++        close(m.into_raw_fd()).unwrap();
++        tempfile().unwrap()
++    };
++    // This should work.  But if there's been a double close, then it will
++    // return EBADF
++    f.write_all(b"whatever").unwrap();
++}
++
++/// Test equivalence of `ptsname` and `ptsname_r`
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptsname_equivalence() {
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open a new PTTY master
++    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
++    assert!(master_fd.as_raw_fd() > 0);
++
++    // Get the name of the slave
++    let slave_name = unsafe { ptsname(&master_fd) }.unwrap() ;
++    let slave_name_r = ptsname_r(&master_fd).unwrap();
++    assert_eq!(slave_name, slave_name_r);
++}
++
++/// Test data copying of `ptsname`
++// TODO need to run in a subprocess, since ptsname is non-reentrant
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptsname_copy() {
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open a new PTTY master
++    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
++    assert!(master_fd.as_raw_fd() > 0);
++
++    // Get the name of the slave
++    let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
++    let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
++    assert!(slave_name1 == slave_name2);
++    // Also make sure that the string was actually copied and they point to different parts of
++    // memory.
++    assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
++}
++
++/// Test data copying of `ptsname_r`
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptsname_r_copy() {
++    // Open a new PTTY master
++    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
++    assert!(master_fd.as_raw_fd() > 0);
++
++    // Get the name of the slave
++    let slave_name1 = ptsname_r(&master_fd).unwrap();
++    let slave_name2 = ptsname_r(&master_fd).unwrap();
++    assert!(slave_name1 == slave_name2);
++    assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
++}
++
++/// Test that `ptsname` returns different names for different devices
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_ptsname_unique() {
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open a new PTTY master
++    let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
++    assert!(master1_fd.as_raw_fd() > 0);
++
++    // Open a second PTTY master
++    let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap();
++    assert!(master2_fd.as_raw_fd() > 0);
++
++    // Get the name of the slave
++    let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap();
++    let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap();
++    assert!(slave_name1 != slave_name2);
++}
++
++/// Test opening a master/slave PTTY pair
++///
++/// This is a single larger test because much of these functions aren't useful by themselves. So for
++/// this test we perform the basic act of getting a file handle for a connect master/slave PTTY
++/// pair.
++#[test]
++fn test_open_ptty_pair() {
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open a new PTTY master
++    let master_fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
++    assert!(master_fd.as_raw_fd() > 0);
++
++    // Allow a slave to be generated for it
++    grantpt(&master_fd).expect("grantpt failed");
++    unlockpt(&master_fd).expect("unlockpt failed");
++
++    // Get the name of the slave
++    let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed");
++
++    // Open the slave device
++    let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
++    assert!(slave_fd > 0);
++}
++
++#[test]
++fn test_openpty() {
++    // openpty uses ptname(3) internally
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    let pty = openpty(None, None).unwrap();
++    assert!(pty.master > 0);
++    assert!(pty.slave > 0);
++
++    // Writing to one should be readable on the other one
++    let string = "foofoofoo\n";
++    let mut buf = [0u8; 10];
++    write(pty.master, string.as_bytes()).unwrap();
++    ::read_exact(pty.slave, &mut buf);
++
++    assert_eq!(&buf, string.as_bytes());
++
++    // Read the echo as well
++    let echoed_string = "foofoofoo\r\n";
++    let mut buf = [0u8; 11];
++    ::read_exact(pty.master, &mut buf);
++    assert_eq!(&buf, echoed_string.as_bytes());
++
++    let string2 = "barbarbarbar\n";
++    let echoed_string2 = "barbarbarbar\r\n";
++    let mut buf = [0u8; 14];
++    write(pty.slave, string2.as_bytes()).unwrap();
++    ::read_exact(pty.master, &mut buf);
++
++    assert_eq!(&buf, echoed_string2.as_bytes());
++
++    close(pty.master).unwrap();
++    close(pty.slave).unwrap();
++}
++
++#[test]
++fn test_openpty_with_termios() {
++    // openpty uses ptname(3) internally
++    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Open one pty to get attributes for the second one
++    let mut termios = {
++        let pty = openpty(None, None).unwrap();
++        assert!(pty.master > 0);
++        assert!(pty.slave > 0);
++        let termios = tcgetattr(pty.master).unwrap();
++        close(pty.master).unwrap();
++        close(pty.slave).unwrap();
++        termios
++    };
++    // Make sure newlines are not transformed so the data is preserved when sent.
++    termios.output_flags.remove(OutputFlags::ONLCR);
++
++    let pty = openpty(None, &termios).unwrap();
++    // Must be valid file descriptors
++    assert!(pty.master > 0);
++    assert!(pty.slave > 0);
++
++    // Writing to one should be readable on the other one
++    let string = "foofoofoo\n";
++    let mut buf = [0u8; 10];
++    write(pty.master, string.as_bytes()).unwrap();
++    ::read_exact(pty.slave, &mut buf);
++
++    assert_eq!(&buf, string.as_bytes());
++
++    // read the echo as well
++    let echoed_string = "foofoofoo\n";
++    ::read_exact(pty.master, &mut buf);
++    assert_eq!(&buf, echoed_string.as_bytes());
++
++    let string2 = "barbarbarbar\n";
++    let echoed_string2 = "barbarbarbar\n";
++    let mut buf = [0u8; 13];
++    write(pty.slave, string2.as_bytes()).unwrap();
++    ::read_exact(pty.master, &mut buf);
++
++    assert_eq!(&buf, echoed_string2.as_bytes());
++
++    close(pty.master).unwrap();
++    close(pty.slave).unwrap();
++}
++
++#[test]
++fn test_forkpty() {
++    use nix::unistd::ForkResult::*;
++    use nix::sys::signal::*;
++    use nix::sys::wait::wait;
++    // forkpty calls openpty which uses ptname(3) internally.
++    let _m0 = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    // forkpty spawns a child process
++    let _m1 = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    let string = "naninani\n";
++    let echoed_string = "naninani\r\n";
++    let pty = forkpty(None, None).unwrap();
++    match pty.fork_result {
++        Child => {
++            write(STDOUT_FILENO, string.as_bytes()).unwrap();
++            pause();  // we need the child to stay alive until the parent calls read
++            unsafe { _exit(0); }
++        },
++        Parent { child } => {
++            let mut buf = [0u8; 10];
++            assert!(child.as_raw() > 0);
++            ::read_exact(pty.master, &mut buf);
++            kill(child, SIGTERM).unwrap();
++            wait().unwrap(); // keep other tests using generic wait from getting our child
++            assert_eq!(&buf, echoed_string.as_bytes());
++            close(pty.master).unwrap();
++        },
++    }
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs b/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
+new file mode 100644
+index 0000000000000..9b59d66435ed0
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
+@@ -0,0 +1,21 @@
++extern crate nix;
++
++use nix::fcntl::OFlag;
++use nix::pty::*;
++use nix::unistd::close;
++use std::os::unix::io::AsRawFd;
++
++/// Regression test for Issue #659
++/// `PtyMaster` should panic rather than double close the file descriptor
++/// This must run in its own test process because it deliberately creates a race
++/// condition.
++#[test]
++#[should_panic(expected = "Closing an invalid file descriptor!")]
++// In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't know
++// why.  It doesn't happen on any other target, and it doesn't happen on my PC.
++#[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
++fn test_double_close() {
++    let m = posix_openpt(OFlag::O_RDWR).unwrap();
++    close(m.as_raw_fd()).unwrap();
++    drop(m);            // should panic here
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_sendfile.rs b/third_party/rust/nix-0.15.0/test/test_sendfile.rs
+new file mode 100644
+index 0000000000000..3bc7932f4c84f
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_sendfile.rs
+@@ -0,0 +1,129 @@
++use std::io::prelude::*;
++use std::os::unix::prelude::*;
++
++use libc::off_t;
++use nix::sys::sendfile::*;
++use tempfile::tempfile;
++
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        use nix::unistd::{close, pipe, read};
++    } else if #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] {
++        use std::net::Shutdown;
++        use std::os::unix::net::UnixStream;
++    }
++}
++
++#[cfg(any(target_os = "android", target_os = "linux"))]
++#[test]
++fn test_sendfile_linux() {
++    const CONTENTS: &[u8] = b"abcdef123456";
++    let mut tmp = tempfile().unwrap();
++    tmp.write_all(CONTENTS).unwrap();
++
++    let (rd, wr) = pipe().unwrap();
++    let mut offset: off_t = 5;
++    let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap();
++
++    assert_eq!(2, res);
++
++    let mut buf = [0u8; 1024];
++    assert_eq!(2, read(rd, &mut buf).unwrap());
++    assert_eq!(b"f1", &buf[0..2]);
++    assert_eq!(7, offset);
++
++    close(rd).unwrap();
++    close(wr).unwrap();
++}
++
++#[cfg(target_os = "freebsd")]
++#[test]
++fn test_sendfile_freebsd() {
++    // Declare the content
++    let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
++    let body = "Xabcdef123456";
++    let body_offset = 1;
++    let trailer_strings = vec!["\n", "Served by Make Believe\n"];
++
++    // Write the body to a file
++    let mut tmp = tempfile().unwrap();
++    tmp.write_all(body.as_bytes()).unwrap();
++
++    // Prepare headers and trailers for sendfile
++    let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
++    let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
++
++    // Prepare socket pair
++    let (mut rd, wr) = UnixStream::pair().unwrap();
++
++    // Call the test method
++    let (res, bytes_written) = sendfile(
++        tmp.as_raw_fd(),
++        wr.as_raw_fd(),
++        body_offset as off_t,
++        None,
++        Some(headers.as_slice()),
++        Some(trailers.as_slice()),
++        SfFlags::empty(),
++        0,
++    );
++    assert!(res.is_ok());
++    wr.shutdown(Shutdown::Both).unwrap();
++
++    // Prepare the expected result
++    let expected_string =
++        header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
++
++    // Verify the message that was sent
++    assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
++
++    let mut read_string = String::new();
++    let bytes_read = rd.read_to_string(&mut read_string).unwrap();
++    assert_eq!(bytes_written as usize, bytes_read);
++    assert_eq!(expected_string, read_string);
++}
++
++#[cfg(any(target_os = "ios", target_os = "macos"))]
++#[test]
++fn test_sendfile_darwin() {
++    // Declare the content
++    let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
++    let body = "Xabcdef123456";
++    let body_offset = 1;
++    let trailer_strings = vec!["\n", "Served by Make Believe\n"];
++
++    // Write the body to a file
++    let mut tmp = tempfile().unwrap();
++    tmp.write_all(body.as_bytes()).unwrap();
++
++    // Prepare headers and trailers for sendfile
++    let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
++    let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
++
++    // Prepare socket pair
++    let (mut rd, wr) = UnixStream::pair().unwrap();
++
++    // Call the test method
++    let (res, bytes_written) = sendfile(
++        tmp.as_raw_fd(),
++        wr.as_raw_fd(),
++        body_offset as off_t,
++        None,
++        Some(headers.as_slice()),
++        Some(trailers.as_slice()),
++    );
++    assert!(res.is_ok());
++    wr.shutdown(Shutdown::Both).unwrap();
++
++    // Prepare the expected result
++    let expected_string =
++        header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
++
++    // Verify the message that was sent
++    assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
++
++    let mut read_string = String::new();
++    let bytes_read = rd.read_to_string(&mut read_string).unwrap();
++    assert_eq!(bytes_written as usize, bytes_read);
++    assert_eq!(expected_string, read_string);
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_stat.rs b/third_party/rust/nix-0.15.0/test/test_stat.rs
+new file mode 100644
+index 0000000000000..1173455fae8db
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_stat.rs
+@@ -0,0 +1,296 @@
++use std::fs::{self, File};
++use std::os::unix::fs::{symlink, PermissionsExt};
++use std::os::unix::prelude::AsRawFd;
++use std::time::{Duration, UNIX_EPOCH};
++use std::path::Path;
++
++#[cfg(not(any(target_os = "netbsd")))]
++use libc::{S_IFMT, S_IFLNK, mode_t};
++
++use nix::{fcntl, Error};
++use nix::errno::{Errno};
++use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
++#[cfg(any(target_os = "linux",
++          target_os = "haiku",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "freebsd",
++          target_os = "netbsd"))]
++use nix::sys::stat::lutimes;
++use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags};
++
++#[cfg(not(any(target_os = "netbsd")))]
++use nix::sys::stat::FileStat;
++
++use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
++use nix::unistd::chdir;
++
++#[cfg(not(any(target_os = "netbsd")))]
++use nix::Result;
++use tempfile;
++
++#[allow(unused_comparisons)]
++// uid and gid are signed on Windows, but not on other platforms. This function
++// allows warning free compiles on all platforms, and can be removed when
++// expression-level #[allow] is available.
++#[cfg(not(any(target_os = "netbsd")))]
++fn valid_uid_gid(stat: FileStat) -> bool {
++    // uid could be 0 for the `root` user. This quite possible when
++    // the tests are being run on a rooted Android device.
++    stat.st_uid >= 0 && stat.st_gid >= 0
++}
++
++#[cfg(not(any(target_os = "netbsd")))]
++fn assert_stat_results(stat_result: Result<FileStat>) {
++    let stats = stat_result.expect("stat call failed");
++    assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
++    assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
++    assert!(stats.st_mode > 0);     // must be positive integer
++    assert!(stats.st_nlink == 1);   // there links created, must be 1
++    assert!(valid_uid_gid(stats));  // must be positive integers
++    assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
++    assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
++    assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
++}
++
++#[cfg(not(any(target_os = "netbsd")))]
++fn assert_lstat_results(stat_result: Result<FileStat>) {
++    let stats = stat_result.expect("stat call failed");
++    assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
++    assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
++    assert!(stats.st_mode > 0);     // must be positive integer
++
++    // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
++    // (u16 on Android), and that will be a compile error.
++    // On other platforms they are the same (either both are u16 or u32).
++    assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
++    assert!(stats.st_nlink == 1);   // there links created, must be 1
++    assert!(valid_uid_gid(stats));  // must be positive integers
++    assert!(stats.st_size > 0);    // size is > 0 because it points to another file
++    assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
++
++    // st_blocks depends on whether the machine's file system uses fast
++    // or slow symlinks, so just make sure it's not negative
++    // (Android's st_blocks is ulonglong which is always non-negative.)
++    assert!(stats.st_blocks >= 0);
++}
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_stat_and_fstat() {
++    use nix::sys::stat::fstat;
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = tempdir.path().join("foo.txt");
++    let file = File::create(&filename).unwrap();
++
++    let stat_result = stat(&filename);
++    assert_stat_results(stat_result);
++
++    let fstat_result = fstat(file.as_raw_fd());
++    assert_stat_results(fstat_result);
++}
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_fstatat() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = tempdir.path().join("foo.txt");
++    File::create(&filename).unwrap();
++    let dirfd = fcntl::open(tempdir.path(),
++                            fcntl::OFlag::empty(),
++                            stat::Mode::empty());
++
++    let result = stat::fstatat(dirfd.unwrap(),
++                               &filename,
++                               fcntl::AtFlags::empty());
++    assert_stat_results(result);
++}
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_stat_fstat_lstat() {
++    use nix::sys::stat::{fstat, lstat};
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = tempdir.path().join("bar.txt");
++    let linkname = tempdir.path().join("barlink");
++
++    File::create(&filename).unwrap();
++    symlink("bar.txt", &linkname).unwrap();
++    let link = File::open(&linkname).unwrap();
++
++    // should be the same result as calling stat,
++    // since it's a regular file
++    let stat_result = stat(&filename);
++    assert_stat_results(stat_result);
++
++    let lstat_result = lstat(&linkname);
++    assert_lstat_results(lstat_result);
++
++    let fstat_result = fstat(link.as_raw_fd());
++    assert_stat_results(fstat_result);
++}
++
++#[test]
++fn test_fchmod() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = tempdir.path().join("foo.txt");
++    let file = File::create(&filename).unwrap();
++
++    let mut mode1 = Mode::empty();
++    mode1.insert(Mode::S_IRUSR);
++    mode1.insert(Mode::S_IWUSR);
++    fchmod(file.as_raw_fd(), mode1).unwrap();
++
++    let file_stat1 = stat(&filename).unwrap();
++    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
++
++    let mut mode2 = Mode::empty();
++    mode2.insert(Mode::S_IROTH);
++    fchmod(file.as_raw_fd(), mode2).unwrap();
++
++    let file_stat2 = stat(&filename).unwrap();
++    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
++}
++
++#[test]
++fn test_fchmodat() {
++    let _dr = ::DirRestore::new();
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = "foo.txt";
++    let fullpath = tempdir.path().join(filename);
++    File::create(&fullpath).unwrap();
++
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    let mut mode1 = Mode::empty();
++    mode1.insert(Mode::S_IRUSR);
++    mode1.insert(Mode::S_IWUSR);
++    fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap();
++
++    let file_stat1 = stat(&fullpath).unwrap();
++    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
++
++    chdir(tempdir.path()).unwrap();
++
++    let mut mode2 = Mode::empty();
++    mode2.insert(Mode::S_IROTH);
++    fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap();
++
++    let file_stat2 = stat(&fullpath).unwrap();
++    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
++}
++
++/// Asserts that the atime and mtime in a file's metadata match expected values.
++///
++/// The atime and mtime are expressed with a resolution of seconds because some file systems
++/// (like macOS's HFS+) do not have higher granularity.
++fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
++    assert_eq!(
++        Duration::new(exp_atime_sec, 0),
++        attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap());
++    assert_eq!(
++        Duration::new(exp_mtime_sec, 0),
++        attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
++}
++
++#[test]
++fn test_utimes() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let fullpath = tempdir.path().join("file");
++    drop(File::create(&fullpath).unwrap());
++
++    utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550)).unwrap();
++    assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
++}
++
++#[test]
++#[cfg(any(target_os = "linux",
++          target_os = "haiku",
++          target_os = "ios",
++          target_os = "macos",
++          target_os = "freebsd",
++          target_os = "netbsd"))]
++fn test_lutimes() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let target = tempdir.path().join("target");
++    let fullpath = tempdir.path().join("symlink");
++    drop(File::create(&target).unwrap());
++    symlink(&target, &fullpath).unwrap();
++
++    let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
++    lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)).unwrap();
++    assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
++
++    let target_metadata = fs::symlink_metadata(&target).unwrap();
++    assert_eq!(exp_target_metadata.accessed().unwrap(), target_metadata.accessed().unwrap(),
++               "atime of symlink target was unexpectedly modified");
++    assert_eq!(exp_target_metadata.modified().unwrap(), target_metadata.modified().unwrap(),
++               "mtime of symlink target was unexpectedly modified");
++}
++
++#[test]
++fn test_futimens() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let fullpath = tempdir.path().join("file");
++    drop(File::create(&fullpath).unwrap());
++
++    let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
++    assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
++}
++
++#[test]
++fn test_utimensat() {
++    let _dr = ::DirRestore::new();
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = "foo.txt";
++    let fullpath = tempdir.path().join(filename);
++    drop(File::create(&fullpath).unwrap());
++
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    utimensat(Some(dirfd), filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678),
++              UtimensatFlags::FollowSymlink).unwrap();
++    assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
++
++    chdir(tempdir.path()).unwrap();
++
++    utimensat(None, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800),
++              UtimensatFlags::FollowSymlink).unwrap();
++    assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
++}
++
++#[test]
++fn test_mkdirat_success_path() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = "example_subdir";
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++    assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
++    assert!(Path::exists(&tempdir.path().join(filename)));
++}
++
++#[test]
++fn test_mkdirat_success_mode() {
++    let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = "example_subdir";
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++    assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
++    let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions();
++    let mode = permissions.mode();
++    assert_eq!(mode as mode_t, expected_bits)
++}
++
++#[test]
++fn test_mkdirat_fail() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let not_dir_filename= "example_not_dir";
++    let filename = "example_subdir_dir";
++    let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT,
++                            stat::Mode::empty()).unwrap();
++    let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
++    assert_eq!(result, Error::Sys(Errno::ENOTDIR));
++}
+diff --git a/third_party/rust/nix-0.15.0/test/test_unistd.rs b/third_party/rust/nix-0.15.0/test/test_unistd.rs
+new file mode 100644
+index 0000000000000..46196dec7ccce
+--- /dev/null
++++ b/third_party/rust/nix-0.15.0/test/test_unistd.rs
+@@ -0,0 +1,669 @@
++use nix::fcntl::{self, fcntl, FcntlArg, FdFlag, open, OFlag, readlink};
++use nix::unistd::*;
++use nix::unistd::ForkResult::*;
++use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
++use nix::sys::wait::*;
++use nix::sys::stat::{self, Mode, SFlag};
++use nix::errno::Errno;
++use nix::Error;
++use std::{env, iter};
++use std::ffi::CString;
++use std::fs::{self, DirBuilder, File};
++use std::io::Write;
++use std::os::unix::prelude::*;
++use tempfile::{self, tempfile};
++use libc::{self, _exit, off_t};
++
++#[test]
++#[cfg(not(any(target_os = "netbsd")))]
++fn test_fork_and_waitpid() {
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Safe: Child only calls `_exit`, which is signal-safe
++    match fork().expect("Error: Fork Failed") {
++        Child => unsafe { _exit(0) },
++        Parent { child } => {
++            // assert that child was created and pid > 0
++            let child_raw: ::libc::pid_t = child.into();
++            assert!(child_raw > 0);
++            let wait_status = waitpid(child, None);
++            match wait_status {
++                // assert that waitpid returned correct status and the pid is the one of the child
++                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),
++
++                // panic, must never happen
++                s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
++
++                // panic, waitpid should never fail
++                Err(s) => panic!("Error: waitpid returned Err({:?}", s)
++            }
++
++        },
++    }
++}
++
++#[test]
++fn test_wait() {
++    // Grab FORK_MTX so wait doesn't reap a different test's child process
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Safe: Child only calls `_exit`, which is signal-safe
++    match fork().expect("Error: Fork Failed") {
++        Child => unsafe { _exit(0) },
++        Parent { child } => {
++            let wait_status = wait();
++
++            // just assert that (any) one child returns with WaitStatus::Exited
++            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
++        },
++    }
++}
++
++#[test]
++fn test_mkstemp() {
++    let mut path = env::temp_dir();
++    path.push("nix_tempfile.XXXXXX");
++
++    let result = mkstemp(&path);
++    match result {
++        Ok((fd, path)) => {
++            close(fd).unwrap();
++            unlink(path.as_path()).unwrap();
++        },
++        Err(e) => panic!("mkstemp failed: {}", e)
++    }
++}
++
++#[test]
++fn test_mkstemp_directory() {
++    // mkstemp should fail if a directory is given
++    assert!(mkstemp(&env::temp_dir()).is_err());
++}
++
++#[test]
++fn test_mkfifo() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let mkfifo_fifo = tempdir.path().join("mkfifo_fifo");
++
++    mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
++
++    let stats = stat::stat(&mkfifo_fifo).unwrap();
++    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
++    assert!(typ == SFlag::S_IFIFO);
++}
++
++#[test]
++fn test_mkfifo_directory() {
++    // mkfifo should fail if a directory is given
++    assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err());
++}
++
++#[test]
++fn test_getpid() {
++    let pid: ::libc::pid_t = getpid().into();
++    let ppid: ::libc::pid_t = getppid().into();
++    assert!(pid > 0);
++    assert!(ppid > 0);
++}
++
++#[test]
++fn test_getsid() {
++    let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
++    let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
++    assert!(none_sid > 0);
++    assert!(none_sid == pid_sid);
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++mod linux_android {
++    use nix::unistd::gettid;
++
++    #[test]
++    fn test_gettid() {
++        let tid: ::libc::pid_t = gettid().into();
++        assert!(tid > 0);
++    }
++}
++
++#[test]
++// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++fn test_setgroups() {
++    // Skip this test when not run as root as `setgroups()` requires root.
++    skip_if_not_root!("test_setgroups");
++
++    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Save the existing groups
++    let old_groups = getgroups().unwrap();
++
++    // Set some new made up groups
++    let groups = [Gid::from_raw(123), Gid::from_raw(456)];
++    setgroups(&groups).unwrap();
++
++    let new_groups = getgroups().unwrap();
++    assert_eq!(new_groups, groups);
++
++    // Revert back to the old groups
++    setgroups(&old_groups).unwrap();
++}
++
++#[test]
++// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
++#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++fn test_initgroups() {
++    // Skip this test when not run as root as `initgroups()` and `setgroups()`
++    // require root.
++    skip_if_not_root!("test_initgroups");
++
++    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
++
++    // Save the existing groups
++    let old_groups = getgroups().unwrap();
++
++    // It doesn't matter if the root user is not called "root" or if a user
++    // called "root" doesn't exist. We are just checking that the extra,
++    // made-up group, `123`, is set.
++    // FIXME: Test the other half of initgroups' functionality: whether the
++    // groups that the user belongs to are also set.
++    let user = CString::new("root").unwrap();
++    let group = Gid::from_raw(123);
++    let group_list = getgrouplist(&user, group).unwrap();
++    assert!(group_list.contains(&group));
++
++    initgroups(&user, group).unwrap();
++
++    let new_groups = getgroups().unwrap();
++    assert_eq!(new_groups, group_list);
++
++    // Revert back to the old groups
++    setgroups(&old_groups).unwrap();
++}
++
++macro_rules! execve_test_factory(
++    ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
++    #[test]
++    fn $test_name() {
++        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++        // The `exec`d process will write to `writer`, and we'll read that
++        // data from `reader`.
++        let (reader, writer) = pipe().unwrap();
++
++        // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
++        // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
++        //       The tests make sure not to do that, though.
++        match fork().unwrap() {
++            Child => {
++                // Close stdout.
++                close(1).unwrap();
++                // Make `writer` be the stdout of the new process.
++                dup(writer).unwrap();
++                // exec!
++                $syscall(
++                    $exe,
++                    $(&CString::new($pathname).unwrap(), )*
++                    &[CString::new(b"".as_ref()).unwrap(),
++                      CString::new(b"-c".as_ref()).unwrap(),
++                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
++                                   .as_ref()).unwrap()],
++                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
++                      CString::new(b"baz=quux".as_ref()).unwrap()]
++                    $(, $flags)*).unwrap();
++            },
++            Parent { child } => {
++                // Wait for the child to exit.
++                waitpid(child, None).unwrap();
++                // Read 1024 bytes.
++                let mut buf = [0u8; 1024];
++                read(reader, &mut buf).unwrap();
++                // It should contain the things we printed using `/bin/sh`.
++                let string = String::from_utf8_lossy(&buf);
++                assert!(string.contains("nix!!!"));
++                assert!(string.contains("foo=bar"));
++                assert!(string.contains("baz=quux"));
++            }
++        }
++    }
++    )
++);
++
++cfg_if!{
++    if #[cfg(target_os = "android")] {
++        execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
++        execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
++    } else if #[cfg(any(target_os = "freebsd",
++                        target_os = "linux"))] {
++        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
++        execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
++    } else if #[cfg(any(target_os = "dragonfly",
++                        target_os = "ios",
++                        target_os = "macos",
++                        target_os = "netbsd",
++                        target_os = "openbsd"))] {
++        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
++        // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
++        //
++        // Note for NetBSD and OpenBSD: although rust-lang/libc includes it
++        // (under unix/bsd/netbsdlike/) fexecve is not currently implemented on
++        // NetBSD nor on OpenBSD.
++    }
++}
++
++#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))]
++execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
++
++cfg_if!{
++    if #[cfg(target_os = "android")] {
++        use nix::fcntl::AtFlags;
++        execve_test_factory!(test_execveat_empty, execveat, File::open("/system/bin/sh").unwrap().into_raw_fd(),
++                             "", AtFlags::AT_EMPTY_PATH);
++        execve_test_factory!(test_execveat_relative, execveat, File::open("/system/bin/").unwrap().into_raw_fd(),
++                             "./sh", AtFlags::empty());
++        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
++                             "/system/bin/sh", AtFlags::empty());
++    } else if #[cfg(all(target_os = "linux"), any(target_arch ="x86_64", target_arch ="x86"))] {
++        use nix::fcntl::AtFlags;
++        execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
++                             "", AtFlags::AT_EMPTY_PATH);
++        execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(),
++                             "./sh", AtFlags::empty());
++        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
++                             "/bin/sh", AtFlags::empty());
++    }
++}
++
++#[test]
++fn test_fchdir() {
++    // fchdir changes the process's cwd
++    let _dr = ::DirRestore::new();
++
++    let tmpdir = tempfile::tempdir().unwrap();
++    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
++    let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
++
++    assert!(fchdir(tmpdir_fd).is_ok());
++    assert_eq!(getcwd().unwrap(), tmpdir_path);
++
++    assert!(close(tmpdir_fd).is_ok());
++}
++
++#[test]
++fn test_getcwd() {
++    // chdir changes the process's cwd
++    let _dr = ::DirRestore::new();
++
++    let tmpdir = tempfile::tempdir().unwrap();
++    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
++    assert!(chdir(&tmpdir_path).is_ok());
++    assert_eq!(getcwd().unwrap(), tmpdir_path);
++
++    // make path 500 chars longer so that buffer doubling in getcwd
++    // kicks in.  Note: One path cannot be longer than 255 bytes
++    // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
++    // 4096 on linux, 1024 on macos)
++    let mut inner_tmp_dir = tmpdir_path.to_path_buf();
++    for _ in 0..5 {
++        let newdir = iter::repeat("a").take(100).collect::<String>();
++        inner_tmp_dir.push(newdir);
++        assert!(mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU).is_ok());
++    }
++    assert!(chdir(inner_tmp_dir.as_path()).is_ok());
++    assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
++}
++
++#[test]
++fn test_chown() {
++    // Testing for anything other than our own UID/GID is hard.
++    let uid = Some(getuid());
++    let gid = Some(getgid());
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let path = tempdir.path().join("file");
++    {
++        File::create(&path).unwrap();
++    }
++
++    chown(&path, uid, gid).unwrap();
++    chown(&path, uid, None).unwrap();
++    chown(&path, None, gid).unwrap();
++
++    fs::remove_file(&path).unwrap();
++    chown(&path, uid, gid).unwrap_err();
++}
++
++#[test]
++fn test_fchownat() {
++    let _dr = ::DirRestore::new();
++    // Testing for anything other than our own UID/GID is hard.
++    let uid = Some(getuid());
++    let gid = Some(getgid());
++
++    let tempdir = tempfile::tempdir().unwrap();
++    let path = tempdir.path().join("file");
++    {
++        File::create(&path).unwrap();
++    }
++
++    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
++
++    fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
++
++    chdir(tempdir.path()).unwrap();
++    fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
++
++    fs::remove_file(&path).unwrap();
++    fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
++}
++
++#[test]
++fn test_lseek() {
++    const CONTENTS: &[u8] = b"abcdef123456";
++    let mut tmp = tempfile().unwrap();
++    tmp.write_all(CONTENTS).unwrap();
++    let tmpfd = tmp.into_raw_fd();
++
++    let offset: off_t = 5;
++    lseek(tmpfd, offset, Whence::SeekSet).unwrap();
++
++    let mut buf = [0u8; 7];
++    ::read_exact(tmpfd, &mut buf);
++    assert_eq!(b"f123456", &buf);
++
++    close(tmpfd).unwrap();
++}
++
++#[cfg(any(target_os = "linux", target_os = "android"))]
++#[test]
++fn test_lseek64() {
++    const CONTENTS: &[u8] = b"abcdef123456";
++    let mut tmp = tempfile().unwrap();
++    tmp.write_all(CONTENTS).unwrap();
++    let tmpfd = tmp.into_raw_fd();
++
++    lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
++
++    let mut buf = [0u8; 7];
++    ::read_exact(tmpfd, &mut buf);
++    assert_eq!(b"f123456", &buf);
++
++    close(tmpfd).unwrap();
++}
++
++cfg_if!{
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        macro_rules! require_acct{
++            () => {
++                require_capability!(CAP_SYS_PACCT);
++            }
++        }
++    } else if #[cfg(target_os = "freebsd")] {
++        macro_rules! require_acct{
++            () => {
++                skip_if_not_root!("test_acct");
++                skip_if_jailed!("test_acct");
++            }
++        }
++    } else {
++        macro_rules! require_acct{
++            () => {
++                skip_if_not_root!("test_acct");
++            }
++        }
++    }
++}
++
++#[test]
++fn test_acct() {
++    use tempfile::NamedTempFile;
++    use std::process::Command;
++    use std::{thread, time};
++
++    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    require_acct!();
++
++    let file = NamedTempFile::new().unwrap();
++    let path = file.path().to_str().unwrap();
++
++    acct::enable(path).unwrap();
++
++    loop {
++        Command::new("echo").arg("Hello world");
++        let len = fs::metadata(path).unwrap().len();
++        if len > 0 { break; }
++        thread::sleep(time::Duration::from_millis(10));
++    }
++    acct::disable().unwrap();
++}
++
++#[test]
++fn test_fpathconf_limited() {
++    let f = tempfile().unwrap();
++    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
++    let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
++    assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
++}
++
++#[test]
++fn test_pathconf_limited() {
++    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
++    let path_max = pathconf("/", PathconfVar::PATH_MAX);
++    assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0);
++}
++
++#[test]
++fn test_sysconf_limited() {
++    // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
++    let open_max = sysconf(SysconfVar::OPEN_MAX);
++    assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0);
++}
++
++#[cfg(target_os = "freebsd")]
++#[test]
++fn test_sysconf_unsupported() {
++    // I know of no sysconf variables that are unsupported everywhere, but
++    // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms
++    // we test.
++    let open_max = sysconf(SysconfVar::_XOPEN_CRYPT);
++    assert!(open_max.expect("sysconf failed").is_none())
++}
++
++// Test that we can create a pair of pipes.  No need to verify that they pass
++// data; that's the domain of the OS, not nix.
++#[test]
++fn test_pipe() {
++    let (fd0, fd1) = pipe().unwrap();
++    let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode);
++    // S_IFIFO means it's a pipe
++    assert_eq!(m0, SFlag::S_IFIFO);
++    let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode);
++    assert_eq!(m1, SFlag::S_IFIFO);
++}
++
++// pipe2(2) is the same as pipe(2), except it allows setting some flags.  Check
++// that we can set a flag.
++#[test]
++fn test_pipe2() {
++    let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
++    let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
++    assert!(f0.contains(FdFlag::FD_CLOEXEC));
++    let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
++    assert!(f1.contains(FdFlag::FD_CLOEXEC));
++}
++
++#[test]
++fn test_truncate() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let path = tempdir.path().join("file");
++
++    {
++        let mut tmp = File::create(&path).unwrap();
++        const CONTENTS: &[u8] = b"12345678";
++        tmp.write_all(CONTENTS).unwrap();
++    }
++
++    truncate(&path, 4).unwrap();
++
++    let metadata = fs::metadata(&path).unwrap();
++    assert_eq!(4, metadata.len());
++}
++
++#[test]
++fn test_ftruncate() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let path = tempdir.path().join("file");
++
++    let tmpfd = {
++        let mut tmp = File::create(&path).unwrap();
++        const CONTENTS: &[u8] = b"12345678";
++        tmp.write_all(CONTENTS).unwrap();
++        tmp.into_raw_fd()
++    };
++
++    ftruncate(tmpfd, 2).unwrap();
++    close(tmpfd).unwrap();
++
++    let metadata = fs::metadata(&path).unwrap();
++    assert_eq!(2, metadata.len());
++}
++
++// Used in `test_alarm`.
++static mut ALARM_CALLED: bool = false;
++
++// Used in `test_alarm`.
++pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
++    assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
++    unsafe { ALARM_CALLED = true };
++}
++
++#[test]
++fn test_alarm() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    let handler = SigHandler::Handler(alarm_signal_handler);
++    let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
++    let old_handler = unsafe {
++        sigaction(Signal::SIGALRM, &signal_action)
++            .expect("unable to set signal handler for alarm")
++    };
++
++    // Set an alarm.
++    assert_eq!(alarm::set(60), None);
++
++    // Overwriting an alarm should return the old alarm.
++    assert_eq!(alarm::set(1), Some(60));
++
++    // We should be woken up after 1 second by the alarm, so we'll sleep for 2
++    // seconds to be sure.
++    sleep(2);
++    assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");
++
++    // Reset the signal.
++    unsafe {
++        sigaction(Signal::SIGALRM, &old_handler)
++            .expect("unable to set signal handler for alarm");
++    }
++}
++
++#[test]
++fn test_canceling_alarm() {
++    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    assert_eq!(alarm::cancel(), None);
++
++    assert_eq!(alarm::set(60), None);
++    assert_eq!(alarm::cancel(), Some(60));
++}
++
++#[test]
++fn test_symlinkat() {
++    let mut buf = [0; 1024];
++    let tempdir = tempfile::tempdir().unwrap();
++
++    let target = tempdir.path().join("a");
++    let linkpath = tempdir.path().join("b");
++    symlinkat(&target, None, &linkpath).unwrap();
++    assert_eq!(
++        readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
++        target.to_str().unwrap()
++    );
++
++    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
++    let target = "c";
++    let linkpath = "d";
++    symlinkat(target, Some(dirfd), linkpath).unwrap();
++    assert_eq!(
++        readlink(&tempdir.path().join(linkpath), &mut buf)
++            .unwrap()
++            .to_str()
++            .unwrap(),
++        target
++    );
++}
++
++
++#[test]
++fn test_unlinkat_dir_noremovedir() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let dirname = "foo_dir";
++    let dirpath = tempdir.path().join(dirname);
++
++    // Create dir
++    DirBuilder::new().recursive(true).create(&dirpath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt unlink dir at relative path without proper flag
++    let err_result = unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
++    assert!(err_result == Error::Sys(Errno::EISDIR) || err_result == Error::Sys(Errno::EPERM));
++ }
++
++#[test]
++fn test_unlinkat_dir_removedir() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let dirname = "foo_dir";
++    let dirpath = tempdir.path().join(dirname);
++
++    // Create dir
++    DirBuilder::new().recursive(true).create(&dirpath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt unlink dir at relative path with proper flag
++    unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap();
++    assert!(!dirpath.exists());
++ }
++
++#[test]
++fn test_unlinkat_file() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let filename = "foo.txt";
++    let filepath = tempdir.path().join(filename);
++
++    // Create file
++    File::create(&filepath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt unlink file at relative path
++    unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap();
++    assert!(!filepath.exists());
++ }
++
++#[test]
++fn test_access_not_existing() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let dir = tempdir.path().join("does_not_exist.txt");
++    assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
++               Errno::ENOENT);
++}
++
++#[test]
++fn test_access_file_exists() {
++    let tempdir = tempfile::tempdir().unwrap();
++    let path  = tempdir.path().join("does_exist.txt");
++    let _file = File::create(path.clone()).unwrap();
++    assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
++}
+diff --git a/third_party/rust/nix/.cargo-checksum.json b/third_party/rust/nix/.cargo-checksum.json
+index e5f2bc789185a..85adbc1eae931 100644
+--- a/third_party/rust/nix/.cargo-checksum.json
++++ b/third_party/rust/nix/.cargo-checksum.json
+@@ -1 +1 @@
+-{"files":{"CHANGELOG.md":"91af9fd5f2d9cdb9c8bb750e24b625742e95a6c74bcff419f3de70eb26578281","CONTRIBUTING.md":"a9101e3d1487170d691d5f062ff49a433c167582ac8984dd41a744be92652f74","CONVENTIONS.md":"e150ce43c1d188c392c1a3bf7f2e08e3cf84906705c7bef43f319037d29ea385","Cargo.toml":"af0cc0ae7ff4bf6c2e5b35fe062f54fe2d619f70ba67795f4f43a981420b5de0","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"80d71b9eaac7bf7f0d307372592ed1467f994291e6fad816a44f3c70e2887d0f","build.rs":"14c9c678c33f5894509da47f77d6a326b14aecb4190ce87a24cce98687ca63b2","src/dir.rs":"21e330cbe6594274335b94d9e9b6059f1fa8e53d2e5b5c697058c52ec6b3c5ff","src/errno.rs":"a009ccf18b45c0a4c9319c65b0dc5bc322d9ad43cfe462ec4661559f44162451","src/errno_dragonfly.c":"a857e47b114acb85fddcb252a610ab5734d225c26b7bedd7c35d7789d46c8526","src/fcntl.rs":"6ae2f7f01dd2568b82a4e57f86e02b1d63eec6c26111c5adb2ca5d78a2a99fe7","src/features.rs":"22ff626ff8287a07dd55bcfc63c9f518c19c56144e15f9b6f9e3bbdcda51c2a8","
 src/ifaddrs.rs":"9a93de176edcca4613e668b8ccc2c3e3b6b711aa2d8d94ccb0ba08694d1ef35f","src/kmod.rs":"4d8a695d3d761f351a39d654303a1bd168e74295b7d142b918737e355b24f34d","src/lib.rs":"fdd8049a79ffb92384c72f0a6b0bab717001ddfa9b01f2b33413c83f424f2ac8","src/macros.rs":"aec27fa0fd98900913fada926c9a4581cd28f2640e3a7b5480707f923c9200f8","src/mount.rs":"cdf5db8409017483132db9d7493b5d6cc96df5560d0fa5ad8f385aff72db10ca","src/mqueue.rs":"82af42b31381af73e7966f845d1ed93957f0b9976bf2da524b178fad15b2b08d","src/net/if_.rs":"f7e02076fcf3cadf3fdf141884c9bd2c468a7047ba60bc490f0057df802b53ce","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"7305e250066cd1a7318cd239ed3db787937ee98426fe9289cf00fa874d76b6c7","src/pty.rs":"6b965b586579933af47d4efef4c82c391b927037eaa08d8c83fc974ef17fc7c8","src/sched.rs":"f9b214fa60006b5450ffb3589a55ec59c3694bd49597c65c38ac813fcd96c7dd","src/sys/aio.rs":"a1ba629258b3ce1268e5fe8e5b41dce3581f77d415dc5e2455c1f82f26dd3085","src/sys/e
 poll.rs":"f0b539e0645569657f2142db91a38c94ebe1925f44852d64c61c818758dbbf0b","src/sys/event.rs":"ef8bc02a08d9ce7924c87f8f891fa051587b195a36913712fe85237a2fe0685b","src/sys/eventfd.rs":"08008cf3dc64c2216847c02c0dd8d7189cf08edbaafe35ba2c57c053fde09ef4","src/sys/inotify.rs":"687c8417d737939aa93f805d6003afc4f84f50828b1bd9429ef5d00bef0e0955","src/sys/ioctl/bsd.rs":"56ca6ecf5f7cfb566f4f3ba589fcc778f747a517dd45e13780981922e6215344","src/sys/ioctl/linux.rs":"6cfbdff4dbfa1a3782acdedebe89ffa9f000fdfc4ab68cb46f52890ebc1c6f2d","src/sys/ioctl/mod.rs":"20bc3cf1fcbbc7c31e4d507baa4e576a793ea42fb33618d2e7afeda730c4324f","src/sys/memfd.rs":"11cd93c867fdbdbc9588cecb94268691de42b2ef2a38fe33525be7c7f60c85d5","src/sys/mman.rs":"f77d28611a7ff3bf62784a3c4f26d7d79969395b1d9bbc6ff15e734f52dc404f","src/sys/mod.rs":"f39a08c72e37638c7cecfb9c087e0a41e2b69409aa545b0ef7bbd59c0a063ee2","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"8a7eacfc172b55763ae
 32109bf9b252669ba68b72cd5122f7504eb35c0c08345","src/sys/ptrace/linux.rs":"f09b45148004f4b28d8503c397a8d112d31046c98e68335bf4e89425d5b33f07","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"7eb8e797466b506f6ed882f18eda92c4639cf43d9384a19bc39cd1bf982989c9","src/sys/reboot.rs":"fde9da27c2928f7026231430fa14fec2058df4e49a0aeda2a237a60524f11241","src/sys/select.rs":"57d6c4403d1bf788bd52ab6f03cfc16a189d31b6bfb338b135cb775fe369121f","src/sys/sendfile.rs":"ea386e83baf9b5b23488aca26635aacdc92f2bfe238e4399a7380bd0331e0ef7","src/sys/signal.rs":"9216cdd609b4dfb9c2e559c411be6b7c722f7ddd8024682c0895a32126b488aa","src/sys/signalfd.rs":"bfcfce619bf199e50f9cc80a3eb778d48474a015cfdafc64a0c3517373a225a9","src/sys/socket/addr.rs":"8b297ce13cd8ad200b3e764888c26ceb582ee505385d1e172440de94ade99644","src/sys/socket/mod.rs":"e0353f04f3d098a8bf5e2aae431645897b96e0889fb76537dc0330159c6f233d","src/sys/socket/sockopt.rs":"c663505d6a7a7ae9d76e03fbc17e5
 3d308ea6b1eae92212812e1d76b2bf2916f","src/sys/stat.rs":"c4807048f86be67026756737cf81f448ec23c2a4745776cb40f40b533a88e0c8","src/sys/statfs.rs":"d2b72069f20aa7782ce5de4ec2d00c76a82a92376c2066bbb270cdac2167719e","src/sys/statvfs.rs":"2d328cf525ba04ab1e1351128624a7df7d0c55ea91fda6c8d620d13710d61606","src/sys/sysinfo.rs":"0c05244655aa9e6dff5138392c5c1ae97630d35bae0e5510d7f51a75c31fd425","src/sys/termios.rs":"a2e99afdfc3526641a2cb82b57bfd0a25a362fb9be5ad37ff9f11acaeb0b9439","src/sys/time.rs":"8a1224b9262026086af698630aedbed21b45d661fbd045fc6c6af41a16a23374","src/sys/uio.rs":"60a974275ff8c485ea183bdd6f7e25894e6f2360a5bfb25442391a825a3b9b8c","src/sys/utsname.rs":"c977a1aec6e051c72b27506395e942abab9cbd9523e6d345ea66dc10875ee87d","src/sys/wait.rs":"30b14a8f518d031805cae6c6ff644116f162d8c8a75fddcfce4479d8d55fd1c0","src/ucontext.rs":"075560ec08a362881534211f8c6b78844886d6b767c2f7067174600e38ed3f63","src/unistd.rs":"82308ec31b6293b55f86fafd04e976a41127fedebb8f158abd1399c7399af947","test/sys/mod.
 rs":"e0821cbc289ad952f17229609c7de4282cca1e44cd13e1a7494a6378ecbc12f8","test/sys/test_aio.rs":"b2544bfb321ca7fbed276ee637c769fb438156d14666cdc1e1d547b3514a44e3","test/sys/test_aio_drop.rs":"30dd1d238269d00381fa50f6d3cb2b13794b7cceb9f6455f3878fcbffa9aa62d","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"eea690ed386da0a666df5eb23a417421fddb99dc8e39556f63b30969bb6cf779","test/sys/test_lio_listio_resubmit.rs":"203a583313542593148f375b087ae30620222a745680173fa98fc448d1e5ae7f","test/sys/test_pthread.rs":"3890e5ecbf2082e0d05d102cc9cec6e76ede3c15f250d104e3483b1c1c3400b1","test/sys/test_ptrace.rs":"4e8d5dff5fe6bc56e4ae53bdfd10f5e8ea567d8099576d1c690cf7a6b2bc955f","test/sys/test_select.rs":"bdb20211fc6ec1e3f186337eac51e08757acb6901d307d67c71bf9011f0d54bd","test/sys/test_signal.rs":"84ae63c2baa49eebeabe5bbd347b9c5417e14ba97f342719d7
 53dc1c1c768d60","test/sys/test_signalfd.rs":"71b5d6d782283f6db64ca90f7fb06617faec71091d59d2587e41bbc9d8c43d5c","test/sys/test_socket.rs":"09a7ef0322e07b4579893e0307a7c4f81fbbc653d005b827a519c33a33e185ce","test/sys/test_sockopt.rs":"b3d386c8279f86bf9439c772317bafcdba5630fa806c8319e87ddac0ccfa3a03","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"fa4be3ade859b527bf33408f85a6f57b127917cf5f2afb662d09f6019d07913a","test/sys/test_uio.rs":"9da234e3bd5003fd200cc37c4a5be147ecda1a7670feb1d505f23d646d3e1c57","test/sys/test_wait.rs":"e6c5147e213daa93892cd828f53214995d2e019ff2372cc48d85ce9b93d26ec9","test/test.rs":"e6307f82a39426a949b8e925a2df4a62e31c0e43081d7a33d23759bdfeeece1f","test/test_dir.rs":"5d137a62f11d1a4993b4bb35dccc38a4c4416b7da374887f2335a9895b4fdee4","test/test_fcntl.rs":"730e64e99dc867ba5af7cc4ca83a4489c8b96b1a52f8937bcc666d673af27002","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c903
 33ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"f4754f028402a8ba788c87686288424cd3784e77c7eb5d96682ef491b1dd5262","test/test_mount.rs":"78ddc657f5098360c764fffa3a7d844503e4b6b65b44bfd42d9aa9045b415cb6","test/test_mq.rs":"5806f8825e91edc79dd0e2bc81d8be3ba094c2de6c0b2ac0268221ae2ad22701","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"46c71ee988fe1b85561ea0530d099750be8c1b8f95ab6e845c8a9f46f16f060c","test/test_pty.rs":"be04f99904fa47b60400c2bd156a388b73df4b9aec2eebf13df7dcdfc9aacf45","test/test_ptymaster_drop.rs":"5cfbbb79551c205ab510c2d4ef497bf937ceac9151fbe2f2e543d6515e406990","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"1dc420d3119bf4d863a7ae0ba63efa7f1416f6e46e4
 100ea161003fe1c3f66ba","test/test_unistd.rs":"0325c998acca1e826e9e2b3d351d55ab9723a6cb2ca2072245978e7f5a9acee8"},"package":"3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"}
+\ No newline at end of file
++{"files":{"CHANGELOG.md":"9294216482039acf0dd5911548feaaf04d410298fc5cd3df450d8d36c914756e","CONTRIBUTING.md":"7da4f8c2ff8e06850bdd9ebc0a3552419fd21d2c6bb0c6f0719566e263b0a1b9","CONVENTIONS.md":"df0d4fe9fe65af0bfa4723dc7b641d5130087259799e6b404ad63884f79031cb","Cargo.toml":"03e8c7ae8afb88e9d698712e2428d19a367c19079e994a170cb16dca985cc48d","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"d7a8568ffb72d76acc2812d8f545ad71b24a7c1301d2a258f49057fcaded0b9f","src/dir.rs":"52170e8bfc8c4bc1996db2f5cd5a2aace71beac59e4a0e7c1817fdecbf8bd6a7","src/env.rs":"bc52e80d3fa6c5388e3e23767d214a72f88d2927c5604246016c4cf978bbbeb7","src/errno.rs":"1aab33e5dcab9c6f83e48e452f361840645ce6a434bc13bd8ab9abb0e0ef25c3","src/fcntl.rs":"7f3f95baad70ceb1231b8a647988a8e54292d84176820eb6a9f89d40f309c3a6","src/features.rs":"2cb080da3f26eca2d2e18282a41afec921426423a6354a50b840cf20f3f153f6","src/ifaddrs.rs":"4f19ed3b15f5059c2859958c6aa313d6fa75703e68f8608359ef8e0089508ed3","src/k
 mod.rs":"873bec7f32e30a552a4fd86d5f884c2b3a0cd73012121dfe1587b508475beb0a","src/lib.rs":"ae1a16e142c47afc3f52a07a2afb2fc013cfd427df955aa42e4bd372c77c49d5","src/macros.rs":"7c6c81441c967d73a75a975bb660ae48efde22c6f5ae2705c62a8db446ce0d39","src/mount.rs":"cde7c59b79a8e535c4d8c57c53d7825384b110be244803b1f895d5a3b97bc72f","src/mqueue.rs":"3520495f6a881a7239fba19e90234f7fc9df6729b6bc150bd2e6664b7c98d6a1","src/net/if_.rs":"928066a6ec473ce565e2323858ff64e179e4b81b80768d830dd29008f2fafb7f","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"ba635fbed688a165279a9851269310220befd211c8fcf5761d1a62dab39ba52b","src/pty.rs":"7a73ba21b2ec8910f7932e456d2fb097a0553c5fe07717238c58455e3de7b275","src/sched.rs":"2bdb5ce449bc093a8eecdd8964e5d05feee3e7b804e4271e40d674178295df79","src/sys/aio.rs":"bbcc1d8639a9c89c66c00357353dde94d0f48b516b4354ab3d3dcfc16a2e0b56","src/sys/epoll.rs":"a3ace2282e77989e9b927dcdca8ad2070d4fb7710398af0763ea6eb26d431968","src/sys/even
 t.rs":"075e84e5a5d1fd922fbcac8c01c8e7cd7f1a1c1f8f60ede8f7ebc5fe6d5e76ac","src/sys/eventfd.rs":"b5301029e95f77f280cc169bb8aa247352efbb600c749f26e2fffa0474c872bb","src/sys/inotify.rs":"114be3860c9daaee1c781df90b63abb87cd82d677c4470b359bbf0787a25d302","src/sys/ioctl/bsd.rs":"853b50c3539dc4a1284c847f2689fde3dbed5dca7a8599db36193048e030296a","src/sys/ioctl/linux.rs":"642b25d3997518815dea454fa976e9067ad5fe4ed75622e7540e3f0d0c7d320a","src/sys/ioctl/mod.rs":"dd3435e44c42f55a600e40599038bebc7417934dade00113ef0f3b6318bf54de","src/sys/memfd.rs":"35dba6c3eeb4f74edbf86530ba1696d9251495b82b814a36b76e6d2b26490e3c","src/sys/mman.rs":"bdca4a151dc31d27c7435e30a5030ad2edef9dd3ac69a33363454cada8466ca3","src/sys/mod.rs":"b8d7d9e3cb331f1d972699cfbaa54fff34a9f26eaba38b8ee49e84bfeee22bd3","src/sys/personality.rs":"2019e58aa69c5ad68ae060e1b9a399138a2e4742f37a868e2681588963ca8acf","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"feced79575c5dbea
 f0a0877ba888761675310b277f477acee820c785e132dbe9","src/sys/ptrace/linux.rs":"34524ad4911d2ef7ec0e21a49e479d6fd91d4ef5c660e0b7e2afa4878b27367a","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"4ceb895896bbd0bb67ce98e91dec3bd40c9a7d5936abbe13b74691c6afa07f9f","src/sys/reboot.rs":"1fd26955bc095bd4f8804c850183f527560803cbceaf345c3760c8f32fe1224f","src/sys/select.rs":"02226a733d160701f07d27384f87bf21032f3cc4d5a6214dc61e398dd1606b60","src/sys/sendfile.rs":"110955788e3f5f36a7e563c334c6fe400edfb93d6cb2fdce6b8a79d2e892f8ce","src/sys/signal.rs":"53232ef1165272d109173fbba769cde77f3446050dbdaf36e56c4c0fde084348","src/sys/signalfd.rs":"37704804eb75571d03bbc1c99bd90846ae50ce361cc9998777744f8265d51074","src/sys/socket/addr.rs":"0513e0fbe57c19f8f9538e31074a4ed50c443fd45dd66ce1fa56db2dee46b371","src/sys/socket/mod.rs":"7d0d0b2da45d45493c494ad8669f53577439510914777b03febb6d2f18dcc787","src/sys/socket/sockopt.rs":"42b335e7a2e2b8cf1605065244
 90bb685bd2488ebff65921aa10f60363ffda7b","src/sys/stat.rs":"a969ae88221a50c89d54f97987d108d3c017339d7eedd66ac7218463d2bb07db","src/sys/statfs.rs":"6bd23f941107dc79ec34dc50516ff5eb18d9fad108ad976796669505692c1582","src/sys/statvfs.rs":"09a7268f3f6f321961e4f25943236fe103fe8c7661ea841f4e71014fda0d8952","src/sys/sysinfo.rs":"1aa6f402bc10689c5dd7ad454ecb60834e2b065dddbd3d87d1daecf88cb2b3ee","src/sys/termios.rs":"c3c310cdec9c7c80e7b11ada25d3dc87c0d0fc6c30fcda8f94edab1d27132300","src/sys/time.rs":"cc955b6b6647ca1db33ac076780ca6c984200e3cc47df5d836b1528489cdef70","src/sys/timerfd.rs":"51443f37b1dd4b03f16e1b569945f0ae715db4028f69e3ddd6c311db00e67ab3","src/sys/uio.rs":"a25dd7a84135ea50a671a7a06a8989dc9d53d3e755d36cef9f37cdc79a123d9d","src/sys/utsname.rs":"9509a092c837d1700f9f4ac30e4568e5b9b63ad8925a56cd8ad7add05d0ac452","src/sys/wait.rs":"ab18e66acaf161750394d802409ee8c95707dbd68d2fb59c88f7d4ed8936a1be","src/time.rs":"957845f8c689aec3c5dcf1af8bbc274a28ed5a214e4ee31ec8a89ed5eea0d3f1","src/ucont
 ext.rs":"10fdfebcecafa8d1c6cf573a5768adc07b87e9ff52a0bdc2527e77f73608f264","src/unistd.rs":"9c2b170f2b217393e571fb8021e000dfec4a5d99e170e11532a665163ecf3d54","test/common/mod.rs":"a26ecf30fc06008bab21d96eabf711bb0c41e8b50fe4c1f35cb2797ef405296c","test/sys/mod.rs":"c6f6a376fca73025bd76043a1739f54d24e856d4d0af9c58cc2b9d730ab87144","test/sys/test_aio.rs":"f21c157a07a29d60b0d68baa78ce24b352a19a35eaced0a792f62fa16d38617f","test/sys/test_aio_drop.rs":"eb086fcebd53ec82359ed7323f039b16ef7abced66b111f4876486fb058476e5","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"39ddd52b27d942ab1b4018d213a378fb221598febc8fc7759ae5e6f746364396","test/sys/test_lio_listio_resubmit.rs":"29718e5fd04ef041125db4963f518f6f518b50436ea2df91e44c9c6b9418b704","test/sys/test_mman.rs":"b129b1d40d7a6e23cfc10956f9aa689d578a745f82fa267d24c40475063b592c","test/
 sys/test_pthread.rs":"891726053083bf488655eca1518630b08fa7c5937433fb5e446a9eed181ff7c5","test/sys/test_ptrace.rs":"46e51267cc93e45894a1e5a194563af5fb65a170dca95ad7cf9110520d764703","test/sys/test_select.rs":"7ece285a78cb66852ba8e89cac82c2d4fcff7d17a5f35e282cc52a09f5820daf","test/sys/test_signal.rs":"753f2ccbfcf2c5353a75b1e48d746a07c1949defba515c0ceee589ad1ed0aff6","test/sys/test_signalfd.rs":"2068a028c88395ff51c09e43b18c03d16e2d851f1d26ca1d121cdb5cb050f5c5","test/sys/test_socket.rs":"0f5fe9637f196cef459aadee27e449e5f9f968c10bf8dd017763c607cb6261d3","test/sys/test_sockopt.rs":"3334e12322e8b4e7c095ddc4a40a2d0e73a0d3a6e1820a6e0970eb8e1136c6de","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"93cd5cc181f1d8cef5c69aa23ddfabbf0480369cffab523e677c81e208998328","test/sys/test_timerfd.rs":"fcada956abd981e4d846da58e5640c5705b16026d47bccd1d603fae765ad10db","test/sys/test_uio.rs":"ae915c03e4f64ce370ae46f5dbe37834dae2849bb9
 fa7961872cec50f45de1f4","test/sys/test_wait.rs":"1fefed60ea3f9c5d8d4518e1d7a122d50aad44c2bd87873ac9ddc31ecdcc5a39","test/test.rs":"be9c29b8a8c9669b6674746ac8065c828a5d1d40ba41226846fe964310a18188","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e0dc7c317871eda3873a5d9df801c2ebb34cd958210c42a15f8dff623f05cae0","test/test_fcntl.rs":"e60c1dde6d0a6fde7a52cf98332e5b96fef5749868f0313cb7082bda7a66adb9","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"07f5445812593c994d1c25d5c8669aa3c4b1750f3b8ed2c1ddb1c661809983dc","test/test_mount.rs":"55503e8b28f77b45d755d549375cab34fa3a3cc9b94cbb23cfbd4426c5d9cb9c","test/test_mq.rs":"1020a4eb2f88cc29c59c44ad965d0573fba2beeb4c8986060aac56de99eea63c","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe
 49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"fbcf1780447f75a0177b4f47ba3d99b68f4324059ff66d993034ae5035c6d3ef","test/test_pty.rs":"56198cb9537ec3409717acecb133a49eb48bfc180c135ff0296974ec466d1171","test/test_ptymaster_drop.rs":"d162510cc96b8b7389d8bc34e097db1c80b84b5070c1d16f15b053ffd20cfa17","test/test_sched.rs":"f8ad92eb554164b0f92428f716db99040186d741cc6e1976f7930f099652f70c","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"9668fc1f894b7f8a60dfddbdaef4bc833463e4e0cf04c1cff7f8c0569a226ad2","test/test_time.rs":"199b1c89d373e9398cca97f83ecd6459c6bd5ba7adca28013d9109d5cbad03f3","test/test_unistd.rs":"9bf047d877fd7c0826a2241737574923c3fd102a6b143b6d9710f52af5655588"},"package":"f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"}
+\ No newline at end of file
+diff --git a/third_party/rust/nix/CHANGELOG.md b/third_party/rust/nix/CHANGELOG.md
+index d93a5ce6bbfc9..234f2307c6d36 100644
+--- a/third_party/rust/nix/CHANGELOG.md
++++ b/third_party/rust/nix/CHANGELOG.md
+@@ -2,12 +2,316 @@
+ 
+ All notable changes to this project will be documented in this file.
+ This project adheres to [Semantic Versioning](http://semver.org/).
++This project adheres to [Semantic Versioning](https://semver.org/).
+ 
+-## [Unreleased] - ReleaseDate
++## [0.20.2] - 28 September 2021
+ ### Added
+ ### Changed
+ ### Fixed
++
++- Fixed buffer overflow in `unistd::getgrouplist`.
++  (#[1545](https://github.com/nix-rust/nix/pull/1545))
++
++## [0.20.1] - 13 August 2021
++### Added
++### Changed
++### Fixed
++
++- Locked bitflags to < 1.3.0 to fix the build with rust < 1.46.0.
++
++### Removed
++
++- Removed a couple of termios constants on redox that were never actually
++  supported.
++  (#[1483](https://github.com/nix-rust/nix/pull/1483))
++
++## [0.20.0] - 20 February 2021
++### Added
++
++- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338))
++- Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306))
++- Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331))
++- Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285))
++- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342))
++- Implemented `IntoIterator` for `Dir`
++  (#[1333](https://github.com/nix-rust/nix/pull/1333)).
++
++### Changed
++
++- Minimum supported Rust version is now 1.40.0.
++  ([#1356](https://github.com/nix-rust/nix/pull/1356))
++- i686-apple-darwin has been demoted to Tier 2 support, because it's deprecated
++  by Xcode.
++  (#[1350](https://github.com/nix-rust/nix/pull/1350))
++- Fixed calling `recvfrom` on an `AddrFamily::Packet` socket
++  (#[1344](https://github.com/nix-rust/nix/pull/1344))
++
++### Fixed
++- `TimerFd` now closes the underlying fd on drop.
++  ([#1381](https://github.com/nix-rust/nix/pull/1381))
++- Define `*_MAGIC` filesystem constants on Linux s390x
++  (#[1372](https://github.com/nix-rust/nix/pull/1372))
++- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32
++  (#[1366](https://github.com/nix-rust/nix/pull/1366))
++
++### Removed
++
++- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`.
++  (#[1382](https://github.com/nix-rust/nix/pull/1382))
++- Removed `SockLevel`, which hasn't been used for a few years
++  (#[1362](https://github.com/nix-rust/nix/pull/1362))
++- Removed both `Copy` and `Clone` from `TimerFd`.
++  ([#1381](https://github.com/nix-rust/nix/pull/1381))
++
++## [0.19.1] - 28 November 2020
++### Fixed
++- Fixed bugs in `recvmmsg`.
++  (#[1341](https://github.com/nix-rust/nix/pull/1341))
++
++## [0.19.0] - 6 October 2020
++### Added
++- Added Netlink protocol families to the `SockProtocol` enum
++  (#[1289](https://github.com/nix-rust/nix/pull/1289))
++- Added `clock_gettime`, `clock_settime`, `clock_getres`,
++  `clock_getcpuclockid` functions and `ClockId` struct.
++  (#[1281](https://github.com/nix-rust/nix/pull/1281))
++- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`.
++  (#[1300](https://github.com/nix-rust/nix/pull/1300))
++- Add support for Vsock on Android rather than just Linux.
++  (#[1301](https://github.com/nix-rust/nix/pull/1301))
++- Added `TCP_KEEPCNT` and `TCP_KEEPINTVL` TCP keepalive options.
++  (#[1283](https://github.com/nix-rust/nix/pull/1283))
++### Changed
++- Expose `SeekData` and `SeekHole` on all Linux targets
++  (#[1284](https://github.com/nix-rust/nix/pull/1284))
++- Changed unistd::{execv,execve,execvp,execvpe,fexecve,execveat} to take both `&[&CStr]` and `&[CString]` as its list argument(s).
++  (#[1278](https://github.com/nix-rust/nix/pull/1278))
++- Made `unistd::fork` an unsafe funtion, bringing it in line with [libstd's decision](https://github.com/rust-lang/rust/pull/58059).
++  (#[1293](https://github.com/nix-rust/nix/pull/1293))
++### Fixed
++### Removed
++
++## [0.18.0] - 26 July 2020
++### Added
++- Added `fchown(2)` wrapper.
++  (#[1257](https://github.com/nix-rust/nix/pull/1257))
++- Added support on linux systems for `MAP_HUGE_`_`SIZE`_ family of flags.
++  (#[1211](https://github.com/nix-rust/nix/pull/1211))
++- Added support for `F_OFD_*` `fcntl` commands on Linux and Android.
++  (#[1195](https://github.com/nix-rust/nix/pull/1195))
++- Added `env::clearenv()`: calls `libc::clearenv` on platforms
++  where it's available, and clears the environment of all variables
++  via `std::env::vars` and `std::env::remove_var` on others.
++  (#[1185](https://github.com/nix-rust/nix/pull/1185))
++- `FsType` inner value made public.
++  (#[1187](https://github.com/nix-rust/nix/pull/1187))
++- Added `unistd::setfsuid` and `unistd::setfsgid` to set the user or group
++  identity for filesystem checks per-thread.
++  (#[1163](https://github.com/nix-rust/nix/pull/1163))
++- Derived `Ord`, `PartialOrd` for `unistd::Pid` (#[1189](https://github.com/nix-rust/nix/pull/1189))
++- Added `select::FdSet::fds` method to iterate over file descriptors in a set.
++  ([#1207](https://github.com/nix-rust/nix/pull/1207))
++- Added support for UDP generic segmentation offload (GSO) and generic
++  receive offload (GRO) ([#1209](https://github.com/nix-rust/nix/pull/1209))
++- Added support for `sendmmsg` and `recvmmsg` calls
++  (#[1208](https://github.com/nix-rust/nix/pull/1208))
++- Added support for `SCM_CREDS` messages (`UnixCredentials`) on FreeBSD/DragonFly
++  (#[1216](https://github.com/nix-rust/nix/pull/1216))
++- Added `BindToDevice` socket option (sockopt) on Linux
++  (#[1233](https://github.com/nix-rust/nix/pull/1233))
++- Added `EventFilter` bitflags for `EV_DISPATCH` and `EV_RECEIPT` on OpenBSD.
++  (#[1252](https://github.com/nix-rust/nix/pull/1252))
++- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage`.
++  (#[1222](https://github.com/nix-rust/nix/pull/1222))
++- `CpuSet` and `UnixCredentials` now implement `Default`.
++  (#[1244](https://github.com/nix-rust/nix/pull/1244))
++- Added `unistd::ttyname`
++  (#[1259](https://github.com/nix-rust/nix/pull/1259))
++- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage` for iOS and Android.
++  (#[1265](https://github.com/nix-rust/nix/pull/1265))
++- Added support for `TimerFd`.
++  (#[1261](https://github.com/nix-rust/nix/pull/1261))
++
++### Changed
++- Changed `fallocate` return type from `c_int` to `()` (#[1201](https://github.com/nix-rust/nix/pull/1201))
++- Enabled `sys::ptrace::setregs` and `sys::ptrace::getregs` on x86_64-unknown-linux-musl target
++  (#[1198](https://github.com/nix-rust/nix/pull/1198))
++- On Linux, `ptrace::write` is now an `unsafe` function. Caveat programmer.
++  (#[1245](https://github.com/nix-rust/nix/pull/1245))
++- `execv`, `execve`, `execvp` and `execveat` in `::nix::unistd` and `reboot` in
++  `::nix::sys::reboot` now return `Result<Infallible>` instead of `Result<Void>` (#[1239](https://github.com/nix-rust/nix/pull/1239))
++- `sys::socket::sockaddr_storage_to_addr` is no longer `unsafe`.  So is
++  `offset_of!`.
++- `sys::socket::sockaddr_storage_to_addr`, `offset_of!`, and `Errno::clear` are
++  no longer `unsafe`.
++- `SockAddr::as_ffi_pair`,`sys::socket::sockaddr_storage_to_addr`, `offset_of!`,
++  and `Errno::clear` are no longer `unsafe`.
++  (#[1244](https://github.com/nix-rust/nix/pull/1244))
++- Several `Inotify` methods now take `self` by value instead of by reference
++  (#[1244](https://github.com/nix-rust/nix/pull/1244))
++- `nix::poll::ppoll`: `timeout` parameter is now optional, None is equivalent for infinite timeout.
++
++### Fixed
++
++- Fixed `getsockopt`.  The old code produced UB which triggers a panic with
++  Rust 1.44.0.
++  (#[1214](https://github.com/nix-rust/nix/pull/1214))
++
++- Fixed a bug in nix::unistd that would result in an infinite loop
++  when a group or user lookup required a buffer larger than
++  16KB. (#[1198](https://github.com/nix-rust/nix/pull/1198))
++- Fixed unaligned casting of `cmsg_data` to `af_alg_iv` (#[1206](https://github.com/nix-rust/nix/pull/1206))
++- Fixed `readlink`/`readlinkat` when reading symlinks longer than `PATH_MAX` (#[1231](https://github.com/nix-rust/nix/pull/1231))
++- `PollFd`, `EpollEvent`, `IpMembershipRequest`, `Ipv6MembershipRequest`,
++  `TimeVal`, and `IoVec` are now `repr(transparent)`.  This is required for
++  correctness's sake across all architectures and compilers, though now bugs
++  have been reported so far.
++  (#[1243](https://github.com/nix-rust/nix/pull/1243))
++- Fixed unaligned pointer read in `Inotify::read_events`.
++  (#[1244](https://github.com/nix-rust/nix/pull/1244))
++
++### Removed
++
++- Removed `sys::socket::addr::from_libc_sockaddr` from the public API.
++  (#[1215](https://github.com/nix-rust/nix/pull/1215))
++- Removed `sys::termios::{get_libc_termios, get_libc_termios_mut, update_wrapper`
++  from the public API. These were previously hidden in the docs but still usable
++  by downstream.
++  (#[1235](https://github.com/nix-rust/nix/pull/1235))
++
++- Nix no longer implements `NixPath` for `Option<P> where P: NixPath`.  Most
++  Nix functions that accept `NixPath` arguments can't do anything useful with
++  `None`.  The exceptions (`mount` and `quotactl_sync`) already take explicitly
++  optional arguments.
++  (#[1242](https://github.com/nix-rust/nix/pull/1242))
++
++- Removed `unistd::daemon` and `unistd::pipe2` on OSX and ios
++  (#[1255](https://github.com/nix-rust/nix/pull/1255))
++
++- Removed `sys::event::FilterFlag::NOTE_EXIT_REPARENTED` and
++  `sys::event::FilterFlag::NOTE_REAP` on OSX and ios.
++  (#[1255](https://github.com/nix-rust/nix/pull/1255))
++
++- Removed `sys::ptrace::ptrace` on Android and Linux.
++  (#[1255](https://github.com/nix-rust/nix/pull/1255))
++
++- Dropped support for powerpc64-unknown-linux-gnu
++  (#[1266](https://github.com/nix-rust/nix/pull/1268))
++
++## [0.17.0] - 3 February 2020
++### Added
++- Add `CLK_TCK` to `SysconfVar`
++  (#[1177](https://github.com/nix-rust/nix/pull/1177))
++### Changed
++### Fixed
++### Removed
++- Removed deprecated Error::description from error types
++  (#[1175](https://github.com/nix-rust/nix/pull/1175))
++
++## [0.16.1] - 23 December 2019
++### Added
++### Changed
++### Fixed
++
++- Fixed the build for OpenBSD
++  (#[1168](https://github.com/nix-rust/nix/pull/1168))
++
++### Removed
++
++## [0.16.0] - 1 December 2019
++### Added
++- Added `ptrace::seize()`: similar to `attach()` on Linux
++  but with better-defined semantics.
++  (#[1154](https://github.com/nix-rust/nix/pull/1154))
++
++- Added `Signal::as_str()`: returns signal name as `&'static str`
++  (#[1138](https://github.com/nix-rust/nix/pull/1138))
++
++- Added `posix_fallocate`.
++  ([#1105](https://github.com/nix-rust/nix/pull/1105))
++
++- Implemented `Default` for `FdSet`
++  ([#1107](https://github.com/nix-rust/nix/pull/1107))
++
++- Added `NixPath::is_empty`.
++  ([#1107](https://github.com/nix-rust/nix/pull/1107))
++
++- Added `mkfifoat`
++  ([#1133](https://github.com/nix-rust/nix/pull/1133))
++
++- Added `User::from_uid`, `User::from_name`, `User::from_gid` and
++  `Group::from_name`,
++  ([#1139](https://github.com/nix-rust/nix/pull/1139))
++
++- Added `linkat`
++  ([#1101](https://github.com/nix-rust/nix/pull/1101))
++
++- Added `sched_getaffinity`.
++  ([#1148](https://github.com/nix-rust/nix/pull/1148))
++
++- Added optional `Signal` argument to `ptrace::{detach, syscall}` for signal
++  injection. ([#1083](https://github.com/nix-rust/nix/pull/1083))
++
++### Changed
++- `sys::termios::BaudRate` now implements `TryFrom<speed_t>` instead of
++  `From<speed_t>`.  The old `From` implementation would panic on failure.
++  ([#1159](https://github.com/nix-rust/nix/pull/1159))
++
++- `sys::socket::ControlMessage::ScmCredentials` and
++  `sys::socket::ControlMessageOwned::ScmCredentials` now wrap `UnixCredentials`
++  rather than `libc::ucred`.
++  ([#1160](https://github.com/nix-rust/nix/pull/1160))
++
++- `sys::socket::recvmsg` now takes a plain `Vec` instead of a `CmsgBuffer`
++  implementor.  If you were already using `cmsg_space!`, then you needn't worry.
++  ([#1156](https://github.com/nix-rust/nix/pull/1156))
++
++- `sys::socket::recvfrom` now returns
++  `Result<(usize, Option<SockAddr>)>` instead of `Result<(usize, SockAddr)>`.
++  ([#1145](https://github.com/nix-rust/nix/pull/1145))
++
++- `Signal::from_c_int` has been replaced by `Signal::try_from`
++  ([#1113](https://github.com/nix-rust/nix/pull/1113))
++
++- Changed `readlink` and `readlinkat` to return `OsString`
++  ([#1109](https://github.com/nix-rust/nix/pull/1109))
++
++  ```rust
++  # use nix::fcntl::{readlink, readlinkat};
++  // the buffer argument of `readlink` and `readlinkat` has been removed,
++  // and the return value is now an owned type (`OsString`).
++  // Existing code can be updated by removing the buffer argument
++  // and removing any clone or similar operation on the output
++
++  // old code `readlink(&path, &mut buf)` can be replaced with the following
++  let _: OsString = readlink(&path);
++
++  // old code `readlinkat(dirfd, &path, &mut buf)` can be replaced with the following
++  let _: OsString = readlinkat(dirfd, &path);
++  ```
++
++- Minimum supported Rust version is now 1.36.0.
++  ([#1108](https://github.com/nix-rust/nix/pull/1108))
++
++- `Ipv4Addr::octets`, `Ipv4Addr::to_std`, `Error::as_errno`,
++  `ForkResult::is_child`, `ForkResult::is_parent`, `Gid::as_raw`,
++  `Uid::is_root`, `Uid::as_raw`, `Pid::as_raw`, and `PollFd::revents` now take
++  `self` by value.
++  ([#1107](https://github.com/nix-rust/nix/pull/1107))
++
++- Type `&CString` for parameters of `exec(v|ve|vp|vpe|veat)` are changed to `&CStr`.
++  ([#1121](https://github.com/nix-rust/nix/pull/1121))
++
++### Fixed
++- Fix length of abstract socket addresses
++  ([#1120](https://github.com/nix-rust/nix/pull/1120))
++
++- Fix initialization of msghdr in recvmsg/sendmsg when built with musl
++  ([#1136](https://github.com/nix-rust/nix/pull/1136))
++
+ ### Removed
++- Remove the deprecated `CmsgSpace`.
++  ([#1156](https://github.com/nix-rust/nix/pull/1156))
+ 
+ ## [0.15.0] - 10 August 2019
+ ### Added
+diff --git a/third_party/rust/nix/CONTRIBUTING.md b/third_party/rust/nix/CONTRIBUTING.md
+index 03a1f630dbb06..55990c4f1a24f 100644
+--- a/third_party/rust/nix/CONTRIBUTING.md
++++ b/third_party/rust/nix/CONTRIBUTING.md
+@@ -76,21 +76,21 @@ add a test that would have failed without the fix.
+ 
+ After you've made your change, make sure the tests pass in your development
+ environment. We also have [continuous integration set up on
+-Travis-CI][travis-ci], which might find some issues on other platforms. The CI
++Cirrus-CI][cirrus-ci], which might find some issues on other platforms. The CI
+ will run once you open a pull request.
+ 
+ There is also infrastructure for running tests for other targets
+ locally.  More information is available in the [CI Readme][ci-readme].
+ 
+-[travis-ci]: https://travis-ci.org/nix-rust/nix
++[cirrus-ci]: https://cirrus-ci.com/github/nix-rust/nix
+ [ci-readme]: ci/README.md
+ 
+ ### Disabling a test in the CI environment
+ 
+ Sometimes there are features that cannot be tested in the CI environment.
+-To stop a test from running under CI, add `#[cfg_attr(travis, ignore)]`
+-to it. Please include a comment describing the reason it shouldn't run
+-under CI, and a link to an upstream issue if possible!
++To stop a test from running under CI, add `skip_if_cirrus!()` to it. Please
++describe the reason it shouldn't run under CI, and a link to an issue if
++possible!
+ 
+ ## bors, the bot who merges all the PRs
+ 
+diff --git a/third_party/rust/nix/CONVENTIONS.md b/third_party/rust/nix/CONVENTIONS.md
+index 48daa937345d2..2461085eb664a 100644
+--- a/third_party/rust/nix/CONVENTIONS.md
++++ b/third_party/rust/nix/CONVENTIONS.md
+@@ -76,12 +76,11 @@ to parameters of functions by [enumerations][enum].
+ 
+ Whenever we need to use a [libc][libc] function to properly initialize a
+ variable and said function allows us to use uninitialized memory, we use
+-[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized])
+-when defining the variable. This allows us to avoid the overhead incurred by
+-zeroing or otherwise initializing the variable.
++[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This
++allows us to avoid the overhead incurred by zeroing or otherwise initializing
++the variable.
+ 
+ [bitflags]: https://crates.io/crates/bitflags/
+-[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html
+ [enum]: https://doc.rust-lang.org/reference.html#enumerations
+ [libc]: https://crates.io/crates/libc/
+-[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
++[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html
+diff --git a/third_party/rust/nix/Cargo.toml b/third_party/rust/nix/Cargo.toml
+index 555b99020d68f..456bdca9c2599 100644
+--- a/third_party/rust/nix/Cargo.toml
++++ b/third_party/rust/nix/Cargo.toml
+@@ -3,22 +3,24 @@
+ # When uploading crates to the registry Cargo will automatically
+ # "normalize" Cargo.toml files for maximal compatibility
+ # with all versions of Cargo and also rewrite `path` dependencies
+-# to registry (e.g., crates.io) dependencies
++# to registry (e.g., crates.io) dependencies.
+ #
+-# If you believe there's an error in this file please file an
+-# issue against the rust-lang/cargo repository. If you're
+-# editing this file be aware that the upstream Cargo.toml
+-# will likely look very different (and much more reasonable)
++# If you are reading this file be aware that the original Cargo.toml
++# will likely look very different (and much more reasonable).
++# See Cargo.toml.orig for the original contents.
+ 
+ [package]
++edition = "2018"
+ name = "nix"
+-version = "0.15.0"
++version = "0.20.2"
+ authors = ["The nix-rust Project Developers"]
+-exclude = ["/.gitignore", "/.travis.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
++exclude = ["/.gitignore", "/.cirrus.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
+ description = "Rust friendly bindings to *nix APIs"
+ categories = ["os::unix-apis"]
+ license = "MIT"
+ repository = "https://github.com/nix-rust/nix"
++[package.metadata.docs.rs]
++targets = ["x86_64-unknown-linux-gnu", "aarch64-linux-android", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-openbsd", "x86_64-unknown-netbsd", "x86_64-unknown-dragonfly", "x86_64-fuchsia", "x86_64-unknown-redox"]
+ 
+ [[test]]
+ name = "test"
+@@ -28,6 +30,10 @@ path = "test/test.rs"
+ name = "test-aio-drop"
+ path = "test/sys/test_aio_drop.rs"
+ 
++[[test]]
++name = "test-clearenv"
++path = "test/test_clearenv.rs"
++
+ [[test]]
+ name = "test-lio-listio-resubmit"
+ path = "test/sys/test_lio_listio_resubmit.rs"
+@@ -41,17 +47,14 @@ harness = false
+ name = "test-ptymaster-drop"
+ path = "test/test_ptymaster_drop.rs"
+ [dependencies.bitflags]
+-version = "1.0"
++version = ">= 1.1.0, < 1.3.0"
+ 
+ [dependencies.cfg-if]
+-version = "0.1.2"
++version = "1.0"
+ 
+ [dependencies.libc]
+-version = "0.2.60"
++version = "0.2.99"
+ features = ["extra_traits"]
+-
+-[dependencies.void]
+-version = "1.0.2"
+ [dev-dependencies.bytes]
+ version = "0.4.8"
+ 
+@@ -59,12 +62,17 @@ version = "0.4.8"
+ version = "1.2"
+ 
+ [dev-dependencies.rand]
+-version = ">= 0.6, < 0.7"
++version = "0.6"
++
++[dev-dependencies.semver]
++version = "0.9.0"
+ 
+ [dev-dependencies.tempfile]
+-version = ">= 3.0.5, < 3.0.9"
++version = "3.0.5"
+ [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
+-version = "0.3.1"
++version = "0.5.1"
++[target."cfg(not(target_os = \"redox\"))".dependencies.memoffset]
++version = "0.6.3"
+ [target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
+ version = "1"
+ [target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
+diff --git a/third_party/rust/nix/README.md b/third_party/rust/nix/README.md
+index 0e540ba5b968e..b4909ea4345cc 100644
+--- a/third_party/rust/nix/README.md
++++ b/third_party/rust/nix/README.md
+@@ -1,6 +1,6 @@
+ # Rust bindings to *nix APIs
+ 
+-[![Build Status](https://travis-ci.org/nix-rust/nix.svg?branch=master)](https://travis-ci.org/nix-rust/nix)
++[![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix)
+ [![crates.io](http://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
+ 
+ [Documentation (Releases)](https://docs.rs/nix/)
+@@ -50,7 +50,6 @@ Tier 1:
+   * aarch64-unknown-linux-gnu
+   * arm-unknown-linux-gnueabi
+   * armv7-unknown-linux-gnueabihf
+-  * i686-apple-darwin
+   * i686-unknown-freebsd
+   * i686-unknown-linux-gnu
+   * i686-unknown-linux-musl
+@@ -58,7 +57,6 @@ Tier 1:
+   * mips64-unknown-linux-gnuabi64
+   * mips64el-unknown-linux-gnuabi64
+   * mipsel-unknown-linux-gnu
+-  * powerpc64-unknown-linux-gnu
+   * powerpc64le-unknown-linux-gnu
+   * x86_64-apple-darwin
+   * x86_64-unknown-freebsd
+@@ -74,6 +72,7 @@ Tier 2:
+   * armv7-linux-androideabi
+   * armv7s-apple-ios
+   * i386-apple-ios
++  * i686-apple-darwin
+   * i686-linux-android
+   * powerpc-unknown-linux-gnu
+   * s390x-unknown-linux-gnu
+@@ -81,21 +80,20 @@ Tier 2:
+   * x86_64-linux-android
+   * x86_64-unknown-netbsd
+ 
++Tier 3:
++  * x86_64-fuchsia
++  * x86_64-unknown-redox
++  * x86_64-unknown-linux-gnux32
++
+ ## Usage
+ 
+-`nix` requires Rust 1.31.0 or newer.
++`nix` requires Rust 1.40.0 or newer.
+ 
+-To use `nix`, first add this to your `Cargo.toml`:
++To use `nix`, add this to your `Cargo.toml`:
+ 
+ ```toml
+ [dependencies]
+-nix = "0.15.0"
+-```
+-
+-Then, add this to your crate root:
+-
+-```rust,ignore
+-extern crate nix;
++nix = "0.20.2"
+ ```
+ 
+ ## Contributing
+diff --git a/third_party/rust/nix/src/dir.rs b/third_party/rust/nix/src/dir.rs
+index 1820b5330ff60..7d4ab82f79e0d 100644
+--- a/third_party/rust/nix/src/dir.rs
++++ b/third_party/rust/nix/src/dir.rs
+@@ -1,10 +1,10 @@
+-use {Error, NixPath, Result};
+-use errno::Errno;
+-use fcntl::{self, OFlag};
+-use libc;
++use crate::{Error, NixPath, Result};
++use crate::errno::Errno;
++use crate::fcntl::{self, OFlag};
+ use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
+-use std::{ffi, ptr};
+-use sys;
++use std::ptr;
++use std::ffi;
++use crate::sys;
+ 
+ #[cfg(target_os = "linux")]
+ use libc::{dirent64 as dirent, readdir64_r as readdir_r};
+@@ -25,7 +25,7 @@ use libc::{dirent, readdir_r};
+ ///    * returns entries for `.` (current directory) and `..` (parent directory).
+ ///    * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
+ ///      does).
+-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++#[derive(Debug, Eq, Hash, PartialEq)]
+ pub struct Dir(
+     ptr::NonNull<libc::DIR>
+ );
+@@ -85,7 +85,32 @@ impl AsRawFd for Dir {
+ 
+ impl Drop for Dir {
+     fn drop(&mut self) {
+-        unsafe { libc::closedir(self.0.as_ptr()) };
++        let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) });
++        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
++            panic!("Closing an invalid file descriptor!");
++        };
++    }
++}
++
++fn next(dir: &mut Dir) -> Option<Result<Entry>> {
++    unsafe {
++        // Note: POSIX specifies that portable applications should dynamically allocate a
++        // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
++        // for the NUL byte. It doesn't look like the std library does this; it just uses
++        // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
++        // Probably fine here too then.
++        let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
++        let mut result = ptr::null_mut();
++        if let Err(e) = Errno::result(
++            readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result))
++        {
++            return Some(Err(e));
++        }
++        if result.is_null() {
++            return None;
++        }
++        assert_eq!(result, ent.as_mut_ptr());
++        Some(Ok(Entry(ent.assume_init())))
+     }
+ }
+ 
+@@ -96,23 +121,7 @@ impl<'d> Iterator for Iter<'d> {
+     type Item = Result<Entry>;
+ 
+     fn next(&mut self) -> Option<Self::Item> {
+-        unsafe {
+-            // Note: POSIX specifies that portable applications should dynamically allocate a
+-            // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
+-            // for the NUL byte. It doesn't look like the std library does this; it just uses
+-            // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
+-            // Probably fine here too then.
+-            let mut ent: Entry = Entry(::std::mem::uninitialized());
+-            let mut result = ptr::null_mut();
+-            if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) {
+-                return Some(Err(e));
+-            }
+-            if result == ptr::null_mut() {
+-                return None;
+-            }
+-            assert_eq!(result, &mut ent.0 as *mut dirent);
+-            return Some(Ok(ent));
+-        }
++        next(self.0)
+     }
+ }
+ 
+@@ -122,10 +131,48 @@ impl<'d> Drop for Iter<'d> {
+     }
+ }
+ 
++/// The return type of [Dir::into_iter]
++#[derive(Debug, Eq, Hash, PartialEq)]
++pub struct OwningIter(Dir);
++
++impl Iterator for OwningIter {
++    type Item = Result<Entry>;
++
++    fn next(&mut self) -> Option<Self::Item> {
++        next(&mut self.0)
++    }
++}
++
++impl IntoIterator for Dir {
++    type Item = Result<Entry>;
++    type IntoIter = OwningIter;
++
++    /// Creates a owning iterator, that is, one that takes ownership of the
++    /// `Dir`. The `Dir` cannot be used after calling this.  This can be useful
++    /// when you have a function that both creates a `Dir` instance and returns
++    /// an `Iterator`.
++    ///
++    /// Example:
++    ///
++    /// ```
++    /// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode};
++    /// use std::{iter::Iterator, string::String};
++    ///
++    /// fn ls_upper(dirname: &str) -> impl Iterator<Item=String> {
++    ///     let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap();
++    ///     d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase())
++    /// }
++    /// ```
++    fn into_iter(self) -> Self::IntoIter {
++        OwningIter(self)
++    }
++}
++
+ /// A directory entry, similar to `std::fs::DirEntry`.
+ ///
+ /// Note that unlike the std version, this may represent the `.` or `..` entries.
+ #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++#[repr(transparent)]
+ pub struct Entry(dirent);
+ 
+ #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
+@@ -165,7 +212,7 @@ impl Entry {
+                   target_os = "macos",
+                   target_os = "solaris")))]
+     pub fn ino(&self) -> u64 {
+-        self.0.d_fileno as u64
++        u64::from(self.0.d_fileno)
+     }
+ 
+     /// Returns the bare file name of this directory entry without any other leading path component.
+diff --git a/third_party/rust/nix/src/env.rs b/third_party/rust/nix/src/env.rs
+new file mode 100644
+index 0000000000000..f144dfedd0c1a
+--- /dev/null
++++ b/third_party/rust/nix/src/env.rs
+@@ -0,0 +1,53 @@
++use cfg_if::cfg_if;
++use crate::{Error, Result};
++
++/// Clear the environment of all name-value pairs.
++///
++/// On platforms where libc provides `clearenv()`, it will be used. libc's
++/// `clearenv()` is documented to return an error code but not set errno; if the
++/// return value indicates a failure, this function will return
++/// `Error::UnsupportedOperation`.
++///
++/// On platforms where libc does not provide `clearenv()`, a fallback
++/// implementation will be used that iterates over all environment variables and
++/// removes them one-by-one.
++///
++/// # Safety
++///
++/// This function is not threadsafe and can cause undefined behavior in
++/// combination with `std::env` or other program components that access the
++/// environment. See, for example, the discussion on `std::env::remove_var`; this
++/// function is a case of an "inherently unsafe non-threadsafe API" dealing with
++/// the environment.
++///
++///  The caller must ensure no other threads access the process environment while
++///  this function executes and that no raw pointers to an element of libc's
++///  `environ` is currently held. The latter is not an issue if the only other
++///  environment access in the program is via `std::env`, but the requirement on
++///  thread safety must still be upheld.
++pub unsafe fn clearenv() -> Result<()> {
++    let ret;
++    cfg_if! {
++        if #[cfg(any(target_os = "fuchsia",
++                     target_os = "wasi",
++                     target_env = "wasi",
++                     target_env = "uclibc",
++                     target_os = "linux",
++                     target_os = "android",
++                     target_os = "emscripten"))] {
++            ret = libc::clearenv();
++        } else {
++            use std::env;
++            for (name, _) in env::vars_os() {
++                env::remove_var(name);
++            }
++            ret = 0;
++        }
++    }
++
++    if ret == 0 {
++        Ok(())
++    } else {
++        Err(Error::UnsupportedOperation)
++    }
++}
+diff --git a/third_party/rust/nix/src/errno.rs b/third_party/rust/nix/src/errno.rs
+index 6a2447bc52675..e5c709252025c 100644
+--- a/third_party/rust/nix/src/errno.rs
++++ b/third_party/rust/nix/src/errno.rs
+@@ -1,8 +1,7 @@
+-#[cfg(not(target_os = "dragonfly"))]
+-use libc;
++use cfg_if::cfg_if;
+ use libc::{c_int, c_void};
+ use std::{fmt, io, error};
+-use {Error, Result};
++use crate::{Error, Result};
+ 
+ pub use self::consts::*;
+ 
+@@ -13,32 +12,16 @@ cfg_if! {
+         unsafe fn errno_location() -> *mut c_int {
+             libc::__error()
+         }
+-    } else if #[cfg(target_os = "dragonfly")] {
+-        // DragonFly uses a thread-local errno variable, but #[thread_local] is
+-        // feature-gated and not available in stable Rust as of this writing
+-        // (Rust 1.21.0). We have to use a C extension to access it
+-        // (src/errno_dragonfly.c).
+-        //
+-        // Tracking issue for `thread_local` stabilization:
+-        //
+-        //     https://github.com/rust-lang/rust/issues/29594
+-        //
+-        // Once this becomes stable, we can remove build.rs,
+-        // src/errno_dragonfly.c, and use:
+-        //
+-        //     extern { #[thread_local] static errno: c_int; }
+-        //
+-        #[link(name="errno_dragonfly", kind="static")]
+-        extern {
+-            pub fn errno_location() -> *mut c_int;
+-        }
+     } else if #[cfg(any(target_os = "android",
+                         target_os = "netbsd",
+                         target_os = "openbsd"))] {
+         unsafe fn errno_location() -> *mut c_int {
+             libc::__errno()
+         }
+-    } else if #[cfg(target_os = "linux")] {
++    } else if #[cfg(any(target_os = "linux",
++                        target_os = "redox",
++                        target_os = "dragonfly",
++                        target_os = "fuchsia"))] {
+         unsafe fn errno_location() -> *mut c_int {
+             libc::__errno_location()
+         }
+@@ -46,8 +29,11 @@ cfg_if! {
+ }
+ 
+ /// Sets the platform-specific errno to no-error
+-unsafe fn clear() -> () {
+-    *errno_location() = 0;
++fn clear() {
++    // Safe because errno is a thread-local variable
++    unsafe {
++        *errno_location() = 0;
++    }
+ }
+ 
+ /// Returns the platform-specific value of errno
+@@ -70,7 +56,7 @@ impl Errno {
+         from_i32(err)
+     }
+ 
+-    pub unsafe fn clear() -> () {
++    pub fn clear() {
+         clear()
+     }
+ 
+@@ -111,11 +97,7 @@ impl ErrnoSentinel for libc::sighandler_t {
+     fn sentinel() -> Self { libc::SIG_ERR }
+ }
+ 
+-impl error::Error for Errno {
+-    fn description(&self) -> &str {
+-        self.desc()
+-    }
+-}
++impl error::Error for Errno {}
+ 
+ impl fmt::Display for Errno {
+     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+@@ -207,200 +189,263 @@ fn desc(errno: Errno) -> &'static str {
+         EHOSTDOWN       => "Host is down",
+         EHOSTUNREACH    => "No route to host",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ECHRNG          => "Channel number out of range",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EL2NSYNC        => "Level 2 not synchronized",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EL3HLT          => "Level 3 halted",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EL3RST          => "Level 3 reset",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELNRNG          => "Link number out of range",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EUNATCH         => "Protocol driver not attached",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOCSI          => "No CSI structure available",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EL2HLT          => "Level 2 halted",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADE           => "Invalid exchange",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADR           => "Invalid request descriptor",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EXFULL          => "Exchange full",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOANO          => "No anode",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADRQC         => "Invalid request code",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADSLT         => "Invalid slot",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBFONT          => "Bad font file format",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOSTR          => "Device not a stream",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENODATA         => "No data available",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ETIME           => "Timer expired",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOSR           => "Out of streams resources",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENONET          => "Machine is not on the network",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOPKG          => "Package not installed",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EREMOTE         => "Object is remote",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOLINK         => "Link has been severed",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EADV            => "Advertise error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ESRMNT          => "Srmount error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ECOMM           => "Communication error on send",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EPROTO          => "Protocol error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EMULTIHOP       => "Multihop attempted",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EDOTDOT         => "RFS specific error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADMSG         => "Not a data message",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[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"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOTUNIQ        => "Name not unique on network",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EBADFD          => "File descriptor in bad state",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EREMCHG         => "Remote address changed",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELIBACC         => "Can not access a needed shared library",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELIBBAD         => "Accessing a corrupted shared library",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELIBSCN         => ".lib section in a.out corrupted",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELIBMAX         => "Attempting to link in too many shared libraries",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ELIBEXEC        => "Cannot exec a shared library directly",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia", target_os = "openbsd"))]
+         EILSEQ          => "Illegal byte sequence",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ERESTART        => "Interrupted system call should be restarted",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ESTRPIPE        => "Streams pipe error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EUSERS          => "Too many users",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia", target_os = "netbsd",
++                  target_os = "redox"))]
+         EOPNOTSUPP      => "Operation not supported on transport endpoint",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ESTALE          => "Stale file handle",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EUCLEAN         => "Structure needs cleaning",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOTNAM         => "Not a XENIX named type file",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENAVAIL         => "No XENIX semaphores available",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EISNAM          => "Is a named type file",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EREMOTEIO       => "Remote I/O error",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EDQUOT          => "Quota exceeded",
+ 
+         #[cfg(any(target_os = "linux", target_os = "android",
+-                  target_os = "openbsd", target_os = "dragonfly"))]
++                  target_os = "fuchsia", target_os = "openbsd",
++                  target_os = "dragonfly"))]
+         ENOMEDIUM       => "No medium found",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia", target_os = "openbsd"))]
+         EMEDIUMTYPE     => "Wrong medium type",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ECANCELED       => "Operation canceled",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOKEY          => "Required key not available",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EKEYEXPIRED     => "Key has expired",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EKEYREVOKED     => "Key has been revoked",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EKEYREJECTED    => "Key was rejected by service",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         EOWNERDEAD      => "Owner died",
+ 
+-        #[cfg(any(target_os = "linux", target_os = "android"))]
++        #[cfg(any(target_os = "linux", target_os = "android",
++                  target_os = "fuchsia"))]
+         ENOTRECOVERABLE => "State not recoverable",
+ 
+-        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
++        #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
++                  target_os = "fuchsia"))]
+         ERFKILL         => "Operation not possible due to RF-kill",
+ 
+-        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
++        #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
++                  target_os = "fuchsia"))]
+         EHWPOISON       => "Memory page has hardware error",
+ 
+         #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
+         EDOOFUS         => "Programming error",
+ 
+-        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
+         EMULTIHOP       => "Multihop attempted",
+ 
+-        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
+         ENOLINK         => "Link has been severed",
+ 
+         #[cfg(target_os = "freebsd")]
+@@ -416,12 +461,13 @@ fn desc(errno: Errno) -> &'static str {
+ 
+         #[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 = "redox"))]
+         EOVERFLOW       => "Value too large to be stored in data type",
+ 
+         #[cfg(any(target_os = "macos", target_os = "freebsd",
+                   target_os = "dragonfly", target_os = "ios",
+-                  target_os = "netbsd"))]
++                  target_os = "netbsd", target_os = "redox"))]
+         EILSEQ          => "Illegal byte sequence",
+ 
+         #[cfg(any(target_os = "macos", target_os = "freebsd",
+@@ -431,12 +477,14 @@ fn desc(errno: Errno) -> &'static str {
+ 
+         #[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 = "redox"))]
+         EBADMSG         => "Bad message",
+ 
+         #[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 = "redox"))]
+         EPROTO          => "Protocol error",
+ 
+         #[cfg(any(target_os = "macos", target_os = "freebsd",
+@@ -459,22 +507,26 @@ fn desc(errno: Errno) -> &'static str {
+ 
+         #[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 = "redox"))]
+         EUSERS          => "Too many users",
+ 
+         #[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 = "redox"))]
+         EDQUOT          => "Disc quota exceeded",
+ 
+         #[cfg(any(target_os = "macos", target_os = "freebsd",
+                   target_os = "dragonfly", target_os = "ios",
+-                  target_os = "openbsd", target_os = "netbsd"))]
++                  target_os = "openbsd", target_os = "netbsd",
++                  target_os = "redox"))]
+         ESTALE          => "Stale NFS file handle",
+ 
+         #[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 = "redox"))]
+         EREMOTE         => "Too many levels of remote in path",
+ 
+         #[cfg(any(target_os = "macos", target_os = "freebsd",
+@@ -514,7 +566,8 @@ fn desc(errno: Errno) -> &'static str {
+ 
+         #[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 = "redox"))]
+         ECANCELED       => "Operation canceled",
+ 
+         #[cfg(any(target_os = "macos", target_os = "ios"))]
+@@ -538,19 +591,23 @@ fn desc(errno: Errno) -> &'static str {
+         #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
+         EMULTIHOP       => "Reserved",
+ 
+-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        #[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"))]
+         ENOLINK         => "Reserved",
+ 
+-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        #[cfg(any(target_os = "macos", target_os = "ios",
++                  target_os = "netbsd", target_os = "redox"))]
+         ENOSR           => "No STREAM resources",
+ 
+-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        #[cfg(any(target_os = "macos", target_os = "ios",
++                  target_os = "netbsd", target_os = "redox"))]
+         ENOSTR          => "Not a STREAM",
+ 
+-        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
++        #[cfg(any(target_os = "macos", target_os = "ios",
++                  target_os = "netbsd", target_os = "redox"))]
+         ETIME           => "STREAM ioctl timeout",
+ 
+         #[cfg(any(target_os = "macos", target_os = "ios"))]
+@@ -573,10 +630,9 @@ fn desc(errno: Errno) -> &'static str {
+     }
+ }
+ 
+-#[cfg(any(target_os = "linux", target_os = "android"))]
++#[cfg(any(target_os = "linux", target_os = "android",
++          target_os = "fuchsia"))]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -864,8 +920,6 @@ mod consts {
+ 
+ #[cfg(any(target_os = "macos", target_os = "ios"))]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -1101,8 +1155,6 @@ mod consts {
+ 
+ #[cfg(target_os = "freebsd")]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -1319,8 +1371,6 @@ mod consts {
+ 
+ #[cfg(target_os = "dragonfly")]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -1534,8 +1584,6 @@ mod consts {
+ 
+ #[cfg(target_os = "openbsd")]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -1748,8 +1796,6 @@ mod consts {
+ 
+ #[cfg(target_os = "netbsd")]
+ mod consts {
+-    use libc;
+-
+     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+     #[repr(i32)]
+     pub enum Errno {
+@@ -1961,3 +2007,195 @@ mod consts {
+         }
+     }
+ }
++
++#[cfg(target_os = "redox")]
++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,
++        EDEADLK = libc::EDEADLK,
++        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,
++        EAGAIN = libc::EAGAIN,
++        EINPROGRESS = libc::EINPROGRESS,
++        EALREADY = libc::EALREADY,
++        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,
++        ELOOP = libc::ELOOP,
++        ENAMETOOLONG = libc::ENAMETOOLONG,
++        EHOSTDOWN = libc::EHOSTDOWN,
++        EHOSTUNREACH = libc::EHOSTUNREACH,
++        ENOTEMPTY = libc::ENOTEMPTY,
++        EUSERS = libc::EUSERS,
++        EDQUOT = libc::EDQUOT,
++        ESTALE = libc::ESTALE,
++        EREMOTE = libc::EREMOTE,
++        ENOLCK = libc::ENOLCK,
++        ENOSYS = libc::ENOSYS,
++        EIDRM = libc::EIDRM,
++        ENOMSG = libc::ENOMSG,
++        EOVERFLOW = libc::EOVERFLOW,
++        EILSEQ = libc::EILSEQ,
++        ECANCELED = libc::ECANCELED,
++        EBADMSG = libc::EBADMSG,
++        ENODATA = libc::ENODATA,
++        ENOSR = libc::ENOSR,
++        ENOSTR = libc::ENOSTR,
++        ETIME = libc::ETIME,
++        EMULTIHOP = libc::EMULTIHOP,
++        ENOLINK = libc::ENOLINK,
++        EPROTO = libc::EPROTO,
++    }
++
++    pub const ELAST: Errno = Errno::UnknownErrno;
++    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
++
++    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
++
++    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::EDEADLK => EDEADLK,
++            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::EAGAIN => EAGAIN,
++            libc::EINPROGRESS => EINPROGRESS,
++            libc::EALREADY => EALREADY,
++            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::ELOOP => ELOOP,
++            libc::ENAMETOOLONG => ENAMETOOLONG,
++            libc::EHOSTDOWN => EHOSTDOWN,
++            libc::EHOSTUNREACH => EHOSTUNREACH,
++            libc::ENOTEMPTY => ENOTEMPTY,
++            libc::EUSERS => EUSERS,
++            libc::EDQUOT => EDQUOT,
++            libc::ESTALE => ESTALE,
++            libc::EREMOTE => EREMOTE,
++            libc::ENOLCK => ENOLCK,
++            libc::ENOSYS => ENOSYS,
++            libc::EIDRM => EIDRM,
++            libc::ENOMSG => ENOMSG,
++            libc::EOVERFLOW => EOVERFLOW,
++            libc::EILSEQ => EILSEQ,
++            libc::ECANCELED => ECANCELED,
++            libc::EBADMSG => EBADMSG,
++            libc::ENODATA => ENODATA,
++            libc::ENOSR => ENOSR,
++            libc::ENOSTR => ENOSTR,
++            libc::ETIME => ETIME,
++            libc::EMULTIHOP => EMULTIHOP,
++            libc::ENOLINK => ENOLINK,
++            libc::EPROTO => EPROTO,
++            _ => UnknownErrno,
++        }
++    }
++}
+diff --git a/third_party/rust/nix/src/fcntl.rs b/third_party/rust/nix/src/fcntl.rs
+index be6ee0f73a8be..d2242dacd61b0 100644
+--- a/third_party/rust/nix/src/fcntl.rs
++++ b/third_party/rust/nix/src/fcntl.rs
+@@ -1,29 +1,34 @@
+-use {Error, Result, NixPath};
+-use errno::Errno;
+-use libc::{self, c_int, c_uint, c_char, size_t, ssize_t};
+-use sys::stat::Mode;
++use crate::errno::Errno;
++use libc::{self, c_char, c_int, c_uint, size_t, ssize_t};
++use std::ffi::OsString;
++#[cfg(not(target_os = "redox"))]
+ use std::os::raw;
++use std::os::unix::ffi::OsStringExt;
+ use std::os::unix::io::RawFd;
+-use std::ffi::OsStr;
+-use std::os::unix::ffi::OsStrExt;
++use crate::sys::stat::Mode;
++use crate::{NixPath, Result};
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ use std::ptr; // For splice and copy_file_range
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+-use sys::uio::IoVec;  // For vmsplice
+-
+-#[cfg(any(target_os = "linux",
+-          target_os = "android",
+-          target_os = "emscripten",
+-          target_os = "fuchsia",
+-          any(target_os = "wasi", target_env = "wasi"),
+-          target_env = "uclibc",
+-          target_env = "freebsd"))]
++use crate::sys::uio::IoVec; // For vmsplice
++
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++    target_os = "fuchsia",
++    any(target_os = "wasi", target_env = "wasi"),
++    target_env = "uclibc",
++    target_os = "freebsd"
++))]
+ pub use self::posix_fadvise::*;
+ 
+-libc_bitflags!{
++#[cfg(not(target_os = "redox"))]
++libc_bitflags! {
+     pub struct AtFlags: c_int {
+         AT_REMOVEDIR;
++        AT_SYMLINK_FOLLOW;
+         AT_SYMLINK_NOFOLLOW;
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+         AT_NO_AUTOMOUNT;
+@@ -78,7 +83,8 @@ libc_bitflags!(
+                   target_os = "ios",
+                   target_os = "macos",
+                   target_os = "netbsd",
+-                  target_os = "openbsd"))]
++                  target_os = "openbsd",
++                  target_os = "redox"))]
+         O_EXLOCK;
+         /// Same as `O_SYNC`.
+         #[cfg(any(target_os = "dragonfly",
+@@ -87,7 +93,8 @@ libc_bitflags!(
+                   all(target_os = "linux", not(target_env = "musl")),
+                   target_os = "macos",
+                   target_os = "netbsd",
+-                  target_os = "openbsd"))]
++                  target_os = "openbsd",
++                  target_os = "redox"))]
+         O_FSYNC;
+         /// Allow files whose sizes can't be represented in an `off_t` to be opened.
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -96,8 +103,10 @@ libc_bitflags!(
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+         O_NOATIME;
+         /// Don't attach the device as the process' controlling terminal.
++        #[cfg(not(target_os = "redox"))]
+         O_NOCTTY;
+         /// Same as `O_NONBLOCK`.
++        #[cfg(not(target_os = "redox"))]
+         O_NDELAY;
+         /// `open()` will fail if the given path is a symbolic link.
+         O_NOFOLLOW;
+@@ -109,7 +118,7 @@ libc_bitflags!(
+         /// Obtain a file descriptor for low-level access.
+         ///
+         /// The file itself is not opened and other file operations will fail.
+-        #[cfg(any(target_os = "android", target_os = "linux"))]
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+         O_PATH;
+         /// Only allow reading.
+         ///
+@@ -131,9 +140,11 @@ libc_bitflags!(
+                   target_os = "ios",
+                   target_os = "macos",
+                   target_os = "netbsd",
+-                  target_os = "openbsd"))]
++                  target_os = "openbsd",
++                  target_os = "redox"))]
+         O_SHLOCK;
+         /// Implicitly follow each `write()` with an `fsync()`.
++        #[cfg(not(target_os = "redox"))]
+         O_SYNC;
+         /// Create an unnamed temporary file.
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -150,6 +161,8 @@ libc_bitflags!(
+     }
+ );
+ 
++// The conversion is not identical on all operating systems.
++#[allow(clippy::identity_conversion)]
+ pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
+     let fd = path.with_nix_path(|cstr| {
+         unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
+@@ -158,56 +171,125 @@ pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<R
+     Errno::result(fd)
+ }
+ 
+-pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
++// The conversion is not identical on all operating systems.
++#[allow(clippy::identity_conversion)]
++#[cfg(not(target_os = "redox"))]
++pub fn openat<P: ?Sized + NixPath>(
++    dirfd: RawFd,
++    path: &P,
++    oflag: OFlag,
++    mode: Mode,
++) -> Result<RawFd> {
+     let fd = path.with_nix_path(|cstr| {
+         unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
+     })?;
+     Errno::result(fd)
+ }
+ 
+-pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<RawFd>, old_path: &P1,
+-                                                            new_dirfd: Option<RawFd>, new_path: &P2)
+-                                                            -> Result<()> {
++#[cfg(not(target_os = "redox"))]
++pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
++    old_dirfd: Option<RawFd>,
++    old_path: &P1,
++    new_dirfd: Option<RawFd>,
++    new_path: &P2,
++) -> Result<()> {
+     let res = old_path.with_nix_path(|old_cstr| {
+         new_path.with_nix_path(|new_cstr| unsafe {
+-            libc::renameat(at_rawfd(old_dirfd), old_cstr.as_ptr(),
+-                           at_rawfd(new_dirfd), new_cstr.as_ptr())
++            libc::renameat(
++                at_rawfd(old_dirfd),
++                old_cstr.as_ptr(),
++                at_rawfd(new_dirfd),
++                new_cstr.as_ptr(),
++            )
+         })
+     })??;
+     Errno::result(res).map(drop)
+ }
+ 
+-fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
+-    match Errno::result(res) {
+-        Err(err) => Err(err),
+-        Ok(len) => {
+-            if (len as usize) >= buffer.len() {
+-                Err(Error::Sys(Errno::ENAMETOOLONG))
+-            } else {
+-                Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
++fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
++    unsafe { v.set_len(len as usize) }
++    v.shrink_to_fit();
++    Ok(OsString::from_vec(v.to_vec()))
++}
++
++fn readlink_maybe_at<P: ?Sized + NixPath>(
++    dirfd: Option<RawFd>,
++    path: &P,
++    v: &mut Vec<u8>,
++) -> Result<libc::ssize_t> {
++    path.with_nix_path(|cstr| unsafe {
++        match dirfd {
++            #[cfg(target_os = "redox")]
++            Some(_) => unreachable!(),
++            #[cfg(not(target_os = "redox"))]
++            Some(dirfd) => libc::readlinkat(
++                dirfd,
++                cstr.as_ptr(),
++                v.as_mut_ptr() as *mut c_char,
++                v.capacity() as size_t,
++            ),
++            None => libc::readlink(
++                cstr.as_ptr(),
++                v.as_mut_ptr() as *mut c_char,
++                v.capacity() as size_t,
++            ),
++        }
++    })
++}
++
++fn inner_readlink<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P) -> Result<OsString> {
++    let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
++    // simple case: result is strictly less than `PATH_MAX`
++    let res = readlink_maybe_at(dirfd, path, &mut v)?;
++    let len = Errno::result(res)?;
++    debug_assert!(len >= 0);
++    if (len as usize) < v.capacity() {
++        return wrap_readlink_result(v, res);
++    }
++    // 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))
++        .unwrap_or(0);
++    let mut try_size = if reported_size > 0 {
++        // Note: even if `lstat`'s apparently valid answer turns out to be
++        // wrong, we will still read the full symlink no matter what.
++        reported_size as usize + 1
++    } else {
++        // If lstat doesn't cooperate, or reports an error, be a little less
++        // precise.
++        (libc::PATH_MAX as usize).max(128) << 1
++    };
++    loop {
++        v.reserve_exact(try_size);
++        let res = readlink_maybe_at(dirfd, path, &mut v)?;
++        let len = Errno::result(res)?;
++        debug_assert!(len >= 0);
++        if (len as usize) < v.capacity() {
++            break wrap_readlink_result(v, res);
++        } else {
++            // Ugh! Still not big enough!
++            match try_size.checked_shl(1) {
++                Some(next_size) => try_size = next_size,
++                // It's absurd that this would happen, but handle it sanely
++                // anyway.
++                None => break Err(super::Error::Sys(Errno::ENAMETOOLONG)),
+             }
+         }
+     }
+ }
+ 
+-pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
+-    let res = path.with_nix_path(|cstr| {
+-        unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
+-    })?;
+-
+-    wrap_readlink_result(buffer, res)
++pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
++    inner_readlink(None, path)
+ }
+ 
+-
+-pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
+-    let res = path.with_nix_path(|cstr| {
+-        unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
+-    })?;
+-
+-    wrap_readlink_result(buffer, res)
++#[cfg(not(target_os = "redox"))]
++pub fn readlinkat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
++    inner_readlink(Some(dirfd), path)
+ }
+ 
+ /// Computes the raw fd consumed by a function of the form `*at`.
++#[cfg(not(target_os = "redox"))]
+ pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
+     match fd {
+         None => libc::AT_FDCWD,
+@@ -238,6 +320,7 @@ libc_bitflags!(
+     }
+ );
+ 
++#[cfg(not(target_os = "redox"))]
+ #[derive(Debug, Eq, Hash, PartialEq)]
+ pub enum FcntlArg<'a> {
+     F_DUPFD(RawFd),
+@@ -265,9 +348,19 @@ pub enum FcntlArg<'a> {
+     F_GETPIPE_SZ,
+     #[cfg(any(target_os = "linux", target_os = "android"))]
+     F_SETPIPE_SZ(c_int),
+-
+     // TODO: Rest of flags
+ }
++
++#[cfg(target_os = "redox")]
++#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
++pub enum FcntlArg {
++    F_DUPFD(RawFd),
++    F_DUPFD_CLOEXEC(RawFd),
++    F_GETFD,
++    F_SETFD(FdFlag), // FD_FLAGS
++    F_GETFL,
++    F_SETFL(OFlag), // O_NONBLOCK
++}
+ pub use self::FcntlArg::*;
+ 
+ // TODO: Figure out how to handle value fcntl returns
+@@ -280,10 +373,19 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
+             F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
+             F_GETFL => libc::fcntl(fd, libc::F_GETFL),
+             F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
++            #[cfg(not(target_os = "redox"))]
+             F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
++            #[cfg(not(target_os = "redox"))]
+             F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
++            #[cfg(not(target_os = "redox"))]
+             F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
++            F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
+             F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+             F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
+@@ -293,8 +395,6 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
+             F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
+             #[cfg(any(target_os = "linux", target_os = "android"))]
+             F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
+-            #[cfg(any(target_os = "linux", target_os = "android"))]
+-            _ => unimplemented!()
+         }
+     };
+ 
+@@ -311,6 +411,7 @@ pub enum FlockArg {
+     UnlockNonblock,
+ }
+ 
++#[cfg(not(target_os = "redox"))]
+ pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
+     use self::FlockArg::*;
+ 
+@@ -410,9 +511,7 @@ pub fn splice(
+         .map(|offset| offset as *mut libc::loff_t)
+         .unwrap_or(ptr::null_mut());
+ 
+-    let ret = unsafe {
+-        libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
+-    };
++    let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) };
+     Errno::result(ret).map(|r| r as usize)
+ }
+ 
+@@ -425,7 +524,12 @@ pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Resu
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<usize> {
+     let ret = unsafe {
+-        libc::vmsplice(fd, iov.as_ptr() as *const libc::iovec, iov.len(), flags.bits())
++        libc::vmsplice(
++            fd,
++            iov.as_ptr() as *const libc::iovec,
++            iov.len(),
++            flags.bits(),
++        )
+     };
+     Errno::result(ret).map(|r| r as usize)
+ }
+@@ -466,23 +570,30 @@ libc_bitflags!(
+ /// Allows the caller to directly manipulate the allocated disk space for the
+ /// file referred to by fd.
+ #[cfg(any(target_os = "linux"))]
+-pub fn fallocate(fd: RawFd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t) -> Result<c_int> {
++pub fn fallocate(
++    fd: RawFd,
++    mode: FallocateFlags,
++    offset: libc::off_t,
++    len: libc::off_t,
++) -> Result<()> {
+     let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
+-    Errno::result(res)
++    Errno::result(res).map(drop)
+ }
+ 
+-#[cfg(any(target_os = "linux",
+-          target_os = "android",
+-          target_os = "emscripten",
+-          target_os = "fuchsia",
+-          any(target_os = "wasi", target_env = "wasi"),
+-          target_env = "uclibc",
+-          target_env = "freebsd"))]
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++    target_os = "fuchsia",
++    any(target_os = "wasi", target_env = "wasi"),
++    target_env = "uclibc",
++    target_os = "freebsd"
++))]
+ mod posix_fadvise {
+-    use Result;
++    use crate::errno::Errno;
+     use libc;
+-    use errno::Errno;
+     use std::os::unix::io::RawFd;
++    use crate::Result;
+ 
+     libc_enum! {
+         #[repr(i32)]
+@@ -496,11 +607,30 @@ mod posix_fadvise {
+         }
+     }
+ 
+-    pub fn posix_fadvise(fd: RawFd,
+-                         offset: libc::off_t,
+-                         len: libc::off_t,
+-                         advice: PosixFadviseAdvice) -> Result<libc::c_int> {
++    pub fn posix_fadvise(
++        fd: RawFd,
++        offset: libc::off_t,
++        len: libc::off_t,
++        advice: PosixFadviseAdvice,
++    ) -> Result<libc::c_int> {
+         let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
+         Errno::result(res)
+     }
+ }
++
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++    target_os = "fuchsia",
++    any(target_os = "wasi", target_env = "wasi"),
++    target_os = "freebsd"
++))]
++pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> {
++    let res = unsafe { libc::posix_fallocate(fd, offset, len) };
++    match Errno::result(res) {
++        Err(err) => Err(err),
++        Ok(0) => Ok(()),
++        Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))),
++    }
++}
+diff --git a/third_party/rust/nix/src/features.rs b/third_party/rust/nix/src/features.rs
+index 76cdfd3a1a6f1..6b1cff5deed1d 100644
+--- a/third_party/rust/nix/src/features.rs
++++ b/third_party/rust/nix/src/features.rs
+@@ -3,7 +3,7 @@ pub use self::os::*;
+ 
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ mod os {
+-    use sys::utsname::uname;
++    use crate::sys::utsname::uname;
+ 
+     // Features:
+     // * atomic cloexec on socket: 2.6.27
+@@ -94,7 +94,10 @@ mod os {
+     }
+ }
+ 
+-#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))]
++#[cfg(any(target_os = "macos", target_os = "freebsd",
++          target_os = "dragonfly", target_os = "ios",
++          target_os = "openbsd", target_os = "netbsd",
++          target_os = "redox", target_os = "fuchsia"))]
+ mod os {
+     /// Check if the OS supports atomic close-on-exec for sockets
+     pub fn socket_atomic_cloexec() -> bool {
+diff --git a/third_party/rust/nix/src/ifaddrs.rs b/third_party/rust/nix/src/ifaddrs.rs
+index 12b59bcc92bef..ed6328f3efab2 100644
+--- a/third_party/rust/nix/src/ifaddrs.rs
++++ b/third_party/rust/nix/src/ifaddrs.rs
+@@ -3,16 +3,15 @@
+ //! Uses the Linux and/or BSD specific function `getifaddrs` to query the list
+ //! of interfaces and their associated addresses.
+ 
++use cfg_if::cfg_if;
+ use std::ffi;
+ use std::iter::Iterator;
+ use std::mem;
+ use std::option::Option;
+ 
+-use libc;
+-
+-use {Result, Errno};
+-use sys::socket::SockAddr;
+-use net::if_::*;
++use crate::{Result, Errno};
++use crate::sys::socket::SockAddr;
++use crate::net::if_::*;
+ 
+ /// Describes a single address for an interface as returned by `getifaddrs`.
+ #[derive(Clone, Debug, Eq, Hash, PartialEq)]
+@@ -52,8 +51,8 @@ impl InterfaceAddress {
+         let mut addr = InterfaceAddress {
+             interface_name: ifname.to_string_lossy().to_string(),
+             flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
+-            address: address,
+-            netmask: netmask,
++            address,
++            netmask,
+             broadcast: None,
+             destination: None,
+         };
+@@ -125,13 +124,15 @@ impl Iterator for InterfaceAddressIterator {
+ /// }
+ /// ```
+ pub fn getifaddrs() -> Result<InterfaceAddressIterator> {
+-    let mut addrs: *mut libc::ifaddrs = unsafe { mem::uninitialized() };
+-    Errno::result(unsafe { libc::getifaddrs(&mut addrs) }).map(|_| {
+-        InterfaceAddressIterator {
+-            base: addrs,
+-            next: addrs,
+-        }
+-    })
++    let mut addrs = mem::MaybeUninit::<*mut libc::ifaddrs>::uninit();
++    unsafe {
++        Errno::result(libc::getifaddrs(addrs.as_mut_ptr())).map(|_| {
++            InterfaceAddressIterator {
++                base: addrs.assume_init(),
++                next: addrs.assume_init(),
++            }
++        })
++    }
+ }
+ 
+ #[cfg(test)]
+diff --git a/third_party/rust/nix/src/kmod.rs b/third_party/rust/nix/src/kmod.rs
+index e853261b14f9d..8789cb69f4617 100644
+--- a/third_party/rust/nix/src/kmod.rs
++++ b/third_party/rust/nix/src/kmod.rs
+@@ -6,8 +6,8 @@ use libc;
+ use std::ffi::CStr;
+ use std::os::unix::io::AsRawFd;
+ 
+-use errno::Errno;
+-use Result;
++use crate::errno::Errno;
++use crate::Result;
+ 
+ /// Loads a kernel module from a buffer.
+ ///
+diff --git a/third_party/rust/nix/src/lib.rs b/third_party/rust/nix/src/lib.rs
+index 71485d2af1824..e62c158c8bc9b 100644
+--- a/third_party/rust/nix/src/lib.rs
++++ b/third_party/rust/nix/src/lib.rs
+@@ -14,24 +14,17 @@
+ #![deny(unstable_features)]
+ #![deny(missing_copy_implementations)]
+ #![deny(missing_debug_implementations)]
+-// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
+-#![allow(deprecated)]
+-
+-// External crates
+-#[macro_use]
+-extern crate bitflags;
+-#[macro_use]
+-extern crate cfg_if;
+-extern crate void;
+ 
+ // Re-exported external crates
+-pub extern crate libc;
++pub use libc;
+ 
+ // Private internal modules
+ #[macro_use] mod macros;
+ 
+ // Public crates
++#[cfg(not(target_os = "redox"))]
+ pub mod dir;
++pub mod env;
+ pub mod errno;
+ #[deny(missing_docs)]
+ pub mod features;
+@@ -59,13 +52,16 @@ pub mod mount;
+           target_os = "netbsd"))]
+ pub mod mqueue;
+ #[deny(missing_docs)]
++#[cfg(not(target_os = "redox"))]
+ pub mod net;
+ #[deny(missing_docs)]
+ pub mod poll;
+ #[deny(missing_docs)]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ pub mod pty;
+ pub mod sched;
+ pub mod sys;
++pub mod time;
+ // This can be implemented for other platforms as soon as libc
+ // provides bindings for them.
+ #[cfg(all(target_os = "linux",
+@@ -121,9 +117,9 @@ impl Error {
+     /// let e = Error::from(Errno::EPERM);
+     /// assert_eq!(Some(Errno::EPERM), e.as_errno());
+     /// ```
+-    pub fn as_errno(&self) -> Option<Errno> {
+-        if let &Error::Sys(ref e) = self {
+-            Some(*e)
++    pub fn as_errno(self) -> Option<Errno> {
++        if let Error::Sys(e) = self {
++            Some(e)
+         } else {
+             None
+         }
+@@ -154,16 +150,7 @@ impl From<std::string::FromUtf8Error> for Error {
+     fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
+ }
+ 
+-impl error::Error for Error {
+-    fn description(&self) -> &str {
+-        match *self {
+-            Error::InvalidPath => "Invalid path",
+-            Error::InvalidUtf8 => "Invalid UTF-8 string",
+-            Error::UnsupportedOperation => "Unsupported Operation",
+-            Error::Sys(ref errno) => errno.desc(),
+-        }
+-    }
+-}
++impl error::Error for Error {}
+ 
+ impl fmt::Display for Error {
+     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+@@ -177,6 +164,8 @@ impl fmt::Display for Error {
+ }
+ 
+ pub trait NixPath {
++    fn is_empty(&self) -> bool;
++
+     fn len(&self) -> usize;
+ 
+     fn with_nix_path<T, F>(&self, f: F) -> Result<T>
+@@ -184,6 +173,10 @@ pub trait NixPath {
+ }
+ 
+ impl NixPath for str {
++    fn is_empty(&self) -> bool {
++        NixPath::is_empty(OsStr::new(self))
++    }
++
+     fn len(&self) -> usize {
+         NixPath::len(OsStr::new(self))
+     }
+@@ -195,6 +188,10 @@ impl NixPath for str {
+ }
+ 
+ impl NixPath for OsStr {
++    fn is_empty(&self) -> bool {
++        self.as_bytes().is_empty()
++    }
++
+     fn len(&self) -> usize {
+         self.as_bytes().len()
+     }
+@@ -206,6 +203,10 @@ impl NixPath for OsStr {
+ }
+ 
+ impl NixPath for CStr {
++    fn is_empty(&self) -> bool {
++        self.to_bytes().is_empty()
++    }
++
+     fn len(&self) -> usize {
+         self.to_bytes().len()
+     }
+@@ -222,6 +223,10 @@ impl NixPath for CStr {
+ }
+ 
+ impl NixPath for [u8] {
++    fn is_empty(&self) -> bool {
++        self.is_empty()
++    }
++
+     fn len(&self) -> usize {
+         self.len()
+     }
+@@ -249,6 +254,10 @@ impl NixPath for [u8] {
+ }
+ 
+ impl NixPath for Path {
++    fn is_empty(&self) -> bool {
++        NixPath::is_empty(self.as_os_str())
++    }
++
+     fn len(&self) -> usize {
+         NixPath::len(self.as_os_str())
+     }
+@@ -259,26 +268,15 @@ impl NixPath for Path {
+ }
+ 
+ impl NixPath for PathBuf {
+-    fn len(&self) -> usize {
+-        NixPath::len(self.as_os_str())
++    fn is_empty(&self) -> bool {
++        NixPath::is_empty(self.as_os_str())
+     }
+ 
+-    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
+-        self.as_os_str().with_nix_path(f)
+-    }
+-}
+-
+-/// Treats `None` as an empty string.
+-impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
+     fn len(&self) -> usize {
+-        self.map_or(0, NixPath::len)
++        NixPath::len(self.as_os_str())
+     }
+ 
+     fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
+-        if let Some(nix_path) = *self {
+-            nix_path.with_nix_path(f)
+-        } else {
+-            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
+-        }
++        self.as_os_str().with_nix_path(f)
+     }
+ }
+diff --git a/third_party/rust/nix/src/macros.rs b/third_party/rust/nix/src/macros.rs
+index 3d1b0e4b7699c..7d6ac8dfbf5f7 100644
+--- a/third_party/rust/nix/src/macros.rs
++++ b/third_party/rust/nix/src/macros.rs
+@@ -48,7 +48,7 @@ macro_rules! libc_bitflags {
+             )+
+         }
+     ) => {
+-        bitflags! {
++        ::bitflags::bitflags! {
+             $(#[$outer])*
+             pub struct $BitFlags: $T {
+                 $(
+@@ -81,9 +81,10 @@ macro_rules! libc_bitflags {
+ /// }
+ /// ```
+ macro_rules! libc_enum {
+-    // (non-pub) Exit rule.
++    // Exit rule.
+     (@make_enum
+         {
++            $v:vis
+             name: $BitFlags:ident,
+             attrs: [$($attrs:tt)*],
+             entries: [$($entries:tt)*],
+@@ -91,49 +92,15 @@ macro_rules! libc_enum {
+     ) => {
+         $($attrs)*
+         #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+-        enum $BitFlags {
++        $v enum $BitFlags {
+             $($entries)*
+         }
+     };
+ 
+-    // (pub) Exit rule.
+-    (@make_enum
+-        {
+-            pub,
+-            name: $BitFlags:ident,
+-            attrs: [$($attrs:tt)*],
+-            entries: [$($entries:tt)*],
+-        }
+-    ) => {
+-        $($attrs)*
+-        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
+-        pub enum $BitFlags {
+-            $($entries)*
+-        }
+-    };
+-
+-    // (non-pub) Done accumulating.
+-    (@accumulate_entries
+-        {
+-            name: $BitFlags:ident,
+-            attrs: $attrs:tt,
+-        },
+-        $entries:tt;
+-    ) => {
+-        libc_enum! {
+-            @make_enum
+-            {
+-                name: $BitFlags,
+-                attrs: $attrs,
+-                entries: $entries,
+-            }
+-        }
+-    };
+-
+-    // (pub) Done accumulating.
++    // Done accumulating.
+     (@accumulate_entries
+         {
+-            pub,
++            $v:vis
+             name: $BitFlags:ident,
+             attrs: $attrs:tt,
+         },
+@@ -142,7 +109,7 @@ macro_rules! libc_enum {
+         libc_enum! {
+             @make_enum
+             {
+-                pub,
++                $v
+                 name: $BitFlags,
+                 attrs: $attrs,
+                 entries: $entries,
+@@ -217,35 +184,17 @@ macro_rules! libc_enum {
+         }
+     };
+ 
+-    // (non-pub) Entry rule.
+-    (
+-        $(#[$attr:meta])*
+-        enum $BitFlags:ident {
+-            $($vals:tt)*
+-        }
+-    ) => {
+-        libc_enum! {
+-            @accumulate_entries
+-            {
+-                name: $BitFlags,
+-                attrs: [$(#[$attr])*],
+-            },
+-            [];
+-            $($vals)*
+-        }
+-    };
+-
+-    // (pub) Entry rule.
++    // Entry rule.
+     (
+         $(#[$attr:meta])*
+-        pub enum $BitFlags:ident {
++        $v:vis enum $BitFlags:ident {
+             $($vals:tt)*
+         }
+     ) => {
+         libc_enum! {
+             @accumulate_entries
+             {
+-                pub,
++                $v
+                 name: $BitFlags,
+                 attrs: [$(#[$attr])*],
+             },
+@@ -254,11 +203,3 @@ macro_rules! libc_enum {
+         }
+     };
+ }
+-
+-/// A Rust version of the familiar C `offset_of` macro.  It returns the byte
+-/// offset of `field` within struct `ty`
+-macro_rules! offset_of {
+-    ($ty:ty, $field:ident) => {
+-        &(*(0 as *const $ty)).$field as *const _ as usize
+-    }
+-}
+diff --git a/third_party/rust/nix/src/mount.rs b/third_party/rust/nix/src/mount.rs
+index a9902b170ace8..2c54761e2bb0c 100644
+--- a/third_party/rust/nix/src/mount.rs
++++ b/third_party/rust/nix/src/mount.rs
+@@ -1,6 +1,6 @@
+ use libc::{self, c_ulong, c_int};
+-use {Result, NixPath};
+-use errno::Errno;
++use crate::{Result, NixPath};
++use crate::errno::Errno;
+ 
+ libc_bitflags!(
+     pub struct MsFlags: c_ulong {
+@@ -61,22 +61,33 @@ pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P
+         flags: MsFlags,
+         data: Option<&P4>) -> Result<()> {
+ 
+-    let res =
+-        source.with_nix_path(|source| {
+-            target.with_nix_path(|target| {
+-                fstype.with_nix_path(|fstype| {
+-                    data.with_nix_path(|data| {
+-                        unsafe {
+-                            libc::mount(source.as_ptr(),
+-                                       target.as_ptr(),
+-                                       fstype.as_ptr(),
+-                                       flags.bits,
+-                                       data.as_ptr() as *const libc::c_void)
+-                        }
+-                    })
++    fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
++        where P: ?Sized + NixPath,
++              F: FnOnce(*const libc::c_char) -> T
++    {
++        match p {
++            Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
++            None => Ok(f(std::ptr::null()))
++        }
++    }
++
++    let res = with_opt_nix_path(source, |s| {
++        target.with_nix_path(|t| {
++            with_opt_nix_path(fstype, |ty| {
++                with_opt_nix_path(data, |d| {
++                    unsafe {
++                        libc::mount(
++                            s,
++                            t.as_ptr(),
++                            ty,
++                            flags.bits,
++                            d as *const libc::c_void
++                        )
++                    }
+                 })
+             })
+-        })????;
++        })
++    })????;
+ 
+     Errno::result(res).map(drop)
+ }
+diff --git a/third_party/rust/nix/src/mqueue.rs b/third_party/rust/nix/src/mqueue.rs
+index b958b71cddb46..0215de5af214b 100644
+--- a/third_party/rust/nix/src/mqueue.rs
++++ b/third_party/rust/nix/src/mqueue.rs
+@@ -2,12 +2,12 @@
+ //!
+ //! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
+ 
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ 
+-use libc::{self, c_char, c_long, mqd_t, size_t};
++use libc::{self, c_char, mqd_t, size_t};
+ use std::ffi::CString;
+-use sys::stat::Mode;
++use crate::sys::stat::Mode;
+ use std::mem;
+ 
+ libc_bitflags!{
+@@ -34,21 +34,32 @@ pub struct MqAttr {
+     mq_attr: libc::mq_attr,
+ }
+ 
++// x32 compatibility
++// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
++#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
++pub type mq_attr_member_t = i64;
++#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
++pub type mq_attr_member_t = libc::c_long;
++
+ impl MqAttr {
+-    pub fn new(mq_flags: c_long,
+-               mq_maxmsg: c_long,
+-               mq_msgsize: c_long,
+-               mq_curmsgs: c_long)
+-               -> MqAttr {
+-        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
+-        attr.mq_flags = mq_flags;
+-        attr.mq_maxmsg = mq_maxmsg;
+-        attr.mq_msgsize = mq_msgsize;
+-        attr.mq_curmsgs = mq_curmsgs;
+-        MqAttr { mq_attr: attr }
++    pub fn new(mq_flags: mq_attr_member_t,
++               mq_maxmsg: mq_attr_member_t,
++               mq_msgsize: mq_attr_member_t,
++               mq_curmsgs: mq_attr_member_t)
++               -> MqAttr
++    {
++        let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
++        unsafe {
++            let p = attr.as_mut_ptr();
++            (*p).mq_flags = mq_flags;
++            (*p).mq_maxmsg = mq_maxmsg;
++            (*p).mq_msgsize = mq_msgsize;
++            (*p).mq_curmsgs = mq_curmsgs;
++            MqAttr { mq_attr: attr.assume_init() }
++        }
+     }
+ 
+-    pub fn flags(&self) -> c_long {
++    pub fn flags(&self) -> mq_attr_member_t {
+         self.mq_attr.mq_flags
+     }
+ }
+@@ -57,6 +68,8 @@ impl MqAttr {
+ /// Open a message queue
+ ///
+ /// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
++// The mode.bits cast is only lossless on some OSes
++#[allow(clippy::cast_lossless)]
+ pub fn mq_open(name: &CString,
+                oflag: MQ_OFlag,
+                mode: Mode,
+@@ -121,9 +134,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
+ ///
+ /// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
+ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
+-    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
+-    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
+-    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
++    let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
++    let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) };
++    Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
+ }
+ 
+ /// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
+@@ -132,17 +145,19 @@ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
+ ///
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
+ pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
+-    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
+-    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
+-    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
++    let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
++    let res = unsafe {
++        libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
++    };
++    Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
+ }
+ 
+ /// Convenience function.
+ /// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
+ /// Returns the old attributes
+-pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
++pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
+     let oldattr = mq_getattr(mqd)?;
+-    let newattr = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long,
++    let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
+                               oldattr.mq_attr.mq_maxmsg,
+                               oldattr.mq_attr.mq_msgsize,
+                               oldattr.mq_attr.mq_curmsgs);
+@@ -152,7 +167,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
+ /// Convenience function.
+ /// Removes `O_NONBLOCK` attribute for a given message queue descriptor
+ /// Returns the old attributes
+-pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
++pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<MqAttr> {
+     let oldattr = mq_getattr(mqd)?;
+     let newattr = MqAttr::new(0,
+                               oldattr.mq_attr.mq_maxmsg,
+diff --git a/third_party/rust/nix/src/net/if_.rs b/third_party/rust/nix/src/net/if_.rs
+index 58d677ae343d1..96364884e39cb 100644
+--- a/third_party/rust/nix/src/net/if_.rs
++++ b/third_party/rust/nix/src/net/if_.rs
+@@ -3,9 +3,8 @@
+ //! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
+ //! or "socan1" into device numbers.
+ 
+-use libc;
+ use libc::c_uint;
+-use {Result, Error, NixPath};
++use crate::{Result, Error, NixPath};
+ 
+ /// Resolve an interface into a interface number.
+ pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
+diff --git a/third_party/rust/nix/src/poll.rs b/third_party/rust/nix/src/poll.rs
+index c603611e3176f..be5bf224990f2 100644
+--- a/third_party/rust/nix/src/poll.rs
++++ b/third_party/rust/nix/src/poll.rs
+@@ -1,13 +1,12 @@
+ //! Wait for events to trigger on specific file descriptors
+ #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+-use sys::time::TimeSpec;
++use crate::sys::time::TimeSpec;
+ #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+-use sys::signal::SigSet;
++use crate::sys::signal::SigSet;
+ use std::os::unix::io::RawFd;
+ 
+-use libc;
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ 
+ /// This is a wrapper around `libc::pollfd`.
+ ///
+@@ -17,7 +16,7 @@ use errno::Errno;
+ ///
+ /// After a call to `poll` or `ppoll`, the events that occured can be
+ /// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct PollFd {
+     pollfd: libc::pollfd,
+@@ -29,7 +28,7 @@ impl PollFd {
+     pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
+         PollFd {
+             pollfd: libc::pollfd {
+-                fd: fd,
++                fd,
+                 events: events.bits(),
+                 revents: PollFlags::empty().bits(),
+             },
+@@ -37,7 +36,7 @@ impl PollFd {
+     }
+ 
+     /// Returns the events that occured in the last call to `poll` or `ppoll`.
+-    pub fn revents(&self) -> Option<PollFlags> {
++    pub fn revents(self) -> Option<PollFlags> {
+         PollFlags::from_bits(self.pollfd.revents)
+     }
+ }
+@@ -64,12 +63,16 @@ libc_bitflags! {
+         /// `O_NONBLOCK` is set).
+         POLLOUT;
+         /// Equivalent to [`POLLIN`](constant.POLLIN.html)
++        #[cfg(not(target_os = "redox"))]
+         POLLRDNORM;
++        #[cfg(not(target_os = "redox"))]
+         /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
+         POLLWRNORM;
+         /// Priority band data can be read (generally unused on Linux).
++        #[cfg(not(target_os = "redox"))]
+         POLLRDBAND;
+         /// Priority data may be written.
++        #[cfg(not(target_os = "redox"))]
+         POLLWRBAND;
+         /// Error condition (only returned in
+         /// [`PollFd::revents`](struct.PollFd.html#method.revents);
+@@ -127,16 +130,16 @@ pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
+ /// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
+ ///
+ /// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
+-/// with the `sigmask` argument.
++/// with the `sigmask` argument. If you want `ppoll` to block indefinitely,
++/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`).
+ ///
+ #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+-pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> {
+-
+-
++pub fn ppoll(fds: &mut [PollFd], timeout: Option<TimeSpec>, sigmask: SigSet) -> Result<libc::c_int> {
++    let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
+     let res = unsafe {
+         libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
+                     fds.len() as libc::nfds_t,
+-                    timeout.as_ref(),
++                    timeout,
+                     sigmask.as_ref())
+     };
+     Errno::result(res)
+diff --git a/third_party/rust/nix/src/pty.rs b/third_party/rust/nix/src/pty.rs
+index db012d8158c53..d67518f4744f3 100644
+--- a/third_party/rust/nix/src/pty.rs
++++ b/third_party/rust/nix/src/pty.rs
+@@ -1,18 +1,17 @@
+ //! Create master and slave virtual pseudo-terminals (PTYs)
+ 
+-use libc;
+-
+ pub use libc::pid_t as SessionId;
+ pub use libc::winsize as Winsize;
+ 
+ use std::ffi::CStr;
++use std::io;
+ use std::mem;
+ use std::os::unix::prelude::*;
+ 
+-use sys::termios::Termios;
+-use unistd::ForkResult;
+-use {Result, Error, fcntl};
+-use errno::Errno;
++use crate::sys::termios::Termios;
++use crate::unistd::{self, ForkResult, Pid};
++use crate::{Result, Error, fcntl};
++use crate::errno::Errno;
+ 
+ /// Representation of a master/slave pty pair
+ ///
+@@ -44,7 +43,7 @@ pub struct ForkptyResult {
+ /// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
+ /// functions are given the correct file descriptor. Additionally this type implements `Drop`,
+ /// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
+-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++#[derive(Debug, Eq, Hash, PartialEq)]
+ pub struct PtyMaster(RawFd);
+ 
+ impl AsRawFd for PtyMaster {
+@@ -70,13 +69,28 @@ impl Drop for PtyMaster {
+         // invalid file descriptor.  That frequently indicates a double-close
+         // condition, which can cause confusing errors for future I/O
+         // operations.
+-        let e = ::unistd::close(self.0);
++        let e = unistd::close(self.0);
+         if e == Err(Error::Sys(Errno::EBADF)) {
+             panic!("Closing an invalid file descriptor!");
+         };
+     }
+ }
+ 
++impl io::Read for PtyMaster {
++    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
++        unistd::read(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
++    }
++}
++
++impl io::Write for PtyMaster {
++    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
++        unistd::write(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
++    }
++    fn flush(&mut self) -> io::Result<()> {
++        Ok(())
++    }
++}
++
+ /// Grant access to a slave pseudoterminal (see
+ /// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
+ ///
+@@ -218,16 +232,16 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
+ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
+     use std::ptr;
+ 
+-    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
+-    let mut master: libc::c_int = unsafe { mem::uninitialized() };
++    let mut slave = mem::MaybeUninit::<libc::c_int>::uninit();
++    let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
+     let ret = {
+         match (termios.into(), winsize.into()) {
+             (Some(termios), Some(winsize)) => {
+                 let inner_termios = termios.get_libc_termios();
+                 unsafe {
+                     libc::openpty(
+-                        &mut master,
+-                        &mut slave,
++                        master.as_mut_ptr(),
++                        slave.as_mut_ptr(),
+                         ptr::null_mut(),
+                         &*inner_termios as *const libc::termios as *mut _,
+                         winsize as *const Winsize as *mut _,
+@@ -237,8 +251,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+             (None, Some(winsize)) => {
+                 unsafe {
+                     libc::openpty(
+-                        &mut master,
+-                        &mut slave,
++                        master.as_mut_ptr(),
++                        slave.as_mut_ptr(),
+                         ptr::null_mut(),
+                         ptr::null_mut(),
+                         winsize as *const Winsize as *mut _,
+@@ -249,8 +263,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+                 let inner_termios = termios.get_libc_termios();
+                 unsafe {
+                     libc::openpty(
+-                        &mut master,
+-                        &mut slave,
++                        master.as_mut_ptr(),
++                        slave.as_mut_ptr(),
+                         ptr::null_mut(),
+                         &*inner_termios as *const libc::termios as *mut _,
+                         ptr::null_mut(),
+@@ -260,8 +274,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+             (None, None) => {
+                 unsafe {
+                     libc::openpty(
+-                        &mut master,
+-                        &mut slave,
++                        master.as_mut_ptr(),
++                        slave.as_mut_ptr(),
+                         ptr::null_mut(),
+                         ptr::null_mut(),
+                         ptr::null_mut(),
+@@ -273,10 +287,12 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+ 
+     Errno::result(ret)?;
+ 
+-    Ok(OpenptyResult {
+-        master: master,
+-        slave: slave,
+-    })
++    unsafe {
++        Ok(OpenptyResult {
++            master: master.assume_init(),
++            slave: slave.assume_init(),
++        })
++    }
+ }
+ 
+ /// Create a new pseudoterminal, returning the master file descriptor and forked pid.
+@@ -291,10 +307,8 @@ pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+     termios: U,
+ ) -> Result<ForkptyResult> {
+     use std::ptr;
+-    use unistd::Pid;
+-    use unistd::ForkResult::*;
+ 
+-    let mut master: libc::c_int = unsafe { mem::uninitialized() };
++    let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
+ 
+     let term = match termios.into() {
+         Some(termios) => {
+@@ -310,17 +324,19 @@ pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
+         .unwrap_or(ptr::null_mut());
+ 
+     let res = unsafe {
+-        libc::forkpty(&mut master, ptr::null_mut(), term, win)
++        libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win)
+     };
+ 
+     let fork_result = Errno::result(res).map(|res| match res {
+-        0 => Child,
+-        res => Parent { child: Pid::from_raw(res) },
++        0 => ForkResult::Child,
++        res => ForkResult::Parent { child: Pid::from_raw(res) },
+     })?;
+ 
+-    Ok(ForkptyResult {
+-        master: master,
+-        fork_result: fork_result,
+-    })
++    unsafe {
++        Ok(ForkptyResult {
++            master: master.assume_init(),
++            fork_result,
++        })
++    }
+ }
+ 
+diff --git a/third_party/rust/nix/src/sched.rs b/third_party/rust/nix/src/sched.rs
+index 67188c57eef7d..3b48b4adf6d05 100644
+--- a/third_party/rust/nix/src/sched.rs
++++ b/third_party/rust/nix/src/sched.rs
+@@ -1,18 +1,17 @@
+-use libc;
+-use {Errno, Result};
++use crate::{Errno, Result};
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub use self::sched_linux_like::*;
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ mod sched_linux_like {
+-    use errno::Errno;
++    use crate::errno::Errno;
+     use libc::{self, c_int, c_void};
+     use std::mem;
+     use std::option::Option;
+     use std::os::unix::io::RawFd;
+-    use unistd::Pid;
+-    use {Error, Result};
++    use crate::unistd::Pid;
++    use crate::{Error, Result};
+ 
+     // For some functions taking with a parameter of type CloneFlags,
+     // only a subset of these flags have an effect.
+@@ -46,6 +45,11 @@ mod sched_linux_like {
+ 
+     pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
+ 
++    /// CpuSet represent a bit-mask of CPUs.
++    /// CpuSets are used by sched_setaffinity and
++    /// sched_getaffinity for example.
++    ///
++    /// This is a wrapper around `libc::cpu_set_t`.
+     #[repr(C)]
+     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+     pub struct CpuSet {
+@@ -53,37 +57,78 @@ mod sched_linux_like {
+     }
+ 
+     impl CpuSet {
++        /// Create a new and empty CpuSet.
+         pub fn new() -> CpuSet {
+             CpuSet {
+                 cpu_set: unsafe { mem::zeroed() },
+             }
+         }
+ 
++        /// Test to see if a CPU is in the CpuSet.
++        /// `field` is the CPU id to test
+         pub fn is_set(&self, field: usize) -> Result<bool> {
+-            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++            if field >= CpuSet::count() {
+                 Err(Error::Sys(Errno::EINVAL))
+             } else {
+                 Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
+             }
+         }
+ 
++        /// Add a CPU to CpuSet.
++        /// `field` is the CPU id to add
+         pub fn set(&mut self, field: usize) -> Result<()> {
+-            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++            if field >= CpuSet::count() {
+                 Err(Error::Sys(Errno::EINVAL))
+             } else {
+-                Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
++                unsafe { libc::CPU_SET(field, &mut self.cpu_set); }
++                Ok(())
+             }
+         }
+ 
++        /// Remove a CPU from CpuSet.
++        /// `field` is the CPU id to remove
+         pub fn unset(&mut self, field: usize) -> Result<()> {
+-            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
++            if field >= CpuSet::count() {
+                 Err(Error::Sys(Errno::EINVAL))
+             } else {
+-                Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
++                unsafe { libc::CPU_CLR(field, &mut self.cpu_set);}
++                Ok(())
+             }
+         }
++
++        /// Return the maximum number of CPU in CpuSet
++        pub fn count() -> usize {
++            8 * mem::size_of::<libc::cpu_set_t>()
++        }
+     }
+ 
++    impl Default for CpuSet {
++        fn default() -> Self {
++            Self::new()
++        }
++    }
++
++    /// `sched_setaffinity` set a thread's CPU affinity mask
++    /// ([`sched_setaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
++    ///
++    /// `pid` is the thread ID to update.
++    /// If pid is zero, then the calling thread is updated.
++    ///
++    /// The `cpuset` argument specifies the set of CPUs on which the thread
++    /// will be eligible to run.
++    ///
++    /// # Example
++    ///
++    /// Binding the current thread to CPU 0 can be done as follows:
++    ///
++    /// ```rust,no_run
++    /// use nix::sched::{CpuSet, sched_setaffinity};
++    /// use nix::unistd::Pid;
++    ///
++    /// let mut cpu_set = CpuSet::new();
++    /// cpu_set.set(0);
++    /// sched_setaffinity(Pid::from_raw(0), &cpu_set);
++    /// ```
+     pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
+         let res = unsafe {
+             libc::sched_setaffinity(
+@@ -96,6 +141,41 @@ mod sched_linux_like {
+         Errno::result(res).map(drop)
+     }
+ 
++    /// `sched_getaffinity` get a thread's CPU affinity mask
++    /// ([`sched_getaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
++    ///
++    /// `pid` is the thread ID to check.
++    /// If pid is zero, then the calling thread is checked.
++    ///
++    /// Returned `cpuset` is the set of CPUs on which the thread
++    /// is eligible to run.
++    ///
++    /// # Example
++    ///
++    /// Checking if the current thread can run on CPU 0 can be done as follows:
++    ///
++    /// ```rust,no_run
++    /// use nix::sched::sched_getaffinity;
++    /// use nix::unistd::Pid;
++    ///
++    /// let cpu_set = sched_getaffinity(Pid::from_raw(0)).unwrap();
++    /// if cpu_set.is_set(0).unwrap() {
++    ///     println!("Current thread can run on CPU 0");
++    /// }
++    /// ```
++    pub fn sched_getaffinity(pid: Pid) -> Result<CpuSet> {
++        let mut cpuset = CpuSet::new();
++        let res = unsafe {
++            libc::sched_getaffinity(
++                pid.into(),
++                mem::size_of::<CpuSet>() as libc::size_t,
++                &mut cpuset.cpu_set,
++            )
++        };
++
++        Errno::result(res).and(Ok(cpuset))
++    }
++
+     pub fn clone(
+         mut cb: CloneCb,
+         stack: &mut [u8],
+@@ -109,8 +189,8 @@ mod sched_linux_like {
+ 
+         let res = unsafe {
+             let combined = flags.bits() | signal.unwrap_or(0);
+-            let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
+-            let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
++            let ptr = stack.as_mut_ptr().add(stack.len());
++            let ptr_aligned = ptr.sub(ptr as usize % 16);
+             libc::clone(
+                 mem::transmute(
+                     callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
+diff --git a/third_party/rust/nix/src/sys/aio.rs b/third_party/rust/nix/src/sys/aio.rs
+index 9258a0657cc8a..1afdb35866c28 100644
+--- a/third_party/rust/nix/src/sys/aio.rs
++++ b/third_party/rust/nix/src/sys/aio.rs
+@@ -21,20 +21,19 @@
+ //! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
+ //! not support this for all filesystems and devices.
+ 
+-use {Error, Result};
+-use errno::Errno;
++use crate::{Error, Result};
++use crate::errno::Errno;
+ use std::os::unix::io::RawFd;
+ use libc::{c_void, off_t, size_t};
+-use libc;
+ use std::borrow::{Borrow, BorrowMut};
+ use std::fmt;
+ use std::fmt::Debug;
+ use std::marker::PhantomData;
+ use std::mem;
+ use std::ptr::{null, null_mut};
+-use sys::signal::*;
++use crate::sys::signal::*;
+ use std::thread;
+-use sys::time::TimeSpec;
++use crate::sys::time::TimeSpec;
+ 
+ libc_enum! {
+     /// Mode for `AioCb::fsync`.  Controls whether only data or both data and
+@@ -226,8 +225,6 @@ impl<'a> AioCb<'a> {
+     /// [`fsync`](#method.fsync) operation.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -287,8 +284,6 @@ impl<'a> AioCb<'a> {
+     /// Create an `AioCb` from a mutable slice and read into it.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -363,8 +358,6 @@ impl<'a> AioCb<'a> {
+     /// Create an `AioCb` from a Vector and use it for writing
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -394,9 +387,6 @@ impl<'a> AioCb<'a> {
+     /// Create an `AioCb` from a `Bytes` object
+     ///
+     /// ```
+-    /// # extern crate bytes;
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use bytes::Bytes;
+     /// # use nix::sys::aio::*;
+     /// # use nix::sys::signal::SigevNotify;
+@@ -419,9 +409,6 @@ impl<'a> AioCb<'a> {
+     /// using an un`Box`ed `Bytes` object.
+     ///
+     /// ```
+-    /// # extern crate bytes;
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use bytes::Bytes;
+     /// # use nix::sys::aio::*;
+     /// # use nix::sys::signal::SigevNotify;
+@@ -480,8 +467,6 @@ impl<'a> AioCb<'a> {
+     /// Create an `AioCb` from a Vector and use it for reading
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -642,8 +627,6 @@ impl<'a> AioCb<'a> {
+     /// Construct an `AioCb` from a slice and use it for writing.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -726,8 +709,6 @@ impl<'a> AioCb<'a> {
+     /// result.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -781,8 +762,6 @@ impl<'a> AioCb<'a> {
+     /// is an alternative to `aio_suspend`, used by most of the other examples.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::errno::Errno;
+     /// # use nix::Error;
+     /// # use nix::sys::aio::*;
+@@ -925,8 +904,6 @@ impl<'a> AioCb<'a> {
+ /// descriptor.
+ ///
+ /// ```
+-/// # extern crate tempfile;
+-/// # extern crate nix;
+ /// # use nix::errno::Errno;
+ /// # use nix::Error;
+ /// # use nix::sys::aio::*;
+@@ -978,13 +955,7 @@ pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
+ ///
+ /// Use `aio_suspend` to block until an aio operation completes.
+ ///
+-// Disable doctest due to a known bug in FreeBSD's 32-bit emulation.  The fix
+-// will be included in release 11.2.
+-// FIXME reenable the doc test when the CI machine gets upgraded to that release.
+-// https://svnweb.freebsd.org/base?view=revision&revision=325018
+-/// ```no_run
+-/// # extern crate tempfile;
+-/// # extern crate nix;
++/// ```
+ /// # use nix::sys::aio::*;
+ /// # use nix::sys::signal::SigevNotify;
+ /// # use std::os::unix::io::AsRawFd;
+@@ -1091,8 +1062,6 @@ impl<'a> LioCb<'a> {
+     /// [`AioCb::error`] to poll.
+     ///
+     /// ```
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::sys::aio::*;
+     /// # use nix::sys::signal::SigevNotify;
+     /// # use std::os::unix::io::AsRawFd;
+@@ -1148,8 +1117,6 @@ impl<'a> LioCb<'a> {
+     ///
+     /// # Examples
+     /// ```no_run
+-    /// # extern crate tempfile;
+-    /// # extern crate nix;
+     /// # use nix::Error;
+     /// # use nix::errno::Errno;
+     /// # use nix::sys::aio::*;
+@@ -1213,7 +1180,6 @@ impl<'a> LioCb<'a> {
+                 },
+                 Err(Error::Sys(Errno::EINPROGRESS)) => {
+                     // aiocb is was successfully queued; no need to do anything
+-                    ()
+                 },
+                 Err(Error::Sys(Errno::EINVAL)) => panic!(
+                     "AioCb was never submitted, or already finalized"),
+diff --git a/third_party/rust/nix/src/sys/epoll.rs b/third_party/rust/nix/src/sys/epoll.rs
+index fef6f4e3ec92c..2437bbe2ddb3b 100644
+--- a/third_party/rust/nix/src/sys/epoll.rs
++++ b/third_party/rust/nix/src/sys/epoll.rs
+@@ -1,10 +1,10 @@
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ use libc::{self, c_int};
+ use std::os::unix::io::RawFd;
+ use std::ptr;
+ use std::mem;
+-use ::Error;
++use crate::Error;
+ 
+ libc_bitflags!(
+     pub struct EpollFlags: c_int {
+@@ -43,7 +43,7 @@ libc_bitflags!{
+ }
+ 
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+-#[repr(C)]
++#[repr(transparent)]
+ pub struct EpollEvent {
+     event: libc::epoll_event,
+ }
+diff --git a/third_party/rust/nix/src/sys/event.rs b/third_party/rust/nix/src/sys/event.rs
+index 8cd7372f88188..8050af313245d 100644
+--- a/third_party/rust/nix/src/sys/event.rs
++++ b/third_party/rust/nix/src/sys/event.rs
+@@ -1,12 +1,11 @@
+ /* TOOD: Implement for other kqueue based systems
+  */
+ 
+-use {Errno, Result};
++use crate::{Errno, Result};
+ #[cfg(not(target_os = "netbsd"))]
+ use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
+ #[cfg(target_os = "netbsd")]
+ use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
+-use libc;
+ use std::os::unix::io::RawFd;
+ use std::ptr;
+ use std::mem;
+@@ -28,7 +27,7 @@ type type_of_data = intptr_t;
+ #[cfg(any(target_os = "netbsd"))]
+ type type_of_udata = intptr_t;
+ #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
+-type type_of_data = libc::int64_t;
++type type_of_data = i64;
+ 
+ #[cfg(target_os = "netbsd")]
+ type type_of_event_filter = u32;
+@@ -90,14 +89,9 @@ libc_bitflags!{
+         EV_CLEAR;
+         EV_DELETE;
+         EV_DISABLE;
+-        // No released version of OpenBSD supports EV_DISPATCH or EV_RECEIPT.
+-        // These have been commited to the -current branch though and are
+-        // expected to be part of the OpenBSD 6.2 release in Nov 2017.
+-        // See: https://marc.info/?l=openbsd-tech&m=149621427511219&w=2
+-        // https://github.com/rust-lang/libc/pull/613
+         #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
+                   target_os = "ios", target_os = "macos",
+-                  target_os = "netbsd"))]
++                  target_os = "netbsd", target_os = "openbsd"))]
+         EV_DISPATCH;
+         #[cfg(target_os = "freebsd")]
+         EV_DROP;
+@@ -116,7 +110,7 @@ libc_bitflags!{
+         EV_POLL;
+         #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
+                   target_os = "ios", target_os = "macos",
+-                  target_os = "netbsd"))]
++                  target_os = "netbsd", target_os = "openbsd"))]
+         EV_RECEIPT;
+         EV_SYSFLAGS;
+     }
+@@ -134,10 +128,6 @@ libc_bitflags!(
+         NOTE_EXEC;
+         NOTE_EXIT;
+         #[cfg(any(target_os = "macos", target_os = "ios"))]
+-        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
+-        #[allow(deprecated)]
+-        NOTE_EXIT_REPARENTED;
+-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+         NOTE_EXITSTATUS;
+         NOTE_EXTEND;
+         #[cfg(any(target_os = "macos",
+@@ -183,11 +173,6 @@ libc_bitflags!(
+         NOTE_OOB;
+         NOTE_PCTRLMASK;
+         NOTE_PDATAMASK;
+-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+-        #[cfg(any(target_os = "macos", target_os = "ios"))]
+-        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
+-        #[allow(deprecated)]
+-        NOTE_REAP;
+         NOTE_RENAME;
+         NOTE_REVOKE;
+         #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
+@@ -234,7 +219,7 @@ impl KEvent {
+     pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
+                fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
+         KEvent { kevent: libc::kevent {
+-            ident: ident,
++            ident,
+             filter: filter as type_of_event_filter,
+             flags: flags.bits(),
+             fflags: fflags.bits(),
+@@ -329,23 +314,17 @@ pub fn ev_set(ev: &mut KEvent,
+ fn test_struct_kevent() {
+     let udata : intptr_t = 12345;
+ 
+-    let expected = libc::kevent{ident: 0xdead_beef,
+-                                filter: libc::EVFILT_READ,
+-                                flags: libc::EV_ONESHOT | libc::EV_ADD,
+-                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
+-                                data: 0x1337,
+-                                udata: udata as type_of_udata};
+     let actual = KEvent::new(0xdead_beef,
+                              EventFilter::EVFILT_READ,
+                              EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
+                              FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
+                              0x1337,
+                              udata);
+-    assert!(expected.ident == actual.ident());
+-    assert!(expected.filter == actual.filter() as type_of_event_filter);
+-    assert!(expected.flags == actual.flags().bits());
+-    assert!(expected.fflags == actual.fflags().bits());
+-    assert!(expected.data == actual.data() as type_of_data);
+-    assert!(expected.udata == actual.udata() as type_of_udata);
+-    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
++    assert_eq!(0xdead_beef, actual.ident());
++    assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
++    assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
++    assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
++    assert_eq!(0x1337, actual.data() as type_of_data);
++    assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
++    assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
+ }
+diff --git a/third_party/rust/nix/src/sys/eventfd.rs b/third_party/rust/nix/src/sys/eventfd.rs
+index c5a54e46a1735..baaaa89ddd52e 100644
+--- a/third_party/rust/nix/src/sys/eventfd.rs
++++ b/third_party/rust/nix/src/sys/eventfd.rs
+@@ -1,7 +1,7 @@
+ use libc;
+ use std::os::unix::io::RawFd;
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ 
+ libc_bitflags! {
+     pub struct EfdFlags: libc::c_int {
+diff --git a/third_party/rust/nix/src/sys/inotify.rs b/third_party/rust/nix/src/sys/inotify.rs
+index e6c2cf64d29dc..4880a4a514e77 100644
+--- a/third_party/rust/nix/src/sys/inotify.rs
++++ b/third_party/rust/nix/src/sys/inotify.rs
+@@ -23,19 +23,19 @@
+ //! }
+ //! ```
+ 
+-use libc;
+ use libc::{
+     c_char,
+     c_int,
+ };
+ use std::ffi::{OsString,OsStr,CStr};
+ use std::os::unix::ffi::OsStrExt;
+-use std::mem::size_of;
++use std::mem::{MaybeUninit, size_of};
+ use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
+-use unistd::read;
+-use Result;
+-use NixPath;
+-use errno::Errno;
++use std::ptr;
++use crate::unistd::read;
++use crate::Result;
++use crate::NixPath;
++use crate::errno::Errno;
+ 
+ libc_bitflags! {
+     /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
+@@ -131,7 +131,7 @@ impl Inotify {
+     /// 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).
+-    pub fn add_watch<P: ?Sized + NixPath>(&self,
++    pub fn add_watch<P: ?Sized + NixPath>(self,
+                                           path: &P,
+                                           mask: AddWatchFlags) 
+                                             -> Result<WatchDescriptor>
+@@ -152,14 +152,14 @@ impl Inotify {
+     ///
+     /// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
+     #[cfg(target_os = "linux")]
+-    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
++    pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
+         let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
+ 
+         Errno::result(res).map(drop)
+     }
+ 
+     #[cfg(target_os = "android")]
+-    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
++    pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
+         let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) };
+ 
+         Errno::result(res).map(drop)
+@@ -171,9 +171,10 @@ impl Inotify {
+     /// 
+     /// 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>> {
++    pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
+         let header_size = size_of::<libc::inotify_event>();
+-        let mut buffer = [0u8; 4096];
++        const BUFSIZ: usize = 4096;
++        let mut buffer = [0u8; BUFSIZ];
+         let mut events = Vec::new();
+         let mut offset = 0;
+ 
+@@ -181,11 +182,13 @@ impl Inotify {
+ 
+         while (nread - offset) >= header_size {
+             let event = unsafe {
+-                &*(
+-                    buffer
+-                        .as_ptr()
+-                        .offset(offset as isize) as *const libc::inotify_event
+-                )
++                let mut event = MaybeUninit::<libc::inotify_event>::uninit();
++                ptr::copy_nonoverlapping(
++                    buffer.as_ptr().add(offset),
++                    event.as_mut_ptr() as *mut u8,
++                    (BUFSIZ - offset).min(header_size)
++                );
++                event.assume_init()
+             };
+ 
+             let name = match event.len {
+@@ -194,7 +197,7 @@ impl Inotify {
+                     let ptr = unsafe { 
+                         buffer
+                             .as_ptr()
+-                            .offset(offset as isize + header_size as isize)
++                            .add(offset + header_size)
+                             as *const c_char
+                     };
+                     let cstr = unsafe { CStr::from_ptr(ptr) };
+diff --git a/third_party/rust/nix/src/sys/ioctl/bsd.rs b/third_party/rust/nix/src/sys/ioctl/bsd.rs
+index 9b8b0ff1a155f..f39c0eb688f8a 100644
+--- a/third_party/rust/nix/src/sys/ioctl/bsd.rs
++++ b/third_party/rust/nix/src/sys/ioctl/bsd.rs
+@@ -6,7 +6,7 @@ pub type ioctl_num_type = ::libc::c_ulong;
+ pub type ioctl_param_type = ::libc::c_int;
+ 
+ mod consts {
+-    use ::sys::ioctl::ioctl_num_type;
++    use crate::sys::ioctl::ioctl_num_type;
+     #[doc(hidden)]
+     pub const VOID: ioctl_num_type = 0x2000_0000;
+     #[doc(hidden)]
+@@ -14,7 +14,7 @@ mod consts {
+     #[doc(hidden)]
+     pub const IN: ioctl_num_type = 0x8000_0000;
+     #[doc(hidden)]
+-    pub const INOUT: ioctl_num_type = (IN|OUT);
++    pub const INOUT: ioctl_num_type = IN|OUT;
+     #[doc(hidden)]
+     pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
+ }
+diff --git a/third_party/rust/nix/src/sys/ioctl/linux.rs b/third_party/rust/nix/src/sys/ioctl/linux.rs
+index 9cdac72a4b80b..68ebaba9bf496 100644
+--- a/third_party/rust/nix/src/sys/ioctl/linux.rs
++++ b/third_party/rust/nix/src/sys/ioctl/linux.rs
+@@ -33,7 +33,8 @@ mod consts {
+           target_arch = "arm",
+           target_arch = "s390x",
+           target_arch = "x86_64",
+-          target_arch = "aarch64"))]
++          target_arch = "aarch64",
++          target_arch = "riscv64"))]
+ mod consts {
+     #[doc(hidden)]
+     pub const NONE: u8 = 0;
+diff --git a/third_party/rust/nix/src/sys/ioctl/mod.rs b/third_party/rust/nix/src/sys/ioctl/mod.rs
+index 4513bf877434a..8858a9d57779f 100644
+--- a/third_party/rust/nix/src/sys/ioctl/mod.rs
++++ b/third_party/rust/nix/src/sys/ioctl/mod.rs
+@@ -29,7 +29,7 @@
+ //! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
+ //! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
+ //! subcomponents (For linux this is documented in
+-//! [`Documentation/ioctl/ioctl-number.txt`](http://elixir.free-electrons.com/linux/latest/source/Documentation/ioctl/ioctl-number.txt)):
++//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)):
+ //!
+ //!   * Number: The actual ioctl ID
+ //!   * Type: A grouping of ioctls for a common purpose or driver
+@@ -221,11 +221,13 @@
+ //!
+ //! # fn main() {}
+ //! ```
+-#[cfg(any(target_os = "android", target_os = "linux"))]
++use cfg_if::cfg_if;
++
++#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+ #[macro_use]
+ mod linux;
+ 
+-#[cfg(any(target_os = "android", target_os = "linux"))]
++#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+ pub use self::linux::*;
+ 
+ #[cfg(any(target_os = "dragonfly",
+@@ -317,7 +319,6 @@ macro_rules! ioctl_none {
+ ///
+ /// ```no_run
+ /// # #[macro_use] extern crate nix;
+-/// # extern crate libc;
+ /// # use libc::TIOCNXCL;
+ /// # use std::fs::File;
+ /// # use std::os::unix::io::AsRawFd;
+@@ -396,7 +397,6 @@ macro_rules! ioctl_read {
+ /// # Example
+ ///
+ /// ```
+-/// # extern crate libc;
+ /// # #[macro_use] extern crate nix;
+ /// # #[cfg(any(target_os = "android", target_os = "linux"))]
+ /// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
+@@ -470,7 +470,6 @@ macro_rules! ioctl_write_ptr {
+ /// # Example
+ ///
+ /// ```
+-/// # extern crate libc;
+ /// # #[macro_use] extern crate nix;
+ /// # #[cfg(any(target_os = "android", target_os = "linux"))]
+ /// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
+@@ -590,7 +589,6 @@ cfg_if!{
+ /// # Examples
+ ///
+ /// ```
+-/// # extern crate libc;
+ /// # #[macro_use] extern crate nix;
+ /// # #[cfg(any(target_os = "android", target_os = "linux"))]
+ /// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
+diff --git a/third_party/rust/nix/src/sys/memfd.rs b/third_party/rust/nix/src/sys/memfd.rs
+index 9672429b31e7f..51b7e6b18849b 100644
+--- a/third_party/rust/nix/src/sys/memfd.rs
++++ b/third_party/rust/nix/src/sys/memfd.rs
+@@ -1,7 +1,7 @@
+ use libc;
+ use std::os::unix::io::RawFd;
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ use std::ffi::CStr;
+ 
+ libc_bitflags!(
+diff --git a/third_party/rust/nix/src/sys/mman.rs b/third_party/rust/nix/src/sys/mman.rs
+index 4e250501dd0f0..63a0779c19382 100644
+--- a/third_party/rust/nix/src/sys/mman.rs
++++ b/third_party/rust/nix/src/sys/mman.rs
+@@ -1,12 +1,12 @@
+-use {Error, Result};
++use crate::{Error, Result};
+ #[cfg(not(target_os = "android"))]
+-use NixPath;
+-use errno::Errno;
++use crate::NixPath;
++use crate::errno::Errno;
+ #[cfg(not(target_os = "android"))]
+-use fcntl::OFlag;
++use crate::fcntl::OFlag;
+ use libc::{self, c_int, c_void, size_t, off_t};
+ #[cfg(not(target_os = "android"))]
+-use sys::stat::Mode;
++use crate::sys::stat::Mode;
+ use std::os::unix::io::RawFd;
+ 
+ libc_bitflags!{
+@@ -77,6 +77,43 @@ libc_bitflags!{
+         /// Allocate the mapping using "huge pages."
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+         MAP_HUGETLB;
++        /// Make use of 64KB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_64KB;
++        /// Make use of 512KB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_512KB;
++        /// Make use of 1MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_1MB;
++        /// Make use of 2MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_2MB;
++        /// Make use of 8MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_8MB;
++        /// Make use of 16MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_16MB;
++        /// Make use of 32MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_32MB;
++        /// Make use of 256MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_256MB;
++        /// Make use of 512MB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_512MB;
++        /// Make use of 1GB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_1GB;
++        /// Make use of 2GB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_2GB;
++        /// Make use of 16GB huge page (must be supported by the system)
++        #[cfg(target_os = "linux")]
++        MAP_HUGE_16GB;
++
+         /// Lock the mapped region into memory as with `mlock(2)`.
+         #[cfg(target_os = "netbsd")]
+         MAP_WIRED;
+@@ -102,6 +139,17 @@ libc_bitflags!{
+     }
+ }
+ 
++#[cfg(target_os = "linux")]
++libc_bitflags!{
++    /// Options for `mremap()`.
++    pub struct MRemapFlags: c_int {
++        /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
++        MREMAP_MAYMOVE;
++        /// Place the mapping at exactly the address specified in `new_address`.
++        MREMAP_FIXED;
++    }
++}
++
+ libc_enum!{
+     /// Usage information for a range of memory to allow for performance optimizations by the kernel.
+     ///
+@@ -223,20 +271,37 @@ libc_bitflags!{
+     }
+ }
+ 
+-/// Locks all memory pages that contain part of the address range with `length` bytes starting at
+-/// `addr`. Locked pages never move to the swap area.
++/// Locks all memory pages that contain part of the address range with `length`
++/// bytes starting at `addr`.
++///
++/// Locked pages never move to the swap area.
++///
++/// # Safety
++///
++/// `addr` must meet all the requirements described in the `mlock(2)` man page.
+ pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
+     Errno::result(libc::mlock(addr, length)).map(drop)
+ }
+ 
+-/// Unlocks all memory pages that contain part of the address range with `length` bytes starting at
+-/// `addr`.
++/// Unlocks all memory pages that contain part of the address range with
++/// `length` bytes starting at `addr`.
++///
++/// # Safety
++///
++/// `addr` must meet all the requirements described in the `munlock(2)` man
++/// page.
+ pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
+     Errno::result(libc::munlock(addr, length)).map(drop)
+ }
+ 
+-/// Locks all memory pages mapped into this process' address space. Locked pages never move to the
+-/// swap area.
++/// Locks all memory pages mapped into this process' address space.
++///
++/// Locked pages never move to the swap area.
++///
++/// # Safety
++///
++/// `addr` must meet all the requirements described in the `mlockall(2)` man
++/// page.
+ pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
+     unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
+ }
+@@ -246,8 +311,11 @@ pub fn munlockall() -> Result<()> {
+     unsafe { Errno::result(libc::munlockall()) }.map(drop)
+ }
+ 
+-/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
+-/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
++/// allocate memory, or map files or devices into memory
++///
++/// # Safety
++///
++/// See the `mmap(2)` man page for detailed requirements.
+ pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
+     let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
+ 
+@@ -258,10 +326,46 @@ pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: Ma
+     }
+ }
+ 
++/// Expands (or shrinks) an existing memory mapping, potentially moving it at
++/// the same time.
++///
++/// # Safety
++///
++/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
++/// detailed requirements.
++#[cfg(target_os = "linux")]
++pub unsafe fn mremap(
++    addr: *mut c_void,
++    old_size: size_t,
++    new_size: size_t,
++    flags: MRemapFlags,
++    new_address: Option<* mut c_void>,
++) -> Result<*mut c_void> {
++    let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
++
++    if ret == libc::MAP_FAILED {
++        Err(Error::Sys(Errno::last()))
++    } else {
++        Ok(ret)
++    }
++}
++
++/// remove a mapping
++///
++/// # Safety
++///
++/// `addr` must meet all the requirements described in the `munmap(2)` man
++/// page.
+ pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
+     Errno::result(libc::munmap(addr, len)).map(drop)
+ }
+ 
++/// give advice about use of memory
++///
++/// # Safety
++///
++/// See the `madvise(2)` man page.  Take special care when using
++/// `MmapAdvise::MADV_FREE`.
+ pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
+     Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
+ }
+@@ -295,6 +399,12 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Re
+     Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
+ }
+ 
++/// synchronize a mapped region
++///
++/// # Safety
++///
++/// `addr` must meet all the requirements described in the `msync(2)` man
++/// page.
+ pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
+     Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
+ }
+diff --git a/third_party/rust/nix/src/sys/mod.rs b/third_party/rust/nix/src/sys/mod.rs
+index d3c2f92bbaaea..438fb4fdcb438 100644
+--- a/third_party/rust/nix/src/sys/mod.rs
++++ b/third_party/rust/nix/src/sys/mod.rs
+@@ -25,6 +25,7 @@ pub mod eventfd;
+           target_os = "freebsd",
+           target_os = "ios",
+           target_os = "linux",
++          target_os = "redox",
+           target_os = "macos",
+           target_os = "netbsd",
+           target_os = "openbsd"))]
+@@ -34,8 +35,12 @@ pub mod ioctl;
+ #[cfg(target_os = "linux")]
+ pub mod memfd;
+ 
++#[cfg(not(target_os = "redox"))]
+ pub mod mman;
+ 
++#[cfg(target_os = "linux")]
++pub mod personality;
++
+ pub mod pthread;
+ 
+ #[cfg(any(target_os = "android",
+@@ -53,6 +58,7 @@ pub mod quota;
+ #[cfg(any(target_os = "linux"))]
+ pub mod reboot;
+ 
++#[cfg(not(target_os = "redox"))]
+ pub mod select;
+ 
+ #[cfg(any(target_os = "android",
+@@ -67,6 +73,7 @@ pub mod signal;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod signalfd;
+ 
++#[cfg(not(target_os = "redox"))]
+ pub mod socket;
+ 
+ pub mod stat;
+@@ -98,3 +105,6 @@ pub mod wait;
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod inotify;
++
++#[cfg(target_os = "linux")]
++pub mod timerfd;
+diff --git a/third_party/rust/nix/src/sys/personality.rs b/third_party/rust/nix/src/sys/personality.rs
+new file mode 100644
+index 0000000000000..6548b654aa1f4
+--- /dev/null
++++ b/third_party/rust/nix/src/sys/personality.rs
+@@ -0,0 +1,70 @@
++use crate::Result;
++use crate::errno::Errno;
++
++use libc::{self, c_int, c_ulong};
++
++libc_bitflags! {
++    /// Flags used and returned by [`get()`](fn.get.html) and
++    /// [`set()`](fn.set.html).
++    pub struct Persona: c_int {
++        ADDR_COMPAT_LAYOUT;
++        ADDR_NO_RANDOMIZE;
++        ADDR_LIMIT_32BIT;
++        ADDR_LIMIT_3GB;
++        #[cfg(not(target_env = "musl"))]
++        FDPIC_FUNCPTRS;
++        MMAP_PAGE_ZERO;
++        READ_IMPLIES_EXEC;
++        SHORT_INODE;
++        STICKY_TIMEOUTS;
++        #[cfg(not(target_env = "musl"))]
++        UNAME26;
++        WHOLE_SECONDS;
++    }
++}
++
++/// Retrieve the current process personality.
++///
++/// Returns a Result containing a Persona instance.
++///
++/// Example:
++///
++/// ```
++/// # use nix::sys::personality::{self, Persona};
++/// let pers = personality::get().unwrap();
++/// assert!(!pers.contains(Persona::WHOLE_SECONDS));
++/// ```
++pub fn get() -> Result<Persona> {
++    let res = unsafe {
++        libc::personality(0xFFFFFFFF)
++    };
++
++    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
++}
++
++/// Set the current process personality.
++///
++/// Returns a Result containing the *previous* personality for the
++/// process, as a Persona.
++///
++/// For more information, see [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html)
++///
++/// **NOTE**: This call **replaces** the current personality entirely.
++/// To **update** the personality, first call `get()` and then `set()`
++/// with the modified persona.
++///
++/// Example:
++///
++/// ```
++/// # use nix::sys::personality::{self, Persona};
++/// let mut pers = personality::get().unwrap();
++/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE));
++/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE);
++/// ```
++pub fn set(persona: Persona) -> Result<Persona> {
++    let res = unsafe {
++        libc::personality(persona.bits() as c_ulong)
++    };
++
++    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
++}
+diff --git a/third_party/rust/nix/src/sys/ptrace/bsd.rs b/third_party/rust/nix/src/sys/ptrace/bsd.rs
+index 7797d10647ef4..e85afc761198b 100644
+--- a/third_party/rust/nix/src/sys/ptrace/bsd.rs
++++ b/third_party/rust/nix/src/sys/ptrace/bsd.rs
+@@ -1,9 +1,10 @@
+-use errno::Errno;
++use cfg_if::cfg_if;
++use crate::errno::Errno;
+ use libc::{self, c_int};
+ use std::ptr;
+-use sys::signal::Signal;
+-use unistd::Pid;
+-use Result;
++use crate::sys::signal::Signal;
++use crate::unistd::Pid;
++use crate::Result;
+ 
+ pub type RequestType = c_int;
+ 
+@@ -77,16 +78,23 @@ pub fn traceme() -> Result<()> {
+ 
+ /// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
+ ///
+-/// Attaches to the process specified in pid, making it a tracee of the calling process.
++/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
+ pub fn attach(pid: Pid) -> Result<()> {
+     unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
+ }
+ 
+ /// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
+ ///
+-/// Detaches from the process specified in pid allowing it to run freely
+-pub fn detach(pid: Pid) -> Result<()> {
+-    unsafe { ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), 0).map(drop) }
++/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
++/// signal specified by `sig`.
++pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as c_int,
++        None => 0,
++    };
++    unsafe {
++        ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop)
++    }
+ }
+ 
+ /// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
+@@ -121,7 +129,6 @@ pub fn kill(pid: Pid) -> Result<()> {
+ ///
+ /// # Example
+ /// ```rust
+-/// extern crate nix;
+ /// use nix::sys::ptrace::step;
+ /// use nix::unistd::Pid;
+ /// use nix::sys::signal::Signal;
+diff --git a/third_party/rust/nix/src/sys/ptrace/linux.rs b/third_party/rust/nix/src/sys/ptrace/linux.rs
+index df15e66527562..8d1dd16e5dd76 100644
+--- a/third_party/rust/nix/src/sys/ptrace/linux.rs
++++ b/third_party/rust/nix/src/sys/ptrace/linux.rs
+@@ -1,18 +1,21 @@
+ //! For detailed description of the ptrace requests, consult `man ptrace`.
+ 
++use cfg_if::cfg_if;
+ use std::{mem, ptr};
+-use {Error, Result};
+-use errno::Errno;
++use crate::{Error, Result};
++use crate::errno::Errno;
+ use libc::{self, c_void, c_long, siginfo_t};
+-use ::unistd::Pid;
+-use sys::signal::Signal;
++use crate::unistd::Pid;
++use crate::sys::signal::Signal;
+ 
+ pub type AddressType = *mut ::libc::c_void;
+ 
+-#[cfg(all(target_os = "linux",
+-          any(target_arch = "x86_64",
+-              target_arch = "x86"),
+-          target_env = "gnu"))]
++#[cfg(all(
++    target_os = "linux",
++    any(all(target_arch = "x86_64",
++            any(target_env = "gnu", target_env = "musl")),
++        all(target_arch = "x86", target_env = "gnu"))
++))]
+ use libc::user_regs_struct;
+ 
+ cfg_if! {
+@@ -106,6 +109,12 @@ libc_enum!{
+         #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
+                                                target_arch = "mips64"))))]
+         PTRACE_PEEKSIGINFO,
++        #[cfg(all(target_os = "linux", target_env = "gnu",
++                  any(target_arch = "x86", target_arch = "x86_64")))]
++        PTRACE_SYSEMU,
++        #[cfg(all(target_os = "linux", target_env = "gnu",
++                  any(target_arch = "x86", target_arch = "x86_64")))]
++        PTRACE_SYSEMU_SINGLESTEP,
+     }
+ }
+ 
+@@ -165,22 +174,6 @@ libc_bitflags! {
+     }
+ }
+ 
+-/// Performs a ptrace request. If the request in question is provided by a specialised function
+-/// this function will return an unsupported operation error.
+-#[deprecated(
+-    since="0.10.0",
+-    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
+-)]
+-pub unsafe fn ptrace(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
+-    use self::Request::*;
+-    match request {
+-        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_GETSIGINFO | 
+-            PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS | 
+-            PTRACE_POKETEXT | PTRACE_POKEDATA | PTRACE_KILL => Err(Error::UnsupportedOperation),
+-        _ => ptrace_other(request, pid, addr, data)
+-    }
+-}
+-
+ fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
+     let ret = unsafe {
+         Errno::clear();
+@@ -193,19 +186,23 @@ fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void)
+ }
+ 
+ /// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
+-#[cfg(all(target_os = "linux",
+-          any(target_arch = "x86_64",
+-              target_arch = "x86"),
+-          target_env = "gnu"))]
++#[cfg(all(
++    target_os = "linux",
++    any(all(target_arch = "x86_64",
++            any(target_env = "gnu", target_env = "musl")),
++        all(target_arch = "x86", target_env = "gnu"))
++))]
+ pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
+     ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
+ }
+ 
+ /// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
+-#[cfg(all(target_os = "linux",
+-          any(target_arch = "x86_64",
+-              target_arch = "x86"),
+-          target_env = "gnu"))]
++#[cfg(all(
++    target_os = "linux",
++    any(all(target_arch = "x86_64",
++            any(target_env = "gnu", target_env = "musl")),
++        all(target_arch = "x86", target_env = "gnu"))
++))]
+ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
+     let res = unsafe {
+         libc::ptrace(Request::PTRACE_SETREGS as RequestType,
+@@ -221,16 +218,15 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
+ /// and therefore use the data field to return values. This function handles these
+ /// requests.
+ fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
+-    // Creates an uninitialized pointer to store result in
+-    let data: T = unsafe { mem::uninitialized() };
++    let mut data = mem::MaybeUninit::uninit();
+     let res = unsafe {
+         libc::ptrace(request as RequestType,
+                      libc::pid_t::from(pid),
+                      ptr::null_mut::<T>(),
+-                     &data as *const _ as *const c_void)
++                     data.as_mut_ptr() as *const _ as *const c_void)
+     };
+     Errno::result(res)?;
+-    Ok(data)
++    Ok(unsafe{ data.assume_init() })
+ }
+ 
+ unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
+@@ -288,23 +284,45 @@ pub fn traceme() -> Result<()> {
+     }
+ }
+ 
+-/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
++/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
+ ///
+-/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
+-pub fn syscall(pid: Pid) -> Result<()> {
++/// Arranges for the tracee to be stopped at the next entry to or exit from a system call,
++/// optionally delivering a signal specified by `sig`.
++pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
+     unsafe {
+         ptrace_other(
+             Request::PTRACE_SYSCALL,
+             pid,
+             ptr::null_mut(),
+-            ptr::null_mut(),
++            data,
+         ).map(drop) // ignore the useless return value
+     }
+ }
+ 
++/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
++///
++/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
++/// Thus the the tracee will only be stopped once per syscall,
++/// optionally delivering a signal specified by `sig`.
++#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
++pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
++    unsafe {
++        ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
++        // ignore the useless return value
++    }
++}
++
+ /// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
+ ///
+-/// Attaches to the process specified in pid, making it a tracee of the calling process.
++/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
+ pub fn attach(pid: Pid) -> Result<()> {
+     unsafe {
+         ptrace_other(
+@@ -316,16 +334,36 @@ pub fn attach(pid: Pid) -> Result<()> {
+     }
+ }
+ 
++/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
++///
++/// Attaches to the process specified in pid, making it a tracee of the calling process.
++#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64"))))]
++pub fn seize(pid: Pid, options: Options) -> Result<()> {
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_SEIZE,
++            pid,
++            ptr::null_mut(),
++            options.bits() as *mut c_void,
++        ).map(drop) // ignore the useless return value
++    }
++}
++
+ /// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
+ ///
+-/// Detaches from the process specified in pid allowing it to run freely
+-pub fn detach(pid: Pid) -> Result<()> {
++/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
++/// signal specified by `sig`.
++pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
+     unsafe {
+         ptrace_other(
+             Request::PTRACE_DETACH,
+             pid,
+             ptr::null_mut(),
+-            ptr::null_mut()
++            data
+         ).map(drop)
+     }
+ }
+@@ -361,7 +399,6 @@ pub fn kill(pid: Pid) -> Result<()> {
+ ///
+ /// # Example
+ /// ```rust
+-/// extern crate nix;
+ /// use nix::sys::ptrace::step;
+ /// use nix::unistd::Pid;
+ /// use nix::sys::signal::Signal; 
+@@ -388,6 +425,28 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
+     }
+ }
+ 
++/// Move the stopped tracee process forward by a single step or stop at the next syscall
++/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)`
++///
++/// Advances the execution by a single step or until the next syscall.
++/// In case the tracee is stopped at a syscall, the syscall will not be executed.
++/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
++#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
++pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
++    let data = match sig.into() {
++        Some(s) => s as i32 as *mut c_void,
++        None => ptr::null_mut(),
++    };
++    unsafe {
++        ptrace_other(
++            Request::PTRACE_SYSEMU_SINGLESTEP,
++            pid,
++            ptr::null_mut(),
++            data,
++        )
++        .map(drop) // ignore the useless return value
++    }
++}
+ 
+ /// Reads a word from a processes memory at the given address
+ pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
+@@ -395,8 +454,15 @@ pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
+ }
+ 
+ /// Writes a word into the processes memory at the given address
+-pub fn write(pid: Pid, addr: AddressType, data: *mut c_void) -> Result<()> {
+-    unsafe {
+-        ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
+-    }
++///
++/// # Safety
++///
++/// The `data` argument is passed directly to `ptrace(2)`.  Read that man page
++/// for guidance.
++pub unsafe fn write(
++    pid: Pid,
++    addr: AddressType,
++    data: *mut c_void) -> Result<()>
++{
++    ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
+ }
+diff --git a/third_party/rust/nix/src/sys/quota.rs b/third_party/rust/nix/src/sys/quota.rs
+index 8946fca2213c8..1933013219102 100644
+--- a/third_party/rust/nix/src/sys/quota.rs
++++ b/third_party/rust/nix/src/sys/quota.rs
+@@ -15,12 +15,13 @@
+ use std::default::Default;
+ use std::{mem, ptr};
+ use libc::{self, c_int, c_char};
+-use {Result, NixPath};
+-use errno::Errno;
++use crate::{Result, NixPath};
++use crate::errno::Errno;
+ 
+ struct QuotaCmd(QuotaSubCmd, QuotaType);
+ 
+ impl QuotaCmd {
++    #[allow(unused_unsafe)]
+     fn as_int(&self) -> c_int {
+         unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
+     }
+@@ -94,8 +95,7 @@ libc_bitflags!(
+ );
+ 
+ /// Wrapper type for `if_dqblk`
+-// FIXME: Change to repr(transparent)
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct Dqblk(libc::dqblk);
+ 
+@@ -254,15 +254,17 @@ pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Resul
+ }
+ 
+ /// Update the on-disk copy of quota usages for a filesystem.
++///
++/// If `special` is `None`, then all file systems with active quotas are sync'd.
+ pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
+     quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
+ }
+ 
+ /// Get disk quota limits and current usage for the given user/group id.
+ pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
+-    let mut dqblk = unsafe { mem::uninitialized() };
+-    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?;
+-    dqblk
++    let mut dqblk = mem::MaybeUninit::uninit();
++    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?;
++    Ok(unsafe{ Dqblk(dqblk.assume_init())})
+ }
+ 
+ /// Configure quota values for the specified fields for a given user/group id.
+diff --git a/third_party/rust/nix/src/sys/reboot.rs b/third_party/rust/nix/src/sys/reboot.rs
+index bafa8fc11996d..e319130698e82 100644
+--- a/third_party/rust/nix/src/sys/reboot.rs
++++ b/third_party/rust/nix/src/sys/reboot.rs
+@@ -1,9 +1,9 @@
+ //! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
+ 
+-use {Error, Result};
+-use errno::Errno;
++use crate::{Error, Result};
++use crate::errno::Errno;
+ use libc;
+-use void::Void;
++use std::convert::Infallible;
+ use std::mem::drop;
+ 
+ libc_enum! {
+@@ -22,7 +22,7 @@ libc_enum! {
+     }
+ }
+ 
+-pub fn reboot(how: RebootMode) -> Result<Void> {
++pub fn reboot(how: RebootMode) -> Result<Infallible> {
+     unsafe {
+         libc::reboot(how as libc::c_int)
+     };
+diff --git a/third_party/rust/nix/src/sys/select.rs b/third_party/rust/nix/src/sys/select.rs
+index 1b518e29f67a6..a576c7e4929c4 100644
+--- a/third_party/rust/nix/src/sys/select.rs
++++ b/third_party/rust/nix/src/sys/select.rs
+@@ -1,24 +1,27 @@
++use std::iter::FusedIterator;
+ use std::mem;
++use std::ops::Range;
+ use std::os::unix::io::RawFd;
+ use std::ptr::{null, null_mut};
+ use libc::{self, c_int};
+-use Result;
+-use errno::Errno;
+-use sys::signal::SigSet;
+-use sys::time::{TimeSpec, TimeVal};
++use crate::Result;
++use crate::errno::Errno;
++use crate::sys::signal::SigSet;
++use crate::sys::time::{TimeSpec, TimeVal};
+ 
+ pub use libc::FD_SETSIZE;
+ 
+-// FIXME: Change to repr(transparent) once it's stable
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct FdSet(libc::fd_set);
+ 
+ impl FdSet {
+     pub fn new() -> FdSet {
+-        let mut fdset = unsafe { mem::uninitialized() };
+-        unsafe { libc::FD_ZERO(&mut fdset) };
+-        FdSet(fdset)
++        let mut fdset = mem::MaybeUninit::uninit();
++        unsafe {
++            libc::FD_ZERO(fdset.as_mut_ptr());
++            FdSet(fdset.assume_init())
++        }
+     }
+ 
+     pub fn insert(&mut self, fd: RawFd) {
+@@ -46,7 +49,6 @@ impl FdSet {
+     /// # Example
+     ///
+     /// ```
+-    /// # extern crate nix;
+     /// # use nix::sys::select::FdSet;
+     /// # fn main() {
+     /// let mut set = FdSet::new();
+@@ -58,17 +60,81 @@ impl FdSet {
+     ///
+     /// [`select`]: fn.select.html
+     pub fn highest(&mut self) -> Option<RawFd> {
+-        for i in (0..FD_SETSIZE).rev() {
+-            let i = i as RawFd;
+-            if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
+-                return Some(i)
++        self.fds(None).next_back()
++    }
++
++    /// Returns an iterator over the file descriptors in the set.
++    /// 
++    /// For performance, it takes an optional higher bound: the iterator will
++    /// not return any elements of the set greater than the given file
++    /// descriptor.
++    ///
++    /// # Examples
++    ///
++    /// ```
++    /// # use nix::sys::select::FdSet;
++    /// # use std::os::unix::io::RawFd;
++    /// let mut set = FdSet::new();
++    /// set.insert(4);
++    /// set.insert(9);
++    /// let fds: Vec<RawFd> = set.fds(None).collect();
++    /// assert_eq!(fds, vec![4, 9]);
++    /// ```
++    #[inline]
++    pub fn fds(&mut self, highest: Option<RawFd>) -> Fds {
++        Fds {
++            set: self,
++            range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
++        }
++    }
++}
++
++impl Default for FdSet {
++    fn default() -> Self {
++        Self::new()
++    }
++}
++
++/// Iterator over `FdSet`.
++#[derive(Debug)]
++pub struct Fds<'a> {
++    set: &'a mut FdSet,
++    range: Range<usize>,
++}
++
++impl<'a> Iterator for Fds<'a> {
++    type Item = RawFd;
++
++    fn next(&mut self) -> Option<RawFd> {
++        while let Some(i) = self.range.next() {
++            if self.set.contains(i as RawFd) {
++                return Some(i as RawFd);
+             }
+         }
++        None
++    }
++
++    #[inline]
++    fn size_hint(&self) -> (usize, Option<usize>) {
++        let (_, upper) = self.range.size_hint();
++        (0, upper)
++    }
++}
+ 
++impl<'a> DoubleEndedIterator for Fds<'a> {
++    #[inline]
++    fn next_back(&mut self) -> Option<RawFd> {
++        while let Some(i) = self.range.next_back() {
++            if self.set.contains(i as RawFd) {
++                return Some(i as RawFd);
++            }
++        }
+         None
+     }
+ }
+ 
++impl<'a> FusedIterator for Fds<'a> {}
++
+ /// Monitors file descriptors for readiness
+ ///
+ /// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
+@@ -93,9 +159,9 @@ impl FdSet {
+ ///
+ /// [`FdSet::highest`]: struct.FdSet.html#method.highest
+ pub fn select<'a, N, R, W, E, T>(nfds: N,
+-                                 readfds: R,
+-                                 writefds: W,
+-                                 errorfds: E,
++    readfds: R,
++    writefds: W,
++    errorfds: E,
+                                  timeout: T) -> Result<c_int>
+ where
+     N: Into<Option<c_int>>,
+@@ -122,7 +188,7 @@ where
+     let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
+     let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
+     let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
+-                         .unwrap_or(null_mut());
++        .unwrap_or(null_mut());
+ 
+     let res = unsafe {
+         libc::select(nfds, readfds, writefds, errorfds, timeout)
+@@ -161,10 +227,10 @@ where
+ ///
+ /// [`FdSet::highest`]: struct.FdSet.html#method.highest
+ pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
+-                                     readfds: R,
+-                                     writefds: W,
+-                                     errorfds: E,
+-                                     timeout: T,
++    readfds: R,
++    writefds: W,
++    errorfds: E,
++    timeout: T,
+                                      sigmask: S) -> Result<c_int>
+ where
+     N: Into<Option<c_int>>,
+@@ -207,8 +273,8 @@ where
+ mod tests {
+     use super::*;
+     use std::os::unix::io::RawFd;
+-    use sys::time::{TimeVal, TimeValLike};
+-    use unistd::{write, pipe};
++    use crate::sys::time::{TimeVal, TimeValLike};
++    use crate::unistd::{write, pipe};
+ 
+     #[test]
+     fn fdset_insert() {
+@@ -272,6 +338,20 @@ mod tests {
+         assert_eq!(set.highest(), Some(7));
+     }
+ 
++    #[test]
++    fn fdset_fds() {
++        let mut set = FdSet::new();
++        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
++        set.insert(0);
++        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
++        set.insert(90);
++        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
++
++        // highest limit
++        assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
++        assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
++    }
++
+     #[test]
+     fn test_select() {
+         let (r1, w1) = pipe().unwrap();
+@@ -304,9 +384,9 @@ mod tests {
+ 
+         let mut timeout = TimeVal::seconds(10);
+         assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
+-                             &mut fd_set,
+-                             None,
+-                             None,
++                &mut fd_set,
++                None,
++                None,
+                              &mut timeout).unwrap());
+         assert!(fd_set.contains(r1));
+         assert!(!fd_set.contains(r2));
+@@ -324,9 +404,9 @@ mod tests {
+ 
+         let mut timeout = TimeVal::seconds(10);
+         assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
+-                             &mut fd_set,
+-                             None,
+-                             None,
++                &mut fd_set,
++                None,
++                None,
+                              &mut timeout).unwrap());
+         assert!(fd_set.contains(r1));
+         assert!(!fd_set.contains(r2));
+diff --git a/third_party/rust/nix/src/sys/sendfile.rs b/third_party/rust/nix/src/sys/sendfile.rs
+index a47d8962f73fb..84fe2a919e8b4 100644
+--- a/third_party/rust/nix/src/sys/sendfile.rs
++++ b/third_party/rust/nix/src/sys/sendfile.rs
+@@ -1,10 +1,11 @@
++use cfg_if::cfg_if;
+ use std::os::unix::io::RawFd;
+ use std::ptr;
+ 
+ use libc::{self, off_t};
+ 
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ 
+ /// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
+ ///
+@@ -36,7 +37,7 @@ cfg_if! {
+     if #[cfg(any(target_os = "freebsd",
+                  target_os = "ios",
+                  target_os = "macos"))] {
+-        use sys::uio::IoVec;
++        use crate::sys::uio::IoVec;
+ 
+         #[derive(Clone, Debug, Eq, Hash, PartialEq)]
+         struct SendfileHeaderTrailer<'a>(
+@@ -123,6 +124,7 @@ cfg_if! {
+         ///
+         /// For more information, see
+         /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
++        #[allow(clippy::too_many_arguments)]
+         pub fn sendfile(
+             in_fd: RawFd,
+             out_sock: RawFd,
+@@ -136,7 +138,8 @@ cfg_if! {
+             // Readahead goes in upper 16 bits
+             // Flags goes in lower 16 bits
+             // see `man 2 sendfile`
+-            let flags: u32 = ((readahead as u32) << 16) | (flags.bits() as u32);
++            let ra32 = u32::from(readahead);
++            let flags: u32 = (ra32 << 16) | (flags.bits() as u32);
+             let mut bytes_sent: off_t = 0;
+             let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
+             let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
+diff --git a/third_party/rust/nix/src/sys/signal.rs b/third_party/rust/nix/src/sys/signal.rs
+index 1013a77fd4b40..2f8b5fa88823d 100644
+--- a/third_party/rust/nix/src/sys/signal.rs
++++ b/third_party/rust/nix/src/sys/signal.rs
+@@ -3,9 +3,10 @@
+ 
+ ///! Operating system signals.
+ 
+-use libc;
+-use {Error, Result};
+-use errno::Errno;
++use crate::{Error, Result};
++use crate::errno::Errno;
++use crate::unistd::Pid;
++use std::convert::TryFrom;
+ use std::mem;
+ use std::fmt;
+ use std::str::FromStr;
+@@ -13,7 +14,7 @@ use std::str::FromStr;
+ use std::os::unix::io::RawFd;
+ use std::ptr;
+ 
+-#[cfg(not(target_os = "openbsd"))]
++#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
+ pub use self::sigevent::*;
+ 
+ libc_enum!{
+@@ -38,8 +39,10 @@ libc_enum!{
+         SIGPIPE,
+         SIGALRM,
+         SIGTERM,
+-        #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
+-                  not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++        #[cfg(all(any(target_os = "android", target_os = "emscripten",
++                      target_os = "fuchsia", target_os = "linux"),
++                  not(any(target_arch = "mips", target_arch = "mips64",
++                          target_arch = "sparc64"))))]
+         SIGSTKFLT,
+         SIGCHLD,
+         SIGCONT,
+@@ -54,12 +57,17 @@ libc_enum!{
+         SIGPROF,
+         SIGWINCH,
+         SIGIO,
+-        #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++        #[cfg(any(target_os = "android", target_os = "emscripten",
++                  target_os = "fuchsia", target_os = "linux"))]
+         SIGPWR,
+         SIGSYS,
+-        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++        #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                      target_os = "fuchsia", target_os = "linux",
++                      target_os = "redox")))]
+         SIGEMT,
+-        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++        #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                      target_os = "fuchsia", target_os = "linux",
++                      target_os = "redox")))]
+         SIGINFO,
+     }
+ }
+@@ -83,8 +91,10 @@ impl FromStr for Signal {
+             "SIGPIPE" => Signal::SIGPIPE,
+             "SIGALRM" => Signal::SIGALRM,
+             "SIGTERM" => Signal::SIGTERM,
+-            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
+-                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++            #[cfg(all(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux"),
++                      not(any(target_arch = "mips", target_arch = "mips64",
++                              target_arch = "sparc64"))))]
+             "SIGSTKFLT" => Signal::SIGSTKFLT,
+             "SIGCHLD" => Signal::SIGCHLD,
+             "SIGCONT" => Signal::SIGCONT,
+@@ -99,21 +109,31 @@ impl FromStr for Signal {
+             "SIGPROF" => Signal::SIGPROF,
+             "SIGWINCH" => Signal::SIGWINCH,
+             "SIGIO" => Signal::SIGIO,
+-            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++            #[cfg(any(target_os = "android", target_os = "emscripten",
++                      target_os = "fuchsia", target_os = "linux"))]
+             "SIGPWR" => Signal::SIGPWR,
+             "SIGSYS" => Signal::SIGSYS,
+-            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux",
++                          target_os = "redox")))]
+             "SIGEMT" => Signal::SIGEMT,
+-            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux",
++                          target_os = "redox")))]
+             "SIGINFO" => Signal::SIGINFO,
+             _ => return Err(Error::invalid_argument()),
+         })
+     }
+ }
+ 
+-impl AsRef<str> for Signal {
+-    fn as_ref(&self) -> &str {
+-        match *self {
++impl Signal {
++    /// Returns name of signal.
++    ///
++    /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
++    /// with difference that returned string is `'static`
++    /// and not bound to `self`'s lifetime.
++    pub fn as_str(self) -> &'static str {
++        match self {
+             Signal::SIGHUP => "SIGHUP",
+             Signal::SIGINT => "SIGINT",
+             Signal::SIGQUIT => "SIGQUIT",
+@@ -129,7 +149,8 @@ impl AsRef<str> for Signal {
+             Signal::SIGPIPE => "SIGPIPE",
+             Signal::SIGALRM => "SIGALRM",
+             Signal::SIGTERM => "SIGTERM",
+-            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
++            #[cfg(all(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux"),
+                       not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
+             Signal::SIGSTKFLT => "SIGSTKFLT",
+             Signal::SIGCHLD => "SIGCHLD",
+@@ -145,17 +166,28 @@ impl AsRef<str> for Signal {
+             Signal::SIGPROF => "SIGPROF",
+             Signal::SIGWINCH => "SIGWINCH",
+             Signal::SIGIO => "SIGIO",
+-            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
++            #[cfg(any(target_os = "android", target_os = "emscripten",
++                      target_os = "fuchsia", target_os = "linux"))]
+             Signal::SIGPWR => "SIGPWR",
+             Signal::SIGSYS => "SIGSYS",
+-            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux",
++                          target_os = "redox")))]
+             Signal::SIGEMT => "SIGEMT",
+-            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
++            #[cfg(not(any(target_os = "android", target_os = "emscripten",
++                          target_os = "fuchsia", target_os = "linux",
++                          target_os = "redox")))]
+             Signal::SIGINFO => "SIGINFO",
+         }
+     }
+ }
+ 
++impl AsRef<str> for Signal {
++    fn as_ref(&self) -> &str {
++        self.as_str()
++    }
++}
++
+ impl fmt::Display for Signal {
+     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+         f.write_str(self.as_ref())
+@@ -164,7 +196,41 @@ impl fmt::Display for Signal {
+ 
+ pub use self::Signal::*;
+ 
+-#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
++#[cfg(target_os = "redox")]
++const SIGNALS: [Signal; 29] = [
++    SIGHUP,
++    SIGINT,
++    SIGQUIT,
++    SIGILL,
++    SIGTRAP,
++    SIGABRT,
++    SIGBUS,
++    SIGFPE,
++    SIGKILL,
++    SIGUSR1,
++    SIGSEGV,
++    SIGUSR2,
++    SIGPIPE,
++    SIGALRM,
++    SIGTERM,
++    SIGCHLD,
++    SIGCONT,
++    SIGSTOP,
++    SIGTSTP,
++    SIGTTIN,
++    SIGTTOU,
++    SIGURG,
++    SIGXCPU,
++    SIGXFSZ,
++    SIGVTALRM,
++    SIGPROF,
++    SIGWINCH,
++    SIGIO,
++    SIGSYS];
++#[cfg(all(any(target_os = "linux", target_os = "android",
++              target_os = "emscripten", target_os = "fuchsia"),
++          not(any(target_arch = "mips", target_arch = "mips64",
++                  target_arch = "sparc64"))))]
+ const SIGNALS: [Signal; 31] = [
+     SIGHUP,
+     SIGINT,
+@@ -197,7 +263,10 @@ const SIGNALS: [Signal; 31] = [
+     SIGIO,
+     SIGPWR,
+     SIGSYS];
+-#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")))]
++#[cfg(all(any(target_os = "linux", target_os = "android",
++              target_os = "emscripten", target_os = "fuchsia"),
++          any(target_arch = "mips", target_arch = "mips64",
++              target_arch = "sparc64")))]
+ const SIGNALS: [Signal; 30] = [
+     SIGHUP,
+     SIGINT,
+@@ -229,7 +298,9 @@ const SIGNALS: [Signal; 30] = [
+     SIGIO,
+     SIGPWR,
+     SIGSYS];
+-#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
++#[cfg(not(any(target_os = "linux", target_os = "android",
++              target_os = "fuchsia", target_os = "emscripten",
++              target_os = "redox")))]
+ const SIGNALS: [Signal; 31] = [
+     SIGHUP,
+     SIGINT,
+@@ -288,12 +359,12 @@ impl Signal {
+     pub fn iterator() -> SignalIterator {
+         SignalIterator{next: 0}
+     }
++}
++
++impl TryFrom<libc::c_int> for Signal {
++    type Error = Error;
+ 
+-    // We do not implement the From trait, because it is supposed to be infallible.
+-    // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
+-    // implemented, we'll replace this function.
+-    #[inline]
+-    pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
++    fn try_from(signum: libc::c_int) -> Result<Signal> {
+         if 0 < signum && signum < NSIG {
+             Ok(unsafe { mem::transmute(signum) })
+         } else {
+@@ -306,8 +377,13 @@ pub const SIGIOT : Signal = SIGABRT;
+ pub const SIGPOLL : Signal = SIGIO;
+ pub const SIGUNUSED : Signal = SIGSYS;
+ 
++#[cfg(not(target_os = "redox"))]
++type SaFlags_t = libc::c_int;
++#[cfg(target_os = "redox")]
++type SaFlags_t = libc::c_ulong;
++
+ libc_bitflags!{
+-    pub struct SaFlags: libc::c_int {
++    pub struct SaFlags: SaFlags_t {
+         SA_NOCLDSTOP;
+         SA_NOCLDWAIT;
+         SA_NODEFER;
+@@ -335,17 +411,17 @@ pub struct SigSet {
+ 
+ impl SigSet {
+     pub fn all() -> SigSet {
+-        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
+-        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };
++        let mut sigset = mem::MaybeUninit::uninit();
++        let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
+ 
+-        SigSet { sigset: sigset }
++        unsafe{ SigSet { sigset: sigset.assume_init() } }
+     }
+ 
+     pub fn empty() -> SigSet {
+-        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
+-        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
++        let mut sigset = mem::MaybeUninit::uninit();
++        let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
+ 
+-        SigSet { sigset: sigset }
++        unsafe{ SigSet { sigset: sigset.assume_init() } }
+     }
+ 
+     pub fn add(&mut self, signal: Signal) {
+@@ -380,9 +456,9 @@ impl SigSet {
+ 
+     /// Gets the currently blocked (masked) set of signals for the calling thread.
+     pub fn thread_get_mask() -> Result<SigSet> {
+-        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
+-        pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?;
+-        Ok(oldmask)
++        let mut oldmask = mem::MaybeUninit::uninit();
++        do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
++        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
+     }
+ 
+     /// Sets the set of signals as the signal mask for the calling thread.
+@@ -402,18 +478,21 @@ impl SigSet {
+ 
+     /// Sets the set of signals as the signal mask, and returns the old mask.
+     pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
+-        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
+-        pthread_sigmask(how, Some(self), Some(&mut oldmask))?;
+-        Ok(oldmask)
++        let mut oldmask = mem::MaybeUninit::uninit();
++        do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
++        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
+     }
+ 
+     /// Suspends execution of the calling thread until one of the signals in the
+     /// signal mask becomes pending, and returns the accepted signal.
++    #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
+     pub fn wait(&self) -> Result<Signal> {
+-        let mut signum: libc::c_int = unsafe { mem::uninitialized() };
+-        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
++        let mut signum = mem::MaybeUninit::uninit();
++        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
+ 
+-        Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
++        Errno::result(res).map(|_| unsafe {
++            Signal::try_from(signum.assume_init()).unwrap()
++        })
+     }
+ }
+ 
+@@ -435,6 +514,7 @@ pub enum SigHandler {
+     Handler(extern fn(libc::c_int)),
+     /// Use the given signal-catching function, which takes in the signal, information about how
+     /// the signal was generated, and a pointer to the threads `ucontext_t`.
++    #[cfg(not(target_os = "redox"))]
+     SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
+ }
+ 
+@@ -451,20 +531,38 @@ impl SigAction {
+     /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
+     /// the signal-catching function.
+     pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
+-        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
+-        s.sa_sigaction = match handler {
+-            SigHandler::SigDfl => libc::SIG_DFL,
+-            SigHandler::SigIgn => libc::SIG_IGN,
+-            SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
+-            SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
+-        };
+-        s.sa_flags = match handler {
+-            SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
+-            _ => (flags - SaFlags::SA_SIGINFO).bits(),
+-        };
+-        s.sa_mask = mask.sigset;
+-
+-        SigAction { sigaction: s }
++        #[cfg(target_os = "redox")]
++        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
++            (*p).sa_handler = match handler {
++                SigHandler::SigDfl => libc::SIG_DFL,
++                SigHandler::SigIgn => libc::SIG_IGN,
++                SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
++            };
++        }
++
++        #[cfg(not(target_os = "redox"))]
++        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
++            (*p).sa_sigaction = match handler {
++                SigHandler::SigDfl => libc::SIG_DFL,
++                SigHandler::SigIgn => libc::SIG_IGN,
++                SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
++                SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
++            };
++        }
++
++        let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
++        unsafe {
++            let p = s.as_mut_ptr();
++            install_sig(p, handler);
++            (*p).sa_flags = match handler {
++                #[cfg(not(target_os = "redox"))]
++                SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
++                _ => (flags - SaFlags::SA_SIGINFO).bits(),
++            };
++            (*p).sa_mask = mask.sigset;
++
++            SigAction { sigaction: s.assume_init() }
++        }
+     }
+ 
+     /// Returns the flags set on the action.
+@@ -479,6 +577,7 @@ impl SigAction {
+     }
+ 
+     /// Returns the action's handler.
++    #[cfg(not(target_os = "redox"))]
+     pub fn handler(&self) -> SigHandler {
+         match self.sigaction.sa_sigaction {
+             libc::SIG_DFL => SigHandler::SigDfl,
+@@ -488,6 +587,16 @@ impl SigAction {
+             f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
+         }
+     }
++
++    /// Returns the action's handler.
++    #[cfg(target_os = "redox")]
++    pub fn handler(&self) -> SigHandler {
++        match self.sigaction.sa_handler {
++            libc::SIG_DFL => SigHandler::SigDfl,
++            libc::SIG_IGN => SigHandler::SigIgn,
++            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
++        }
++    }
+ }
+ 
+ /// Changes the action taken by a process on receipt of a specific signal.
+@@ -501,12 +610,13 @@ impl SigAction {
+ /// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
+ /// marked safe for signal handlers and only share global data using atomics.
+ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
+-    let mut oldact = mem::uninitialized::<libc::sigaction>();
++    let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
+ 
+-    let res =
+-        libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
++    let res = libc::sigaction(signal as libc::c_int,
++                              &sigaction.sigaction as *const libc::sigaction,
++                              oldact.as_mut_ptr());
+ 
+-    Errno::result(res).map(|_| SigAction { sigaction: oldact })
++    Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
+ }
+ 
+ /// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
+@@ -534,8 +644,7 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
+ ///
+ /// ```no_run
+ /// # #[macro_use] extern crate lazy_static;
+-/// # extern crate libc;
+-/// # extern crate nix;
++/// # use std::convert::TryFrom;
+ /// # use std::sync::atomic::{AtomicBool, Ordering};
+ /// # use nix::sys::signal::{self, Signal, SigHandler};
+ /// lazy_static! {
+@@ -543,7 +652,7 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
+ /// }
+ ///
+ /// extern fn handle_sigint(signal: libc::c_int) {
+-///     let signal = Signal::from_c_int(signal).unwrap();
++///     let signal = Signal::try_from(signal).unwrap();
+ ///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
+ /// }
+ ///
+@@ -571,6 +680,7 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
+         SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
+         SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
+         SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
++        #[cfg(not(target_os = "redox"))]
+         SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
+     };
+     Errno::result(res).map(|oldhandler| {
+@@ -582,6 +692,25 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
+     })
+ }
+ 
++fn do_pthread_sigmask(how: SigmaskHow,
++                       set: Option<&SigSet>,
++                       oldset: Option<*mut libc::sigset_t>) -> Result<()> {
++    if set.is_none() && oldset.is_none() {
++        return Ok(())
++    }
++
++    let res = unsafe {
++        // if set or oldset is None, pass in null pointers instead
++        libc::pthread_sigmask(how as libc::c_int,
++                             set.map_or_else(ptr::null::<libc::sigset_t>,
++                                             |s| &s.sigset as *const libc::sigset_t),
++                             oldset.unwrap_or(ptr::null_mut())
++                             )
++    };
++
++    Errno::result(res).map(drop)
++}
++
+ /// Manages the signal mask (set of blocked signals) for the calling thread.
+ ///
+ /// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
+@@ -599,21 +728,9 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
+ /// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
+ pub fn pthread_sigmask(how: SigmaskHow,
+                        set: Option<&SigSet>,
+-                       oldset: Option<&mut SigSet>) -> Result<()> {
+-    if set.is_none() && oldset.is_none() {
+-        return Ok(())
+-    }
+-
+-    let res = unsafe {
+-        // if set or oldset is None, pass in null pointers instead
+-        libc::pthread_sigmask(how as libc::c_int,
+-                             set.map_or_else(ptr::null::<libc::sigset_t>,
+-                                             |s| &s.sigset as *const libc::sigset_t),
+-                             oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
+-                                                |os| &mut os.sigset as *mut libc::sigset_t))
+-    };
+-
+-    Errno::result(res).map(drop)
++                       oldset: Option<&mut SigSet>) -> Result<()>
++{
++    do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
+ }
+ 
+ /// Examine and change blocked signals.
+@@ -637,7 +754,7 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si
+     Errno::result(res).map(drop)
+ }
+ 
+-pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
++pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
+     let res = unsafe { libc::kill(pid.into(),
+                                   match signal.into() {
+                                       Some(s) => s as libc::c_int,
+@@ -653,7 +770,8 @@ pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()
+ /// If `pgrp` less then or equal 1, the behavior is platform-specific.
+ /// If `signal` is `None`, `killpg` will only preform error checking and won't
+ /// send any signal.
+-pub fn killpg<T: Into<Option<Signal>>>(pgrp: ::unistd::Pid, signal: T) -> Result<()> {
++#[cfg(not(target_os = "fuchsia"))]
++pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
+     let res = unsafe { libc::killpg(pgrp.into(),
+                                   match signal.into() {
+                                       Some(s) => s as libc::c_int,
+@@ -702,9 +820,8 @@ pub enum SigevNotify {
+                     si_value: libc::intptr_t },
+ }
+ 
+-#[cfg(not(target_os = "openbsd"))]
++#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
+ mod sigevent {
+-    use libc;
+     use std::mem;
+     use std::ptr;
+     use super::SigevNotify;
+@@ -734,7 +851,10 @@ mod sigevent {
+         /// `SIGEV_SIGNAL`.  That field is part of a union that shares space with the
+         /// more genuinely useful `sigev_notify_thread_id`
+         pub fn new(sigev_notify: SigevNotify) -> SigEvent {
+-            let mut sev = unsafe { mem::zeroed::<libc::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,
+                 SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
+@@ -793,6 +913,7 @@ mod sigevent {
+ 
+ #[cfg(test)]
+ mod tests {
++    #[cfg(not(target_os = "redox"))]
+     use std::thread;
+     use super::*;
+ 
+@@ -848,6 +969,7 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_thread_signal_set_mask() {
+         thread::spawn(|| {
+             let prev_mask = SigSet::thread_get_mask()
+@@ -868,6 +990,7 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_thread_signal_block() {
+         thread::spawn(|| {
+             let mut mask = SigSet::empty();
+@@ -880,6 +1003,7 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_thread_signal_unblock() {
+         thread::spawn(|| {
+             let mut mask = SigSet::empty();
+@@ -892,6 +1016,7 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_thread_signal_swap() {
+         thread::spawn(|| {
+             let mut mask = SigSet::empty();
+@@ -914,8 +1039,8 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_sigaction() {
+-        use libc;
+         thread::spawn(|| {
+             extern fn test_sigaction_handler(_: libc::c_int) {}
+             extern fn test_sigaction_action(_: libc::c_int,
+@@ -952,6 +1077,7 @@ mod tests {
+     }
+ 
+     #[test]
++    #[cfg(not(target_os = "redox"))]
+     fn test_sigwait() {
+         thread::spawn(|| {
+             let mut mask = SigSet::empty();
+diff --git a/third_party/rust/nix/src/sys/signalfd.rs b/third_party/rust/nix/src/sys/signalfd.rs
+index 5425a27be9e52..c43b45046f719 100644
+--- a/third_party/rust/nix/src/sys/signalfd.rs
++++ b/third_party/rust/nix/src/sys/signalfd.rs
+@@ -16,10 +16,10 @@
+ //! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
+ //! signal handlers.
+ use libc;
+-use unistd;
+-use {Error, Result};
+-use errno::Errno;
+-pub use sys::signal::{self, SigSet};
++use crate::unistd;
++use crate::{Error, Result};
++use crate::errno::Errno;
++pub use crate::sys::signal::{self, SigSet};
+ pub use libc::signalfd_siginfo as siginfo;
+ 
+ use std::os::unix::io::{RawFd, AsRawFd};
+@@ -79,7 +79,7 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
+ ///     Err(err) => (), // some error happend
+ /// }
+ /// ```
+-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
++#[derive(Debug, Eq, Hash, PartialEq)]
+ pub struct SignalFd(RawFd);
+ 
+ impl SignalFd {
+@@ -98,10 +98,15 @@ impl SignalFd {
+     }
+ 
+     pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
+-        let mut buffer: [u8; SIGNALFD_SIGINFO_SIZE] = unsafe { mem::uninitialized() };
+-
+-        match unistd::read(self.0, &mut buffer) {
+-            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer) })),
++        let mut buffer = mem::MaybeUninit::<[u8; SIGNALFD_SIGINFO_SIZE]>::uninit();
++
++        let res = Errno::result(unsafe {
++            libc::read(self.0,
++                       buffer.as_mut_ptr() as *mut libc::c_void,
++                       SIGNALFD_SIGINFO_SIZE as libc::size_t)
++        }).map(|r| r as usize);
++        match res {
++            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })),
+             Ok(_) => unreachable!("partial read on signalfd"),
+             Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
+             Err(error) => Err(error)
+@@ -111,7 +116,10 @@ impl SignalFd {
+ 
+ impl Drop for SignalFd {
+     fn drop(&mut self) {
+-        let _ = unistd::close(self.0);
++        let e = unistd::close(self.0);
++        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
++            panic!("Closing an invalid file descriptor!");
++        };
+     }
+ }
+ 
+diff --git a/third_party/rust/nix/src/sys/socket/addr.rs b/third_party/rust/nix/src/sys/socket/addr.rs
+index ed41441155361..5a2739bd10194 100644
+--- a/third_party/rust/nix/src/sys/socket/addr.rs
++++ b/third_party/rust/nix/src/sys/socket/addr.rs
+@@ -1,20 +1,20 @@
+ use super::sa_family_t;
+-use {Error, Result, NixPath};
+-use errno::Errno;
+-use libc;
++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};
+ use std::path::Path;
+ use std::os::unix::ffi::OsStrExt;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+-use ::sys::socket::addr::netlink::NetlinkAddr;
++use crate::sys::socket::addr::netlink::NetlinkAddr;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+-use ::sys::socket::addr::alg::AlgAddr;
++use crate::sys::socket::addr::alg::AlgAddr;
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ use std::os::unix::io::RawFd;
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+-use ::sys::socket::addr::sys_control::SysControlAddr;
++use crate::sys::socket::addr::sys_control::SysControlAddr;
+ #[cfg(any(target_os = "android",
+           target_os = "dragonfly",
+           target_os = "freebsd",
+@@ -22,9 +22,10 @@ use ::sys::socket::addr::sys_control::SysControlAddr;
+           target_os = "linux",
+           target_os = "macos",
+           target_os = "netbsd",
+-          target_os = "openbsd"))]
++          target_os = "openbsd",
++          target_os = "fuchsia"))]
+ pub use self::datalink::LinkAddr;
+-#[cfg(target_os = "linux")]
++#[cfg(any(target_os = "android", target_os = "linux"))]
+ pub use self::vsock::VsockAddr;
+ 
+ /// These constants specify the protocol family to be used
+@@ -42,7 +43,7 @@ pub enum AddressFamily {
+     #[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"))]
++    #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
+     Packet = libc::AF_PACKET,
+     /// KEXT Controls and Notifications
+     #[cfg(any(target_os = "ios", target_os = "macos"))]
+@@ -116,7 +117,7 @@ pub enum AddressFamily {
+     Alg = libc::AF_ALG,
+     #[cfg(target_os = "linux")]
+     Nfc = libc::AF_NFC,
+-    #[cfg(target_os = "linux")]
++    #[cfg(any(target_os = "android", target_os = "linux"))]
+     Vsock = libc::AF_VSOCK,
+     #[cfg(any(target_os = "dragonfly",
+               target_os = "freebsd",
+@@ -243,7 +244,7 @@ impl AddressFamily {
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+             libc::AF_LINK => Some(AddressFamily::Link),
+-            #[cfg(target_os = "linux")]
++            #[cfg(any(target_os = "android", target_os = "linux"))]
+             libc::AF_VSOCK => Some(AddressFamily::Vsock),
+             _ => None
+         }
+@@ -367,6 +368,8 @@ impl IpAddr {
+     /// Create a new IpAddr that contains an IPv6 address.
+     ///
+     /// The result will represent the IP address a:b:c:d:e:f
++    #[allow(clippy::many_single_char_names)]
++    #[allow(clippy::too_many_arguments)]
+     pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
+         IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
+     }
+@@ -405,15 +408,18 @@ impl fmt::Display for IpAddr {
+ pub struct Ipv4Addr(pub libc::in_addr);
+ 
+ impl Ipv4Addr {
++    #[allow(clippy::identity_op)]   // More readable this way
+     pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
+-        let ip = (((a as u32) << 24) |
+-                  ((b as u32) << 16) |
+-                  ((c as u32) <<  8) |
+-                  ((d as u32) <<  0)).to_be();
++        let ip = ((u32::from(a) << 24) |
++                  (u32::from(b) << 16) |
++                  (u32::from(c) <<  8) |
++                  (u32::from(d) <<  0)).to_be();
+ 
+         Ipv4Addr(libc::in_addr { s_addr: ip })
+     }
+ 
++    // Use pass by reference for symmetry with Ipv6Addr::from_std
++    #[allow(clippy::trivially_copy_pass_by_ref)]
+     pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
+         let bits = std.octets();
+         Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
+@@ -423,12 +429,12 @@ impl Ipv4Addr {
+         Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
+     }
+ 
+-    pub fn octets(&self) -> [u8; 4] {
++    pub fn octets(self) -> [u8; 4] {
+         let bits = u32::from_be(self.0.s_addr);
+         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
+     }
+ 
+-    pub fn to_std(&self) -> net::Ipv4Addr {
++    pub fn to_std(self) -> net::Ipv4Addr {
+         let bits = self.octets();
+         net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
+     }
+@@ -467,10 +473,10 @@ macro_rules! to_u16_array {
+ }
+ 
+ impl Ipv6Addr {
++    #[allow(clippy::many_single_char_names)]
++    #[allow(clippy::too_many_arguments)]
+     pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
+-        let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()};
+-        in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h);
+-        Ipv6Addr(in6_addr_var)
++        Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
+     }
+ 
+     pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
+@@ -555,7 +561,7 @@ impl UnixAddr {
+                                      ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
+                                      path.len());
+ 
+-            Ok(UnixAddr(ret, ret.sun_path.len()))
++            Ok(UnixAddr(ret, path.len() + 1))
+         }
+     }
+ 
+@@ -643,7 +649,7 @@ pub enum SockAddr {
+               target_os = "netbsd",
+               target_os = "openbsd"))]
+     Link(LinkAddr),
+-    #[cfg(target_os = "linux")]
++    #[cfg(any(target_os = "android", target_os = "linux"))]
+     Vsock(VsockAddr),
+ }
+ 
+@@ -671,7 +677,7 @@ impl SockAddr {
+         SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
+     }
+ 
+-    #[cfg(target_os = "linux")]
++    #[cfg(any(target_os = "android", target_os = "linux"))]
+     pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
+         SockAddr::Vsock(VsockAddr::new(cid, port))
+     }
+@@ -696,7 +702,7 @@ impl SockAddr {
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+             SockAddr::Link(..) => AddressFamily::Link,
+-            #[cfg(target_os = "linux")]
++            #[cfg(any(target_os = "android", target_os = "linux"))]
+             SockAddr::Vsock(..) => AddressFamily::Vsock,
+         }
+     }
+@@ -709,11 +715,17 @@ impl SockAddr {
+     ///
+     /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
+     /// Returns None for unsupported families.
+-    pub unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
++    ///
++    /// # Safety
++    ///
++    /// unsafe because it takes a raw pointer as argument.  The caller must
++    /// ensure that the pointer is valid.
++    #[cfg(not(target_os = "fuchsia"))]
++    pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
+         if addr.is_null() {
+             None
+         } else {
+-            match AddressFamily::from_i32((*addr).sa_family as i32) {
++            match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
+                 Some(AddressFamily::Unix) => None,
+                 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
+                     InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
+@@ -742,7 +754,7 @@ impl SockAddr {
+                         Some(SockAddr::Link(ether_addr))
+                     }
+                 },
+-                #[cfg(target_os = "linux")]
++                #[cfg(any(target_os = "android", target_os = "linux"))]
+                 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
+                     VsockAddr(*(addr as *const libc::sockaddr_vm)))),
+                 // Other address families are currently not supported and simply yield a None
+@@ -759,28 +771,83 @@ impl SockAddr {
+     /// with the size of the actual data type. sockaddr is commonly used as a proxy for
+     /// a superclass as C doesn't support inheritance, so many functions that take
+     /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
+-    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
++    pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
+         match *self {
+-            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
+-            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
+-            SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
++            SockAddr::Inet(InetAddr::V4(ref addr)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
++                },
++                mem::size_of_val(addr) as libc::socklen_t
++            ),
++            SockAddr::Inet(InetAddr::V6(ref addr)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
++                },
++                mem::size_of_val(addr) as libc::socklen_t
++            ),
++            SockAddr::Unix(UnixAddr(ref addr, len)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(addr as *const libc::sockaddr_un as *const libc::sockaddr)
++                },
++                (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
++            ),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
++            SockAddr::Netlink(NetlinkAddr(ref sa)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
++                },
++                mem::size_of_val(sa) as libc::socklen_t
++            ),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            SockAddr::Alg(AlgAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t),
++            SockAddr::Alg(AlgAddr(ref sa)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
++                },
++                mem::size_of_val(sa) as libc::socklen_t
++            ),
+             #[cfg(any(target_os = "ios", target_os = "macos"))]
+-            SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
++            SockAddr::SysControl(SysControlAddr(ref sa)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
++                },
++                mem::size_of_val(sa) as libc::socklen_t
++
++            ),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t),
++            SockAddr::Link(LinkAddr(ref addr)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
++                },
++                mem::size_of_val(addr) as libc::socklen_t
++            ),
+             #[cfg(any(target_os = "dragonfly",
+                       target_os = "freebsd",
+                       target_os = "ios",
+                       target_os = "macos",
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+-            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t),
+-            #[cfg(target_os = "linux")]
+-            SockAddr::Vsock(VsockAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t),
++            SockAddr::Link(LinkAddr(ref addr)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
++                },
++                mem::size_of_val(addr) as libc::socklen_t
++            ),
++            #[cfg(any(target_os = "android", target_os = "linux"))]
++            SockAddr::Vsock(VsockAddr(ref sa)) => (
++                // This cast is always allowed in C
++                unsafe {
++                    &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
++                },
++                mem::size_of_val(sa) as libc::socklen_t
++            ),
+         }
+     }
+ }
+@@ -805,7 +872,7 @@ impl fmt::Display for SockAddr {
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+             SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
+-            #[cfg(target_os = "linux")]
++            #[cfg(any(target_os = "android", target_os = "linux"))]
+             SockAddr::Vsock(ref svm) => svm.fmt(f),
+         }
+     }
+@@ -813,7 +880,7 @@ impl fmt::Display for SockAddr {
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod netlink {
+-    use ::sys::socket::addr::AddressFamily;
++    use crate::sys::socket::addr::AddressFamily;
+     use libc::{sa_family_t, sockaddr_nl};
+     use std::{fmt, mem};
+ 
+@@ -911,11 +978,11 @@ pub mod alg {
+ 
+ #[cfg(any(target_os = "ios", target_os = "macos"))]
+ pub mod sys_control {
+-    use ::sys::socket::addr::AddressFamily;
++    use crate::sys::socket::addr::AddressFamily;
+     use libc::{self, c_uchar};
+     use std::{fmt, mem};
+     use std::os::unix::io::RawFd;
+-    use {Errno, Error, Result};
++    use crate::{Errno, Error, Result};
+ 
+     // FIXME: Move type into `libc`
+     #[repr(C)]
+@@ -957,7 +1024,7 @@ pub mod sys_control {
+ 
+             let mut ctl_name = [0; MAX_KCTL_NAME];
+             ctl_name[..name.len()].clone_from_slice(name.as_bytes());
+-            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
++            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
+ 
+             unsafe { ctl_info(sockfd, &mut info)?; }
+ 
+@@ -981,9 +1048,9 @@ pub mod sys_control {
+ }
+ 
+ 
+-#[cfg(any(target_os = "android", target_os = "linux"))]
++#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
+ mod datalink {
+-    use super::{libc, fmt, AddressFamily};
++    use super::{fmt, AddressFamily};
+ 
+     /// Hardware Address
+     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+@@ -1023,14 +1090,14 @@ mod datalink {
+ 
+         /// Physical-layer address (MAC)
+         pub fn addr(&self) -> [u8; 6] {
+-            let a = self.0.sll_addr[0] as u8;
+-            let b = self.0.sll_addr[1] as u8;
+-            let c = self.0.sll_addr[2] as u8;
+-            let d = self.0.sll_addr[3] as u8;
+-            let e = self.0.sll_addr[4] as u8;
+-            let f = self.0.sll_addr[5] as u8;
+-
+-            [a, b, c, d, e, f]
++            [
++                self.0.sll_addr[0] as u8,
++                self.0.sll_addr[1] as u8,
++                self.0.sll_addr[2] as u8,
++                self.0.sll_addr[3] as u8,
++                self.0.sll_addr[4] as u8,
++                self.0.sll_addr[5] as u8,
++            ]
+         }
+     }
+ 
+@@ -1055,7 +1122,7 @@ mod datalink {
+           target_os = "netbsd",
+           target_os = "openbsd"))]
+ mod datalink {
+-    use super::{libc, fmt, AddressFamily};
++    use super::{fmt, AddressFamily};
+ 
+     /// Hardware Address
+     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+@@ -1069,7 +1136,7 @@ mod datalink {
+ 
+         /// always == AF_LINK
+         pub fn family(&self) -> AddressFamily {
+-            assert_eq!(self.0.sdl_family as i32, libc::AF_LINK);
++            assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
+             AddressFamily::Link
+         }
+ 
+@@ -1105,11 +1172,7 @@ mod datalink {
+             let alen = self.alen();
+             let data_len = self.0.sdl_data.len();
+ 
+-            if alen > 0 && nlen + alen < data_len {
+-                false
+-            } else {
+-                true
+-            }
++            alen == 0 || nlen + alen >= data_len
+         }
+ 
+         /// Physical-layer address (MAC)
+@@ -1119,14 +1182,14 @@ mod datalink {
+ 
+             assert!(!self.is_empty());
+ 
+-            let a = data[nlen] as u8;
+-            let b = data[nlen + 1] as u8;
+-            let c = data[nlen + 2] as u8;
+-            let d = data[nlen + 3] as u8;
+-            let e = data[nlen + 4] as u8;
+-            let f = data[nlen + 5] as u8;
+-
+-            [a, b, c, d, e, f]
++            [
++                data[nlen] as u8,
++                data[nlen + 1] as u8,
++                data[nlen + 2] as u8,
++                data[nlen + 3] as u8,
++                data[nlen + 4] as u8,
++                data[nlen + 5] as u8,
++            ]
+         }
+     }
+ 
+@@ -1144,9 +1207,9 @@ mod datalink {
+     }
+ }
+ 
+-#[cfg(target_os = "linux")]
++#[cfg(any(target_os = "android", target_os = "linux"))]
+ pub mod vsock {
+-    use ::sys::socket::addr::AddressFamily;
++    use crate::sys::socket::addr::AddressFamily;
+     use libc::{sa_family_t, sockaddr_vm};
+     use std::{fmt, mem};
+     use std::hash::{Hash, Hasher};
+@@ -1269,7 +1332,7 @@ mod tests {
+         let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
+ 
+         let sun_path1 = addr.sun_path();
+-        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
++        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
+         assert_eq!(sun_path1.len(), sun_path2.len());
+         for i in 0..sun_path1.len() {
+             assert_eq!(sun_path1[i], sun_path2[i]);
+diff --git a/third_party/rust/nix/src/sys/socket/mod.rs b/third_party/rust/nix/src/sys/socket/mod.rs
+index 1c12c5f851734..631d281ed16af 100644
+--- a/third_party/rust/nix/src/sys/socket/mod.rs
++++ b/third_party/rust/nix/src/sys/socket/mod.rs
+@@ -1,14 +1,15 @@
+ //! Socket interface functions
+ //!
+ //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
+-use {Error, Result};
+-use errno::Errno;
++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;
+-use sys::time::TimeVal;
+-use sys::uio::IoVec;
++use crate::sys::time::TimeVal;
++use crate::sys::uio::IoVec;
+ 
+ mod addr;
+ pub mod sockopt;
+@@ -30,11 +31,11 @@ pub use self::addr::{
+     LinkAddr,
+ };
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+-pub use ::sys::socket::addr::netlink::NetlinkAddr;
++pub use crate::sys::socket::addr::netlink::NetlinkAddr;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+-pub use sys::socket::addr::alg::AlgAddr;
+-#[cfg(target_os = "linux")]
+-pub use sys::socket::addr::vsock::VsockAddr;
++pub use crate::sys::socket::addr::alg::AlgAddr;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++pub use crate::sys::socket::addr::vsock::VsockAddr;
+ 
+ pub use libc::{
+     cmsghdr,
+@@ -92,6 +93,64 @@ pub enum SockProtocol {
+     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
+     #[cfg(any(target_os = "ios", target_os = "macos"))]
+     KextControl = libc::SYSPROTO_CONTROL,
++    /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
++    // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkRoute = libc::NETLINK_ROUTE,
++    /// Reserved for user-mode socket protocols
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkUserSock = libc::NETLINK_USERSOCK,
++    /// Query information about sockets of various protocol families from the kernel
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
++    /// SELinux event notifications.
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkSELinux = libc::NETLINK_SELINUX,
++    /// Open-iSCSI
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkISCSI = libc::NETLINK_ISCSI,
++    /// Auditing
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkAudit = libc::NETLINK_AUDIT,
++    /// Access to FIB lookup from user space
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
++    /// Netfilter subsystem
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkNetFilter = libc::NETLINK_NETFILTER,
++    /// SCSI Transports
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
++    /// Infiniband RDMA
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkRDMA = libc::NETLINK_RDMA,
++    /// Transport IPv6 packets from netfilter to user space.  Used by ip6_queue kernel module.
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
++    /// DECnet routing messages
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
++    /// Kernel messages to user space
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
++    /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
++    /// configuration of the kernel crypto API.
++    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    NetlinkCrypto = libc::NETLINK_CRYPTO,
+ }
+ 
+ libc_bitflags!{
+@@ -189,12 +248,22 @@ cfg_if! {
+     if #[cfg(any(target_os = "android", target_os = "linux"))] {
+         /// Unix credentials of the sending process.
+         ///
+-        /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
+-        #[repr(C)]
++        /// This struct is used with the `SO_PEERCRED` ancillary message
++        /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
++        #[repr(transparent)]
+         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+         pub struct UnixCredentials(libc::ucred);
+ 
+         impl UnixCredentials {
++            /// Creates a new instance with the credentials of the current process
++            pub fn new() -> Self {
++                UnixCredentials(libc::ucred {
++                    pid: crate::unistd::getpid().as_raw(),
++                    uid: crate::unistd::getuid().as_raw(),
++                    gid: crate::unistd::getgid().as_raw(),
++                })
++            }
++
+             /// Returns the process identifier
+             pub fn pid(&self) -> libc::pid_t {
+                 self.0.pid
+@@ -211,6 +280,12 @@ cfg_if! {
+             }
+         }
+ 
++        impl Default for UnixCredentials {
++            fn default() -> Self {
++                Self::new()
++            }
++        }
++
+         impl From<libc::ucred> for UnixCredentials {
+             fn from(cred: libc::ucred) -> Self {
+                 UnixCredentials(cred)
+@@ -222,13 +297,53 @@ cfg_if! {
+                 self.0
+             }
+         }
++    } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
++        /// Unix credentials of the sending process.
++        ///
++        /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
++        #[repr(transparent)]
++        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
++        pub struct UnixCredentials(libc::cmsgcred);
++
++        impl UnixCredentials {
++            /// Returns the process identifier
++            pub fn pid(&self) -> libc::pid_t {
++                self.0.cmcred_pid
++            }
++
++            /// Returns the real user identifier
++            pub fn uid(&self) -> libc::uid_t {
++                self.0.cmcred_uid
++            }
++
++            /// Returns the effective user identifier
++            pub fn euid(&self) -> libc::uid_t {
++                self.0.cmcred_euid
++            }
++
++            /// Returns the real group identifier
++            pub fn gid(&self) -> libc::gid_t {
++                self.0.cmcred_gid
++            }
++
++            /// Returns a list group identifiers (the first one being the effective GID)
++            pub fn groups(&self) -> &[libc::gid_t] {
++                unsafe { slice::from_raw_parts(self.0.cmcred_groups.as_ptr() as *const libc::gid_t, self.0.cmcred_ngroups as _) }
++            }
++        }
++
++        impl From<libc::cmsgcred> for UnixCredentials {
++            fn from(cred: libc::cmsgcred) -> Self {
++                UnixCredentials(cred)
++            }
++        }
+     }
+ }
+ 
+ /// Request for multicast socket operations
+ ///
+ /// This is a wrapper type around `ip_mreq`.
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+ pub struct IpMembershipRequest(libc::ip_mreq);
+ 
+@@ -247,7 +362,7 @@ impl IpMembershipRequest {
+ /// Request for ipv6 multicast socket operations
+ ///
+ /// This is a wrapper type around `ipv6_mreq`.
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+ pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
+ 
+@@ -261,21 +376,6 @@ impl Ipv6MembershipRequest {
+     }
+ }
+ 
+-cfg_if! {
+-    // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
+-    if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
+-        type align_of_cmsg_data = u32;
+-    } else {
+-        type align_of_cmsg_data = size_t;
+-    }
+-}
+-
+-/// A type that can be used to store ancillary data received by
+-/// [`recvmsg`](fn.recvmsg.html)
+-pub trait CmsgBuffer {
+-    fn as_bytes_mut(&mut self) -> &mut [u8];
+-}
+-
+ /// Create a buffer large enough for storing some control messages as returned
+ /// by [`recvmsg`](fn.recvmsg.html).
+ ///
+@@ -311,61 +411,11 @@ macro_rules! cmsg_space {
+                     CMSG_SPACE(mem::size_of::<$x>() as c_uint)
+                 } as usize;
+             )*
+-            let mut v = Vec::<u8>::with_capacity(space);
+-            // safe because any bit pattern is a valid u8
+-            unsafe {v.set_len(space)};
+-            v
++            Vec::<u8>::with_capacity(space)
+         }
+     }
+ }
+ 
+-/// A structure used to make room in a cmsghdr passed to recvmsg. The
+-/// size and alignment match that of a cmsghdr followed by a T, but the
+-/// fields are not accessible, as the actual types will change on a call
+-/// to recvmsg.
+-///
+-/// To make room for multiple messages, nest the type parameter with
+-/// tuples:
+-///
+-/// ```
+-/// use std::os::unix::io::RawFd;
+-/// use nix::sys::socket::CmsgSpace;
+-/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
+-/// ```
+-#[repr(C)]
+-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+-pub struct CmsgSpace<T> {
+-    _hdr: cmsghdr,
+-    _pad: [align_of_cmsg_data; 0],
+-    _data: T,
+-}
+-
+-impl<T> CmsgSpace<T> {
+-    /// Create a CmsgSpace<T>. The structure is used only for space, so
+-    /// the fields are uninitialized.
+-    #[deprecated( since="0.14.0", note="Use the cmsg_space! macro instead")]
+-    pub fn new() -> Self {
+-        // Safe because the fields themselves aren't accessible.
+-        unsafe { mem::uninitialized() }
+-    }
+-}
+-
+-impl<T> CmsgBuffer for CmsgSpace<T> {
+-    fn as_bytes_mut(&mut self) -> &mut [u8] {
+-        // Safe because nothing ever attempts to access CmsgSpace's fields
+-        unsafe {
+-            slice::from_raw_parts_mut(self as *mut CmsgSpace<T> as *mut u8,
+-                                      mem::size_of::<Self>())
+-        }
+-    }
+-}
+-
+-impl CmsgBuffer for Vec<u8> {
+-    fn as_bytes_mut(&mut self) -> &mut [u8] {
+-        &mut self[..]
+-    }
+-}
+-
+ #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+ pub struct RecvMsg<'a> {
+     pub bytes: usize,
+@@ -433,7 +483,11 @@ pub enum ControlMessageOwned {
+     /// Received version of
+     /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
+     #[cfg(any(target_os = "android", target_os = "linux"))]
+-    ScmCredentials(libc::ucred),
++    ScmCredentials(UnixCredentials),
++    /// Received version of
++    /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    ScmCreds(UnixCredentials),
+     /// A message of type `SCM_TIMESTAMP`, containing the time the
+     /// packet was received by the kernel.
+     ///
+@@ -442,10 +496,6 @@ pub enum ControlMessageOwned {
+     ///
+     /// # Examples
+     ///
+-    // Disable this test on FreeBSD i386
+-    // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
+-    #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
+-    #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
+     /// # #[macro_use] extern crate nix;
+     /// # use nix::sys::socket::*;
+     /// # use nix::sys::uio::IoVec;
+@@ -528,6 +578,18 @@ pub enum ControlMessageOwned {
+         target_os = "openbsd",
+     ))]
+     Ipv4RecvDstAddr(libc::in_addr),
++
++    /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
++    /// packets from a single sender.
++    /// Fixed-size payloads are following one by one in a receive buffer.
++    /// This Control Message indicates the size of all smaller packets,
++    /// except, maybe, the last one.
++    ///
++    /// `UdpGroSegment` socket option should be enabled on a socket
++    /// to allow receiving GRO packets.
++    #[cfg(target_os = "linux")]
++    UdpGroSegments(u16),
++
+     /// Catch-all variant for unimplemented cmsg types.
+     #[doc(hidden)]
+     Unknown(UnknownCmsg),
+@@ -540,9 +602,9 @@ impl ControlMessageOwned {
+     /// specified in the header. Normally, the kernel ensures that this is the
+     /// case. "Correct" in this case includes correct length, alignment and
+     /// actual content.
+-    ///
+-    /// Returns `None` if the data may be unaligned.  In that case use
+-    /// `ControlMessageOwned::decode_from`.
++    // Clippy complains about the pointer alignment of `p`, not understanding
++    // that it's being fed to a function that can handle that.
++    #[allow(clippy::cast_ptr_alignment)]
+     unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
+     {
+         let p = CMSG_DATA(header);
+@@ -553,16 +615,20 @@ impl ControlMessageOwned {
+                 let n = len / mem::size_of::<RawFd>();
+                 let mut fds = Vec::with_capacity(n);
+                 for i in 0..n {
+-                    let fdp = (p as *const RawFd).offset(i as isize);
++                    let fdp = (p as *const RawFd).add(i);
+                     fds.push(ptr::read_unaligned(fdp));
+                 }
+-                let cmo = ControlMessageOwned::ScmRights(fds);
+-                cmo
++                ControlMessageOwned::ScmRights(fds)
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+             (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
+                 let cred: libc::ucred = ptr::read_unaligned(p as *const _);
+-                ControlMessageOwned::ScmCredentials(cred)
++                ControlMessageOwned::ScmCredentials(cred.into())
++            }
++            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++            (libc::SOL_SOCKET, libc::SCM_CREDS) => {
++                let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
++                ControlMessageOwned::ScmCreds(cred.into())
+             }
+             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
+                 let tv: libc::timeval = ptr::read_unaligned(p as *const _);
+@@ -612,6 +678,11 @@ impl ControlMessageOwned {
+                 let dl = ptr::read_unaligned(p as *const libc::in_addr);
+                 ControlMessageOwned::Ipv4RecvDstAddr(dl)
+             },
++            #[cfg(target_os = "linux")]
++            (libc::SOL_UDP, libc::UDP_GRO) => {
++                let gso_size: u16 = ptr::read_unaligned(p as *const _);
++                ControlMessageOwned::UdpGroSegments(gso_size)
++            },
+             (_, _) => {
+                 let sl = slice::from_raw_parts(p, len);
+                 let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
+@@ -650,10 +721,22 @@ pub enum ControlMessage<'a> {
+     ///
+     /// For further information, please refer to the
+     /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
+-    // FIXME: When `#[repr(transparent)]` is stable, use it on `UnixCredentials`
+-    // and put that in here instead of a raw ucred.
+     #[cfg(any(target_os = "android", target_os = "linux"))]
+-    ScmCredentials(&'a libc::ucred),
++    ScmCredentials(&'a UnixCredentials),
++    /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
++    /// a process connected to the socket.
++    ///
++    /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
++    /// requires a process to explicitly send its credentials.
++    ///
++    /// Credentials are always overwritten by the kernel, so this variant does have
++    /// any data, unlike the receive-side
++    /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
++    ///
++    /// For further information, please refer to the
++    /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    ScmCreds,
+ 
+     /// Set IV for `AF_ALG` crypto API.
+     ///
+@@ -685,6 +768,39 @@ pub enum ControlMessage<'a> {
+     ))]
+     AlgSetAeadAssoclen(&'a u32),
+ 
++    /// UDP GSO makes it possible for applications to generate network packets
++    /// for a virtual MTU much greater than the real one.
++    /// The length of the send data no longer matches the expected length on
++    /// the wire.
++    /// The size of the datagram payload as it should appear on the wire may be
++    /// passed through this control message.
++    /// Send buffer should consist of multiple fixed-size wire payloads
++    /// following one by one, and the last, possibly smaller one.
++    #[cfg(target_os = "linux")]
++    UdpGsoSegments(&'a u16),
++
++    /// 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.
++    #[cfg(any(target_os = "linux",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "android",
++              target_os = "ios",))]
++    Ipv4PacketInfo(&'a libc::in_pktinfo),
++
++    /// 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.
++    #[cfg(any(target_os = "linux",
++              target_os = "macos",
++              target_os = "netbsd",
++              target_os = "freebsd",
++              target_os = "android",
++              target_os = "ios",))]
++    Ipv6PacketInfo(&'a libc::in6_pktinfo),
+ }
+ 
+ // An opaque structure used to prevent cmsghdr from being a public type
+@@ -715,35 +831,66 @@ impl<'a> ControlMessage<'a> {
+ 
+     /// Return a reference to the payload data as a byte pointer
+     fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
+-        let data_ptr = match self {
+-            &ControlMessage::ScmRights(fds) => {
++        let data_ptr = match *self {
++            ControlMessage::ScmRights(fds) => {
+                 fds as *const _ as *const u8
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::ScmCredentials(creds) => {
+-                creds as *const libc::ucred as *const u8
++            ControlMessage::ScmCredentials(creds) => {
++                &creds.0 as *const libc::ucred as *const u8
++            }
++            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++            ControlMessage::ScmCreds => {
++                // The kernel overwrites the data, we just zero it
++                // to make sure it's not uninitialized memory
++                unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
++                return
+             }
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetIv(iv) => {
++            ControlMessage::AlgSetIv(iv) => {
++                #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
++                let af_alg_iv = libc::af_alg_iv {
++                    ivlen: iv.len() as u32,
++                    iv: [0u8; 0],
++                };
++
++                let size = mem::size_of_val(&af_alg_iv);
++
+                 unsafe {
+-                    let alg_iv = cmsg_data as *mut libc::af_alg_iv;
+-                    (*alg_iv).ivlen = iv.len() as u32;
++                    ptr::copy_nonoverlapping(
++                        &af_alg_iv as *const _ as *const u8,
++                        cmsg_data,
++                        size,
++                    );
+                     ptr::copy_nonoverlapping(
+                         iv.as_ptr(),
+-                        (*alg_iv).iv.as_mut_ptr(),
++                        cmsg_data.add(size),
+                         iv.len()
+                     );
+                 };
++
+                 return
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetOp(op) => {
++            ControlMessage::AlgSetOp(op) => {
+                 op as *const _ as *const u8
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetAeadAssoclen(len) => {
++            ControlMessage::AlgSetAeadAssoclen(len) => {
+                 len as *const _ as *const u8
+             },
++            #[cfg(target_os = "linux")]
++            ControlMessage::UdpGsoSegments(gso_size) => {
++                gso_size as *const _ as *const u8
++            },
++            #[cfg(any(target_os = "linux", target_os = "macos",
++                      target_os = "netbsd", target_os = "android",
++                      target_os = "ios",))]
++            ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
++            #[cfg(any(target_os = "linux", target_os = "macos",
++                      target_os = "netbsd", target_os = "freebsd",
++                      target_os = "android", target_os = "ios",))]
++            ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
+         };
+         unsafe {
+             ptr::copy_nonoverlapping(
+@@ -756,60 +903,101 @@ impl<'a> ControlMessage<'a> {
+ 
+     /// The size of the payload, excluding its cmsghdr
+     fn len(&self) -> usize {
+-        match self {
+-            &ControlMessage::ScmRights(fds) => {
++        match *self {
++            ControlMessage::ScmRights(fds) => {
+                 mem::size_of_val(fds)
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::ScmCredentials(creds) => {
++            ControlMessage::ScmCredentials(creds) => {
+                 mem::size_of_val(creds)
+             }
++            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++            ControlMessage::ScmCreds => {
++                mem::size_of::<libc::cmsgcred>()
++            }
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetIv(iv) => {
+-                mem::size_of::<libc::af_alg_iv>() + iv.len()
++            ControlMessage::AlgSetIv(iv) => {
++                mem::size_of_val(&iv) + iv.len()
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetOp(op) => {
++            ControlMessage::AlgSetOp(op) => {
+                 mem::size_of_val(op)
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetAeadAssoclen(len) => {
++            ControlMessage::AlgSetAeadAssoclen(len) => {
+                 mem::size_of_val(len)
+             },
++            #[cfg(target_os = "linux")]
++            ControlMessage::UdpGsoSegments(gso_size) => {
++                mem::size_of_val(gso_size)
++            },
++            #[cfg(any(target_os = "linux", target_os = "macos",
++              target_os = "netbsd", target_os = "android",
++              target_os = "ios",))]
++            ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
++            #[cfg(any(target_os = "linux", target_os = "macos",
++              target_os = "netbsd", target_os = "freebsd",
++              target_os = "android", target_os = "ios",))]
++            ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
+         }
+     }
+ 
+     /// Returns the value to put into the `cmsg_level` field of the header.
+     fn cmsg_level(&self) -> libc::c_int {
+-        match self {
+-            &ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
++        match *self {
++            ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
++            ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
++            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++            ControlMessage::ScmCreds => libc::SOL_SOCKET,
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetIv(_) | &ControlMessage::AlgSetOp(_) | &ControlMessage::AlgSetAeadAssoclen(_) => {
+-                libc::SOL_ALG
+-            },
++            ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
++                ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
++            #[cfg(target_os = "linux")]
++            ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
++            #[cfg(any(target_os = "linux", target_os = "macos",
++                      target_os = "netbsd", target_os = "android",
++                      target_os = "ios",))]
++            ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
++            #[cfg(any(target_os = "linux", target_os = "macos",
++              target_os = "netbsd", target_os = "freebsd",
++              target_os = "android", target_os = "ios",))]
++            ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
+         }
+     }
+ 
+     /// Returns the value to put into the `cmsg_type` field of the header.
+     fn cmsg_type(&self) -> libc::c_int {
+-        match self {
+-            &ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
++        match *self {
++            ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
++            ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
++            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++            ControlMessage::ScmCreds => libc::SCM_CREDS,
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetIv(_) => {
++            ControlMessage::AlgSetIv(_) => {
+                 libc::ALG_SET_IV
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetOp(_) => {
++            ControlMessage::AlgSetOp(_) => {
+                 libc::ALG_SET_OP
+             },
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            &ControlMessage::AlgSetAeadAssoclen(_) => {
++            ControlMessage::AlgSetAeadAssoclen(_) => {
+                 libc::ALG_SET_AEAD_ASSOCLEN
+             },
++            #[cfg(target_os = "linux")]
++            ControlMessage::UdpGsoSegments(_) => {
++                libc::UDP_SEGMENT
++            },
++            #[cfg(any(target_os = "linux", target_os = "macos",
++                      target_os = "netbsd", target_os = "android",
++                      target_os = "ios",))]
++            ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
++            #[cfg(any(target_os = "linux", target_os = "macos",
++                      target_os = "netbsd", target_os = "freebsd",
++                      target_os = "android", target_os = "ios",))]
++            ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
+         }
+     }
+ 
+@@ -836,12 +1024,303 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
+ 
+     // First size the buffer needed to hold the cmsgs.  It must be zeroed,
+     // because subsequent code will not clear the padding bytes.
+-    let cmsg_buffer = vec![0u8; capacity];
++    let mut cmsg_buffer = vec![0u8; capacity];
++
++    let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr);
++
++    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
++
++    Errno::result(ret).map(|r| r as usize)
++}
++
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "netbsd",
++))]
++#[derive(Debug)]
++pub struct SendMmsgData<'a, I, C>
++    where
++        I: AsRef<[IoVec<&'a [u8]>]>,
++        C: AsRef<[ControlMessage<'a>]>
++{
++    pub iov: I,
++    pub cmsgs: C,
++    pub addr: Option<SockAddr>,
++    pub _lt: std::marker::PhantomData<&'a I>,
++}
++
++/// An extension of `sendmsg` that allows the caller to transmit multiple
++/// messages on a socket using a single system call. This has performance
++/// benefits for some applications.
++///
++/// Allocations are performed for cmsgs and to build `msghdr` buffer
++///
++/// # Arguments
++///
++/// * `fd`:             Socket file descriptor
++/// * `data`:           Struct that implements `IntoIterator` with `SendMmsgData` items
++/// * `flags`:          Optional flags passed directly to the operating system.
++///
++/// # Returns
++/// `Vec` with numbers of sent bytes on each sent message.
++///
++/// # References
++/// [`sendmsg`](fn.sendmsg.html)
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "netbsd",
++))]
++pub fn sendmmsg<'a, I, C>(
++    fd: RawFd,
++    data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
++    flags: MsgFlags
++) -> Result<Vec<usize>>
++    where
++        I: AsRef<[IoVec<&'a [u8]>]> + 'a,
++        C: AsRef<[ControlMessage<'a>]> + 'a,
++{
++    let iter = data.into_iter();
++
++    let size_hint = iter.size_hint();
++    let reserve_items = size_hint.1.unwrap_or(size_hint.0);
++
++    let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
++
++    let mut cmsgs_buffer = vec![0u8; 0];
++
++    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);
++
++        output.push(libc::mmsghdr {
++            msg_hdr: pack_mhdr_to_send(
++                &mut cmsgs_buffer[cmsgs_start..],
++                &d.iov,
++                &d.cmsgs,
++                d.addr.as_ref()
++            ),
++            msg_len: 0,
++        });
++    };
++
++    let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
++
++    let sent_messages = Errno::result(ret)? as usize;
++    let mut sent_bytes = Vec::with_capacity(sent_messages);
++
++    for item in &output {
++        sent_bytes.push(item.msg_len as usize);
++    }
++
++    Ok(sent_bytes)
++}
++
++
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "netbsd",
++))]
++#[derive(Debug)]
++pub struct RecvMmsgData<'a, I>
++    where
++        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
++{
++    pub iov: I,
++    pub cmsg_buffer: Option<&'a mut Vec<u8>>,
++}
++
++/// An extension of `recvmsg` that allows the caller to receive multiple
++/// messages from a socket using a single system call. This has
++/// performance benefits for some applications.
++///
++/// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg`
++///
++/// Multiple allocations are performed
++///
++/// # Arguments
++///
++/// * `fd`:             Socket file descriptor
++/// * `data`:           Struct that implements `IntoIterator` with `RecvMmsgData` items
++/// * `flags`:          Optional flags passed directly to the operating system.
++///
++/// # RecvMmsgData
++///
++/// * `iov`:            Scatter-gather list of buffers to receive the message
++/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
++///                     [`cmsg_space!`](macro.cmsg_space.html)
++///
++/// # Returns
++/// A `Vec` with multiple `RecvMsg`, one per received message
++///
++/// # References
++/// - [`recvmsg`](fn.recvmsg.html)
++/// - [`RecvMsg`](struct.RecvMsg.html)
++#[cfg(any(
++    target_os = "linux",
++    target_os = "android",
++    target_os = "freebsd",
++    target_os = "netbsd",
++))]
++pub fn recvmmsg<'a, I>(
++    fd: RawFd,
++    data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
++        IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
++    flags: MsgFlags,
++    timeout: Option<crate::sys::time::TimeSpec>
++) -> Result<Vec<RecvMsg<'a>>>
++    where
++        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
++{
++    let iter = data.into_iter();
++
++    let num_messages = iter.len();
++
++    let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
++
++    // Addresses should be pre-allocated.  pack_mhdr_to_receive will store them
++    // as raw pointers, so we may not move them.  Turn the vec into a boxed
++    // slice so we won't inadvertently reallocate the vec.
++    let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages]
++        .into_boxed_slice();
++
++    let results: Vec<_> = iter.enumerate().map(|(i, d)| {
++        let (msg_controllen, mhdr) = unsafe {
++            pack_mhdr_to_receive(
++                d.iov.as_ref(),
++                &mut d.cmsg_buffer,
++                addresses[i].as_mut_ptr(),
++            )
++        };
++
++        output.push(
++            libc::mmsghdr {
++                msg_hdr: mhdr,
++                msg_len: 0,
++            }
++        );
++
++        (msg_controllen as usize, &mut d.cmsg_buffer)
++    }).collect();
++
++    let timeout = if let Some(mut t) = timeout {
++        t.as_mut() as *mut libc::timespec
++    } else {
++        ptr::null_mut()
++    };
++
++    let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
++
++    let _ = Errno::result(ret)?;
++
++    Ok(output
++        .into_iter()
++        .take(ret as usize)
++        .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
++        .zip(results.into_iter())
++        .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
++            unsafe {
++                read_mhdr(
++                    mmsghdr.msg_hdr,
++                    mmsghdr.msg_len as isize,
++                    msg_controllen,
++                    address,
++                    cmsg_buffer
++                )
++            }
++        })
++        .collect())
++}
++
++unsafe fn read_mhdr<'a, 'b>(
++    mhdr: msghdr,
++    r: isize,
++    msg_controllen: usize,
++    address: sockaddr_storage,
++    cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
++) -> RecvMsg<'b> {
++    let cmsghdr = {
++        if mhdr.msg_controllen > 0 {
++            // got control message(s)
++            cmsg_buffer
++                .as_mut()
++                .unwrap()
++                .set_len(mhdr.msg_controllen as usize);
++            debug_assert!(!mhdr.msg_control.is_null());
++            debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
++            CMSG_FIRSTHDR(&mhdr as *const msghdr)
++        } else {
++            ptr::null()
++        }.as_ref()
++    };
++
++    let address = sockaddr_storage_to_addr(
++        &address ,
++         mhdr.msg_namelen as usize
++    ).ok();
++
++    RecvMsg {
++        bytes: r as usize,
++        cmsghdr,
++        address,
++        flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
++        mhdr,
++    }
++}
++
++unsafe fn pack_mhdr_to_receive<'a, I>(
++    iov: I,
++    cmsg_buffer: &mut Option<&mut Vec<u8>>,
++    address: *mut sockaddr_storage,
++) -> (usize, msghdr)
++    where
++        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
++{
++    let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
++        .map(|v| (v.as_mut_ptr(), v.capacity()))
++        .unwrap_or((ptr::null_mut(), 0));
++
++    let mhdr = {
++        // Musl's msghdr has private fields, so this is the only way to
++        // initialize it.
++        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
++        let p = mhdr.as_mut_ptr();
++        (*p).msg_name = address as *mut c_void;
++        (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
++        (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
++        (*p).msg_iovlen = iov.as_ref().len() as _;
++        (*p).msg_control = msg_control as *mut c_void;
++        (*p).msg_controllen = msg_controllen as _;
++        (*p).msg_flags = 0;
++        mhdr.assume_init()
++    };
++
++    (msg_controllen, mhdr)
++}
++
++fn pack_mhdr_to_send<'a, I, C>(
++    cmsg_buffer: &mut [u8],
++    iov: I,
++    cmsgs: C,
++    addr: Option<&SockAddr>
++) -> msghdr
++    where
++        I: AsRef<[IoVec<&'a [u8]>]>,
++        C: AsRef<[ControlMessage<'a>]>
++{
++    let capacity = cmsg_buffer.len();
+ 
+     // Next encode the sending address, if provided
+     let (name, namelen) = match addr {
+         Some(addr) => {
+-            let (x, y) = unsafe { addr.as_ffi_pair() };
++            let (x, y) = addr.as_ffi_pair();
+             (x as *const _, y)
+         },
+         None => (ptr::null(), 0),
+@@ -854,97 +1333,68 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
+         ptr::null_mut()
+     };
+ 
+-    let mhdr = {
++    let mhdr = unsafe {
+         // Musl's msghdr has private fields, so this is the only way to
+         // initialize it.
+-        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
+-        mhdr.msg_name = name as *mut _;
+-        mhdr.msg_namelen = namelen;
++        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
++        let p = mhdr.as_mut_ptr();
++        (*p).msg_name = name as *mut _;
++        (*p).msg_namelen = namelen;
+         // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
+         // the buffer, but the standard says that it takes a mutable pointer
+-        mhdr.msg_iov = iov.as_ptr() as *mut _;
+-        mhdr.msg_iovlen = iov.len() as _;
+-        mhdr.msg_control = cmsg_ptr;
+-        mhdr.msg_controllen = capacity as _;
+-        mhdr.msg_flags = 0;
+-        mhdr
++        (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
++        (*p).msg_iovlen = iov.as_ref().len() as _;
++        (*p).msg_control = cmsg_ptr;
++        (*p).msg_controllen = capacity as _;
++        (*p).msg_flags = 0;
++        mhdr.assume_init()
+     };
+ 
+     // Encode each cmsg.  This must happen after initializing the header because
+     // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
+     // CMSG_FIRSTHDR is always safe
+-    let mut pmhdr: *mut cmsghdr = unsafe{CMSG_FIRSTHDR(&mhdr as *const msghdr)};
+-    for cmsg in cmsgs {
++    let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
++    for cmsg in cmsgs.as_ref() {
+         assert_ne!(pmhdr, ptr::null_mut());
+         // Safe because we know that pmhdr is valid, and we initialized it with
+         // sufficient space
+         unsafe { cmsg.encode_into(pmhdr) };
+         // Safe because mhdr is valid
+-        pmhdr = unsafe{CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr)};
++        pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
+     }
+ 
+-    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
+-
+-    Errno::result(ret).map(|r| r as usize)
++    mhdr
+ }
+ 
+ /// Receive message in scatter-gather vectors from a socket, and
+ /// optionally receive ancillary data into the provided buffer.
+ /// If no ancillary data is desired, use () as the type parameter.
+ ///
++/// # Arguments
++///
++/// * `fd`:             Socket file descriptor
++/// * `iov`:            Scatter-gather list of buffers to receive the message
++/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
++///                     [`cmsg_space!`](macro.cmsg_space.html)
++/// * `flags`:          Optional flags passed directly to the operating system.
++///
+ /// # References
+ /// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
+ pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
+-                   cmsg_buffer: Option<&'a mut dyn CmsgBuffer>,
++                   mut cmsg_buffer: Option<&'a mut Vec<u8>>,
+                    flags: MsgFlags) -> Result<RecvMsg<'a>>
+ {
+-    let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
+-    let (msg_control, msg_controllen) = match cmsg_buffer {
+-        Some(cmsgspace) => {
+-            let msg_buf = cmsgspace.as_bytes_mut();
+-            (msg_buf.as_mut_ptr(), msg_buf.len())
+-        },
+-        None => (ptr::null_mut(), 0),
+-    };
+-    let mut mhdr = {
+-        // Musl's msghdr has private fields, so this is the only way to
+-        // initialize it.
+-        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
+-        mhdr.msg_name = &mut address as *mut sockaddr_storage as *mut c_void;
+-        mhdr.msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
+-        mhdr.msg_iov = iov.as_ptr() as *mut iovec;
+-        mhdr.msg_iovlen = iov.len() as _;
+-        mhdr.msg_control = msg_control as *mut c_void;
+-        mhdr.msg_controllen = msg_controllen as _;
+-        mhdr.msg_flags = 0;
+-        mhdr
++    let mut address = mem::MaybeUninit::uninit();
++
++    let (msg_controllen, mut mhdr) = unsafe {
++        pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr())
+     };
+ 
+     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
+ 
+-    Errno::result(ret).map(|r| {
+-        let cmsghdr = unsafe {
+-            if mhdr.msg_controllen > 0 {
+-                // got control message(s)
+-                debug_assert!(!mhdr.msg_control.is_null());
+-                debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
+-                CMSG_FIRSTHDR(&mhdr as *const msghdr)
+-            } else {
+-                ptr::null()
+-            }.as_ref()
+-        };
++    let r = Errno::result(ret)?;
+ 
+-        let address = unsafe {
+-            sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok()
+-        };
+-        RecvMsg {
+-            bytes: r as usize,
+-            cmsghdr,
+-            address,
+-            flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
+-            mhdr,
+-        }
+-    })
++    Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) })
+ }
+ 
+ 
+@@ -1071,12 +1521,15 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
+ }
+ 
+ /// Receive data from a connectionless or connection-oriented socket. Returns
+-/// the number of bytes read and the socket address of the sender.
++/// 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)
+-pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
++pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
++    -> Result<(usize, Option<SockAddr>)>
++{
+     unsafe {
+-        let addr: sockaddr_storage = mem::zeroed();
++        let mut addr: sockaddr_storage = mem::zeroed();
+         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ 
+         let ret = Errno::result(libc::recvfrom(
+@@ -1084,11 +1537,14 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
+             buf.as_ptr() as *mut c_void,
+             buf.len() as size_t,
+             0,
+-            mem::transmute(&addr),
+-            &mut len as *mut socklen_t))?;
++            &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
++            &mut len as *mut socklen_t))? as usize;
+ 
+-        sockaddr_storage_to_addr(&addr, len as usize)
+-            .map(|addr| (ret as usize, addr))
++        match sockaddr_storage_to_addr(&addr, len as usize) {
++            Err(Error::Sys(Errno::ENOTCONN)) => Ok((ret, None)),
++            Ok(addr) => Ok((ret, Some(addr))),
++            Err(e) => Err(e)
++        }
+     }
+ }
+ 
+@@ -1121,24 +1577,6 @@ pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
+  *
+  */
+ 
+-/// The protocol level at which to get / set socket options. Used as an
+-/// argument to `getsockopt` and `setsockopt`.
+-///
+-/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
+-#[repr(i32)]
+-#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+-pub enum SockLevel {
+-    Socket = libc::SOL_SOCKET,
+-    Tcp = libc::IPPROTO_TCP,
+-    Ip = libc::IPPROTO_IP,
+-    Ipv6 = libc::IPPROTO_IPV6,
+-    Udp = libc::IPPROTO_UDP,
+-    #[cfg(any(target_os = "android", target_os = "linux"))]
+-    Netlink = libc::SOL_NETLINK,
+-    #[cfg(any(target_os = "android", target_os = "linux"))]
+-    Alg = libc::SOL_ALG,
+-}
+-
+ /// Represents a socket option that can be accessed or set. Used as an argument
+ /// to `getsockopt`
+ pub trait GetSockOpt : Copy {
+@@ -1190,14 +1628,18 @@ pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
+ pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
+     unsafe {
+-        let addr: sockaddr_storage = mem::uninitialized();
++        let mut addr = mem::MaybeUninit::uninit();
+         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ 
+-        let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
++        let ret = libc::getpeername(
++            fd,
++            addr.as_mut_ptr() as *mut libc::sockaddr,
++            &mut len
++        );
+ 
+         Errno::result(ret)?;
+ 
+-        sockaddr_storage_to_addr(&addr, len as usize)
++        sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
+     }
+ }
+ 
+@@ -1206,60 +1648,92 @@ pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
+ pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
+     unsafe {
+-        let addr: sockaddr_storage = mem::uninitialized();
++        let mut addr = mem::MaybeUninit::uninit();
+         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
+ 
+-        let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
++        let ret = libc::getsockname(
++            fd,
++            addr.as_mut_ptr() as *mut libc::sockaddr,
++            &mut len
++        );
+ 
+         Errno::result(ret)?;
+ 
+-        sockaddr_storage_to_addr(&addr, len as usize)
++        sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
+     }
+ }
+ 
+-/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
+-/// size.  In C this would usually be done by casting.  The `len` argument
++/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
++/// certain size.
++///
++/// In C this would usually be done by casting.  The `len` argument
+ /// should be the number of bytes in the `sockaddr_storage` that are actually
+ /// allocated and valid.  It must be at least as large as all the useful parts
+ /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
+ /// include the terminating null.
+-pub unsafe fn sockaddr_storage_to_addr(
++pub fn sockaddr_storage_to_addr(
+     addr: &sockaddr_storage,
+     len: usize) -> Result<SockAddr> {
+ 
++    assert!(len <= mem::size_of::<sockaddr_un>());
+     if len < mem::size_of_val(&addr.ss_family) {
+         return Err(Error::Sys(Errno::ENOTCONN));
+     }
+ 
+-    match addr.ss_family as c_int {
++    match c_int::from(addr.ss_family) {
+         libc::AF_INET => {
+-            assert!(len as usize == mem::size_of::<sockaddr_in>());
+-            let ret = *(addr as *const _ as *const sockaddr_in);
+-            Ok(SockAddr::Inet(InetAddr::V4(ret)))
++            assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
++            let sin = unsafe {
++                *(addr as *const sockaddr_storage as *const sockaddr_in)
++            };
++            Ok(SockAddr::Inet(InetAddr::V4(sin)))
+         }
+         libc::AF_INET6 => {
+-            assert!(len as usize == mem::size_of::<sockaddr_in6>());
+-            Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
++            assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
++            let sin6 = unsafe {
++                *(addr as *const _ as *const sockaddr_in6)
++            };
++            Ok(SockAddr::Inet(InetAddr::V6(sin6)))
+         }
+         libc::AF_UNIX => {
+-            let sun = *(addr as *const _ as *const sockaddr_un);
+             let pathlen = len - offset_of!(sockaddr_un, sun_path);
++            let sun = unsafe {
++                *(addr as *const _ as *const sockaddr_un)
++            };
+             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
+         }
+         #[cfg(any(target_os = "android", target_os = "linux"))]
++        libc::AF_PACKET => {
++            use libc::sockaddr_ll;
++            assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
++            let sll = unsafe {
++                *(addr as *const _ as *const sockaddr_ll)
++            };
++            Ok(SockAddr::Link(LinkAddr(sll)))
++        }
++        #[cfg(any(target_os = "android", target_os = "linux"))]
+         libc::AF_NETLINK => {
+             use libc::sockaddr_nl;
+-            Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
++            let snl = unsafe {
++                *(addr as *const _ as *const sockaddr_nl)
++            };
++            Ok(SockAddr::Netlink(NetlinkAddr(snl)))
+         }
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+         libc::AF_ALG => {
+             use libc::sockaddr_alg;
+-            Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
++            let salg = unsafe {
++                *(addr as *const _ as *const sockaddr_alg)
++            };
++            Ok(SockAddr::Alg(AlgAddr(salg)))
+         }
+-        #[cfg(target_os = "linux")]
++        #[cfg(any(target_os = "android", target_os = "linux"))]
+         libc::AF_VSOCK => {
+             use libc::sockaddr_vm;
+-            Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
++            let svm = unsafe {
++                *(addr as *const _ as *const sockaddr_vm)
++            };
++            Ok(SockAddr::Vsock(VsockAddr(svm)))
+         }
+         af => panic!("unexpected address family {}", af),
+     }
+diff --git a/third_party/rust/nix/src/sys/socket/sockopt.rs b/third_party/rust/nix/src/sys/socket/sockopt.rs
+index a996010018d5b..5b7b4feafb49a 100644
+--- a/third_party/rust/nix/src/sys/socket/sockopt.rs
++++ b/third_party/rust/nix/src/sys/socket/sockopt.rs
+@@ -1,9 +1,13 @@
++use cfg_if::cfg_if;
+ use super::{GetSockOpt, SetSockOpt};
+-use Result;
+-use errno::Errno;
+-use sys::time::TimeVal;
++use crate::Result;
++use crate::errno::Errno;
++use crate::sys::time::TimeVal;
+ use libc::{self, c_int, c_void, socklen_t};
+-use std::mem;
++use std::mem::{
++    self,
++    MaybeUninit
++};
+ use std::os::unix::io::RawFd;
+ use std::ffi::{OsStr, OsString};
+ #[cfg(target_family = "unix")]
+@@ -84,14 +88,14 @@ macro_rules! getsockopt_impl {
+ 
+             fn get(&self, fd: RawFd) -> Result<$ty> {
+                 unsafe {
+-                    let mut getter: $getter = Get::blank();
++                    let mut getter: $getter = Get::uninit();
+ 
+                     let res = libc::getsockopt(fd, $level, $flag,
+                                                getter.ffi_ptr(),
+                                                getter.ffi_len());
+                     Errno::result(res)?;
+ 
+-                    Ok(getter.unwrap())
++                    Ok(getter.assume_init())
+                 }
+             }
+         }
+@@ -248,6 +252,10 @@ sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
+           target_os = "linux",
+           target_os = "nacl"))]
+ sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
++#[cfg(not(target_os = "openbsd"))]
++sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
++#[cfg(not(target_os = "openbsd"))]
++sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
+ sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
+ sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -257,6 +265,8 @@ sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usiz
+ sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
+ sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
+ #[cfg(any(target_os = "android", target_os = "linux"))]
++sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
++#[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(any(target_os = "android", target_os = "linux"))]
+@@ -305,7 +315,10 @@ sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
+     target_os = "openbsd",
+ ))]
+ sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
+-
++#[cfg(target_os = "linux")]
++sockopt_impl!(Both, UdpGsoSegment, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
++#[cfg(target_os = "linux")]
++sockopt_impl!(Both, UdpGroSegment, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[derive(Copy, Clone, Debug)]
+@@ -364,16 +377,16 @@ impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
+ 
+ /// Helper trait that describes what is expected from a `GetSockOpt` getter.
+ unsafe trait Get<T> {
+-    /// Returns an empty value.
+-    unsafe fn blank() -> Self;
++    /// Returns an uninitialized value.
++    unsafe fn uninit() -> Self;
+     /// Returns a pointer to the stored value. This pointer will be passed to the system's
+     /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
+     fn ffi_ptr(&mut self) -> *mut c_void;
+     /// Returns length of the stored value. This pointer will be passed to the system's
+     /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
+     fn ffi_len(&mut self) -> *mut socklen_t;
+-    /// Returns the stored value.
+-    unsafe fn unwrap(self) -> T;
++    /// Returns the hopefully initialized inner value.
++    unsafe fn assume_init(self) -> T;
+ }
+ 
+ /// Helper trait that describes what is expected from a `SetSockOpt` setter.
+@@ -391,28 +404,28 @@ unsafe trait Set<'a, T> {
+ /// Getter for an arbitrary `struct`.
+ struct GetStruct<T> {
+     len: socklen_t,
+-    val: T,
++    val: MaybeUninit<T>,
+ }
+ 
+ unsafe impl<T> Get<T> for GetStruct<T> {
+-    unsafe fn blank() -> Self {
++    unsafe fn uninit() -> Self {
+         GetStruct {
+             len: mem::size_of::<T>() as socklen_t,
+-            val: mem::zeroed(),
++            val: MaybeUninit::uninit(),
+         }
+     }
+ 
+     fn ffi_ptr(&mut self) -> *mut c_void {
+-        &mut self.val as *mut T as *mut c_void
++        self.val.as_mut_ptr() as *mut c_void
+     }
+ 
+     fn ffi_len(&mut self) -> *mut socklen_t {
+         &mut self.len
+     }
+ 
+-    unsafe fn unwrap(self) -> T {
+-        assert!(self.len as usize == mem::size_of::<T>(), "invalid getsockopt implementation");
+-        self.val
++    unsafe fn assume_init(self) -> T {
++        assert_eq!(self.len as usize, mem::size_of::<T>(), "invalid getsockopt implementation");
++        self.val.assume_init()
+     }
+ }
+ 
+@@ -423,7 +436,7 @@ struct SetStruct<'a, T: 'static> {
+ 
+ unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
+     fn new(ptr: &'a T) -> SetStruct<'a, T> {
+-        SetStruct { ptr: ptr }
++        SetStruct { ptr }
+     }
+ 
+     fn ffi_ptr(&self) -> *const c_void {
+@@ -438,28 +451,28 @@ unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
+ /// Getter for a boolean value.
+ struct GetBool {
+     len: socklen_t,
+-    val: c_int,
++    val: MaybeUninit<c_int>,
+ }
+ 
+ unsafe impl Get<bool> for GetBool {
+-    unsafe fn blank() -> Self {
++    unsafe fn uninit() -> Self {
+         GetBool {
+             len: mem::size_of::<c_int>() as socklen_t,
+-            val: mem::zeroed(),
++            val: MaybeUninit::uninit(),
+         }
+     }
+ 
+     fn ffi_ptr(&mut self) -> *mut c_void {
+-        &mut self.val as *mut c_int as *mut c_void
++        self.val.as_mut_ptr() as *mut c_void
+     }
+ 
+     fn ffi_len(&mut self) -> *mut socklen_t {
+         &mut self.len
+     }
+ 
+-    unsafe fn unwrap(self) -> bool {
+-        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
+-        self.val != 0
++    unsafe fn assume_init(self) -> bool {
++        assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
++        self.val.assume_init() != 0
+     }
+ }
+ 
+@@ -485,28 +498,28 @@ unsafe impl<'a> Set<'a, bool> for SetBool {
+ /// Getter for an `u8` value.
+ struct GetU8 {
+     len: socklen_t,
+-    val: u8,
++    val: MaybeUninit<u8>,
+ }
+ 
+ unsafe impl Get<u8> for GetU8 {
+-    unsafe fn blank() -> Self {
++    unsafe fn uninit() -> Self {
+         GetU8 {
+             len: mem::size_of::<u8>() as socklen_t,
+-            val: mem::zeroed(),
++            val: MaybeUninit::uninit(),
+         }
+     }
+ 
+     fn ffi_ptr(&mut self) -> *mut c_void {
+-        &mut self.val as *mut u8 as *mut c_void
++        self.val.as_mut_ptr() as *mut c_void
+     }
+ 
+     fn ffi_len(&mut self) -> *mut socklen_t {
+         &mut self.len
+     }
+ 
+-    unsafe fn unwrap(self) -> u8 {
+-        assert!(self.len as usize == mem::size_of::<u8>(), "invalid getsockopt implementation");
+-        self.val as u8
++    unsafe fn assume_init(self) -> u8 {
++        assert_eq!(self.len as usize, mem::size_of::<u8>(), "invalid getsockopt implementation");
++        self.val.assume_init()
+     }
+ }
+ 
+@@ -532,28 +545,28 @@ unsafe impl<'a> Set<'a, u8> for SetU8 {
+ /// Getter for an `usize` value.
+ struct GetUsize {
+     len: socklen_t,
+-    val: c_int,
++    val: MaybeUninit<c_int>,
+ }
+ 
+ unsafe impl Get<usize> for GetUsize {
+-    unsafe fn blank() -> Self {
++    unsafe fn uninit() -> Self {
+         GetUsize {
+             len: mem::size_of::<c_int>() as socklen_t,
+-            val: mem::zeroed(),
++            val: MaybeUninit::uninit(),
+         }
+     }
+ 
+     fn ffi_ptr(&mut self) -> *mut c_void {
+-        &mut self.val as *mut c_int as *mut c_void
++        self.val.as_mut_ptr() as *mut c_void
+     }
+ 
+     fn ffi_len(&mut self) -> *mut socklen_t {
+         &mut self.len
+     }
+ 
+-    unsafe fn unwrap(self) -> usize {
+-        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
+-        self.val as usize
++    unsafe fn assume_init(self) -> usize {
++        assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
++        self.val.assume_init() as usize
+     }
+ }
+ 
+@@ -579,27 +592,29 @@ unsafe impl<'a> Set<'a, usize> for SetUsize {
+ /// Getter for a `OsString` value.
+ struct GetOsString<T: AsMut<[u8]>> {
+     len: socklen_t,
+-    val: T,
++    val: MaybeUninit<T>,
+ }
+ 
+ unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
+-    unsafe fn blank() -> Self {
++    unsafe fn uninit() -> Self {
+         GetOsString {
+             len: mem::size_of::<T>() as socklen_t,
+-            val: mem::zeroed(),
++            val: MaybeUninit::uninit(),
+         }
+     }
+ 
+     fn ffi_ptr(&mut self) -> *mut c_void {
+-        &mut self.val as *mut T as *mut c_void
++        self.val.as_mut_ptr() as *mut c_void
+     }
+ 
+     fn ffi_len(&mut self) -> *mut socklen_t {
+         &mut self.len
+     }
+ 
+-    unsafe fn unwrap(mut self) -> OsString {
+-        OsStr::from_bytes(self.val.as_mut()).to_owned()
++    unsafe fn assume_init(self) -> OsString {
++        let len = self.len as usize;
++        let mut v = self.val.assume_init();
++        OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
+     }
+ }
+ 
+@@ -640,11 +655,11 @@ mod test {
+     #[test]
+     fn is_socket_type_unix() {
+         use super::super::*;
+-        use ::unistd::close;
++        use crate::unistd::close;
+ 
+         let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
+         let a_type = getsockopt(a, super::SockType).unwrap();
+-        assert!(a_type == SockType::Stream);
++        assert_eq!(a_type, SockType::Stream);
+         close(a).unwrap();
+         close(b).unwrap();
+     }
+@@ -652,11 +667,11 @@ mod test {
+     #[test]
+     fn is_socket_type_dgram() {
+         use super::super::*;
+-        use ::unistd::close;
++        use crate::unistd::close;
+ 
+         let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
+         let s_type = getsockopt(s, super::SockType).unwrap();
+-        assert!(s_type == SockType::Datagram);
++        assert_eq!(s_type, SockType::Datagram);
+         close(s).unwrap();
+     }
+ 
+@@ -666,7 +681,7 @@ mod test {
+     #[test]
+     fn can_get_listen_on_tcp_socket() {
+         use super::super::*;
+-        use ::unistd::close;
++        use crate::unistd::close;
+ 
+         let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
+         let s_listening = getsockopt(s, super::AcceptConn).unwrap();
+diff --git a/third_party/rust/nix/src/sys/stat.rs b/third_party/rust/nix/src/sys/stat.rs
+index 66c8c9dd1b720..df81a2cb329d6 100644
+--- a/third_party/rust/nix/src/sys/stat.rs
++++ b/third_party/rust/nix/src/sys/stat.rs
+@@ -1,13 +1,12 @@
+ pub use libc::{dev_t, mode_t};
+ pub use libc::stat as FileStat;
+ 
+-use {Result, NixPath};
+-use errno::Errno;
+-use fcntl::{AtFlags, at_rawfd};
+-use libc;
++use crate::{Result, NixPath, errno::Errno};
++#[cfg(not(target_os = "redox"))]
++use crate::fcntl::{AtFlags, at_rawfd};
+ use std::mem;
+ use std::os::unix::io::RawFd;
+-use sys::time::{TimeSpec, TimeVal};
++use crate::sys::time::{TimeSpec, TimeVal};
+ 
+ libc_bitflags!(
+     pub struct SFlag: mode_t {
+@@ -78,49 +77,50 @@ pub fn umask(mode: Mode) -> Mode {
+ }
+ 
+ pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
+-    let mut dst = unsafe { mem::uninitialized() };
++    let mut dst = mem::MaybeUninit::uninit();
+     let res = path.with_nix_path(|cstr| {
+         unsafe {
+-            libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
++            libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
+         }
+     })?;
+ 
+     Errno::result(res)?;
+ 
+-    Ok(dst)
++    Ok(unsafe{dst.assume_init()})
+ }
+ 
+ pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
+-    let mut dst = unsafe { mem::uninitialized() };
++    let mut dst = mem::MaybeUninit::uninit();
+     let res = path.with_nix_path(|cstr| {
+         unsafe {
+-            libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
++            libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
+         }
+     })?;
+ 
+     Errno::result(res)?;
+ 
+-    Ok(dst)
++    Ok(unsafe{dst.assume_init()})
+ }
+ 
+ pub fn fstat(fd: RawFd) -> Result<FileStat> {
+-    let mut dst = unsafe { mem::uninitialized() };
+-    let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) };
++    let mut dst = mem::MaybeUninit::uninit();
++    let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) };
+ 
+     Errno::result(res)?;
+ 
+-    Ok(dst)
++    Ok(unsafe{dst.assume_init()})
+ }
+ 
++#[cfg(not(target_os = "redox"))]
+ pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
+-    let mut dst = unsafe { mem::uninitialized() };
++    let mut dst = mem::MaybeUninit::uninit();
+     let res = pathname.with_nix_path(|cstr| {
+-        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) }
++        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) }
+     })?;
+ 
+     Errno::result(res)?;
+ 
+-    Ok(dst)
++    Ok(unsafe{dst.assume_init()})
+ }
+ 
+ /// Change the file permission bits of the file specified by a file descriptor.
+@@ -150,13 +150,14 @@ pub enum FchmodatFlags {
+ /// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
+ /// then the mode of the symbolic link is changed.
+ ///
+-/// `fchmod(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
++/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
+ /// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
+ /// in the `nix` crate.
+ ///
+ /// # References
+ ///
+ /// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
++#[cfg(not(target_os = "redox"))]
+ pub fn fchmodat<P: ?Sized + NixPath>(
+     dirfd: Option<RawFd>,
+     path: &P,
+@@ -260,6 +261,7 @@ pub enum UtimensatFlags {
+ /// # References
+ ///
+ /// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
++#[cfg(not(target_os = "redox"))]
+ pub fn utimensat<P: ?Sized + NixPath>(
+     dirfd: Option<RawFd>,
+     path: &P,
+@@ -285,6 +287,7 @@ pub fn utimensat<P: ?Sized + NixPath>(
+     Errno::result(res).map(drop)
+ }
+ 
++#[cfg(not(target_os = "redox"))]
+ pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
+     let res = path.with_nix_path(|cstr| {
+         unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
+diff --git a/third_party/rust/nix/src/sys/statfs.rs b/third_party/rust/nix/src/sys/statfs.rs
+index d4596bf336958..27b72592b9a30 100644
+--- a/third_party/rust/nix/src/sys/statfs.rs
++++ b/third_party/rust/nix/src/sys/statfs.rs
+@@ -4,10 +4,7 @@ use std::os::unix::io::AsRawFd;
+ #[cfg(not(any(target_os = "linux", target_os = "android")))]
+ use std::ffi::CStr;
+ 
+-use libc;
+-
+-use {NixPath, Result};
+-use errno::Errno;
++use crate::{NixPath, Result, errno::Errno};
+ 
+ #[cfg(target_os = "android")]
+ pub type fsid_t = libc::__fsid_t;
+@@ -15,81 +12,95 @@ pub type fsid_t = libc::__fsid_t;
+ pub type fsid_t = libc::fsid_t;
+ 
+ #[derive(Clone, Copy)]
++#[repr(transparent)]
+ pub struct Statfs(libc::statfs);
+ 
+ #[cfg(target_os = "freebsd")]
+-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
+-pub struct FsType(u32);
++type fs_type_t = u32;
+ #[cfg(target_os = "android")]
+-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
+-pub struct FsType(libc::c_ulong);
++type fs_type_t = libc::c_ulong;
+ #[cfg(all(target_os = "linux", target_arch = "s390x"))]
+-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
+-pub struct FsType(u32);
++type fs_type_t = libc::c_uint;
+ #[cfg(all(target_os = "linux", target_env = "musl"))]
+-#[derive(Eq, Copy, Clone, PartialEq, Debug)]
+-pub struct FsType(libc::c_ulong);
++type fs_type_t = libc::c_ulong;
+ #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++type fs_type_t = libc::__fsword_t;
++
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "android",
++    all(target_os = "linux", target_arch = "s390x"),
++    all(target_os = "linux", target_env = "musl"),
++    all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))),
++))]
+ #[derive(Eq, Copy, Clone, PartialEq, Debug)]
+-pub struct FsType(libc::c_long);
+-
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
+-#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
+-pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
++pub struct FsType(pub fs_type_t);
++
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
++#[cfg(all(target_os = "linux", not(target_env = "musl")))]
++pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
++
+ 
+ impl Statfs {
+     /// Magic code defining system type
+     #[cfg(not(any(
+         target_os = "openbsd",
++        target_os = "dragonfly",
+         target_os = "ios",
+         target_os = "macos"
+     )))]
+@@ -105,32 +116,35 @@ impl Statfs {
+     }
+ 
+     /// Optimal transfer block size
+-    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
++    #[cfg(any(target_os = "ios", target_os = "macos"))]
+     pub fn optimal_transfer_size(&self) -> i32 {
+         self.0.f_iosize
+     }
+ 
+     /// Optimal transfer block size
+-    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
++    #[cfg(target_os = "openbsd")]
+     pub fn optimal_transfer_size(&self) -> u32 {
+-        self.0.f_bsize
++        self.0.f_iosize
+     }
+ 
+     /// Optimal transfer block size
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
+-    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
++    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
++    pub fn optimal_transfer_size(&self) -> u32 {
+         self.0.f_bsize
+     }
+ 
+     /// Optimal transfer block size
+-    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
+-    pub fn optimal_transfer_size(&self) -> libc::c_long {
++    #[cfg(any(
++        target_os = "android",
++        all(target_os = "linux", target_env = "musl")
++    ))]
++    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
+         self.0.f_bsize
+     }
+ 
+     /// Optimal transfer block size
+-    #[cfg(target_os = "android")]
+-    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
++    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
++    pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
+         self.0.f_bsize
+     }
+ 
+@@ -169,7 +183,7 @@ impl Statfs {
+     /// Size of a block
+     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
+     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
+-    pub fn block_size(&self) -> libc::c_long {
++    pub fn block_size(&self) -> libc::__fsword_t {
+         self.0.f_bsize
+     }
+ 
+@@ -211,7 +225,7 @@ impl Statfs {
+ 
+     /// Maximum length of filenames
+     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
+-    pub fn maximum_name_length(&self) -> libc::c_long {
++    pub fn maximum_name_length(&self) -> libc::__fsword_t {
+         self.0.f_namelen
+     }
+ 
+@@ -240,7 +254,7 @@ impl Statfs {
+     }
+ 
+     /// Total data blocks in filesystem
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+     pub fn blocks(&self) -> u64 {
+         self.0.f_blocks
+     }
+@@ -253,7 +267,7 @@ impl Statfs {
+         target_os = "freebsd",
+         target_os = "openbsd",
+         target_os = "dragonfly",
+-        all(target_os = "linux", target_env = "musl")
++        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
+     )))]
+     pub fn blocks(&self) -> libc::c_ulong {
+         self.0.f_blocks
+@@ -278,7 +292,7 @@ impl Statfs {
+     }
+ 
+     /// Free blocks in filesystem
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+     pub fn blocks_free(&self) -> u64 {
+         self.0.f_bfree
+     }
+@@ -291,7 +305,7 @@ impl Statfs {
+         target_os = "freebsd",
+         target_os = "openbsd",
+         target_os = "dragonfly",
+-        all(target_os = "linux", target_env = "musl")
++        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
+     )))]
+     pub fn blocks_free(&self) -> libc::c_ulong {
+         self.0.f_bfree
+@@ -316,7 +330,7 @@ impl Statfs {
+     }
+ 
+     /// Free blocks available to unprivileged user
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
++    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
+     pub fn blocks_available(&self) -> u64 {
+         self.0.f_bavail
+     }
+@@ -329,7 +343,7 @@ impl Statfs {
+         target_os = "freebsd",
+         target_os = "openbsd",
+         target_os = "dragonfly",
+-        all(target_os = "linux", target_env = "musl")
++        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
+     )))]
+     pub fn blocks_available(&self) -> libc::c_ulong {
+         self.0.f_bavail
+@@ -354,8 +368,8 @@ impl Statfs {
+     }
+ 
+     /// Total file nodes in filesystem
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
+-    pub fn files(&self) -> u64 {
++    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
++    pub fn files(&self) -> libc::fsfilcnt_t {
+         self.0.f_files
+     }
+ 
+@@ -367,14 +381,19 @@ impl Statfs {
+         target_os = "freebsd",
+         target_os = "openbsd",
+         target_os = "dragonfly",
+-        all(target_os = "linux", target_env = "musl")
++        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
+     )))]
+     pub fn files(&self) -> libc::c_ulong {
+         self.0.f_files
+     }
+ 
+     /// Free file nodes in filesystem
+-    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
++    #[cfg(any(
++            target_os = "android",
++            target_os = "ios",
++            target_os = "macos",
++            target_os = "openbsd"
++    ))]
+     pub fn files_free(&self) -> u64 {
+         self.0.f_ffree
+     }
+@@ -386,14 +405,14 @@ impl Statfs {
+     }
+ 
+     /// Free file nodes in filesystem
+-    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
++    #[cfg(target_os = "freebsd")]
+     pub fn files_free(&self) -> i64 {
+         self.0.f_ffree
+     }
+ 
+     /// Free file nodes in filesystem
+-    #[cfg(all(target_os = "linux", target_env = "musl"))]
+-    pub fn files_free(&self) -> u64 {
++    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
++    pub fn files_free(&self) -> libc::fsfilcnt_t {
+         self.0.f_ffree
+     }
+ 
+@@ -405,7 +424,7 @@ impl Statfs {
+         target_os = "freebsd",
+         target_os = "openbsd",
+         target_os = "dragonfly",
+-        all(target_os = "linux", target_env = "musl")
++        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
+     )))]
+     pub fn files_free(&self) -> libc::c_ulong {
+         self.0.f_ffree
+@@ -434,16 +453,17 @@ impl Debug for Statfs {
+ 
+ pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
+     unsafe {
+-        let mut stat: Statfs = mem::uninitialized();
+-        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), &mut stat.0))?;
+-        Errno::result(res).map(|_| stat)
++        let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
++        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
++        Errno::result(res).map(|_| Statfs(stat.assume_init()))
+     }
+ }
+ 
+ pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
+     unsafe {
+-        let mut stat: Statfs = mem::uninitialized();
+-        Errno::result(libc::fstatfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
++        let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
++        Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
++            .map(|_| Statfs(stat.assume_init()))
+     }
+ }
+ 
+@@ -451,8 +471,8 @@ pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
+ mod test {
+     use std::fs::File;
+ 
+-    use sys::statfs::*;
+-    use sys::statvfs::*;
++    use crate::sys::statfs::*;
++    use crate::sys::statvfs::*;
+     use std::path::Path;
+ 
+     #[test]
+diff --git a/third_party/rust/nix/src/sys/statvfs.rs b/third_party/rust/nix/src/sys/statvfs.rs
+index e5980369d5119..9bea9734925f0 100644
+--- a/third_party/rust/nix/src/sys/statvfs.rs
++++ b/third_party/rust/nix/src/sys/statvfs.rs
+@@ -7,9 +7,9 @@ use std::os::unix::io::AsRawFd;
+ 
+ use libc::{self, c_ulong};
+ 
+-use {Result, NixPath};
+-use errno::Errno;
++use crate::{Result, NixPath, errno::Errno};
+ 
++#[cfg(not(target_os = "redox"))]
+ libc_bitflags!(
+     /// File system mount Flags
+     #[repr(C)]
+@@ -55,8 +55,7 @@ libc_bitflags!(
+ /// 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).
+-// FIXME: Replace with repr(transparent)
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct Statvfs(libc::statvfs);
+ 
+@@ -109,6 +108,7 @@ impl Statvfs {
+     }
+ 
+     /// Get the mount flags
++    #[cfg(not(target_os = "redox"))]
+     pub fn flags(&self) -> FsFlags {
+         FsFlags::from_bits_truncate(self.0.f_flag)
+     }
+@@ -124,12 +124,12 @@ impl Statvfs {
+ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
+     unsafe {
+         Errno::clear();
+-        let mut stat: Statvfs = mem::uninitialized();
++        let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
+         let res = path.with_nix_path(|path|
+-            libc::statvfs(path.as_ptr(), &mut stat.0)
++            libc::statvfs(path.as_ptr(), stat.as_mut_ptr())
+         )?;
+ 
+-        Errno::result(res).map(|_| stat)
++        Errno::result(res).map(|_| Statvfs(stat.assume_init()))
+     }
+ }
+ 
+@@ -137,15 +137,16 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
+ pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
+     unsafe {
+         Errno::clear();
+-        let mut stat: Statvfs = mem::uninitialized();
+-        Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
++        let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
++        Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
++            .map(|_| Statvfs(stat.assume_init()))
+     }
+ }
+ 
+ #[cfg(test)]
+ mod test {
+     use std::fs::File;
+-    use sys::statvfs::*;
++    use crate::sys::statvfs::*;
+ 
+     #[test]
+     fn statvfs_call() {
+diff --git a/third_party/rust/nix/src/sys/sysinfo.rs b/third_party/rust/nix/src/sys/sysinfo.rs
+index 4c8e38988886d..222a2fc0480c3 100644
+--- a/third_party/rust/nix/src/sys/sysinfo.rs
++++ b/third_party/rust/nix/src/sys/sysinfo.rs
+@@ -2,13 +2,20 @@ use libc::{self, SI_LOAD_SHIFT};
+ use std::{cmp, mem};
+ use std::time::Duration;
+ 
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ 
+ /// System info structure returned by `sysinfo`.
+ #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
++#[repr(transparent)]
+ pub struct SysInfo(libc::sysinfo);
+ 
++// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32
++#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
++type mem_blocks_t = u64;
++#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
++type mem_blocks_t = libc::c_ulong;
++
+ impl SysInfo {
+     /// Returns the load average tuple.
+     ///
+@@ -57,7 +64,7 @@ impl SysInfo {
+         self.scale_mem(self.0.freeram)
+     }
+ 
+-    fn scale_mem(&self, units: libc::c_ulong) -> u64 {
++    fn scale_mem(&self, units: mem_blocks_t) -> u64 {
+         units as u64 * self.0.mem_unit as u64
+     }
+ }
+@@ -66,7 +73,7 @@ impl SysInfo {
+ ///
+ /// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
+ pub fn sysinfo() -> Result<SysInfo> {
+-    let mut info: libc::sysinfo = unsafe { mem::uninitialized() };
+-    let res = unsafe { libc::sysinfo(&mut info) };
+-    Errno::result(res).map(|_| SysInfo(info))
++    let mut info = mem::MaybeUninit::uninit();
++    let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
++    Errno::result(res).map(|_| unsafe{ SysInfo(info.assume_init()) })
+ }
+diff --git a/third_party/rust/nix/src/sys/termios.rs b/third_party/rust/nix/src/sys/termios.rs
+index c7cdf10b461c1..95148360495f1 100644
+--- a/third_party/rust/nix/src/sys/termios.rs
++++ b/third_party/rust/nix/src/sys/termios.rs
+@@ -25,7 +25,7 @@
+ //! ```
+ //! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
+ //! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
+-//! # let mut termios = unsafe { Termios::default_uninit() };
++//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
+ //! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
+ //! ```
+ //!
+@@ -38,7 +38,7 @@
+ //!
+ //! ```
+ //! # use self::nix::sys::termios::{ControlFlags, Termios};
+-//! # let mut termios = unsafe { Termios::default_uninit() };
++//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
+ //! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
+ //! termios.control_flags |= ControlFlags::CS5;
+ //! ```
+@@ -61,10 +61,9 @@
+ //! platforms:
+ //!
+ //! ```rust
+-//! # #[macro_use] extern crate nix;
+ //! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! cfsetispeed(&mut t, BaudRate::B9600);
+ //! cfsetospeed(&mut t, BaudRate::B9600);
+ //! cfsetspeed(&mut t, BaudRate::B9600);
+@@ -74,102 +73,94 @@
+ //! Additionally round-tripping baud rates is consistent across platforms:
+ //!
+ //! ```rust
+-//! # extern crate nix;
+ //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! # cfsetspeed(&mut t, BaudRate::B9600);
+ //! let speed = cfgetispeed(&t);
+-//! assert!(speed == cfgetospeed(&t));
++//! assert_eq!(speed, cfgetospeed(&t));
+ //! cfsetispeed(&mut t, speed);
+ //! # }
+ //! ```
+ //!
+ //! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
+ //!
+-// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
+ #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
+             doc = " ```rust,ignore")]
+ #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
+             doc = " ```rust")]
+-//! # extern crate nix;
+ //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! # cfsetspeed(&mut t, BaudRate::B9600);
+-//! assert!(cfgetispeed(&t) == BaudRate::B9600);
+-//! assert!(cfgetospeed(&t) == BaudRate::B9600);
++//! assert_eq!(cfgetispeed(&t), BaudRate::B9600);
++//! assert_eq!(cfgetospeed(&t), BaudRate::B9600);
+ //! # }
+ //! ```
+ //!
+ //! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
+ //!
+-// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
+ #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
+             doc = " ```rust")]
+ #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
+             doc = " ```rust,ignore")]
+-//! # extern crate nix;
+ //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! # cfsetspeed(&mut t, 9600u32);
+-//! assert!(cfgetispeed(&t) == 9600u32);
+-//! assert!(cfgetospeed(&t) == 9600u32);
++//! assert_eq!(cfgetispeed(&t), 9600u32);
++//! assert_eq!(cfgetospeed(&t), 9600u32);
+ //! # }
+ //! ```
+ //!
+ //! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
+ //!
+-// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
+ #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
+             doc = " ```rust")]
+ #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
+             doc = " ```rust,ignore")]
+-//! # extern crate nix;
+ //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! # cfsetspeed(&mut t, 9600u32);
+-//! assert!(cfgetispeed(&t) == BaudRate::B9600.into());
+-//! assert!(u32::from(BaudRate::B9600) == 9600u32);
++//! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into());
++//! assert_eq!(u32::from(BaudRate::B9600), 9600u32);
+ //! # }
+ //! ```
+ //!
+ //! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
+ //! by specifying baud rates directly using `u32`s:
+ //!
+-// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
+ #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
+             doc = " ```rust")]
+ #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
+                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
+             doc = " ```rust,ignore")]
+-//! # extern crate nix;
+ //! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
+ //! # fn main() {
+-//! # let mut t = unsafe { Termios::default_uninit() };
++//! # let mut t: Termios = unsafe { std::mem::zeroed() };
+ //! cfsetispeed(&mut t, 9600u32);
+ //! cfsetospeed(&mut t, 9600u32);
+ //! cfsetspeed(&mut t, 9600u32);
+ //! # }
+ //! ```
+-use Result;
+-use errno::Errno;
++use cfg_if::cfg_if;
++use crate::{Error, Result};
++use crate::errno::Errno;
+ use libc::{self, c_int, tcflag_t};
+ use std::cell::{Ref, RefCell};
+-use std::convert::From;
++use std::convert::{From, TryFrom};
+ use std::mem;
+ use std::os::unix::io::RawFd;
+ 
+-use ::unistd::Pid;
++use crate::unistd::Pid;
+ 
+ /// Stores settings for the termios API
+ ///
+@@ -194,24 +185,9 @@ pub struct Termios {
+ impl Termios {
+     /// Exposes an immutable reference to the underlying `libc::termios` data structure.
+     ///
+-    /// This can be used for interfacing with other FFI functions like:
+-    ///
+-    /// ```rust
+-    /// # extern crate libc;
+-    /// # extern crate nix;
+-    /// # fn main() {
+-    /// # use nix::sys::termios::Termios;
+-    /// # let mut termios = unsafe { Termios::default_uninit() };
+-    /// let inner_termios = termios.get_libc_termios();
+-    /// unsafe { libc::cfgetispeed(&*inner_termios) };
+-    /// # }
+-    /// ```
+-    ///
+-    /// There is no public API exposed for functions that modify the underlying `libc::termios`
+-    /// data because it requires additional work to maintain type safety.
+-    // FIXME: Switch this over to use pub(crate)
+-    #[doc(hidden)]
+-    pub fn get_libc_termios(&self) -> Ref<libc::termios> {
++    /// This is not part of `nix`'s public API because it requires additional work to maintain type
++    /// safety.
++    pub(crate) fn get_libc_termios(&self) -> Ref<libc::termios> {
+         {
+             let mut termios = self.inner.borrow_mut();
+             termios.c_iflag = self.input_flags.bits();
+@@ -225,12 +201,11 @@ impl Termios {
+ 
+     /// Exposes the inner `libc::termios` datastore within `Termios`.
+     ///
+-    /// This is unsafe because if this is used to modify the inner libc::termios struct, it will not
+-    /// automatically update the safe wrapper type around it. Therefore we disable docs to
+-    /// effectively limit its use to nix internals. In this case it should also be paired with a
+-    /// call to `update_wrapper()` so that the wrapper-type and internal representation stay
+-    /// consistent.
+-    unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
++    /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will
++    /// not automatically update the safe wrapper type around it. In this case it should also be
++    /// paired with a call to `update_wrapper()` so that the wrapper-type and internal
++    /// representation stay consistent.
++    pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
+         {
+             let mut termios = self.inner.borrow_mut();
+             termios.c_iflag = self.input_flags.bits();
+@@ -242,26 +217,8 @@ impl Termios {
+         self.inner.as_ptr()
+     }
+ 
+-    /// Allows for easily creating new `Termios` structs that will be overwritten with real data.
+-    ///
+-    /// This should only be used when the inner libc::termios struct will be overwritten before it's
+-    /// read.
+-    // FIXME: Switch this over to use pub(crate)
+-    #[doc(hidden)]
+-    pub unsafe fn default_uninit() -> Self {
+-        Termios {
+-            inner: RefCell::new(mem::uninitialized()),
+-            input_flags: InputFlags::empty(),
+-            output_flags: OutputFlags::empty(),
+-            control_flags: ControlFlags::empty(),
+-            local_flags: LocalFlags::empty(),
+-            control_chars: [0 as libc::cc_t; NCCS],
+-        }
+-    }
+-
+     /// Updates the wrapper values from the internal `libc::termios` data structure.
+-    #[doc(hidden)]
+-    pub fn update_wrapper(&mut self) {
++    pub(crate) fn update_wrapper(&mut self) {
+         let termios = *self.inner.borrow_mut();
+         self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
+         self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
+@@ -376,9 +333,10 @@ libc_enum!{
+     }
+ }
+ 
+-impl From<libc::speed_t> for BaudRate {
+-    fn from(s: libc::speed_t) -> BaudRate {
++impl TryFrom<libc::speed_t> for BaudRate {
++    type Error = Error;
+ 
++    fn try_from(s: libc::speed_t) -> Result<BaudRate> {
+         use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
+                    B9600, B19200, B38400, B57600, B115200, B230400};
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -398,85 +356,84 @@ impl From<libc::speed_t> for BaudRate {
+         use libc::{B460800, B921600};
+ 
+         match s {
+-            B0 => BaudRate::B0,
+-            B50 => BaudRate::B50,
+-            B75 => BaudRate::B75,
+-            B110 => BaudRate::B110,
+-            B134 => BaudRate::B134,
+-            B150 => BaudRate::B150,
+-            B200 => BaudRate::B200,
+-            B300 => BaudRate::B300,
+-            B600 => BaudRate::B600,
+-            B1200 => BaudRate::B1200,
+-            B1800 => BaudRate::B1800,
+-            B2400 => BaudRate::B2400,
+-            B4800 => BaudRate::B4800,
++            B0 => Ok(BaudRate::B0),
++            B50 => Ok(BaudRate::B50),
++            B75 => Ok(BaudRate::B75),
++            B110 => Ok(BaudRate::B110),
++            B134 => Ok(BaudRate::B134),
++            B150 => Ok(BaudRate::B150),
++            B200 => Ok(BaudRate::B200),
++            B300 => Ok(BaudRate::B300),
++            B600 => Ok(BaudRate::B600),
++            B1200 => Ok(BaudRate::B1200),
++            B1800 => Ok(BaudRate::B1800),
++            B2400 => Ok(BaudRate::B2400),
++            B4800 => Ok(BaudRate::B4800),
+             #[cfg(any(target_os = "dragonfly",
+                       target_os = "freebsd",
+                       target_os = "macos",
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+-            B7200 => BaudRate::B7200,
+-            B9600 => BaudRate::B9600,
++            B7200 => Ok(BaudRate::B7200),
++            B9600 => Ok(BaudRate::B9600),
+             #[cfg(any(target_os = "dragonfly",
+                       target_os = "freebsd",
+                       target_os = "macos",
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+-            B14400 => BaudRate::B14400,
+-            B19200 => BaudRate::B19200,
++            B14400 => Ok(BaudRate::B14400),
++            B19200 => Ok(BaudRate::B19200),
+             #[cfg(any(target_os = "dragonfly",
+                       target_os = "freebsd",
+                       target_os = "macos",
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+-            B28800 => BaudRate::B28800,
+-            B38400 => BaudRate::B38400,
+-            B57600 => BaudRate::B57600,
++            B28800 => Ok(BaudRate::B28800),
++            B38400 => Ok(BaudRate::B38400),
++            B57600 => Ok(BaudRate::B57600),
+             #[cfg(any(target_os = "dragonfly",
+                       target_os = "freebsd",
+                       target_os = "macos",
+                       target_os = "netbsd",
+                       target_os = "openbsd"))]
+-            B76800 => BaudRate::B76800,
+-            B115200 => BaudRate::B115200,
+-            B230400 => BaudRate::B230400,
++            B76800 => Ok(BaudRate::B76800),
++            B115200 => Ok(BaudRate::B115200),
++            B230400 => Ok(BaudRate::B230400),
+             #[cfg(any(target_os = "android",
+                       target_os = "freebsd",
+                       target_os = "linux",
+                       target_os = "netbsd"))]
+-            B460800 => BaudRate::B460800,
++            B460800 => Ok(BaudRate::B460800),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B500000 => BaudRate::B500000,
++            B500000 => Ok(BaudRate::B500000),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B576000 => BaudRate::B576000,
++            B576000 => Ok(BaudRate::B576000),
+             #[cfg(any(target_os = "android",
+                       target_os = "freebsd",
+                       target_os = "linux",
+                       target_os = "netbsd"))]
+-            B921600 => BaudRate::B921600,
++            B921600 => Ok(BaudRate::B921600),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B1000000 => BaudRate::B1000000,
++            B1000000 => Ok(BaudRate::B1000000),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B1152000 => BaudRate::B1152000,
++            B1152000 => Ok(BaudRate::B1152000),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B1500000 => BaudRate::B1500000,
++            B1500000 => Ok(BaudRate::B1500000),
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+-            B2000000 => BaudRate::B2000000,
++            B2000000 => Ok(BaudRate::B2000000),
+             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+-            B2500000 => BaudRate::B2500000,
++            B2500000 => Ok(BaudRate::B2500000),
+             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+-            B3000000 => BaudRate::B3000000,
++            B3000000 => Ok(BaudRate::B3000000),
+             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+-            B3500000 => BaudRate::B3500000,
++            B3500000 => Ok(BaudRate::B3500000),
+             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
+-            B4000000 => BaudRate::B4000000,
+-            b => unreachable!("Invalid baud constant: {}", b),
++            B4000000 => Ok(BaudRate::B4000000),
++            _ => Err(Error::invalid_argument())
+         }
+     }
+ }
+ 
+-// TODO: Include `TryFrom<u32> for BaudRate` once that API stabilizes
+ #[cfg(any(target_os = "freebsd",
+           target_os = "dragonfly",
+           target_os = "ios",
+@@ -583,6 +540,12 @@ libc_enum! {
+     }
+ }
+ 
++#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
++impl SpecialCharacterIndices {
++    pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
++    pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
++}
++
+ pub use libc::NCCS;
+ #[cfg(any(target_os = "dragonfly",
+           target_os = "freebsd",
+@@ -606,7 +569,9 @@ libc_bitflags! {
+         ICRNL;
+         IXON;
+         IXOFF;
++        #[cfg(not(target_os = "redox"))]
+         IXANY;
++        #[cfg(not(target_os = "redox"))]
+         IMAXBEL;
+         #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
+         IUTF8;
+@@ -816,6 +781,7 @@ libc_bitflags! {
+         PARODD;
+         HUPCL;
+         CLOCAL;
++        #[cfg(not(target_os = "redox"))]
+         CRTSCTS;
+         #[cfg(any(target_os = "android", target_os = "linux"))]
+         CBAUD;
+@@ -866,12 +832,15 @@ libc_bitflags! {
+ libc_bitflags! {
+     /// Flags for setting any local modes
+     pub struct LocalFlags: tcflag_t {
++        #[cfg(not(target_os = "redox"))]
+         ECHOKE;
+         ECHOE;
+         ECHOK;
+         ECHO;
+         ECHONL;
++        #[cfg(not(target_os = "redox"))]
+         ECHOPRT;
++        #[cfg(not(target_os = "redox"))]
+         ECHOCTL;
+         ISIG;
+         ICANON;
+@@ -883,8 +852,10 @@ libc_bitflags! {
+                   target_os = "openbsd"))]
+         ALTWERASE;
+         IEXTEN;
++        #[cfg(not(target_os = "redox"))]
+         EXTPROC;
+         TOSTOP;
++        #[cfg(not(target_os = "redox"))]
+         FLUSHO;
+         #[cfg(any(target_os = "freebsd",
+                   target_os = "dragonfly",
+@@ -893,6 +864,7 @@ libc_bitflags! {
+                   target_os = "netbsd",
+                   target_os = "openbsd"))]
+         NOKERNINFO;
++        #[cfg(not(target_os = "redox"))]
+         PENDIN;
+         NOFLSH;
+     }
+@@ -957,13 +929,15 @@ cfg_if!{
+             Errno::result(res).map(drop)
+         }
+     } else {
++        use std::convert::TryInto;
++
+         /// Get input baud rate (see
+         /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
+         ///
+         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
+         pub fn cfgetispeed(termios: &Termios) -> BaudRate {
+             let inner_termios = termios.get_libc_termios();
+-            unsafe { libc::cfgetispeed(&*inner_termios) }.into()
++            unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap()
+         }
+ 
+         /// Get output baud rate (see
+@@ -972,7 +946,7 @@ cfg_if!{
+         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
+         pub fn cfgetospeed(termios: &Termios) -> BaudRate {
+             let inner_termios = termios.get_libc_termios();
+-            unsafe { libc::cfgetospeed(&*inner_termios) }.into()
++            unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap()
+         }
+ 
+         /// Set input baud rate (see
+@@ -1045,13 +1019,13 @@ pub fn cfmakesane(termios: &mut Termios) {
+ /// this structure *will not* reconfigure the port, instead the modifications should be done to
+ /// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
+ pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
+-    let mut termios: libc::termios = unsafe { mem::uninitialized() };
++    let mut termios = mem::MaybeUninit::uninit();
+ 
+-    let res = unsafe { libc::tcgetattr(fd, &mut termios) };
++    let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
+ 
+     Errno::result(res)?;
+ 
+-    Ok(termios.into())
++    unsafe { Ok(termios.assume_init().into()) }
+ }
+ 
+ /// Set the configuration for a terminal (see
+@@ -1105,3 +1079,14 @@ pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
+ 
+     Errno::result(res).map(Pid::from_raw)
+ }
++
++#[cfg(test)]
++mod test {
++    use super::*;
++
++    #[test]
++    fn try_from() {
++        assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
++        assert!(BaudRate::try_from(999999999).is_err());
++    }
++}
+diff --git a/third_party/rust/nix/src/sys/time.rs b/third_party/rust/nix/src/sys/time.rs
+index 3ad57543b18a7..7546d1b367c5e 100644
+--- a/third_party/rust/nix/src/sys/time.rs
++++ b/third_party/rust/nix/src/sys/time.rs
+@@ -1,6 +1,8 @@
+ use std::{cmp, fmt, ops};
++use std::time::Duration;
+ use std::convert::From;
+-use libc::{c_long, timespec, timeval};
++use libc::{timespec, timeval};
++#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+ pub use libc::{time_t, suseconds_t};
+ 
+ pub trait TimeValLike: Sized {
+@@ -60,6 +62,34 @@ const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
+ 
+ const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
+ 
++// x32 compatibility
++// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
++#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
++type timespec_tv_nsec_t = i64;
++#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
++type timespec_tv_nsec_t = libc::c_long;
++
++impl From<timespec> for TimeSpec {
++    fn from(ts: timespec) -> Self {
++        Self(ts)
++    }
++}
++
++impl From<Duration> for TimeSpec {
++    fn from(duration: Duration) -> Self {
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
++        TimeSpec(timespec {
++            tv_sec: duration.as_secs() as time_t,
++            tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t
++        })
++    }
++}
++
++impl From<TimeSpec> for Duration {
++    fn from(timespec: TimeSpec) -> Self {
++        Duration::new(timespec.0.tv_sec as u64, timespec.0.tv_nsec as u32)
++    }
++}
+ 
+ impl AsRef<timespec> for TimeSpec {
+     fn as_ref(&self) -> &timespec {
+@@ -67,6 +97,12 @@ impl AsRef<timespec> for TimeSpec {
+     }
+ }
+ 
++impl AsMut<timespec> for TimeSpec {
++    fn as_mut(&mut self) -> &mut timespec {
++        &mut self.0
++    }
++}
++
+ impl Ord for TimeSpec {
+     // The implementation of cmp is simplified by assuming that the struct is
+     // normalized.  That is, tv_nsec must always be within [0, 1_000_000_000)
+@@ -90,6 +126,7 @@ impl TimeValLike for TimeSpec {
+     fn seconds(seconds: i64) -> TimeSpec {
+         assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
+                 "TimeSpec out of bounds; seconds={}", seconds);
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+         TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
+     }
+ 
+@@ -116,8 +153,9 @@ impl TimeValLike for TimeSpec {
+         let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
+         assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
+                 "TimeSpec out of bounds");
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+         TimeSpec(timespec {tv_sec: secs as time_t,
+-                           tv_nsec: nanos as c_long })
++                           tv_nsec: nanos as timespec_tv_nsec_t })
+     }
+ 
+     fn num_seconds(&self) -> i64 {
+@@ -144,19 +182,20 @@ impl TimeValLike for TimeSpec {
+ }
+ 
+ impl TimeSpec {
+-    fn nanos_mod_sec(&self) -> c_long {
++    fn nanos_mod_sec(&self) -> timespec_tv_nsec_t {
+         if self.tv_sec() < 0 && self.tv_nsec() > 0 {
+-            self.tv_nsec() - NANOS_PER_SEC as c_long
++            self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t
+         } else {
+             self.tv_nsec()
+         }
+     }
+ 
++    #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+     pub fn tv_sec(&self) -> time_t {
+         self.0.tv_sec
+     }
+ 
+-    pub fn tv_nsec(&self) -> c_long {
++    pub fn tv_nsec(&self) -> timespec_tv_nsec_t {
+         self.0.tv_nsec
+     }
+ }
+@@ -191,7 +230,7 @@ impl ops::Mul<i32> for TimeSpec {
+     type Output = TimeSpec;
+ 
+     fn mul(self, rhs: i32) -> TimeSpec {
+-        let usec = self.num_nanoseconds().checked_mul(rhs as i64)
++        let usec = self.num_nanoseconds().checked_mul(i64::from(rhs))
+             .expect("TimeSpec multiply out of bounds");
+ 
+         TimeSpec::nanoseconds(usec)
+@@ -202,7 +241,7 @@ impl ops::Div<i32> for TimeSpec {
+     type Output = TimeSpec;
+ 
+     fn div(self, rhs: i32) -> TimeSpec {
+-        let usec = self.num_nanoseconds() / rhs as i64;
++        let usec = self.num_nanoseconds() / i64::from(rhs);
+         TimeSpec::nanoseconds(usec)
+     }
+ }
+@@ -239,7 +278,7 @@ impl fmt::Display for TimeSpec {
+ 
+ 
+ 
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct TimeVal(timeval);
+ 
+@@ -259,6 +298,12 @@ impl AsRef<timeval> for TimeVal {
+     }
+ }
+ 
++impl AsMut<timeval> for TimeVal {
++    fn as_mut(&mut self) -> &mut timeval {
++        &mut self.0
++    }
++}
++
+ impl Ord for TimeVal {
+     // The implementation of cmp is simplified by assuming that the struct is
+     // normalized.  That is, tv_usec must always be within [0, 1_000_000)
+@@ -282,6 +327,7 @@ impl TimeValLike for TimeVal {
+     fn seconds(seconds: i64) -> TimeVal {
+         assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
+                 "TimeVal out of bounds; seconds={}", seconds);
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+         TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
+     }
+ 
+@@ -299,6 +345,7 @@ impl TimeValLike for TimeVal {
+         let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
+         assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
+                 "TimeVal out of bounds");
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+         TimeVal(timeval {tv_sec: secs as time_t,
+                            tv_usec: micros as suseconds_t })
+     }
+@@ -311,6 +358,7 @@ impl TimeValLike for TimeVal {
+         let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
+         assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
+                 "TimeVal out of bounds");
++        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+         TimeVal(timeval {tv_sec: secs as time_t,
+                            tv_usec: micros as suseconds_t })
+     }
+@@ -347,6 +395,7 @@ impl TimeVal {
+         }
+     }
+ 
++    #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
+     pub fn tv_sec(&self) -> time_t {
+         self.0.tv_sec
+     }
+@@ -386,7 +435,7 @@ impl ops::Mul<i32> for TimeVal {
+     type Output = TimeVal;
+ 
+     fn mul(self, rhs: i32) -> TimeVal {
+-        let usec = self.num_microseconds().checked_mul(rhs as i64)
++        let usec = self.num_microseconds().checked_mul(i64::from(rhs))
+             .expect("TimeVal multiply out of bounds");
+ 
+         TimeVal::microseconds(usec)
+@@ -397,7 +446,7 @@ impl ops::Div<i32> for TimeVal {
+     type Output = TimeVal;
+ 
+     fn div(self, rhs: i32) -> TimeVal {
+-        let usec = self.num_microseconds() / rhs as i64;
++        let usec = self.num_microseconds() / i64::from(rhs);
+         TimeVal::microseconds(usec)
+     }
+ }
+@@ -467,6 +516,7 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
+ #[cfg(test)]
+ mod test {
+     use super::{TimeSpec, TimeVal, TimeValLike};
++    use std::time::Duration;
+ 
+     #[test]
+     pub fn test_timespec() {
+@@ -477,6 +527,15 @@ mod test {
+                    TimeSpec::seconds(182));
+     }
+ 
++    #[test]
++    pub fn test_timespec_from() {
++        let duration = Duration::new(123, 123_456_789);
++        let timespec = TimeSpec::nanoseconds(123_123_456_789);
++
++        assert_eq!(TimeSpec::from(duration), timespec);
++        assert_eq!(Duration::from(timespec), duration);
++    }
++
+     #[test]
+     pub fn test_timespec_neg() {
+         let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
+diff --git a/third_party/rust/nix/src/sys/timerfd.rs b/third_party/rust/nix/src/sys/timerfd.rs
+new file mode 100644
+index 0000000000000..4a24719498602
+--- /dev/null
++++ b/third_party/rust/nix/src/sys/timerfd.rs
+@@ -0,0 +1,285 @@
++//! Timer API via file descriptors.
++//!
++//! 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).
++//!
++//! # Examples
++//!
++//! Create a new one-shot timer that expires after 1 second.
++//! ```
++//! # use std::os::unix::io::AsRawFd;
++//! # use nix::sys::timerfd::{TimerFd, ClockId, TimerFlags, TimerSetTimeFlags,
++//! #    Expiration};
++//! # use nix::sys::time::{TimeSpec, TimeValLike};
++//! # use nix::unistd::read;
++//! #
++//! // We create a new monotonic timer.
++//! let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())
++//!     .unwrap();
++//!
++//! // We set a new one-shot timer in 1 seconds.
++//! timer.set(
++//!     Expiration::OneShot(TimeSpec::seconds(1)),
++//!     TimerSetTimeFlags::empty()
++//! ).unwrap();
++//!
++//! // We wait for the timer to expire.
++//! timer.wait().unwrap();
++//! ```
++use crate::sys::time::TimeSpec;
++use crate::unistd::read;
++use crate::{errno::Errno, Error, Result};
++use bitflags::bitflags;
++use libc::c_int;
++use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
++
++/// A timerfd instance. This is also a file descriptor, you can feed it to
++/// other interfaces consuming file descriptors, epoll for example.
++#[derive(Debug)]
++pub struct TimerFd {
++    fd: RawFd,
++}
++
++impl AsRawFd for TimerFd {
++    fn as_raw_fd(&self) -> RawFd {
++        self.fd
++    }
++}
++
++impl FromRawFd for TimerFd {
++    unsafe fn from_raw_fd(fd: RawFd) -> Self {
++        TimerFd { fd }
++    }
++}
++
++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).
++    #[repr(i32)]
++    pub enum ClockId {
++        CLOCK_REALTIME,
++        CLOCK_MONOTONIC,
++        CLOCK_BOOTTIME,
++        CLOCK_REALTIME_ALARM,
++        CLOCK_BOOTTIME_ALARM,
++    }
++}
++
++libc_bitflags! {
++    /// Additional flags to change the behaviour of the file descriptor at the
++    /// time of creation.
++    pub struct TimerFlags: c_int {
++        TFD_NONBLOCK;
++        TFD_CLOEXEC;
++    }
++}
++
++bitflags! {
++    /// Flags that are used for arming the timer.
++    pub struct TimerSetTimeFlags: libc::c_int {
++        const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
++    }
++}
++
++#[derive(Debug, Clone, Copy)]
++struct TimerSpec(libc::itimerspec);
++
++impl TimerSpec {
++    pub fn none() -> Self {
++        Self(libc::itimerspec {
++            it_interval: libc::timespec {
++                tv_sec: 0,
++                tv_nsec: 0,
++            },
++            it_value: libc::timespec {
++                tv_sec: 0,
++                tv_nsec: 0,
++            },
++        })
++    }
++}
++
++impl AsRef<libc::itimerspec> for TimerSpec {
++    fn as_ref(&self) -> &libc::itimerspec {
++        &self.0
++    }
++}
++
++impl From<Expiration> for TimerSpec {
++    fn from(expiration: Expiration) -> TimerSpec {
++        match expiration {
++            Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
++                it_interval: libc::timespec {
++                    tv_sec: 0,
++                    tv_nsec: 0,
++                },
++                it_value: *t.as_ref(),
++            }),
++            Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec {
++                it_interval: *interval.as_ref(),
++                it_value: *start.as_ref(),
++            }),
++            Expiration::Interval(t) => TimerSpec(libc::itimerspec {
++                it_interval: *t.as_ref(),
++                it_value: *t.as_ref(),
++            }),
++        }
++    }
++}
++
++impl From<TimerSpec> for Expiration {
++    fn from(timerspec: TimerSpec) -> Expiration {
++        match timerspec {
++            TimerSpec(libc::itimerspec {
++                it_interval:
++                    libc::timespec {
++                        tv_sec: 0,
++                        tv_nsec: 0,
++                    },
++                it_value: ts,
++            }) => Expiration::OneShot(ts.into()),
++            TimerSpec(libc::itimerspec {
++                it_interval: int_ts,
++                it_value: val_ts,
++            }) => {
++                if (int_ts.tv_sec == val_ts.tv_sec) && (int_ts.tv_nsec == val_ts.tv_nsec) {
++                    Expiration::Interval(int_ts.into())
++                } else {
++                    Expiration::IntervalDelayed(val_ts.into(), int_ts.into())
++                }
++            }
++        }
++    }
++}
++
++/// An enumeration allowing the definition of the expiration time of an alarm,
++/// recurring or not.
++#[derive(Debug, Clone, Copy, PartialEq)]
++pub enum Expiration {
++    OneShot(TimeSpec),
++    IntervalDelayed(TimeSpec, TimeSpec),
++    Interval(TimeSpec),
++}
++
++impl TimerFd {
++    /// Creates a new timer based on the clock defined by `clockid`. The
++    /// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
++    /// NONBLOCK). The underlying fd will be closed on drop.
++    pub fn new(clockid: ClockId, flags: TimerFlags) -> Result<Self> {
++        Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) })
++            .map(|fd| Self { fd })
++    }
++
++    /// Sets a new alarm on the timer.
++    ///
++    /// # Types of alarm
++    ///
++    /// There are 3 types of alarms you can set:
++    ///
++    ///   - one shot: the alarm will trigger once after the specified amount of
++    /// time.
++    ///     Example: I want an alarm to go off in 60s and then disables itself.
++    ///
++    ///   - interval: the alarm will trigger every specified interval of time.
++    ///     Example: I want an alarm to go off every 60s. The alarm will first
++    ///     go off 60s after I set it and every 60s after that. The alarm will
++    ///     not disable itself.
++    ///
++    ///   - interval delayed: the alarm will trigger after a certain amount of
++    ///     time and then trigger at a specified interval.
++    ///     Example: I want an alarm to go off every 60s but only start in 1h.
++    ///     The alarm will first trigger 1h after I set it and then every 60s
++    ///     after that. The alarm will not disable itself.
++    ///
++    /// # Relative vs absolute alarm
++    ///
++    /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass
++    /// to the `Expiration` you want is relative. If however you want an alarm
++    /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`.
++    /// Then the one shot TimeSpec and the delay TimeSpec of the delayed
++    /// interval are going to be interpreted as absolute.
++    ///
++    /// # Disabling alarms
++    ///
++    /// Note: Only one alarm can be set for any given timer. Setting a new alarm
++    /// actually removes the previous one.
++    ///
++    /// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm
++    /// altogether.
++    pub fn set(&self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> {
++        let timerspec: TimerSpec = expiration.into();
++        Errno::result(unsafe {
++            libc::timerfd_settime(
++                self.fd,
++                flags.bits(),
++                timerspec.as_ref(),
++                std::ptr::null_mut(),
++            )
++        })
++        .map(drop)
++    }
++
++    /// Get the parameters for the alarm currently set, if any.
++    pub fn get(&self) -> Result<Option<Expiration>> {
++        let mut timerspec = TimerSpec::none();
++        let timerspec_ptr: *mut libc::itimerspec = &mut timerspec.0;
++
++        Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec_ptr) }).map(|_| {
++            if timerspec.0.it_interval.tv_sec == 0
++                && timerspec.0.it_interval.tv_nsec == 0
++                && timerspec.0.it_value.tv_sec == 0
++                && timerspec.0.it_value.tv_nsec == 0
++            {
++                None
++            } else {
++                Some(timerspec.into())
++            }
++        })
++    }
++
++    /// Remove the alarm if any is set.
++    pub fn unset(&self) -> Result<()> {
++        Errno::result(unsafe {
++            libc::timerfd_settime(
++                self.fd,
++                TimerSetTimeFlags::empty().bits(),
++                TimerSpec::none().as_ref(),
++                std::ptr::null_mut(),
++            )
++        })
++        .map(drop)
++    }
++
++    /// Wait for the configured alarm to expire.
++    ///
++    /// Note: If the alarm is unset, then you will wait forever.
++    pub fn wait(&self) -> Result<()> {
++        loop {
++            if let Err(e) = read(self.fd, &mut [0u8; 8]) {
++                match e {
++                    Error::Sys(Errno::EINTR) => continue,
++                    _ => return Err(e),
++                }
++            } else {
++                break;
++            }
++        }
++
++        Ok(())
++    }
++}
++
++impl Drop for TimerFd {
++    fn drop(&mut self) {
++        if !std::thread::panicking() {
++            let result = Errno::result(unsafe {
++                libc::close(self.fd)
++            });
++            if let Err(Error::Sys(Errno::EBADF)) = result {
++                panic!("close of TimerFd encountered EBADF");
++            }
++        }
++    }
++}
+diff --git a/third_party/rust/nix/src/sys/uio.rs b/third_party/rust/nix/src/sys/uio.rs
+index d089084eed711..65334227b4d1d 100644
+--- a/third_party/rust/nix/src/sys/uio.rs
++++ b/third_party/rust/nix/src/sys/uio.rs
+@@ -1,8 +1,8 @@
+ // Silence invalid warnings due to rust-lang/rust#16719
+ #![allow(improper_ctypes)]
+ 
+-use Result;
+-use errno::Errno;
++use crate::Result;
++use crate::errno::Errno;
+ use libc::{self, c_int, c_void, size_t, off_t};
+ use std::marker::PhantomData;
+ use std::os::unix::io::RawFd;
+@@ -117,7 +117,11 @@ pub struct RemoteIoVec {
+ /// [`IoVec`]: struct.IoVec.html
+ /// [`RemoteIoVec`]: struct.RemoteIoVec.html
+ #[cfg(target_os = "linux")]
+-pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
++pub fn process_vm_writev(
++    pid: crate::unistd::Pid,
++    local_iov: &[IoVec<&[u8]>],
++    remote_iov: &[RemoteIoVec]) -> Result<usize>
++{
+     let res = unsafe {
+         libc::process_vm_writev(pid.into(),
+                                 local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
+@@ -148,7 +152,11 @@ pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_
+ /// [`IoVec`]: struct.IoVec.html
+ /// [`RemoteIoVec`]: struct.RemoteIoVec.html
+ #[cfg(any(target_os = "linux"))]
+-pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
++pub fn process_vm_readv(
++    pid: crate::unistd::Pid,
++    local_iov: &[IoVec<&mut [u8]>],
++    remote_iov: &[RemoteIoVec]) -> Result<usize>
++{
+     let res = unsafe {
+         libc::process_vm_readv(pid.into(),
+                                local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
+@@ -158,7 +166,7 @@ pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remo
+     Errno::result(res).map(|r| r as usize)
+ }
+ 
+-#[repr(C)]
++#[repr(transparent)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct IoVec<T>(libc::iovec, PhantomData<T>);
+ 
+diff --git a/third_party/rust/nix/src/sys/utsname.rs b/third_party/rust/nix/src/sys/utsname.rs
+index ab09c7d23232a..bf1a814d6d863 100644
+--- a/third_party/rust/nix/src/sys/utsname.rs
++++ b/third_party/rust/nix/src/sys/utsname.rs
+@@ -3,8 +3,8 @@ use libc::{self, c_char};
+ use std::ffi::CStr;
+ use std::str::from_utf8_unchecked;
+ 
+-#[repr(C)]
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
++#[repr(transparent)]
+ pub struct UtsName(libc::utsname);
+ 
+ impl UtsName {
+@@ -31,9 +31,9 @@ impl UtsName {
+ 
+ pub fn uname() -> UtsName {
+     unsafe {
+-        let mut ret: UtsName = mem::uninitialized();
+-        libc::uname(&mut ret.0);
+-        ret
++        let mut ret = mem::MaybeUninit::uninit();
++        libc::uname(ret.as_mut_ptr());
++        UtsName(ret.assume_init())
+     }
+ }
+ 
+diff --git a/third_party/rust/nix/src/sys/wait.rs b/third_party/rust/nix/src/sys/wait.rs
+index c54f7ec579667..faf8543cb1589 100644
+--- a/third_party/rust/nix/src/sys/wait.rs
++++ b/third_party/rust/nix/src/sys/wait.rs
+@@ -1,9 +1,10 @@
++use crate::errno::Errno;
++use crate::sys::signal::Signal;
++use crate::unistd::Pid;
++use crate::Result;
++use cfg_if::cfg_if;
+ use libc::{self, c_int};
+-use Result;
+-use errno::Errno;
+-use unistd::Pid;
+-
+-use sys::signal::Signal;
++use std::convert::TryFrom;
+ 
+ libc_bitflags!(
+     pub struct WaitPidFlag: c_int {
+@@ -14,6 +15,7 @@ libc_bitflags!(
+                   target_os = "haiku",
+                   target_os = "ios",
+                   target_os = "linux",
++                  target_os = "redox",
+                   target_os = "macos",
+                   target_os = "netbsd"))]
+         WEXITED;
+@@ -23,6 +25,7 @@ libc_bitflags!(
+                   target_os = "haiku",
+                   target_os = "ios",
+                   target_os = "linux",
++                  target_os = "redox",
+                   target_os = "macos",
+                   target_os = "netbsd"))]
+         WSTOPPED;
+@@ -32,16 +35,17 @@ libc_bitflags!(
+                   target_os = "haiku",
+                   target_os = "ios",
+                   target_os = "linux",
++                  target_os = "redox",
+                   target_os = "macos",
+                   target_os = "netbsd"))]
+         WNOWAIT;
+         /// Don't wait on children of other threads in this group
+-        #[cfg(any(target_os = "android", target_os = "linux"))]
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+         __WNOTHREAD;
+         /// Wait on all children, regardless of type
+-        #[cfg(any(target_os = "android", target_os = "linux"))]
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+         __WALL;
+-        #[cfg(any(target_os = "android", target_os = "linux"))]
++        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
+         __WCLONE;
+     }
+ );
+@@ -104,8 +108,7 @@ impl WaitStatus {
+     pub fn pid(&self) -> Option<Pid> {
+         use self::WaitStatus::*;
+         match *self {
+-            Exited(p, _)  | Signaled(p, _, _) |
+-                Stopped(p, _) | Continued(p) => Some(p),
++            Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p),
+             StillAlive => None,
+             #[cfg(any(target_os = "android", target_os = "linux"))]
+             PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
+@@ -114,31 +117,31 @@ impl WaitStatus {
+ }
+ 
+ fn exited(status: i32) -> bool {
+-    unsafe { libc::WIFEXITED(status) }
++    libc::WIFEXITED(status)
+ }
+ 
+ fn exit_status(status: i32) -> i32 {
+-    unsafe { libc::WEXITSTATUS(status) }
++    libc::WEXITSTATUS(status)
+ }
+ 
+ fn signaled(status: i32) -> bool {
+-    unsafe { libc::WIFSIGNALED(status) }
++    libc::WIFSIGNALED(status)
+ }
+ 
+ fn term_signal(status: i32) -> Result<Signal> {
+-    Signal::from_c_int(unsafe { libc::WTERMSIG(status) })
++    Signal::try_from(libc::WTERMSIG(status))
+ }
+ 
+ fn dumped_core(status: i32) -> bool {
+-    unsafe { libc::WCOREDUMP(status) }
++    libc::WCOREDUMP(status)
+ }
+ 
+ fn stopped(status: i32) -> bool {
+-    unsafe { libc::WIFSTOPPED(status) }
++    libc::WIFSTOPPED(status)
+ }
+ 
+ fn stop_signal(status: i32) -> Result<Signal> {
+-    Signal::from_c_int(unsafe { libc::WSTOPSIG(status) })
++    Signal::try_from(libc::WSTOPSIG(status))
+ }
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -147,7 +150,7 @@ fn syscall_stop(status: i32) -> bool {
+     // of delivering SIGTRAP | 0x80 as the signal number for syscall
+     // stops. This allows easily distinguishing syscall stops from
+     // genuine SIGTRAP signals.
+-    unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
++    libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80
+ }
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+@@ -156,7 +159,7 @@ fn stop_additional(status: i32) -> c_int {
+ }
+ 
+ fn continued(status: i32) -> bool {
+-    unsafe { libc::WIFCONTINUED(status) }
++    libc::WIFCONTINUED(status)
+ }
+ 
+ impl WaitStatus {
+@@ -222,7 +225,7 @@ pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Re
+ 
+     let res = unsafe {
+         libc::waitpid(
+-            pid.into().unwrap_or(Pid::from_raw(-1)).into(),
++            pid.into().unwrap_or_else(|| Pid::from_raw(-1)).into(),
+             &mut status as *mut c_int,
+             option_bits,
+         )
+diff --git a/third_party/rust/nix/src/time.rs b/third_party/rust/nix/src/time.rs
+new file mode 100644
+index 0000000000000..e6c3f8ded5a52
+--- /dev/null
++++ b/third_party/rust/nix/src/time.rs
+@@ -0,0 +1,260 @@
++use crate::sys::time::TimeSpec;
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "dragonfly",
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++))]
++use crate::{unistd::Pid, Error};
++use crate::{Errno, Result};
++use libc::{self, clockid_t};
++use std::mem::MaybeUninit;
++
++/// Clock identifier
++///
++/// Newtype pattern around `clockid_t` (which is just alias). It pervents bugs caused by
++/// accidentally passing wrong value.
++#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
++pub struct ClockId(clockid_t);
++
++impl ClockId {
++    /// Creates `ClockId` from raw `clockid_t`
++    pub fn from_raw(clk_id: clockid_t) -> Self {
++        ClockId(clk_id)
++    }
++
++    /// Returns `ClockId` of a `pid` CPU-time clock
++    #[cfg(any(
++        target_os = "freebsd",
++        target_os = "dragonfly",
++        target_os = "linux",
++        target_os = "android",
++        target_os = "emscripten",
++    ))]
++    pub fn pid_cpu_clock_id(pid: Pid) -> Result<Self> {
++        clock_getcpuclockid(pid)
++    }
++
++    /// Returns resolution of the clock id
++    #[cfg(not(target_os = "redox"))]
++    pub fn res(self) -> Result<TimeSpec> {
++        clock_getres(self)
++    }
++
++    /// Returns the current time on the clock id
++    pub fn now(self) -> Result<TimeSpec> {
++        clock_gettime(self)
++    }
++
++    /// Sets time to `timespec` on the clock id
++    #[cfg(not(any(
++        target_os = "macos",
++        target_os = "ios",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlibc")),
++            any(target_os = "redox", target_os = "hermit",),
++        ),
++    )))]
++    pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
++        clock_settime(self, timespec)
++    }
++
++    /// Gets the raw `clockid_t` wrapped by `self`
++    pub fn as_raw(self) -> clockid_t {
++        self.0
++    }
++
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten"),
++        )
++    ))]
++    pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_BOOTTIME_ALARM: ClockId = ClockId(libc::CLOCK_BOOTTIME_ALARM);
++    pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
++    #[cfg(any(
++        target_os = "fuchsia",
++        target_env = "uclibc",
++        target_os = "macos",
++        target_os = "ios",
++        target_os = "freebsd",
++        target_os = "dragonfly",
++        all(
++            not(target_env = "newlib"),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
++    pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten")
++        )
++    ))]
++    pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(
++                target_os = "emscripten",
++                all(target_os = "linux", target_env = "musl")
++            )
++        )
++    ))]
++    pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
++    #[cfg(any(
++        target_os = "fuchsia",
++        all(
++            not(any(target_env = "uclibc", target_env = "newlib")),
++            any(
++                target_os = "emscripten",
++                all(target_os = "linux", target_env = "musl")
++            )
++        )
++    ))]
++    pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
++    #[cfg(any(
++        target_env = "uclibc",
++        target_os = "fuchsia",
++        target_os = "ios",
++        target_os = "macos",
++        target_os = "freebsd",
++        target_os = "dragonfly",
++        all(
++            not(target_env = "newlib"),
++            any(target_os = "linux", target_os = "android", target_os = "emscripten",),
++        ),
++    ))]
++    pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE);
++    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++    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_t> for ClockId {
++    fn from(clk_id: clockid_t) -> Self {
++        ClockId::from_raw(clk_id)
++    }
++}
++
++impl std::fmt::Display for ClockId {
++    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
++        std::fmt::Display::fmt(&self.0, f)
++    }
++}
++
++/// Get the resolution of the specified clock, (see
++/// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)).
++#[cfg(not(target_os = "redox"))]
++pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
++    let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
++    let ret = unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
++    Errno::result(ret)?;
++    let res = unsafe { c_time.assume_init() };
++    Ok(TimeSpec::from(res))
++}
++
++/// Get the time of the specified clock, (see
++/// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)).
++pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
++    let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
++    let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
++    Errno::result(ret)?;
++    let res = unsafe { c_time.assume_init() };
++    Ok(TimeSpec::from(res))
++}
++
++/// Set the time of the specified clock, (see
++/// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)).
++#[cfg(not(any(
++    target_os = "macos",
++    target_os = "ios",
++    all(
++        not(any(target_env = "uclibc", target_env = "newlibc")),
++        any(target_os = "redox", target_os = "hermit",),
++    ),
++)))]
++pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
++    let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
++    Errno::result(ret).map(drop)
++}
++
++/// Get the clock id of the specified process id, (see
++/// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)).
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "dragonfly",
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++))]
++pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
++    let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
++    let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
++    if ret == 0 {
++        let res = unsafe { clk_id.assume_init() };
++        Ok(ClockId::from(res))
++    } else {
++        Err(Error::Sys(Errno::from_i32(ret)))
++    }
++}
+diff --git a/third_party/rust/nix/src/ucontext.rs b/third_party/rust/nix/src/ucontext.rs
+index 5e10e7d1f8934..a5b8cc75cb330 100644
+--- a/third_party/rust/nix/src/ucontext.rs
++++ b/third_party/rust/nix/src/ucontext.rs
+@@ -1,10 +1,11 @@
+ use libc;
+ #[cfg(not(target_env = "musl"))]
+-use Result;
++use crate::Result;
++#[cfg(not(target_env = "musl"))]
++use crate::errno::Errno;
+ #[cfg(not(target_env = "musl"))]
+-use errno::Errno;
+ use std::mem;
+-use sys::signal::SigSet;
++use crate::sys::signal::SigSet;
+ 
+ #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
+ pub struct UContext {
+@@ -14,11 +15,11 @@ pub struct UContext {
+ impl UContext {
+     #[cfg(not(target_env = "musl"))]
+     pub fn get() -> Result<UContext> {
+-        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
+-        let res = unsafe {
+-            libc::getcontext(&mut context as *mut libc::ucontext_t)
+-        };
+-        Errno::result(res).map(|_| UContext { context: context })
++        let mut context = mem::MaybeUninit::<libc::ucontext_t>::uninit();
++        let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
++        Errno::result(res).map(|_| unsafe {
++            UContext { context: context.assume_init()}
++        })
+     }
+ 
+     #[cfg(not(target_env = "musl"))]
+@@ -30,10 +31,14 @@ impl UContext {
+     }
+ 
+     pub fn sigmask_mut(&mut self) -> &mut SigSet {
+-        unsafe { mem::transmute(&mut self.context.uc_sigmask) }
++        unsafe {
++            &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t as *mut SigSet)
++        }
+     }
+ 
+     pub fn sigmask(&self) -> &SigSet {
+-        unsafe { mem::transmute(&self.context.uc_sigmask) }
++        unsafe {
++            &*(&self.context.uc_sigmask as *const libc::sigset_t as *const SigSet)
++        }
+     }
+ }
+diff --git a/third_party/rust/nix/src/unistd.rs b/third_party/rust/nix/src/unistd.rs
+index f422f09198655..59cb1ed8b5901 100644
+--- a/third_party/rust/nix/src/unistd.rs
++++ b/third_party/rust/nix/src/unistd.rs
+@@ -1,18 +1,26 @@
+ //! Safe wrappers around functions found in libc "unistd.h" header
+ 
+-use errno::{self, Errno};
+-use {Error, Result, NixPath};
+-use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag};
+-use fcntl::FcntlArg::F_SETFD;
++#[cfg(not(target_os = "redox"))]
++use cfg_if::cfg_if;
++use crate::errno::{self, Errno};
++use crate::{Error, Result, NixPath};
++#[cfg(not(target_os = "redox"))]
++use crate::fcntl::{AtFlags, at_rawfd};
++use crate::fcntl::{FdFlag, OFlag, fcntl};
++use crate::fcntl::FcntlArg::F_SETFD;
+ use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
+-           uid_t, gid_t, mode_t};
++           uid_t, gid_t, mode_t, PATH_MAX};
+ use std::{fmt, mem, ptr};
+-use std::ffi::{CString, CStr, OsString, OsStr};
+-use std::os::unix::ffi::{OsStringExt, OsStrExt};
++use std::convert::Infallible;
++use std::ffi::{CStr, OsString};
++#[cfg(not(target_os = "redox"))]
++use std::ffi::{CString, OsStr};
++use std::os::unix::ffi::OsStringExt;
++#[cfg(not(target_os = "redox"))]
++use std::os::unix::ffi::OsStrExt;
+ use std::os::unix::io::RawFd;
+ use std::path::PathBuf;
+-use void::Void;
+-use sys::stat::Mode;
++use crate::sys::stat::Mode;
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub use self::pivot_root::*;
+@@ -45,12 +53,12 @@ impl Uid {
+     }
+ 
+     /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
+-    pub fn is_root(&self) -> bool {
+-        *self == ROOT
++    pub fn is_root(self) -> bool {
++        self == ROOT
+     }
+ 
+     /// Get the raw `uid_t` wrapped by `self`.
+-    pub fn as_raw(&self) -> uid_t {
++    pub fn as_raw(self) -> uid_t {
+         self.0
+     }
+ }
+@@ -88,13 +96,13 @@ impl Gid {
+         getgid()
+     }
+ 
+-    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getgid`.
++    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
+     pub fn effective() -> Self {
+         getegid()
+     }
+ 
+     /// Get the raw `gid_t` wrapped by `self`.
+-    pub fn as_raw(&self) -> gid_t {
++    pub fn as_raw(self) -> gid_t {
+         self.0
+     }
+ }
+@@ -115,7 +123,7 @@ impl fmt::Display for Gid {
+ ///
+ /// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
+ /// passing wrong value.
+-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
++#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+ pub struct Pid(pid_t);
+ 
+ impl Pid {
+@@ -135,7 +143,7 @@ impl Pid {
+     }
+ 
+     /// Get the raw `pid_t` wrapped by `self`.
+-    pub fn as_raw(&self) -> pid_t {
++    pub fn as_raw(self) -> pid_t {
+         self.0
+     }
+ }
+@@ -168,8 +176,8 @@ impl ForkResult {
+ 
+     /// Return `true` if this is the child process of the `fork()`
+     #[inline]
+-    pub fn is_child(&self) -> bool {
+-        match *self {
++    pub fn is_child(self) -> bool {
++        match self {
+             ForkResult::Child => true,
+             _ => false
+         }
+@@ -177,7 +185,7 @@ impl ForkResult {
+ 
+     /// Returns `true` if this is the parent process of the `fork()`
+     #[inline]
+-    pub fn is_parent(&self) -> bool {
++    pub fn is_parent(self) -> bool {
+         !self.is_child()
+     }
+ }
+@@ -192,7 +200,7 @@ impl ForkResult {
+ /// ```no_run
+ /// use nix::unistd::{fork, ForkResult};
+ ///
+-/// match fork() {
++/// match unsafe{fork()} {
+ ///    Ok(ForkResult::Parent { child, .. }) => {
+ ///        println!("Continuing execution in parent process, new child has pid: {}", child);
+ ///    }
+@@ -222,9 +230,9 @@ impl ForkResult {
+ ///
+ /// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
+ #[inline]
+-pub fn fork() -> Result<ForkResult> {
++pub unsafe fn fork() -> Result<ForkResult> {
+     use self::ForkResult::*;
+-    let res = unsafe { libc::fork() };
++    let res = libc::fork();
+ 
+     Errno::result(res).map(|res| match res {
+         0 => Child,
+@@ -285,6 +293,7 @@ pub fn setsid() -> Result<Pid> {
+ /// 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.
+ #[inline]
++#[cfg(not(target_os = "redox"))]
+ pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
+     let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
+     Errno::result(res).map(Pid)
+@@ -417,6 +426,7 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
+ /// This function may fail in a number of different scenarios.  See the man
+ /// pages for additional details on possible failure cases.
+ #[inline]
++#[cfg(not(target_os = "fuchsia"))]
+ pub fn fchdir(dirfd: RawFd) -> Result<()> {
+     let res = unsafe { libc::fchdir(dirfd) };
+ 
+@@ -436,9 +446,6 @@ pub fn fchdir(dirfd: RawFd) -> Result<()> {
+ /// # Example
+ ///
+ /// ```rust
+-/// extern crate tempfile;
+-/// extern crate nix;
+-///
+ /// use nix::unistd;
+ /// use nix::sys::stat;
+ /// use tempfile::tempdir;
+@@ -479,9 +486,6 @@ pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+ /// # Example
+ ///
+ /// ```rust
+-/// extern crate tempfile;
+-/// extern crate nix;
+-///
+ /// use nix::unistd;
+ /// use nix::sys::stat;
+ /// use tempfile::tempdir;
+@@ -498,6 +502,7 @@ pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+ /// }
+ /// ```
+ #[inline]
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet
+ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+     let res = path.with_nix_path(|cstr| {
+         unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
+@@ -506,6 +511,28 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+     Errno::result(res).map(drop)
+ }
+ 
++/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
++///
++/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
++///
++/// If `dirfd` is `None`, then `path` is relative to the current working directory.
++///
++/// # References
++///
++/// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
++// mkfifoat is not implemented in OSX or android
++#[inline]
++#[cfg(not(any(
++    target_os = "macos", target_os = "ios",
++    target_os = "android", target_os = "redox")))]
++pub fn mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()> {
++    let res = path.with_nix_path(|cstr| unsafe {
++        libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t)
++    })?;
++
++    Errno::result(res).map(drop)
++}
++
+ /// Creates a symbolic link at `path2` which points to `path1`.
+ ///
+ /// If `dirfd` has a value, then `path2` is relative to directory associated
+@@ -515,6 +542,7 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
+ /// directory. This is identical to `libc::symlink(path1, path2)`.
+ ///
+ /// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
++#[cfg(not(target_os = "redox"))]
+ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
+     path1: &P1,
+     dirfd: Option<RawFd>,
+@@ -534,6 +562,21 @@ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
+     Errno::result(res).map(drop)
+ }
+ 
++// Double the buffer capacity up to limit. In case it already has
++// reached the limit, return Errno::ERANGE.
++fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
++    use std::cmp::min;
++
++    if buf.capacity() >= limit {
++        return Err(Error::Sys(Errno::ERANGE))
++    }
++
++    let capacity = min(buf.capacity() * 2, limit);
++    buf.reserve(capacity);
++
++    Ok(())
++}
++
+ /// Returns the current directory as a `PathBuf`
+ ///
+ /// Err is returned if the current user doesn't have the permission to read or search a component
+@@ -542,8 +585,6 @@ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
+ /// # Example
+ ///
+ /// ```rust
+-/// extern crate nix;
+-///
+ /// use nix::unistd;
+ ///
+ /// fn main() {
+@@ -576,11 +617,8 @@ pub fn getcwd() -> Result<PathBuf> {
+                 }
+             }
+ 
+-            // Trigger the internal buffer resizing logic of `Vec` by requiring
+-            // more space than the current capacity.
+-            let cap = buf.capacity();
+-            buf.set_len(cap);
+-            buf.reserve(1);
++            // Trigger the internal buffer resizing logic.
++            reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
+         }
+     }
+ }
+@@ -590,8 +628,10 @@ fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::
+     // 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
+     // around to get -1.
+-    let uid = owner.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1));
+-    let gid = group.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1));
++    let uid = owner.map(Into::into)
++        .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1));
++    let gid = group.map(Into::into)
++        .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1));
+     (uid, gid)
+ }
+ 
+@@ -612,6 +652,20 @@ pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gi
+     Errno::result(res).map(drop)
+ }
+ 
++/// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by
++/// the specified `owner` (user) and `group` (see
++/// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)).
++///
++/// The owner/group for the provided file will not be modified if `None` is
++/// provided for that argument.  Ownership change will be attempted for the path
++/// only if `Some` owner/group is provided.
++#[inline]
++pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
++    let (uid, gid) = chown_raw_ids(owner, group);
++    let res = unsafe { libc::fchown(fd, uid, gid) };
++    Errno::result(res).map(drop)
++}
++
+ /// Flags for `fchownat` function.
+ #[derive(Clone, Copy, Debug)]
+ pub enum FchownatFlags {
+@@ -640,6 +694,7 @@ pub enum FchownatFlags {
+ /// # References
+ ///
+ /// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
++#[cfg(not(target_os = "redox"))]
+ pub fn fchownat<P: ?Sized + NixPath>(
+     dirfd: Option<RawFd>,
+     path: &P,
+@@ -661,10 +716,9 @@ pub fn fchownat<P: ?Sized + NixPath>(
+     Errno::result(res).map(drop)
+ }
+ 
+-fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
+-    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
+-    args_p.push(ptr::null());
+-    args_p
++fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
++    use std::iter::once;
++    args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect()
+ }
+ 
+ /// Replace the current process image with a new one (see
+@@ -674,7 +728,7 @@ fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
+ /// performs the same action but does not allow for customization of the
+ /// environment for the new process.
+ #[inline]
+-pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
++pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
+     let args_p = to_exec_array(argv);
+ 
+     unsafe {
+@@ -698,7 +752,7 @@ pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
+ /// in the `args` list is an argument to the new process. Each element in the
+ /// `env` list should be a string in the form "key=value".
+ #[inline]
+-pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
++pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
+     let args_p = to_exec_array(args);
+     let env_p = to_exec_array(env);
+ 
+@@ -719,7 +773,7 @@ pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void>
+ /// would not work if "bash" was specified for the path argument, but `execvp`
+ /// would assuming that a bash executable was on the system `PATH`.
+ #[inline]
+-pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
++pub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> {
+     let args_p = to_exec_array(args);
+ 
+     unsafe {
+@@ -739,7 +793,7 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
+ #[cfg(any(target_os = "haiku",
+           target_os = "linux",
+           target_os = "openbsd"))]
+-pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
++pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
+     let args_p = to_exec_array(args);
+     let env_p = to_exec_array(env);
+ 
+@@ -767,7 +821,7 @@ pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<
+           target_os = "linux",
+           target_os = "freebsd"))]
+ #[inline]
+-pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
++pub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> {
+     let args_p = to_exec_array(args);
+     let env_p = to_exec_array(env);
+ 
+@@ -790,8 +844,8 @@ pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
+ /// is referenced as a file descriptor to the base directory plus a path.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ #[inline]
+-pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
+-                env: &[CString], flags: super::fcntl::AtFlags) -> Result<Void> {
++pub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA],
++                env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> {
+     let args_p = to_exec_array(args);
+     let env_p = to_exec_array(env);
+ 
+@@ -828,11 +882,12 @@ pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
+ ///   descriptors will remain identical after daemonizing.
+ /// * `noclose = false`: The process' stdin, stdout, and stderr will point to
+ ///   `/dev/null` after daemonizing.
+-#[cfg_attr(any(target_os = "macos", target_os = "ios"), deprecated(
+-    since="0.14.0",
+-    note="Deprecated in MacOSX 10.5"
+-))]
+-#[cfg_attr(any(target_os = "macos", target_os = "ios"), allow(deprecated))]
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "netbsd",
++          target_os = "openbsd"))]
+ pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
+     let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
+     Errno::result(res).map(drop)
+@@ -845,6 +900,7 @@ pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
+ /// On some systems, the host name is limited to as few as 64 bytes.  An error
+ /// will be return if the name is not valid or the current process does not have
+ /// permissions to update the host name.
++#[cfg(not(target_os = "redox"))]
+ pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
+     // Handle some differences in type of the len arg across platforms.
+     cfg_if! {
+@@ -906,9 +962,6 @@ pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
+ /// # Examples
+ ///
+ /// ```no_run
+-/// extern crate tempfile;
+-/// extern crate nix;
+-///
+ /// use std::os::unix::io::AsRawFd;
+ /// use nix::unistd::close;
+ ///
+@@ -919,9 +972,6 @@ pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
+ /// ```
+ ///
+ /// ```rust
+-/// extern crate tempfile;
+-/// extern crate nix;
+-///
+ /// use std::os::unix::io::IntoRawFd;
+ /// use nix::unistd::close;
+ ///
+@@ -969,20 +1019,14 @@ pub enum Whence {
+     /// 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",
+-          all(target_os = "linux", not(any(target_env = "musl",
+-                                           target_arch = "mips",
+-                                           target_arch = "mips64")))))]
++    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+     SeekData = libc::SEEK_DATA,
+     /// Specify an offset relative to the next hole in the file greater than
+     /// or equal to offset. If offset points into the middle of a hole, then
+     /// the file offset should be set to offset. If there is no hole past offset,
+     /// then the file offset should be adjusted to the end of the file (i.e., there
+     /// is an implicit hole at the end of any file).
+-    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
+-          all(target_os = "linux", not(any(target_env = "musl",
+-                                           target_arch = "mips",
+-                                           target_arch = "mips64")))))]
++    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
+     SeekHole = libc::SEEK_HOLE
+ }
+ 
+@@ -1007,13 +1051,13 @@ pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc:
+ /// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
+ pub fn pipe() -> Result<(RawFd, RawFd)> {
+     unsafe {
+-        let mut fds: [c_int; 2] = mem::uninitialized();
++        let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
+ 
+-        let res = libc::pipe(fds.as_mut_ptr());
++        let res = libc::pipe(fds.as_mut_ptr() as *mut c_int);
+ 
+         Errno::result(res)?;
+ 
+-        Ok((fds[0], fds[1]))
++        Ok((fds.assume_init()[0], fds.assume_init()[1]))
+     }
+ }
+ 
+@@ -1022,7 +1066,9 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
+ /// 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)
+@@ -1031,74 +1077,26 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
+           target_os = "emscripten",
+           target_os = "freebsd",
+           target_os = "linux",
++          target_os = "redox",
+           target_os = "netbsd",
+           target_os = "openbsd"))]
+ pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
+-    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
+-
+-    let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) };
+-
+-    Errno::result(res)?;
+-
+-    Ok((fds[0], fds[1]))
+-}
++    let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
+ 
+-/// Like `pipe`, but allows setting certain file descriptor flags.
+-///
+-/// The following flags are supported, and will be set after the pipe is
+-/// created:
+-///
+-/// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
+-/// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
+-#[cfg(any(target_os = "ios", target_os = "macos"))]
+-#[deprecated(
+-    since="0.10.0",
+-    note="pipe2(2) is not actually atomic on these platforms.  Use pipe(2) and fcntl(2) instead"
+-)]
+-pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
+-    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
+-
+-    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
++    let res = unsafe {
++        libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits())
++    };
+ 
+     Errno::result(res)?;
+ 
+-    pipe2_setflags(fds[0], fds[1], flags)?;
+-
+-    Ok((fds[0], fds[1]))
+-}
+-
+-#[cfg(any(target_os = "ios", target_os = "macos"))]
+-fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
+-    use fcntl::FcntlArg::F_SETFL;
+-
+-    let mut res = Ok(0);
+-
+-    if flags.contains(OFlag::O_CLOEXEC) {
+-        res = res
+-            .and_then(|_| fcntl(fd1, F_SETFD(FdFlag::FD_CLOEXEC)))
+-            .and_then(|_| fcntl(fd2, F_SETFD(FdFlag::FD_CLOEXEC)));
+-    }
+-
+-    if flags.contains(OFlag::O_NONBLOCK) {
+-        res = res
+-            .and_then(|_| fcntl(fd1, F_SETFL(OFlag::O_NONBLOCK)))
+-            .and_then(|_| fcntl(fd2, F_SETFL(OFlag::O_NONBLOCK)));
+-    }
+-
+-    match res {
+-        Ok(_) => Ok(()),
+-        Err(e) => {
+-            let _ = close(fd1);
+-            let _ = close(fd2);
+-            Err(e)
+-        }
+-    }
++    unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
+ }
+ 
+ /// Truncate a file to a specified length
+ ///
+ /// See also
+ /// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
+     let res = path.with_nix_path(|cstr| {
+         unsafe {
+@@ -1132,6 +1130,59 @@ pub fn isatty(fd: RawFd) -> Result<bool> {
+     }
+ }
+ 
++/// Flags for `linkat` function.
++#[derive(Clone, Copy, Debug)]
++pub enum LinkatFlags {
++    SymlinkFollow,
++    NoSymlinkFollow,
++}
++
++/// Link one file to another file
++///
++/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
++/// case of a relative `oldpath`, the path is interpreted relative to the directory associated
++/// with file descriptor `olddirfd` instead of the current working directory and similiarly for
++/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
++/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
++/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
++/// and/or `newpath` is then interpreted relative to the current working directory of the calling
++/// 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)
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
++pub fn linkat<P: ?Sized + NixPath>(
++    olddirfd: Option<RawFd>,
++    oldpath: &P,
++    newdirfd: Option<RawFd>,
++    newpath: &P,
++    flag: LinkatFlags,
++) -> Result<()> {
++
++    let atflag =
++        match flag {
++            LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
++            LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
++        };
++
++    let res =
++        oldpath.with_nix_path(|oldcstr| {
++            newpath.with_nix_path(|newcstr| {
++            unsafe {
++                libc::linkat(
++                    at_rawfd(olddirfd),
++                    oldcstr.as_ptr(),
++                    at_rawfd(newdirfd),
++                    newcstr.as_ptr(),
++                    atflag.bits() as libc::c_int
++                    )
++                }
++            })
++        })??;
++    Errno::result(res).map(drop)
++}
++
++
+ /// Remove a directory entry
+ ///
+ /// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
+@@ -1161,6 +1212,7 @@ pub enum UnlinkatFlags {
+ ///
+ /// # References
+ /// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
++#[cfg(not(target_os = "redox"))]
+ pub fn unlinkat<P: ?Sized + NixPath>(
+     dirfd: Option<RawFd>,
+     path: &P,
+@@ -1181,6 +1233,7 @@ pub fn unlinkat<P: ?Sized + NixPath>(
+ 
+ 
+ #[inline]
++#[cfg(not(target_os = "fuchsia"))]
+ pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
+     let res = path.with_nix_path(|cstr| {
+         unsafe { libc::chroot(cstr.as_ptr()) }
+@@ -1199,7 +1252,7 @@ pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
+     target_os = "netbsd",
+     target_os = "openbsd"
+ ))]
+-pub fn sync() -> () {
++pub fn sync() {
+     unsafe { libc::sync() };
+ }
+ 
+@@ -1309,6 +1362,28 @@ pub fn setgid(gid: Gid) -> Result<()> {
+     Errno::result(res).map(drop)
+ }
+ 
++/// Set the user identity used for filesystem checks per-thread.
++/// 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)
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn setfsuid(uid: Uid) -> Uid {
++    let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
++    Uid::from_raw(prev_fsuid as uid_t)
++}
++
++/// Set the group identity used for filesystem checks per-thread.
++/// 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)
++#[cfg(any(target_os = "linux", target_os = "android"))]
++pub fn setfsgid(gid: Gid) -> Gid {
++    let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
++    Gid::from_raw(prev_fsgid as gid_t)
++}
++
+ /// Get the list of supplementary group IDs of the calling process.
+ ///
+ /// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
+@@ -1318,33 +1393,39 @@ pub fn setgid(gid: Gid) -> Result<()> {
+ /// with the `opendirectoryd` service.
+ #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ pub fn getgroups() -> Result<Vec<Gid>> {
+-    // First get the number of groups so we can size our Vec
+-    let ret = unsafe { libc::getgroups(0, ptr::null_mut()) };
++    // First get the maximum number of groups. The value returned
++    // shall always be greater than or equal to one and less than or
++    // equal to the value of {NGROUPS_MAX} + 1.
++    let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
++        Ok(Some(n)) => (n + 1) as usize,
++        Ok(None) | Err(_) => <usize>::max_value(),
++    };
++
++    // Next, get the number of groups so we can size our Vec
++    let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
+ 
+     // Now actually get the groups. We try multiple times in case the number of
+     // groups has changed since the first call to getgroups() and the buffer is
+     // now too small.
+-    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ret)? as usize);
++    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize);
+     loop {
+         // FIXME: On the platforms we currently support, the `Gid` struct has
+         // the same representation in memory as a bare `gid_t`. This is not
+         // necessarily the case on all Rust platforms, though. See RFC 1785.
+-        let ret = unsafe {
++        let ngroups = unsafe {
+             libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
+         };
+ 
+-        match Errno::result(ret) {
++        match Errno::result(ngroups) {
+             Ok(s) => {
+                 unsafe { groups.set_len(s as usize) };
+                 return Ok(groups);
+             },
+             Err(Error::Sys(Errno::EINVAL)) => {
+-                // EINVAL indicates that the buffer size was too small. Trigger
+-                // the internal buffer resizing logic of `Vec` by requiring
+-                // more space than the current capacity.
+-                let cap = groups.capacity();
+-                unsafe { groups.set_len(cap) };
+-                groups.reserve(1);
++                // EINVAL indicates that the buffer size was too
++                // small, resize it up to ngroups_max as limit.
++                reserve_double_buffer_size(&mut groups, ngroups_max)
++                    .or(Err(Error::Sys(Errno::EINVAL)))?;
+             },
+             Err(e) => return Err(e)
+         }
+@@ -1380,11 +1461,9 @@ pub fn getgroups() -> Result<Vec<Gid>> {
+ /// #     Ok(())
+ /// # }
+ /// #
+-/// # fn main() {
+-/// #     try_main().unwrap();
+-/// # }
++/// # try_main().unwrap();
+ /// ```
+-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+ pub fn setgroups(groups: &[Gid]) -> Result<()> {
+     cfg_if! {
+         if #[cfg(any(target_os = "dragonfly",
+@@ -1428,15 +1507,14 @@ pub fn setgroups(groups: &[Gid]) -> Result<()> {
+ /// 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")))]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
+     let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
+         Ok(Some(n)) => n as c_int,
+         Ok(None) | Err(_) => <c_int>::max_value(),
+     };
+     use std::cmp::min;
+-    let mut ngroups = min(ngroups_max, 8);
+-    let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
++    let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize);
+     cfg_if! {
+         if #[cfg(any(target_os = "ios", target_os = "macos"))] {
+             type getgrouplist_group_t = c_int;
+@@ -1446,6 +1524,7 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
+     }
+     let gid: gid_t = group.into();
+     loop {
++        let mut ngroups = groups.capacity() as i32;
+         let ret = unsafe {
+             libc::getgrouplist(user.as_ptr(),
+                                gid as getgrouplist_group_t,
+@@ -1462,19 +1541,8 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
+             // BSD systems will still fill the groups buffer with as many
+             // groups as possible, but Linux manpages do not mention this
+             // behavior.
+-
+-            let cap = groups.capacity();
+-            if cap >= ngroups_max as usize {
+-                // We already have the largest capacity we can, give up
+-                return Err(Error::invalid_argument());
+-            }
+-
+-            // Reserve space for at least ngroups
+-            groups.reserve(ngroups as usize);
+-
+-            // Even if the buffer gets resized to bigger than ngroups_max,
+-            // don't ever ask for more than ngroups_max groups
+-            ngroups = min(ngroups_max, groups.capacity() as c_int);
++            reserve_double_buffer_size(&mut groups, ngroups_max as usize)
++                .or_else(|_| Err(Error::invalid_argument()))?;
+         }
+     }
+ }
+@@ -1515,11 +1583,9 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
+ /// #     Ok(())
+ /// # }
+ /// #
+-/// # fn main() {
+-/// #     try_main().unwrap();
+-/// # }
++/// # try_main().unwrap();
+ /// ```
+-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
+ pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
+     cfg_if! {
+         if #[cfg(any(target_os = "ios", target_os = "macos"))] {
+@@ -1538,6 +1604,7 @@ pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
+ ///
+ /// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
+ #[inline]
++#[cfg(not(target_os = "redox"))]
+ pub fn pause() {
+     unsafe { libc::pause() };
+ }
+@@ -1568,7 +1635,8 @@ pub mod alarm {
+     //!
+     //! Scheduling an alarm and waiting for the signal:
+     //!
+-    //! ```
++#![cfg_attr(target_os = "redox", doc = " ```rust,ignore")]
++#![cfg_attr(not(target_os = "redox"), doc = " ```rust")]
+     //! use std::time::{Duration, Instant};
+     //!
+     //! use nix::unistd::{alarm, pause};
+@@ -1577,14 +1645,23 @@ pub mod alarm {
+     //! // We need to setup an empty signal handler to catch the alarm signal,
+     //! // otherwise the program will be terminated once the signal is delivered.
+     //! extern fn signal_handler(_: nix::libc::c_int) { }
+-    //! unsafe { sigaction(Signal::SIGALRM, &SigAction::new(SigHandler::Handler(signal_handler), SaFlags::empty(), SigSet::empty())); }
++    //! let sa = SigAction::new(
++    //!     SigHandler::Handler(signal_handler),
++    //!     SaFlags::empty(),
++    //!     SigSet::empty()
++    //! );
++    //! unsafe {
++    //!     sigaction(Signal::SIGALRM, &sa);
++    //! }
+     //!
+     //! // Set an alarm for 1 second from now.
+     //! alarm::set(1);
+     //!
+     //! let start = Instant::now();
+     //! // Pause the process until the alarm signal is received.
+-    //! pause();
++    //! let mut sigset = SigSet::empty();
++    //! sigset.add(Signal::SIGALRM);
++    //! sigset.wait();
+     //!
+     //! assert!(start.elapsed() >= Duration::from_secs(1));
+     //! ```
+@@ -1593,8 +1670,6 @@ pub mod alarm {
+     //!
+     //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
+ 
+-    use libc;
+-
+     /// Schedule an alarm signal.
+     ///
+     /// This will cause the system to generate a `SIGALRM` signal for the
+@@ -1630,10 +1705,10 @@ pub fn sleep(seconds: c_uint) -> c_uint {
+     unsafe { libc::sleep(seconds) }
+ }
+ 
++#[cfg(not(target_os = "redox"))]
+ pub mod acct {
+-    use libc;
+-    use {Result, NixPath};
+-    use errno::Errno;
++    use crate::{Result, NixPath};
++    use crate::errno::Errno;
+     use std::ptr;
+ 
+     /// Enable process accounting
+@@ -1711,7 +1786,7 @@ pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
+ #[repr(i32)]
+ pub enum PathconfVar {
+     #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
+-              target_os = "netbsd", target_os = "openbsd"))]
++              target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
+     /// Minimum number of bits needed to represent, as a signed integer value,
+     /// the maximum size of a regular file allowed in the specified directory.
+     FILESIZEBITS = libc::_PC_FILESIZEBITS,
+@@ -1735,11 +1810,11 @@ pub enum PathconfVar {
+     /// 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 = "netbsd", target_os = "openbsd", target_os = "redox"))]
+     /// Symbolic links can be created.
+     POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "openbsd"))]
++              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+     /// Minimum number of bytes of storage actually allocated for any portion of
+     /// a file.
+     POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
+@@ -1749,19 +1824,20 @@ pub enum PathconfVar {
+     /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
+     POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "openbsd"))]
++              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+     /// Maximum recommended file transfer size.
+     POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "openbsd"))]
++              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+     /// Minimum recommended file transfer size.
+     POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "openbsd"))]
++              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+     ///  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 = "linux", target_os = "netbsd", target_os = "openbsd",
++              target_os = "redox"))]
+     /// Maximum number of bytes in a symbolic link.
+     SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
+     /// The use of `chown` and `fchown` is restricted to a process with
+@@ -1775,17 +1851,18 @@ pub enum PathconfVar {
+     /// 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 = "linux", target_os = "openbsd", target_os = "redox"))]
+     /// Asynchronous input or output operations may be performed for the
+     /// associated file.
+     _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "openbsd"))]
++              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
+     /// Prioritized input or output operations may be performed for the
+     /// associated file.
+     _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
+     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
+-              target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
++              target_os = "linux", target_os = "netbsd", target_os = "openbsd",
++              target_os = "redox"))]
+     /// Synchronized input or output operations may be performed for the
+     /// associated file.
+     _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
+@@ -1886,9 +1963,11 @@ pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Optio
+ pub enum SysconfVar {
+     /// Maximum number of I/O operations in a single list I/O call supported by
+     /// the implementation.
++    #[cfg(not(target_os = "redox"))]
+     AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
+     /// Maximum number of outstanding asynchronous I/O operations supported by
+     /// the implementation.
++    #[cfg(not(target_os = "redox"))]
+     AIO_MAX = libc::_SC_AIO_MAX,
+     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
+               target_os = "ios", target_os="linux", target_os = "macos",
+@@ -1899,25 +1978,34 @@ pub enum SysconfVar {
+     /// Maximum length of argument to the exec functions including environment data.
+     ARG_MAX = libc::_SC_ARG_MAX,
+     /// Maximum number of functions that may be registered with `atexit`.
++    #[cfg(not(target_os = "redox"))]
+     ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
+     /// Maximum obase values allowed by the bc utility.
++    #[cfg(not(target_os = "redox"))]
+     BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
+     /// Maximum number of elements permitted in an array by the bc utility.
++    #[cfg(not(target_os = "redox"))]
+     BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
+     /// Maximum scale value allowed by the bc utility.
++    #[cfg(not(target_os = "redox"))]
+     BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
+     /// Maximum length of a string constant accepted by the bc utility.
++    #[cfg(not(target_os = "redox"))]
+     BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
+     /// Maximum number of simultaneous processes per real user ID.
+     CHILD_MAX = libc::_SC_CHILD_MAX,
+-    // _SC_CLK_TCK is obsolete
++    // The number of clock ticks per second.
++    CLK_TCK = libc::_SC_CLK_TCK,
+     /// Maximum number of weights that can be assigned to an entry of the
+     /// LC_COLLATE order keyword in the locale definition file
++    #[cfg(not(target_os = "redox"))]
+     COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
+     /// Maximum number of timer expiration overruns.
++    #[cfg(not(target_os = "redox"))]
+     DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
+     /// Maximum number of expressions that can be nested within parentheses by
+     /// 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",
+@@ -1927,23 +2015,29 @@ pub enum SysconfVar {
+     HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
+     /// Maximum number of iovec structures that one process has available for
+     /// use with `readv` or `writev`.
++    #[cfg(not(target_os = "redox"))]
+     IOV_MAX = libc::_SC_IOV_MAX,
+     /// Unless otherwise noted, the maximum length, in bytes, of a utility's
+     /// input line (either standard input or another file), when the utility is
+     /// described as processing text files. The length includes room for the
+     /// trailing <newline>.
++    #[cfg(not(target_os = "redox"))]
+     LINE_MAX = libc::_SC_LINE_MAX,
+     /// Maximum length of a login name.
+     LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
+     /// Maximum number of simultaneous supplementary group IDs per process.
+     NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
+     /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
++    #[cfg(not(target_os = "redox"))]
+     GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
+     /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
++    #[cfg(not(target_os = "redox"))]
+     GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
+     /// The maximum number of open message queue descriptors a process may hold.
++    #[cfg(not(target_os = "redox"))]
+     MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
+     /// The maximum number of message priorities supported by the implementation.
++    #[cfg(not(target_os = "redox"))]
+     MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
+     /// A value one greater than the maximum value that the system may assign to
+     /// a newly-created file descriptor.
+@@ -1958,6 +2052,7 @@ pub enum SysconfVar {
+     /// 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",
+@@ -1970,24 +2065,32 @@ pub enum SysconfVar {
+     /// 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"))]
+     /// The implementation supports the IPv6 option.
+     _POSIX_IPV6 = libc::_SC_IPV6,
+     /// The implementation supports job control.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
+     /// The implementation supports memory mapped Files.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
+     /// The implementation supports the Process Memory Locking option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
+     /// The implementation supports the Range Memory Locking option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
+     /// The implementation supports memory protection.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
+     /// The implementation supports the Message Passing option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
+     /// The implementation supports the Monotonic Clock option.
++    #[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",
+@@ -1995,6 +2098,7 @@ pub enum SysconfVar {
+     /// 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"))]
+@@ -2016,10 +2120,13 @@ pub enum SysconfVar {
+     /// 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.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
+     /// The implementation supports semaphores.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
+     /// The implementation supports the Shared Memory Objects option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="netbsd",
+@@ -2044,10 +2151,13 @@ pub enum SysconfVar {
+               target_os="openbsd"))]
+     _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
+     /// The implementation supports the Synchronized Input and Output option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
+     /// The implementation supports the Thread Stack Address Attribute option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
+     /// The implementation supports the Thread Stack Size Attribute option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
+     #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
+               target_os="netbsd", target_os="openbsd"))]
+@@ -2055,10 +2165,13 @@ pub enum SysconfVar {
+     _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
+     /// The implementation supports the Non-Robust Mutex Priority Inheritance
+     /// option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
+     /// The implementation supports the Non-Robust Mutex Priority Protection option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
+     /// The implementation supports the Thread Execution Scheduling option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="netbsd",
+@@ -2073,18 +2186,21 @@ pub enum SysconfVar {
+     /// The implementation supports the Robust Mutex Priority Protection option.
+     _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
+     /// The implementation supports thread-safe functions.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="openbsd"))]
+     /// The implementation supports the Thread Sporadic Server option.
+     _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
+     /// The implementation supports threads.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_THREADS = libc::_SC_THREADS,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="openbsd"))]
+     /// The implementation supports timeouts.
+     _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
+     /// The implementation supports timers.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX_TIMERS = libc::_SC_TIMERS,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="openbsd"))]
+@@ -2149,17 +2265,23 @@ pub enum SysconfVar {
+     /// using at least 64 bits.
+     _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
+     /// The implementation supports the C-Language Binding option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_C_BIND = libc::_SC_2_C_BIND,
+     /// The implementation supports the C-Language Development Utilities option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_C_DEV = libc::_SC_2_C_DEV,
+     /// The implementation supports the Terminal Characteristics option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
+     /// The implementation supports the FORTRAN Development Utilities option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
+     /// The implementation supports the FORTRAN Runtime Utilities option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
+     /// The implementation supports the creation of locales by the localedef
+     /// utility.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="netbsd",
+@@ -2193,26 +2315,34 @@ pub enum SysconfVar {
+     /// The implementation supports the Track Batch Job Request option.
+     _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
+     /// The implementation supports the Software Development Utilities option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
+     /// The implementation supports the User Portability Utilities option.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_UPE = libc::_SC_2_UPE,
+     /// Integer value indicating version of the Shell and Utilities volume of
+     /// POSIX.1 to which the implementation conforms.
++    #[cfg(not(target_os = "redox"))]
+     _POSIX2_VERSION = libc::_SC_2_VERSION,
+     /// The size of a system page in bytes.
+     ///
+     /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
+     /// enum constants to have the same value, so nix omits `PAGESIZE`.
+     PAGE_SIZE = libc::_SC_PAGE_SIZE,
++    #[cfg(not(target_os = "redox"))]
+     PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
++    #[cfg(not(target_os = "redox"))]
+     PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
++    #[cfg(not(target_os = "redox"))]
+     PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
++    #[cfg(not(target_os = "redox"))]
+     PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
+     RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
+     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
+               target_os = "ios", target_os="linux", target_os = "macos",
+               target_os="openbsd"))]
+     RTSIG_MAX = libc::_SC_RTSIG_MAX,
++    #[cfg(not(target_os = "redox"))]
+     SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
+     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
+               target_os = "ios", target_os="linux", target_os = "macos",
+@@ -2227,6 +2357,7 @@ pub enum SysconfVar {
+               target_os="linux", target_os = "macos", target_os="netbsd",
+               target_os="openbsd"))]
+     SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
++    #[cfg(not(target_os = "redox"))]
+     TIMER_MAX = libc::_SC_TIMER_MAX,
+     TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
+     TZNAME_MAX = libc::_SC_TZNAME_MAX,
+@@ -2257,6 +2388,7 @@ pub enum SysconfVar {
+     _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
+     /// The implementation supports the Issue 4, Version 2 Shared Memory Option
+     /// Group.
++    #[cfg(not(target_os = "redox"))]
+     _XOPEN_SHM = libc::_SC_XOPEN_SHM,
+     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
+               target_os="linux", target_os = "macos", target_os="openbsd"))]
+@@ -2309,9 +2441,8 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
+ 
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ mod pivot_root {
+-    use libc;
+-    use {Result, NixPath};
+-    use errno::Errno;
++    use crate::{Result, NixPath};
++    use crate::errno::Errno;
+ 
+     pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
+             new_root: &P1, put_old: &P2) -> Result<()> {
+@@ -2330,9 +2461,8 @@ mod pivot_root {
+ #[cfg(any(target_os = "android", target_os = "freebsd",
+           target_os = "linux", target_os = "openbsd"))]
+ mod setres {
+-    use libc;
+-    use Result;
+-    use errno::Errno;
++    use crate::Result;
++    use crate::errno::Errno;
+     use super::{Uid, Gid};
+ 
+     /// Sets the real, effective, and saved uid.
+@@ -2392,3 +2522,308 @@ pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
+     })?;
+     Errno::result(res).map(drop)
+ }
++
++/// Representation of a User, based on `libc::passwd`
++///
++/// The reason some fields in this struct are `String` and others are `CString` is because some
++/// fields are based on the user's locale, which could be non-UTF8, while other fields are
++/// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only
++/// contains ASCII.
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++#[derive(Debug, Clone, PartialEq)]
++pub struct User {
++    /// Username
++    pub name: String,
++    /// User password (probably encrypted)
++    pub passwd: CString,
++    /// User ID
++    pub uid: Uid,
++    /// Group ID
++    pub gid: Gid,
++    /// User information
++    #[cfg(not(target_os = "android"))]
++    pub gecos: CString,
++    /// Home directory
++    pub dir: PathBuf,
++    /// Path to shell
++    pub shell: PathBuf,
++    /// Login class
++    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                  target_os = "linux")))]
++    pub class: CString,
++    /// Last password change
++    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                  target_os = "linux")))]
++    pub change: libc::time_t,
++    /// Expiration time of account
++    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                  target_os = "linux")))]
++    pub expire: libc::time_t
++}
++
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++impl From<&libc::passwd> for User {
++    fn from(pw: &libc::passwd) -> User {
++        unsafe {
++            User {
++                name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
++                passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
++                #[cfg(not(target_os = "android"))]
++                gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
++                dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
++                shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
++                uid: Uid::from_raw((*pw).pw_uid),
++                gid: Gid::from_raw((*pw).pw_gid),
++                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                              target_os = "linux")))]
++                class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
++                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                              target_os = "linux")))]
++                change: (*pw).pw_change,
++                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
++                              target_os = "linux")))]
++                expire: (*pw).pw_expire
++            }
++        }
++    }
++}
++
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++impl User {
++    fn from_anything<F>(f: F) -> Result<Option<Self>>
++    where
++        F: Fn(*mut libc::passwd,
++              *mut libc::c_char,
++              libc::size_t,
++              *mut *mut libc::passwd) -> libc::c_int
++    {
++        let buflimit = 16384;
++        let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
++            Ok(Some(n)) => n as usize,
++            Ok(None) | Err(_) => buflimit as usize,
++        };
++
++        let mut cbuf = Vec::with_capacity(bufsize);
++        let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
++        let mut res = ptr::null_mut();
++
++        loop {
++            let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
++            if error == 0 {
++                if res.is_null() {
++                    return Ok(None);
++                } else {
++                    let pwd = unsafe { pwd.assume_init() };
++                    return Ok(Some(User::from(&pwd)));
++                }
++            } else if Errno::last() == Errno::ERANGE {
++                // Trigger the internal buffer resizing logic.
++                reserve_double_buffer_size(&mut cbuf, buflimit)?;
++            } else {
++                return Err(Error::Sys(Errno::last()));
++            }
++        }
++    }
++
++    /// Get a user by UID.
++    ///
++    /// Internally, this function calls
++    /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
++    ///
++    /// # Examples
++    ///
++    /// ```
++    /// use nix::unistd::{Uid, User};
++    /// // Returns an Result<Option<User>>, thus the double unwrap.
++    /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
++    /// assert!(res.name == "root");
++    /// ```
++    pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
++        User::from_anything(|pwd, cbuf, cap, res| {
++            unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) }
++        })
++    }
++
++    /// Get a user by name.
++    ///
++    /// Internally, this function calls
++    /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
++    ///
++    /// # Examples
++    ///
++    /// ```
++    /// use nix::unistd::User;
++    /// // Returns an Result<Option<User>>, thus the double unwrap.
++    /// let res = User::from_name("root").unwrap().unwrap();
++    /// assert!(res.name == "root");
++    /// ```
++    pub fn from_name(name: &str) -> Result<Option<Self>> {
++        let name = CString::new(name).unwrap();
++        User::from_anything(|pwd, cbuf, cap, res| {
++            unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
++        })
++    }
++}
++
++/// Representation of a Group, based on `libc::group`
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++#[derive(Debug, Clone, PartialEq)]
++pub struct Group {
++    /// Group name
++    pub name: String,
++    /// Group password
++    pub passwd: CString,
++    /// Group ID
++    pub gid: Gid,
++    /// List of Group members
++    pub mem: Vec<String>
++}
++
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++impl From<&libc::group> for Group {
++    fn from(gr: &libc::group) -> Group {
++        unsafe {
++            Group {
++                name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(),
++                passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(),
++                gid: Gid::from_raw((*gr).gr_gid),
++                mem: Group::members((*gr).gr_mem)
++            }
++        }
++    }
++}
++
++#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
++impl Group {
++    unsafe fn members(mem: *mut *mut c_char) -> Vec<String> {
++        let mut ret = Vec::new();
++
++        for i in 0.. {
++            let u = mem.offset(i);
++            if (*u).is_null() {
++                break;
++            } else {
++                let s = CStr::from_ptr(*u).to_string_lossy().into_owned();
++                ret.push(s);
++            }
++        }
++
++        ret
++    }
++
++    fn from_anything<F>(f: F) -> Result<Option<Self>>
++    where
++        F: Fn(*mut libc::group,
++              *mut libc::c_char,
++              libc::size_t,
++              *mut *mut libc::group) -> libc::c_int
++    {
++        let buflimit = 16384;
++        let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
++            Ok(Some(n)) => n as usize,
++            Ok(None) | Err(_) => buflimit as usize,
++        };
++
++        let mut cbuf = Vec::with_capacity(bufsize);
++        let mut grp = mem::MaybeUninit::<libc::group>::uninit();
++        let mut res = ptr::null_mut();
++
++        loop {
++            let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
++            if error == 0 {
++                if res.is_null() {
++                    return Ok(None);
++                } else {
++                    let grp = unsafe { grp.assume_init() };
++                    return Ok(Some(Group::from(&grp)));
++                }
++            } else if Errno::last() == Errno::ERANGE {
++                // Trigger the internal buffer resizing logic.
++                reserve_double_buffer_size(&mut cbuf, buflimit)?;
++            } else {
++                return Err(Error::Sys(Errno::last()));
++            }
++        }
++    }
++
++    /// Get a group by GID.
++    ///
++    /// Internally, this function calls
++    /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
++    ///
++    /// # Examples
++    ///
++    // Disable this test on all OS except Linux as root group may not exist.
++    #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
++    #[cfg_attr(target_os = "linux", doc = " ```")]
++    /// use nix::unistd::{Gid, Group};
++    /// // Returns an Result<Option<Group>>, thus the double unwrap.
++    /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
++    /// assert!(res.name == "root");
++    /// ```
++    pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
++        Group::from_anything(|grp, cbuf, cap, res| {
++            unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) }
++        })
++    }
++
++    /// Get a group by name.
++    ///
++    /// Internally, this function calls
++    /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
++    ///
++    /// # Examples
++    ///
++    // Disable this test on all OS except Linux as root group may not exist.
++    #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
++    #[cfg_attr(target_os = "linux", doc = " ```")]
++    /// use nix::unistd::Group;
++    /// // Returns an Result<Option<Group>>, thus the double unwrap.
++    /// let res = Group::from_name("root").unwrap().unwrap();
++    /// assert!(res.name == "root");
++    /// ```
++    pub fn from_name(name: &str) -> Result<Option<Self>> {
++        let name = CString::new(name).unwrap();
++        Group::from_anything(|grp, cbuf, cap, res| {
++            unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
++        })
++    }
++}
++
++/// 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)).
++#[cfg(not(target_os = "fuchsia"))]
++pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
++    const PATH_MAX: usize = libc::PATH_MAX as usize;
++    let mut buf = vec![0_u8; PATH_MAX];
++    let c_buf = buf.as_mut_ptr() as *mut libc::c_char;
++
++    let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
++    if ret != 0 {
++        return Err(Error::Sys(Errno::from_i32(ret)));
++    }
++
++    let nul = buf.iter().position(|c| *c == b'\0').unwrap();
++    buf.truncate(nul);
++    Ok(OsString::from_vec(buf).into())
++}
++
++/// Get the effective user ID and group ID associated with a Unix domain socket.
++///
++/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
++#[cfg(any(
++    target_os = "macos",
++    target_os = "ios",
++    target_os = "freebsd",
++    target_os = "openbsd",
++    target_os = "netbsd",
++    target_os = "dragonfly",
++))]
++pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
++    let mut uid = 1;
++    let mut gid = 1;
++
++    let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
++
++    Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
++}
+diff --git a/third_party/rust/nix/test/common/mod.rs b/third_party/rust/nix/test/common/mod.rs
+new file mode 100644
+index 0000000000000..a871b47041d3e
+--- /dev/null
++++ b/third_party/rust/nix/test/common/mod.rs
+@@ -0,0 +1,127 @@
++use cfg_if::cfg_if;
++
++#[macro_export] macro_rules! skip {
++    ($($reason: expr),+) => {
++        use ::std::io::{self, Write};
++
++        let stderr = io::stderr();
++        let mut handle = stderr.lock();
++        writeln!(handle, $($reason),+).unwrap();
++        return;
++    }
++}
++
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        #[macro_export] macro_rules! require_capability {
++            ($capname:ident) => {
++                use ::caps::{Capability, CapSet, has_cap};
++
++                if !has_cap(None, CapSet::Effective, Capability::$capname)
++                    .unwrap()
++                {
++                    skip!("Insufficient capabilities. Skipping test.");
++                }
++            }
++        }
++    } else if #[cfg(not(target_os = "redox"))] {
++        #[macro_export] macro_rules! require_capability {
++            ($capname:ident) => {}
++        }
++    }
++}
++
++#[cfg(any(target_os = "linux", target_os= "android"))]
++#[macro_export] macro_rules! skip_if_cirrus {
++    ($reason:expr) => {
++        if std::env::var_os("CIRRUS_CI").is_some() {
++            skip!("{}", $reason);
++        }
++    }
++}
++
++#[cfg(target_os = "freebsd")]
++#[macro_export] macro_rules! skip_if_jailed {
++    ($name:expr) => {
++        use ::sysctl::CtlValue;
++
++        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
++            .unwrap()
++        {
++            skip!("{} cannot run in a jail. Skipping test.", $name);
++        }
++    }
++}
++
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++#[macro_export] macro_rules! skip_if_not_root {
++    ($name:expr) => {
++        use nix::unistd::Uid;
++
++        if !Uid::current().is_root() {
++            skip!("{} requires root privileges. Skipping test.", $name);
++        }
++    };
++}
++
++cfg_if! {
++    if #[cfg(any(target_os = "android", target_os = "linux"))] {
++        #[macro_export] macro_rules! skip_if_seccomp {
++            ($name:expr) => {
++                if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
++                    for l in s.lines() {
++                        let mut fields = l.split_whitespace();
++                        if fields.next() == Some("Seccomp:") &&
++                            fields.next() != Some("0")
++                        {
++                            skip!("{} cannot be run in Seccomp mode.  Skipping test.",
++                                stringify!($name));
++                        }
++                    }
++                }
++            }
++        }
++    } else if #[cfg(not(target_os = "redox"))] {
++        #[macro_export] macro_rules! skip_if_seccomp {
++            ($name:expr) => {}
++        }
++    }
++}
++
++cfg_if! {
++    if #[cfg(target_os = "linux")] {
++        #[macro_export] macro_rules! require_kernel_version {
++            ($name:expr, $version_requirement:expr) => {
++                use semver::{Version, VersionReq};
++
++                let version_requirement = VersionReq::parse($version_requirement)
++                        .expect("Bad match_version provided");
++
++                let uname = nix::sys::utsname::uname();
++                println!("{}", uname.sysname());
++                println!("{}", uname.nodename());
++                println!("{}", uname.release());
++                println!("{}", uname.version());
++                println!("{}", uname.machine());
++
++                // Fix stuff that the semver parser can't handle
++                let fixed_release = &uname.release().to_string()
++                    // Fedora 33 reports version as 4.18.el8_2.x86_64 or
++                    // 5.18.200-fc33.x86_64.  Remove the underscore.
++                    .replace("_", "-")
++                    // Cirrus-CI reports version as 4.19.112+ .  Remove the +
++                    .replace("+", "");
++                let mut version = Version::parse(fixed_release).unwrap();
++
++                //Keep only numeric parts
++                version.pre.clear();
++                version.build.clear();
++
++                if !version_requirement.matches(&version) {
++                    skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
++                        stringify!($name), version, version_requirement);
++                }
++            }
++        }
++    }
++}
+diff --git a/third_party/rust/nix/test/sys/mod.rs b/third_party/rust/nix/test/sys/mod.rs
+index 60a58dd106f19..14b03784a0a57 100644
+--- a/third_party/rust/nix/test/sys/mod.rs
++++ b/third_party/rust/nix/test/sys/mod.rs
+@@ -13,12 +13,17 @@ mod test_signal;
+ mod test_aio;
+ #[cfg(target_os = "linux")]
+ mod test_signalfd;
++#[cfg(not(target_os = "redox"))]
+ mod test_socket;
++#[cfg(not(target_os = "redox"))]
+ mod test_sockopt;
++#[cfg(not(target_os = "redox"))]
+ mod test_select;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ mod test_sysinfo;
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ mod test_termios;
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ mod test_ioctl;
+ mod test_wait;
+ mod test_uio;
+@@ -36,3 +41,5 @@ mod test_pthread;
+           target_os = "netbsd",
+           target_os = "openbsd"))]
+ mod test_ptrace;
++#[cfg(any(target_os = "android", target_os = "linux"))]
++mod test_timerfd;
+diff --git a/third_party/rust/nix/test/sys/test_aio.rs b/third_party/rust/nix/test/sys/test_aio.rs
+index d4b09b0b81905..3878da94a6ef6 100644
+--- a/third_party/rust/nix/test/sys/test_aio.rs
++++ b/third_party/rust/nix/test/sys/test_aio.rs
+@@ -47,7 +47,7 @@ fn test_accessors() {
+ // our bindings.  So it's sufficient to check that AioCb.cancel returned any
+ // AioCancelStat value.
+ #[test]
+-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++#[cfg_attr(target_env = "musl", ignore)]
+ fn test_cancel() {
+     let wbuf: &[u8] = b"CDEF";
+ 
+@@ -72,7 +72,7 @@ fn test_cancel() {
+ 
+ // Tests using aio_cancel_all for all outstanding IOs.
+ #[test]
+-#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++#[cfg_attr(target_env = "musl", ignore)]
+ fn test_aio_cancel_all() {
+     let wbuf: &[u8] = b"CDEF";
+ 
+@@ -133,6 +133,13 @@ fn test_fsync_error() {
+ 
+ #[test]
+ #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
++// On Travis, aio_suspend hits an assertion within glibc.  This is either a bug
++// in Travis's version of glibc or Linux.  Either way, we must skip the test.
++// https://github.com/nix-rust/nix/issues/1099
++#[cfg_attr(target_os = "linux", ignore)]
++// On Cirrus, aio_suspend is failing with EINVAL
++// https://github.com/nix-rust/nix/issues/1361
++#[cfg_attr(target_os = "macos", ignore)]
+ fn test_aio_suspend() {
+     const INITIAL: &[u8] = b"abcdef123456";
+     const WBUF: &[u8] = b"CDEFG";
+@@ -160,7 +167,12 @@ fn test_aio_suspend() {
+     loop {
+         {
+             let cbbuf = [&wcb, &rcb];
+-            assert!(aio_suspend(&cbbuf[..], Some(timeout)).is_ok());
++            let r = aio_suspend(&cbbuf[..], Some(timeout));
++            match r {
++                Err(Error::Sys(Errno::EINTR)) => continue,
++                Err(e) => panic!("aio_suspend returned {:?}", e),
++                Ok(_) => ()
++            };
+         }
+         if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
+            wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
+@@ -168,8 +180,8 @@ fn test_aio_suspend() {
+         }
+     }
+ 
+-    assert!(wcb.aio_return().unwrap() as usize == WBUF.len());
+-    assert!(rcb.aio_return().unwrap() as usize == rlen);
++    assert_eq!(wcb.aio_return().unwrap() as usize, WBUF.len());
++    assert_eq!(rcb.aio_return().unwrap() as usize, rlen);
+ }
+ 
+ // Test a simple aio operation with no completion notification.  We must poll
+@@ -192,11 +204,11 @@ fn test_read() {
+         aiocb.read().unwrap();
+ 
+         let err = poll_aio(&mut aiocb);
+-        assert!(err == Ok(()));
+-        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++        assert_eq!(err, Ok(()));
++        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
+     }
+ 
+-    assert!(EXPECT == rbuf.deref().deref());
++    assert_eq!(EXPECT, rbuf.deref().deref());
+ }
+ 
+ /// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
+@@ -238,11 +250,11 @@ fn test_read_into_mut_slice() {
+         aiocb.read().unwrap();
+ 
+         let err = poll_aio(&mut aiocb);
+-        assert!(err == Ok(()));
+-        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++        assert_eq!(err, Ok(()));
++        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
+     }
+ 
+-    assert!(rbuf == EXPECT);
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ // Tests from_ptr
+@@ -268,11 +280,11 @@ fn test_read_into_pointer() {
+         aiocb.read().unwrap();
+ 
+         let err = poll_aio(&mut aiocb);
+-        assert!(err == Ok(()));
+-        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
++        assert_eq!(err, Ok(()));
++        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
+     }
+ 
+-    assert!(rbuf == EXPECT);
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ // Test reading into an immutable buffer.  It should fail
+@@ -314,13 +326,13 @@ fn test_write() {
+     aiocb.write().unwrap();
+ 
+     let err = poll_aio(&mut aiocb);
+-    assert!(err == Ok(()));
+-    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
++    assert_eq!(err, Ok(()));
++    assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ // Tests `AioCb::from_boxed_slice` with `Bytes`
+@@ -344,13 +356,13 @@ fn test_write_bytes() {
+     aiocb.write().unwrap();
+ 
+     let err = poll_aio(&mut aiocb);
+-    assert!(err == Ok(()));
+-    assert!(aiocb.aio_return().unwrap() as usize == expected_len);
++    assert_eq!(err, Ok(()));
++    assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ // Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
+@@ -402,13 +414,13 @@ fn test_write_from_pointer() {
+     aiocb.write().unwrap();
+ 
+     let err = poll_aio(&mut aiocb);
+-    assert!(err == Ok(()));
+-    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
++    assert_eq!(err, Ok(()));
++    assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ /// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
+@@ -441,7 +453,7 @@ extern fn sigfunc(_: c_int) {
+ #[test]
+ #[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
+ fn test_write_sigev_signal() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+     let sa = SigAction::new(SigHandler::Handler(sigfunc),
+                             SaFlags::SA_RESETHAND,
+                             SigSet::empty());
+@@ -469,11 +481,11 @@ fn test_write_sigev_signal() {
+         thread::sleep(time::Duration::from_millis(10));
+     }
+ 
+-    assert!(aiocb.aio_return().unwrap() as usize == WBUF.len());
++    assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf, EXPECT);
+ }
+ 
+ // Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
+@@ -512,15 +524,15 @@ fn test_liocb_listio_wait() {
+         let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
+         err.expect("lio_listio");
+ 
+-        assert!(liocb.aio_return(0).unwrap() as usize == WBUF.len());
+-        assert!(liocb.aio_return(1).unwrap() as usize == rlen);
++        assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
++        assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
+     }
+-    assert!(rbuf.deref().deref() == b"3456");
++    assert_eq!(rbuf.deref().deref(), b"3456");
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf2).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf2 == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf2, EXPECT);
+ }
+ 
+ // Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
+@@ -561,15 +573,15 @@ fn test_liocb_listio_nowait() {
+ 
+         poll_aio(&mut liocb.aiocbs[0]).unwrap();
+         poll_aio(&mut liocb.aiocbs[1]).unwrap();
+-        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
+-        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
++        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
++        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
+     }
+-    assert!(rbuf.deref().deref() == b"3456");
++    assert_eq!(rbuf.deref().deref(), b"3456");
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf2).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf2 == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf2, EXPECT);
+ }
+ 
+ // Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
+@@ -579,7 +591,7 @@ fn test_liocb_listio_nowait() {
+ #[cfg(not(any(target_os = "ios", target_os = "macos")))]
+ #[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
+ fn test_liocb_listio_signal() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+     const INITIAL: &[u8] = b"abcdef123456";
+     const WBUF: &[u8] = b"CDEF";
+     let mut rbuf = vec![0; 4];
+@@ -620,15 +632,15 @@ fn test_liocb_listio_signal() {
+             thread::sleep(time::Duration::from_millis(10));
+         }
+ 
+-        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
+-        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
++        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
++        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
+     }
+-    assert!(rbuf.deref().deref() == b"3456");
++    assert_eq!(rbuf.deref().deref(), b"3456");
+ 
+     f.seek(SeekFrom::Start(0)).unwrap();
+     let len = f.read_to_end(&mut rbuf2).unwrap();
+-    assert!(len == EXPECT.len());
+-    assert!(rbuf2 == EXPECT);
++    assert_eq!(len, EXPECT.len());
++    assert_eq!(rbuf2, EXPECT);
+ }
+ 
+ // Try to use LioCb::listio to read into an immutable buffer.  It should fail
+diff --git a/third_party/rust/nix/test/sys/test_aio_drop.rs b/third_party/rust/nix/test/sys/test_aio_drop.rs
+index 492da401ef726..784ee3ef6c75e 100644
+--- a/third_party/rust/nix/test/sys/test_aio_drop.rs
++++ b/third_party/rust/nix/test/sys/test_aio_drop.rs
+@@ -1,6 +1,3 @@
+-extern crate nix;
+-extern crate tempfile;
+-
+ // Test dropping an AioCb that hasn't yet finished.
+ // This must happen in its own process, because on OSX this test seems to hose
+ // the AIO subsystem and causes subsequent tests to fail
+@@ -12,6 +9,7 @@ extern crate tempfile;
+               target_os = "macos",
+               target_os = "freebsd",
+               target_os = "netbsd")))]
++#[cfg_attr(target_env = "gnu", ignore = "Occasionally fails in Travis; glibc bug suspected")]
+ fn test_drop() {
+     use nix::sys::aio::*;
+     use nix::sys::signal::*;
+diff --git a/third_party/rust/nix/test/sys/test_ioctl.rs b/third_party/rust/nix/test/sys/test_ioctl.rs
+index 0a439b3346f53..fa4510a69c089 100644
+--- a/third_party/rust/nix/test/sys/test_ioctl.rs
++++ b/third_party/rust/nix/test/sys/test_ioctl.rs
+@@ -33,22 +33,22 @@ mod linux {
+     #[test]
+     fn test_op_none() {
+         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
+-            assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
+-            assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
++            assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
++            assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
+         } else {
+-            assert_eq!(request_code_none!(b'q', 10), 0x0000_710A);
+-            assert_eq!(request_code_none!(b'a', 255), 0x0000_61FF);
++            assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
++            assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
+         }
+     }
+ 
+     #[test]
+     fn test_op_write() {
+         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
+-            assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
+-            assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
+         } else {
+-            assert_eq!(request_code_write!(b'z', 10, 1), 0x4001_7A0A);
+-            assert_eq!(request_code_write!(b'z', 10, 512), 0x4200_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
+         }
+     }
+ 
+@@ -56,9 +56,11 @@ mod linux {
+     #[test]
+     fn test_op_write_64() {
+         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
+-            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
++                       0x8000_7A0A);
+         } else {
+-            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
++            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
++                       0x4000_7A0A);
+         }
+ 
+     }
+@@ -66,11 +68,11 @@ mod linux {
+     #[test]
+     fn test_op_read() {
+         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
+-            assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
+-            assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
+         } else {
+-            assert_eq!(request_code_read!(b'z', 10, 1), 0x8001_7A0A);
+-            assert_eq!(request_code_read!(b'z', 10, 512), 0x8200_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
+         }
+     }
+ 
+@@ -78,22 +80,25 @@ mod linux {
+     #[test]
+     fn test_op_read_64() {
+         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
+-            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
++                       0x4000_7A0A);
+         } else {
+-            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
++            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
++                       0x8000_7A0A);
+         }
+     }
+ 
+     #[test]
+     fn test_op_read_write() {
+-        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
+-        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
++        assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
++        assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
+     }
+ 
+     #[cfg(target_pointer_width = "64")]
+     #[test]
+     fn test_op_read_write_64() {
+-        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
++        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32) as u32,
++                   0xC000_7A0A);
+     }
+ }
+ 
+@@ -177,7 +182,7 @@ mod linux_ioctls {
+     #[test]
+     fn test_ioctl_read_bad() {
+         let file = tempfile().unwrap();
+-        let mut termios = unsafe { mem::uninitialized() };
++        let mut termios = unsafe { mem::zeroed() };
+         let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
+         assert_eq!(res, Err(Sys(ENOTTY)));
+     }
+@@ -194,7 +199,7 @@ mod linux_ioctls {
+     #[test]
+     fn test_ioctl_write_ptr_bad() {
+         let file = tempfile().unwrap();
+-        let termios: termios = unsafe { mem::uninitialized() };
++        let termios: termios = unsafe { mem::zeroed() };
+         let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
+         assert_eq!(res, Err(Sys(ENOTTY)));
+     }
+@@ -245,7 +250,7 @@ mod linux_ioctls {
+     #[test]
+     fn test_ioctl_read() {
+         let file = tempfile().unwrap();
+-        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
++        let mut data: v4l2_audio = unsafe { mem::zeroed() };
+         let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
+         assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
+     }
+@@ -255,7 +260,7 @@ mod linux_ioctls {
+     #[test]
+     fn test_ioctl_readwrite() {
+         let file = tempfile().unwrap();
+-        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
++        let mut data: v4l2_audio = unsafe { mem::zeroed() };
+         let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
+         assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
+     }
+@@ -318,7 +323,7 @@ mod freebsd_ioctls {
+     #[test]
+     fn test_ioctl_read() {
+         let file = tempfile().unwrap();
+-        let mut termios = unsafe { mem::uninitialized() };
++        let mut termios = unsafe { mem::zeroed() };
+         let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
+         assert_eq!(res, Err(Sys(ENOTTY)));
+     }
+@@ -327,7 +332,7 @@ mod freebsd_ioctls {
+     #[test]
+     fn test_ioctl_write_ptr() {
+         let file = tempfile().unwrap();
+-        let termios: termios = unsafe { mem::uninitialized() };
++        let termios: termios = unsafe { mem::zeroed() };
+         let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
+         assert_eq!(res, Err(Sys(ENOTTY)));
+     }
+diff --git a/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs b/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
+index 19ee3facf87d7..0795370b8c448 100644
+--- a/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
++++ b/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
+@@ -4,10 +4,6 @@
+ // we must disable the test here rather than in Cargo.toml
+ #![cfg(target_os = "freebsd")]
+ 
+-extern crate nix;
+-extern crate sysctl;
+-extern crate tempfile;
+-
+ use nix::Error;
+ use nix::errno::*;
+ use nix::libc::off_t;
+diff --git a/third_party/rust/nix/test/sys/test_mman.rs b/third_party/rust/nix/test/sys/test_mman.rs
+new file mode 100644
+index 0000000000000..152fff69c24de
+--- /dev/null
++++ b/third_party/rust/nix/test/sys/test_mman.rs
+@@ -0,0 +1,80 @@
++use nix::Error;
++use nix::libc::{c_void, size_t};
++use nix::sys::mman::{mmap, MapFlags, ProtFlags};
++
++#[cfg(target_os = "linux")]
++use nix::sys::mman::{mremap, MRemapFlags};
++
++#[test]
++fn test_mmap_anonymous() {
++    let ref mut byte = unsafe {
++        let ptr = mmap(std::ptr::null_mut(), 1,
++                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
++                       MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0)
++                      .unwrap();
++        *(ptr as * mut u8)
++    };
++    assert_eq !(*byte, 0x00u8);
++    *byte = 0xffu8;
++    assert_eq !(*byte, 0xffu8);
++}
++
++#[test]
++#[cfg(target_os = "linux")]
++fn test_mremap_grow() {
++    const ONE_K : size_t = 1024;
++    let slice : &mut[u8] = unsafe {
++        let mem = mmap(std::ptr::null_mut(), ONE_K,
++                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
++                       MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
++                      .unwrap();
++        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
++    };
++    assert_eq !(slice[ONE_K - 1], 0x00);
++    slice[ONE_K - 1] = 0xFF;
++    assert_eq !(slice[ONE_K - 1], 0xFF);
++
++    let slice : &mut[u8] = unsafe {
++        let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
++                         MRemapFlags::MREMAP_MAYMOVE, None)
++                      .unwrap();
++        std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K)
++    };
++
++    // The first KB should still have the old data in it.
++    assert_eq !(slice[ONE_K - 1], 0xFF);
++
++    // The additional range should be zero-init'd and accessible.
++    assert_eq !(slice[10 * ONE_K - 1], 0x00);
++    slice[10 * ONE_K - 1] = 0xFF;
++    assert_eq !(slice[10 * ONE_K - 1], 0xFF);
++}
++
++#[test]
++#[cfg(target_os = "linux")]
++fn test_mremap_shrink() {
++    const ONE_K : size_t = 1024;
++    let slice : &mut[u8] = unsafe {
++        let mem = mmap(std::ptr::null_mut(), 10 * ONE_K,
++                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
++                       MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
++                      .unwrap();
++        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
++    };
++    assert_eq !(slice[ONE_K - 1], 0x00);
++    slice[ONE_K - 1] = 0xFF;
++    assert_eq !(slice[ONE_K - 1], 0xFF);
++
++    let slice : &mut[u8] = unsafe {
++        let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
++                         MRemapFlags::empty(), None)
++                      .unwrap();
++        // Since we didn't supply MREMAP_MAYMOVE, the address should be the
++        // same.
++        assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
++        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
++    };
++
++    // The first KB should still be accessible and have the old data in it.
++    assert_eq !(slice[ONE_K - 1], 0xFF);
++}
+diff --git a/third_party/rust/nix/test/sys/test_pthread.rs b/third_party/rust/nix/test/sys/test_pthread.rs
+index 8928010087a13..1fc3dd900f382 100644
+--- a/third_party/rust/nix/test/sys/test_pthread.rs
++++ b/third_party/rust/nix/test/sys/test_pthread.rs
+@@ -1,13 +1,13 @@
+ use nix::sys::pthread::*;
+ 
+-#[cfg(target_env = "musl")]
++#[cfg(any(target_env = "musl", target_os = "redox"))]
+ #[test]
+ fn test_pthread_self() {
+     let tid = pthread_self();
+     assert!(tid != ::std::ptr::null_mut());
+ }
+ 
+-#[cfg(not(target_env = "musl"))]
++#[cfg(not(any(target_env = "musl", target_os = "redox")))]
+ #[test]
+ fn test_pthread_self() {
+     let tid = pthread_self();
+diff --git a/third_party/rust/nix/test/sys/test_ptrace.rs b/third_party/rust/nix/test/sys/test_ptrace.rs
+index 24d9b522ee4e5..b9793b39c54ae 100644
+--- a/third_party/rust/nix/test/sys/test_ptrace.rs
++++ b/third_party/rust/nix/test/sys/test_ptrace.rs
+@@ -8,10 +8,13 @@ use nix::sys::ptrace::Options;
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ use std::mem;
+ 
++use crate::*;
++
+ #[test]
+ fn test_ptrace() {
+     // Just make sure ptrace can be called at all, for now.
+     // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
++    require_capability!(CAP_SYS_PTRACE);
+     let err = ptrace::attach(getpid()).unwrap_err();
+     assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
+             err == Error::Sys(Errno::ENOSYS));
+@@ -21,6 +24,7 @@ fn test_ptrace() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptrace_setoptions() {
++    require_capability!(CAP_SYS_PTRACE);
+     let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
+     assert!(err != Error::UnsupportedOperation);
+ }
+@@ -29,6 +33,7 @@ fn test_ptrace_setoptions() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptrace_getevent() {
++    require_capability!(CAP_SYS_PTRACE);
+     let err = ptrace::getevent(getpid()).unwrap_err();
+     assert!(err != Error::UnsupportedOperation);
+ }
+@@ -37,6 +42,7 @@ fn test_ptrace_getevent() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptrace_getsiginfo() {
++    require_capability!(CAP_SYS_PTRACE);
+     if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
+         panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
+     }
+@@ -46,7 +52,8 @@ fn test_ptrace_getsiginfo() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptrace_setsiginfo() {
+-    let siginfo = unsafe { mem::uninitialized() };
++    require_capability!(CAP_SYS_PTRACE);
++    let siginfo = unsafe { mem::zeroed() };
+     if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
+         panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
+     }
+@@ -61,7 +68,9 @@ fn test_ptrace_cont() {
+     use nix::unistd::fork;
+     use nix::unistd::ForkResult::*;
+ 
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    require_capability!(CAP_SYS_PTRACE);
++
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // FIXME: qemu-user doesn't implement ptrace on all architectures
+     // and retunrs ENOSYS in this case.
+@@ -74,7 +83,7 @@ fn test_ptrace_cont() {
+         return;
+     }
+ 
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+         Child => {
+             ptrace::traceme().unwrap();
+             // As recommended by ptrace(2), raise SIGTRAP to pause the child
+@@ -91,7 +100,7 @@ fn test_ptrace_cont() {
+             ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
+             match waitpid(child, None) {
+                 Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
+-                    // FIXME It's been observed on some systems (apple) the 
++                    // FIXME It's been observed on some systems (apple) the
+                     // tracee may not be killed but remain as a zombie process
+                     // affecting other wait based tests. Add an extra kill just
+                     // to make sure there are no zombies.
+@@ -105,3 +114,65 @@ fn test_ptrace_cont() {
+         },
+     }
+ }
++
++// ptrace::{setoptions, getregs} are only available in these platforms
++#[cfg(all(target_os = "linux",
++          any(target_arch = "x86_64",
++              target_arch = "x86"),
++          target_env = "gnu"))]
++#[test]
++fn test_ptrace_syscall() {
++    use nix::sys::signal::kill;
++    use nix::sys::ptrace;
++    use nix::sys::signal::Signal;
++    use nix::sys::wait::{waitpid, WaitStatus};
++    use nix::unistd::fork;
++    use nix::unistd::getpid;
++    use nix::unistd::ForkResult::*;
++
++    require_capability!(CAP_SYS_PTRACE);
++
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    match unsafe{fork()}.expect("Error: Fork Failed") {
++        Child => {
++            ptrace::traceme().unwrap();
++            // first sigstop until parent is ready to continue
++            let pid = getpid();
++            kill(pid, Signal::SIGSTOP).unwrap();
++            kill(pid, Signal::SIGTERM).unwrap();
++            unsafe { ::libc::_exit(0); }
++        },
++
++        Parent { child } => {
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGSTOP)));
++
++            // set this option to recognize syscall-stops
++            ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
++
++            #[cfg(target_arch = "x86_64")]
++            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long;
++
++            #[cfg(target_arch = "x86")]
++            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
++
++            // kill entry
++            ptrace::syscall(child, None).unwrap();
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
++            assert_eq!(get_syscall_id(), ::libc::SYS_kill);
++
++            // kill exit
++            ptrace::syscall(child, None).unwrap();
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
++            assert_eq!(get_syscall_id(), ::libc::SYS_kill);
++
++            // receive signal
++            ptrace::syscall(child, None).unwrap();
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTERM)));
++
++            // inject signal
++            ptrace::syscall(child, Signal::SIGTERM).unwrap();
++            assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false)));
++        },
++    }
++}
+diff --git a/third_party/rust/nix/test/sys/test_select.rs b/third_party/rust/nix/test/sys/test_select.rs
+index cf68700c5e16f..37951086c2d8d 100644
+--- a/third_party/rust/nix/test/sys/test_select.rs
++++ b/third_party/rust/nix/test/sys/test_select.rs
+@@ -5,7 +5,7 @@ use nix::sys::time::{TimeSpec, TimeValLike};
+ 
+ #[test]
+ pub fn test_pselect() {
+-    let _mtx = ::SIGNAL_MTX
++    let _mtx = crate::SIGNAL_MTX
+         .lock()
+         .expect("Mutex got poisoned by another test");
+ 
+diff --git a/third_party/rust/nix/test/sys/test_signal.rs b/third_party/rust/nix/test/sys/test_signal.rs
+index 8780763f773ef..ae22527fde278 100644
+--- a/third_party/rust/nix/test/sys/test_signal.rs
++++ b/third_party/rust/nix/test/sys/test_signal.rs
+@@ -1,7 +1,9 @@
+ use libc;
++#[cfg(not(target_os = "redox"))]
+ use nix::Error;
+ use nix::sys::signal::*;
+ use nix::unistd::*;
++use std::convert::TryFrom;
+ use std::sync::atomic::{AtomicBool, Ordering};
+ 
+ #[test]
+@@ -10,6 +12,7 @@ fn test_kill_none() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "fuchsia"))]
+ fn test_killpg_none() {
+     killpg(getpgrp(), None)
+         .expect("Should be able to send signal to my process group.");
+@@ -17,6 +20,8 @@ fn test_killpg_none() {
+ 
+ #[test]
+ fn test_old_sigaction_flags() {
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
+     extern "C" fn handler(_: ::libc::c_int) {}
+     let act = SigAction::new(
+         SigHandler::Handler(handler),
+@@ -37,7 +42,7 @@ fn test_sigprocmask_noop() {
+ 
+ #[test]
+ fn test_sigprocmask() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // This needs to be a signal that rust doesn't use in the test harness.
+     const SIGNAL: Signal = Signal::SIGCHLD;
+@@ -75,16 +80,25 @@ lazy_static! {
+ }
+ 
+ extern fn test_sigaction_handler(signal: libc::c_int) {
+-    let signal = Signal::from_c_int(signal).unwrap();
++    let signal = Signal::try_from(signal).unwrap();
+     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
+ }
+ 
+-extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {
++#[cfg(not(target_os = "redox"))]
++extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
++
++#[test]
++#[cfg(not(target_os = "redox"))]
++fn test_signal_sigaction() {
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++
++    let action_handler = SigHandler::SigAction(test_sigaction_action);
++    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
+ }
+ 
+ #[test]
+ fn test_signal() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
+     raise(Signal::SIGINT).unwrap();
+@@ -96,9 +110,6 @@ fn test_signal() {
+     assert!(SIGNALED.load(Ordering::Relaxed));
+     assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
+ 
+-    let action_handler = SigHandler::SigAction(test_sigaction_action);
+-    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
+-
+     // Restore default signal handler
+     unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
+ }
+diff --git a/third_party/rust/nix/test/sys/test_signalfd.rs b/third_party/rust/nix/test/sys/test_signalfd.rs
+index a3b6098841f1c..af04c222852d8 100644
+--- a/third_party/rust/nix/test/sys/test_signalfd.rs
++++ b/third_party/rust/nix/test/sys/test_signalfd.rs
+@@ -1,10 +1,12 @@
++use std::convert::TryFrom;
++
+ #[test]
+ fn test_signalfd() {
+     use nix::sys::signalfd::SignalFd;
+     use nix::sys::signal::{self, raise, Signal, SigSet};
+ 
+     // Grab the mutex for altering signals so we don't interfere with other tests.
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Block the SIGUSR1 signal from automatic processing for this thread
+     let mut mask = SigSet::empty();
+@@ -20,6 +22,6 @@ fn test_signalfd() {
+ 
+     // And now catch that same signal.
+     let res = fd.read_signal().unwrap().unwrap();
+-    let signo = Signal::from_c_int(res.ssi_signo as i32).unwrap();
++    let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
+     assert_eq!(signo, signal::SIGUSR1);
+ }
+diff --git a/third_party/rust/nix/test/sys/test_socket.rs b/third_party/rust/nix/test/sys/test_socket.rs
+index 7e64d2b77f071..2b89a45336f3e 100644
+--- a/third_party/rust/nix/test/sys/test_socket.rs
++++ b/third_party/rust/nix/test/sys/test_socket.rs
+@@ -1,4 +1,3 @@
+-use nix::ifaddrs::InterfaceAddress;
+ use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
+ use std::collections::hash_map::DefaultHasher;
+ use std::hash::{Hash, Hasher};
+@@ -9,6 +8,8 @@ use std::slice;
+ use std::str::FromStr;
+ use libc::c_char;
+ use tempfile;
++#[cfg(any(target_os = "linux", target_os= "android"))]
++use crate::*;
+ 
+ #[test]
+ pub fn test_inetv4_addr_to_sock_addr() {
+@@ -106,7 +107,7 @@ pub fn test_addr_equality_abstract() {
+     assert_eq!(addr1, addr2);
+     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
+ 
+-    addr2.0.sun_path[18] = 127;
++    addr2.0.sun_path[17] = 127;
+     assert_ne!(addr1, addr2);
+     assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
+ }
+@@ -117,16 +118,13 @@ pub fn test_addr_equality_abstract() {
+ pub fn test_abstract_uds_addr() {
+     let empty = String::new();
+     let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
+-    let sun_path = [0u8; 107];
++    let sun_path: [u8; 0] = [];
+     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
+ 
+     let name = String::from("nix\0abstract\0test");
+     let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
+     let sun_path = [
+-        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+-        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
++        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116
+     ];
+     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
+     assert_eq!(addr.path(), None);
+@@ -164,6 +162,360 @@ pub fn test_socketpair() {
+     assert_eq!(&buf[..], b"hello");
+ }
+ 
++mod recvfrom {
++    use nix::Result;
++    use nix::sys::socket::*;
++    use std::thread;
++    use super::*;
++
++    const MSG: &'static [u8] = b"Hello, World!";
++
++    fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockAddr>
++        where
++            Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static,
++            Fr: FnMut(usize, Option<SockAddr>),
++    {
++        let mut buf: [u8; 13] = [0u8; 13];
++        let mut l = 0;
++        let mut from = None;
++
++        let send_thread = thread::spawn(move || {
++            let mut l = 0;
++            while l < std::mem::size_of_val(MSG) {
++                l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap();
++            }
++        });
++
++        while l < std::mem::size_of_val(MSG) {
++            let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap();
++            f_recv(len, from_);
++            from = from_;
++            l += len;
++        }
++        assert_eq!(&buf, MSG);
++        send_thread.join().unwrap();
++        from
++    }
++
++    #[test]
++    pub fn stream() {
++        let (fd2, fd1) = socketpair(AddressFamily::Unix, SockType::Stream,
++                                    None, SockFlag::empty()).unwrap();
++        // Ignore from for stream sockets
++        let _ = sendrecv(fd1, fd2, |s, m, flags| {
++            send(s, m, flags)
++        }, |_, _| {});
++    }
++
++    #[test]
++    pub fn udp() {
++        let std_sa = SocketAddr::from_str("127.0.0.1:6789").unwrap();
++        let inet_addr = InetAddr::from_std(&std_sa);
++        let sock_addr = SockAddr::new_inet(inet_addr);
++        let rsock = socket(AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None
++        ).unwrap();
++        bind(rsock, &sock_addr).unwrap();
++        let ssock = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++        let from = sendrecv(rsock, ssock, move |s, m, flags| {
++            sendto(s, m, &sock_addr, flags)
++        },|_, _| {});
++        // UDP sockets should set the from address
++        assert_eq!(AddressFamily::Inet, from.unwrap().family());
++    }
++
++    #[cfg(target_os = "linux")]
++    mod udp_offload {
++        use super::*;
++        use nix::sys::uio::IoVec;
++        use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
++
++        #[test]
++        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
++        // support is suspected.
++        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
++        pub fn gso() {
++            require_kernel_version!(udp_offload::gso, ">= 4.18");
++
++            // In this test, we send the data and provide a GSO segment size.
++            // Since we are sending the buffer of size 13, six UDP packets
++            // with size 2 and two UDP packet with size 1 will be sent.
++            let segment_size: u16 = 2;
++
++            let std_sa = SocketAddr::from_str("127.0.0.1:6791").unwrap();
++            let inet_addr = InetAddr::from_std(&std_sa);
++            let sock_addr = SockAddr::new_inet(inet_addr);
++            let rsock = socket(AddressFamily::Inet,
++                               SockType::Datagram,
++                               SockFlag::empty(),
++                               None
++            ).unwrap();
++
++            setsockopt(rsock, UdpGsoSegment, &(segment_size as _))
++                .expect("setsockopt UDP_SEGMENT failed");
++
++            bind(rsock, &sock_addr).unwrap();
++            let ssock = socket(
++                AddressFamily::Inet,
++                SockType::Datagram,
++                SockFlag::empty(),
++                None,
++            ).expect("send socket failed");
++
++            let mut num_packets_received: i32 = 0;
++
++            sendrecv(rsock, ssock, move |s, m, flags| {
++                let iov = [IoVec::from_slice(m)];
++                let cmsg = ControlMessage::UdpGsoSegments(&segment_size);
++                sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr))
++            }, {
++                let num_packets_received_ref = &mut num_packets_received;
++
++                move |len, _| {
++                    // check that we receive UDP packets with payload size
++                    // less or equal to segment size
++                    assert!(len <= segment_size as usize);
++                    *num_packets_received_ref += 1;
++                }
++            });
++
++            // Buffer size is 13, we will receive six packets of size 2,
++            // and one packet of size 1.
++            assert_eq!(7, num_packets_received);
++        }
++
++        #[test]
++        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
++        // support is suspected.
++        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
++        pub fn gro() {
++            require_kernel_version!(udp_offload::gro, ">= 5.3");
++
++            // It's hard to guarantee receiving GRO packets. Just checking
++            // that `setsockopt` doesn't fail with error
++
++            let rsock = socket(AddressFamily::Inet,
++                               SockType::Datagram,
++                               SockFlag::empty(),
++                               None
++            ).unwrap();
++
++            setsockopt(rsock, UdpGroSegment, &true)
++                .expect("setsockopt UDP_GRO failed");
++        }
++    }
++
++    #[cfg(any(
++        target_os = "linux",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "netbsd",
++    ))]
++    #[test]
++    pub fn udp_sendmmsg() {
++        use nix::sys::uio::IoVec;
++
++        let std_sa = SocketAddr::from_str("127.0.0.1:6793").unwrap();
++        let std_sa2 = SocketAddr::from_str("127.0.0.1:6794").unwrap();
++        let inet_addr = InetAddr::from_std(&std_sa);
++        let inet_addr2 = InetAddr::from_std(&std_sa2);
++        let sock_addr = SockAddr::new_inet(inet_addr);
++        let sock_addr2 = SockAddr::new_inet(inet_addr2);
++
++        let rsock = socket(AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None
++        ).unwrap();
++        bind(rsock, &sock_addr).unwrap();
++        let ssock = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++
++        let from = sendrecv(rsock, ssock, move |s, m, flags| {
++            let iov = [IoVec::from_slice(m)];
++            let mut msgs = Vec::new();
++            msgs.push(
++                SendMmsgData {
++                    iov: &iov,
++                    cmsgs: &[],
++                    addr: Some(sock_addr),
++                    _lt: Default::default(),
++                });
++
++            let batch_size = 15;
++
++            for _ in 0..batch_size {
++                msgs.push(
++                    SendMmsgData {
++                        iov: &iov,
++                        cmsgs: &[],
++                        addr: Some(sock_addr2),
++                        _lt: Default::default(),
++                    }
++                );
++            }
++            sendmmsg(s, msgs.iter(), flags)
++                .map(move |sent_bytes| {
++                    assert!(sent_bytes.len() >= 1);
++                    for sent in &sent_bytes {
++                        assert_eq!(*sent, m.len());
++                    }
++                    sent_bytes.len()
++                })
++        }, |_, _ | {});
++        // UDP sockets should set the from address
++        assert_eq!(AddressFamily::Inet, from.unwrap().family());
++    }
++
++    #[cfg(any(
++        target_os = "linux",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "netbsd",
++    ))]
++    #[test]
++    pub fn udp_recvmmsg() {
++        use nix::sys::uio::IoVec;
++        use nix::sys::socket::{MsgFlags, recvmmsg};
++
++        const NUM_MESSAGES_SENT: usize = 2;
++        const DATA: [u8; 2] = [1,2];
++
++        let std_sa = SocketAddr::from_str("127.0.0.1:6798").unwrap();
++        let inet_addr = InetAddr::from_std(&std_sa);
++        let sock_addr = SockAddr::new_inet(inet_addr);
++
++        let rsock = socket(AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None
++        ).unwrap();
++        bind(rsock, &sock_addr).unwrap();
++        let ssock = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++
++        let send_thread = thread::spawn(move || {
++            for _ in 0..NUM_MESSAGES_SENT {
++                sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
++            }
++        });
++
++        let mut msgs = std::collections::LinkedList::new();
++
++        // Buffers to receive exactly `NUM_MESSAGES_SENT` messages
++        let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT];
++        let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
++            [IoVec::from_mut_slice(&mut buf[..])]
++        }).collect();
++
++        for iov in &iovs {
++            msgs.push_back(RecvMmsgData {
++                iov: iov,
++                cmsg_buffer: None,
++            })
++        };
++
++        let res = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg");
++        assert_eq!(res.len(), DATA.len());
++
++        for RecvMsg { address, bytes, .. } in res.into_iter() {
++            assert_eq!(AddressFamily::Inet, address.unwrap().family());
++            assert_eq!(DATA.len(), bytes);
++        }
++
++        for buf in &receive_buffers {
++            assert_eq!(&buf[..DATA.len()], DATA);
++        }
++
++        send_thread.join().unwrap();
++    }
++
++    #[cfg(any(
++        target_os = "linux",
++        target_os = "android",
++        target_os = "freebsd",
++        target_os = "netbsd",
++    ))]
++    #[test]
++    pub fn udp_recvmmsg_dontwait_short_read() {
++        use nix::sys::uio::IoVec;
++        use nix::sys::socket::{MsgFlags, recvmmsg};
++
++        const NUM_MESSAGES_SENT: usize = 2;
++        const DATA: [u8; 4] = [1,2,3,4];
++
++        let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap();
++        let inet_addr = InetAddr::from_std(&std_sa);
++        let sock_addr = SockAddr::new_inet(inet_addr);
++
++        let rsock = socket(AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None
++        ).unwrap();
++        bind(rsock, &sock_addr).unwrap();
++        let ssock = socket(
++            AddressFamily::Inet,
++            SockType::Datagram,
++            SockFlag::empty(),
++            None,
++        ).expect("send socket failed");
++
++        let send_thread = thread::spawn(move || {
++            for _ in 0..NUM_MESSAGES_SENT {
++                sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
++            }
++        });
++        // Ensure we've sent all the messages before continuing so `recvmmsg`
++        // will return right away
++        send_thread.join().unwrap();
++
++        let mut msgs = std::collections::LinkedList::new();
++
++        // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg`
++        // will return when there are fewer than requested messages in the
++        // kernel buffers when using `MSG_DONTWAIT`.
++        let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
++        let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
++            [IoVec::from_mut_slice(&mut buf[..])]
++        }).collect();
++
++        for iov in &iovs {
++            msgs.push_back(RecvMmsgData {
++                iov: iov,
++                cmsg_buffer: None,
++            })
++        };
++
++        let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
++        assert_eq!(res.len(), NUM_MESSAGES_SENT);
++
++        for RecvMsg { address, bytes, .. } in res.into_iter() {
++            assert_eq!(AddressFamily::Inet, address.unwrap().family());
++            assert_eq!(DATA.len(), bytes);
++        }
++
++        for buf in &receive_buffers[..NUM_MESSAGES_SENT] {
++            assert_eq!(&buf[..DATA.len()], DATA);
++        }
++    }
++}
++
+ // Test error handling of our recvmsg wrapper
+ #[test]
+ pub fn test_recvmsg_ebadf() {
+@@ -247,8 +599,13 @@ pub fn test_af_alg_cipher() {
+                            ControlMessage, MsgFlags};
+     use nix::sys::socket::sockopt::AlgSetKey;
+ 
++    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
++    // Travis's seccomp profile blocks AF_ALG
++    // https://docs.docker.com/engine/security/seccomp/
++    skip_if_seccomp!(test_af_alg_cipher);
++
+     let alg_type = "skcipher";
+-    let alg_name = "ctr(aes)";
++    let alg_name = "ctr-aes-aesni";
+     // 256-bits secret key
+     let key = vec![0u8; 32];
+     // 16-bytes IV
+@@ -311,6 +668,11 @@ pub fn test_af_alg_aead() {
+                            ControlMessage, MsgFlags};
+     use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
+ 
++    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
++    // Travis's seccomp profile blocks AF_ALG
++    // https://docs.docker.com/engine/security/seccomp/
++    skip_if_seccomp!(test_af_alg_aead);
++
+     let auth_size = 4usize;
+     let assoc_size = 16u32;
+ 
+@@ -383,6 +745,111 @@ pub fn test_af_alg_aead() {
+     assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]);
+ }
+ 
++// Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`.
++// This creates a (udp) socket bound to localhost, then sends a message to
++// itself but uses Ipv4PacketInfo to force the source address to be localhost.
++//
++// This would be a more interesting test if we could assume that the test host
++// has more than one IP address (since we could select a different address to
++// test from).
++#[cfg(any(target_os = "linux",
++        target_os = "macos",
++        target_os = "netbsd"))]
++#[test]
++pub fn test_sendmsg_ipv4packetinfo() {
++    use nix::sys::uio::IoVec;
++    use nix::sys::socket::{socket, sendmsg, bind,
++                           AddressFamily, SockType, SockFlag, SockAddr,
++                           ControlMessage, MsgFlags};
++
++    let sock = socket(AddressFamily::Inet,
++                      SockType::Datagram,
++                      SockFlag::empty(),
++                      None)
++        .expect("socket failed");
++
++    let std_sa = SocketAddr::from_str("127.0.0.1:4000").unwrap();
++    let inet_addr = InetAddr::from_std(&std_sa);
++    let sock_addr = SockAddr::new_inet(inet_addr);
++
++    bind(sock, &sock_addr).expect("bind failed");
++
++    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++    let iov = [IoVec::from_slice(&slice)];
++
++    if let InetAddr::V4(sin) = inet_addr {
++        let pi = libc::in_pktinfo {
++            ipi_ifindex: 0, /* Unspecified interface */
++            ipi_addr: libc::in_addr { s_addr: 0 },
++            ipi_spec_dst: sin.sin_addr,
++        };
++
++        let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
++
++        sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
++            .expect("sendmsg");
++    } else {
++        panic!("No IPv4 addresses available for testing?");
++    }
++}
++
++// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
++// This creates a (udp) socket bound to ip6-localhost, then sends a message to
++// itself but uses Ipv6PacketInfo to force the source address to be
++// ip6-localhost.
++//
++// This would be a more interesting test if we could assume that the test host
++// has more than one IP address (since we could select a different address to
++// test from).
++#[cfg(any(target_os = "linux",
++        target_os = "macos",
++        target_os = "netbsd",
++        target_os = "freebsd"))]
++#[test]
++pub fn test_sendmsg_ipv6packetinfo() {
++    use nix::Error;
++    use nix::errno::Errno;
++    use nix::sys::uio::IoVec;
++    use nix::sys::socket::{socket, sendmsg, bind,
++                           AddressFamily, SockType, SockFlag, SockAddr,
++                           ControlMessage, MsgFlags};
++
++    let sock = socket(AddressFamily::Inet6,
++                      SockType::Datagram,
++                      SockFlag::empty(),
++                      None)
++        .expect("socket failed");
++
++    let std_sa = SocketAddr::from_str("[::1]:6000").unwrap();
++    let inet_addr = InetAddr::from_std(&std_sa);
++    let sock_addr = SockAddr::new_inet(inet_addr);
++
++    match bind(sock, &sock_addr) {
++        Err(Error::Sys(Errno::EADDRNOTAVAIL)) => {
++            println!("IPv6 not available, skipping test.");
++            return;
++        },
++        _ => (),
++    }
++
++    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
++    let iov = [IoVec::from_slice(&slice)];
++
++    if let InetAddr::V6(sin) = inet_addr {
++        let pi = libc::in6_pktinfo {
++            ipi6_ifindex: 0, /* Unspecified interface */
++            ipi6_addr: sin.sin6_addr,
++        };
++
++        let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
++
++        sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
++            .expect("sendmsg");
++    } else {
++        println!("No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo");
++    }
++}
++
+ /// Tests that passing multiple fds using a single `ControlMessage` works.
+ // Disable the test on emulated platforms due to a bug in QEMU versions <
+ // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
+@@ -468,29 +935,36 @@ pub fn test_sendmsg_empty_cmsgs() {
+     }
+ }
+ 
+-#[cfg(any(target_os = "android", target_os = "linux"))]
++#[cfg(any(
++    target_os = "android",
++    target_os = "linux",
++    target_os = "freebsd",
++    target_os = "dragonfly",
++))]
+ #[test]
+ fn test_scm_credentials() {
+-    use libc;
+     use nix::sys::uio::IoVec;
+     use nix::unistd::{close, getpid, getuid, getgid};
+-    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
++    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
+                            AddressFamily, SockType, SockFlag,
+-                           ControlMessage, ControlMessageOwned, MsgFlags};
+-    use nix::sys::socket::sockopt::PassCred;
++                           ControlMessage, ControlMessageOwned, MsgFlags,
++                           UnixCredentials};
++    #[cfg(any(target_os = "android", target_os = "linux"))]
++    use nix::sys::socket::{setsockopt, sockopt::PassCred};
+ 
+     let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
+         .unwrap();
++    #[cfg(any(target_os = "android", target_os = "linux"))]
+     setsockopt(recv, PassCred, &true).unwrap();
+ 
+     {
+         let iov = [IoVec::from_slice(b"hello")];
+-        let cred = libc::ucred {
+-            pid: getpid().as_raw(),
+-            uid: getuid().as_raw(),
+-            gid: getgid().as_raw(),
+-        };
++        #[cfg(any(target_os = "android", target_os = "linux"))]
++        let cred = UnixCredentials::new();
++        #[cfg(any(target_os = "android", target_os = "linux"))]
+         let cmsg = ControlMessage::ScmCredentials(&cred);
++        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++        let cmsg = ControlMessage::ScmCreds;
+         assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
+         close(send).unwrap();
+     }
+@@ -498,20 +972,23 @@ fn test_scm_credentials() {
+     {
+         let mut buf = [0u8; 5];
+         let iov = [IoVec::from_mut_slice(&mut buf[..])];
+-        let mut cmsgspace = cmsg_space!(libc::ucred);
++        let mut cmsgspace = cmsg_space!(UnixCredentials);
+         let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
+         let mut received_cred = None;
+ 
+         for cmsg in msg.cmsgs() {
+-            if let ControlMessageOwned::ScmCredentials(cred) = cmsg {
+-                assert!(received_cred.is_none());
+-                assert_eq!(cred.pid, getpid().as_raw());
+-                assert_eq!(cred.uid, getuid().as_raw());
+-                assert_eq!(cred.gid, getgid().as_raw());
+-                received_cred = Some(cred);
+-            } else {
+-                panic!("unexpected cmsg");
+-            }
++            let cred = match cmsg {
++                #[cfg(any(target_os = "android", target_os = "linux"))]
++                ControlMessageOwned::ScmCredentials(cred) => cred,
++                #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
++                ControlMessageOwned::ScmCreds(cred) => cred,
++                other => panic!("unexpected cmsg {:?}", other),
++            };
++            assert!(received_cred.is_none());
++            assert_eq!(cred.pid(), getpid().as_raw());
++            assert_eq!(cred.uid(), getuid().as_raw());
++            assert_eq!(cred.gid(), getgid().as_raw());
++            received_cred = Some(cred);
+         }
+         received_cred.expect("no creds received");
+         assert_eq!(msg.bytes, 5);
+@@ -550,7 +1027,7 @@ fn test_too_large_cmsgspace() {
+ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
+     use libc::ucred;
+     use nix::sys::uio::IoVec;
+-    use nix::unistd::{pipe, read, write, close, getpid, getuid, getgid};
++    use nix::unistd::{pipe, write, close, getpid, getuid, getgid};
+     use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
+                            SockType, SockFlag,
+                            ControlMessage, ControlMessageOwned, MsgFlags};
+@@ -569,7 +1046,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
+             pid: getpid().as_raw(),
+             uid: getuid().as_raw(),
+             gid: getgid().as_raw(),
+-        };
++        }.into();
+         let fds = [r];
+         let cmsgs = [
+             ControlMessage::ScmCredentials(&cred),
+@@ -597,9 +1074,9 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
+                 }
+                 ControlMessageOwned::ScmCredentials(cred) => {
+                     assert!(received_cred.is_none());
+-                    assert_eq!(cred.pid, getpid().as_raw());
+-                    assert_eq!(cred.uid, getuid().as_raw());
+-                    assert_eq!(cred.gid, getgid().as_raw());
++                    assert_eq!(cred.pid(), getpid().as_raw());
++                    assert_eq!(cred.uid(), getuid().as_raw());
++                    assert_eq!(cred.gid(), getgid().as_raw());
+                     received_cred = Some(cred);
+                 }
+                 _ => panic!("unexpected cmsg"),
+@@ -683,7 +1160,7 @@ pub fn test_syscontrol() {
+     target_os = "netbsd",
+     target_os = "openbsd",
+ ))]
+-fn loopback_address(family: AddressFamily) -> Option<InterfaceAddress> {
++fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddress> {
+     use std::io;
+     use std::io::Write;
+     use nix::ifaddrs::getifaddrs;
+@@ -1013,7 +1490,7 @@ pub fn test_recv_ipv6pktinfo() {
+     }
+ }
+ 
+-#[cfg(target_os = "linux")]
++#[cfg(any(target_os = "android", target_os = "linux"))]
+ #[test]
+ pub fn test_vsock() {
+     use libc;
+@@ -1030,17 +1507,11 @@ pub fn test_vsock() {
+                     SockFlag::empty(), None)
+              .expect("socket failed");
+ 
+-    // VMADDR_CID_HYPERVISOR and VMADDR_CID_RESERVED are reserved, so we expect
+-    // an EADDRNOTAVAIL error.
++    // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error.
+     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
+     assert_eq!(bind(s1, &sockaddr).err(),
+                Some(Error::Sys(Errno::EADDRNOTAVAIL)));
+ 
+-    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_RESERVED, port);
+-    assert_eq!(bind(s1, &sockaddr).err(),
+-               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
+-
+-
+     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
+     assert_eq!(bind(s1, &sockaddr), Ok(()));
+     listen(s1, 10).expect("listen failed");
+diff --git a/third_party/rust/nix/test/sys/test_sockopt.rs b/third_party/rust/nix/test/sys/test_sockopt.rs
+index c4860c0d61d3d..56065931322ec 100644
+--- a/third_party/rust/nix/test/sys/test_sockopt.rs
++++ b/third_party/rust/nix/test/sys/test_sockopt.rs
+@@ -1,5 +1,7 @@
+ use rand::{thread_rng, Rng};
+ use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
++#[cfg(any(target_os = "android", target_os = "linux"))]
++use crate::*;
+ 
+ #[cfg(target_os = "linux")]
+ #[test]
+@@ -51,3 +53,44 @@ fn test_tcp_congestion() {
+         val
+     );
+ }
++
++#[test]
++#[cfg(any(target_os = "android", target_os = "linux"))]
++fn test_bindtodevice() {
++    skip_if_not_root!("test_bindtodevice");
++
++    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
++
++    let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
++    setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
++
++    assert_eq!(
++        getsockopt(fd, sockopt::BindToDevice).unwrap(),
++        val
++    );
++}
++
++#[test]
++fn test_so_tcp_keepalive() {
++    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
++    setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
++    assert_eq!(getsockopt(fd, sockopt::KeepAlive).unwrap(), true);
++
++    #[cfg(any(target_os = "android",
++              target_os = "dragonfly",
++              target_os = "freebsd",
++              target_os = "linux",
++              target_os = "nacl"))] {
++        let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
++        setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
++        assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
++
++        let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
++        setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
++        assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
++
++        let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
++        setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
++        assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
++    }
++}
+diff --git a/third_party/rust/nix/test/sys/test_termios.rs b/third_party/rust/nix/test/sys/test_termios.rs
+index a14b8ce1a23cb..00aeb2fc57f15 100644
+--- a/third_party/rust/nix/test/sys/test_termios.rs
++++ b/third_party/rust/nix/test/sys/test_termios.rs
+@@ -4,7 +4,7 @@ use tempfile::tempfile;
+ use nix::{Error, fcntl};
+ use nix::errno::Errno;
+ use nix::pty::openpty;
+-use nix::sys::termios::{self, LocalFlags, OutputFlags, Termios, tcgetattr};
++use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr};
+ use nix::unistd::{read, write, close};
+ 
+ /// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
+@@ -19,10 +19,10 @@ fn write_all(f: RawFd, buf: &[u8]) {
+ #[test]
+ fn test_tcgetattr_pty() {
+     // openpty uses ptname(3) internally
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     let pty = openpty(None, None).expect("openpty failed");
+-    assert!(termios::tcgetattr(pty.master).is_ok());
++    assert!(termios::tcgetattr(pty.slave).is_ok());
+     close(pty.master).expect("closing the master failed");
+     close(pty.slave).expect("closing the slave failed");
+ }
+@@ -46,14 +46,14 @@ fn test_tcgetattr_ebadf() {
+ #[test]
+ fn test_output_flags() {
+     // openpty uses ptname(3) internally
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open one pty to get attributes for the second one
+     let mut termios = {
+         let pty = openpty(None, None).expect("openpty failed");
+         assert!(pty.master > 0);
+         assert!(pty.slave > 0);
+-        let termios = tcgetattr(pty.master).expect("tcgetattr failed");
++        let termios = tcgetattr(pty.slave).expect("tcgetattr failed");
+         close(pty.master).unwrap();
+         close(pty.slave).unwrap();
+         termios
+@@ -77,7 +77,7 @@ fn test_output_flags() {
+ 
+     // Read from the slave verifying that the output has been properly transformed
+     let mut buf = [0u8; 10];
+-    ::read_exact(pty.slave, &mut buf);
++    crate::read_exact(pty.slave, &mut buf);
+     let transformed_string = "foofoofoo\n";
+     close(pty.master).unwrap();
+     close(pty.slave).unwrap();
+@@ -88,14 +88,14 @@ fn test_output_flags() {
+ #[test]
+ fn test_local_flags() {
+     // openpty uses ptname(3) internally
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open one pty to get attributes for the second one
+     let mut termios = {
+         let pty = openpty(None, None).unwrap();
+         assert!(pty.master > 0);
+         assert!(pty.slave > 0);
+-        let termios = tcgetattr(pty.master).unwrap();
++        let termios = tcgetattr(pty.slave).unwrap();
+         close(pty.master).unwrap();
+         close(pty.slave).unwrap();
+         termios
+@@ -128,9 +128,3 @@ fn test_local_flags() {
+     close(pty.slave).unwrap();
+     assert_eq!(read, Error::Sys(Errno::EAGAIN));
+ }
+-
+-#[test]
+-fn test_cfmakeraw() {
+-    let mut termios = unsafe { Termios::default_uninit() };
+-    termios::cfmakeraw(&mut termios);
+-}
+diff --git a/third_party/rust/nix/test/sys/test_timerfd.rs b/third_party/rust/nix/test/sys/test_timerfd.rs
+new file mode 100644
+index 0000000000000..24fb2ac002e1d
+--- /dev/null
++++ b/third_party/rust/nix/test/sys/test_timerfd.rs
+@@ -0,0 +1,61 @@
++use nix::sys::time::{TimeSpec, TimeValLike};
++use nix::sys::timerfd::{ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags};
++use std::time::Instant;
++
++#[test]
++pub fn test_timerfd_oneshot() {
++    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
++
++    let before = Instant::now();
++
++    timer
++        .set(
++            Expiration::OneShot(TimeSpec::seconds(1)),
++            TimerSetTimeFlags::empty(),
++        )
++        .unwrap();
++
++    timer.wait().unwrap();
++
++    let millis = before.elapsed().as_millis();
++    assert!(millis > 900);
++}
++
++#[test]
++pub fn test_timerfd_interval() {
++    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
++
++    let before = Instant::now();
++    timer
++        .set(
++            Expiration::IntervalDelayed(TimeSpec::seconds(1), TimeSpec::seconds(2)),
++            TimerSetTimeFlags::empty(),
++        )
++        .unwrap();
++
++    timer.wait().unwrap();
++
++    let start_delay = before.elapsed().as_millis();
++    assert!(start_delay > 900);
++
++    timer.wait().unwrap();
++
++    let interval_delay = before.elapsed().as_millis();
++    assert!(interval_delay > 2900);
++}
++
++#[test]
++pub fn test_timerfd_unset() {
++    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
++
++    timer
++        .set(
++            Expiration::OneShot(TimeSpec::seconds(1)),
++            TimerSetTimeFlags::empty(),
++        )
++        .unwrap();
++
++    timer.unset().unwrap();
++
++    assert!(timer.get().unwrap() == None);
++}
+diff --git a/third_party/rust/nix/test/sys/test_uio.rs b/third_party/rust/nix/test/sys/test_uio.rs
+index 3e4fc28ceb0e4..8d22bf1755a2c 100644
+--- a/third_party/rust/nix/test/sys/test_uio.rs
++++ b/third_party/rust/nix/test/sys/test_uio.rs
+@@ -6,7 +6,9 @@ use std::{cmp, iter};
+ use std::fs::{OpenOptions};
+ use std::os::unix::io::AsRawFd;
+ 
+-use tempfile::{tempfile, tempdir};
++#[cfg(not(target_os = "redox"))]
++use tempfile::tempfile;
++use tempfile::tempdir;
+ 
+ #[test]
+ fn test_writev() {
+@@ -53,6 +55,7 @@ fn test_writev() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_readv() {
+     let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
+     let to_write = s.as_bytes().to_vec();
+@@ -97,6 +100,7 @@ fn test_readv() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_pwrite() {
+     use std::io::Read;
+ 
+@@ -199,15 +203,17 @@ fn test_process_vm_readv() {
+     use nix::unistd::ForkResult::*;
+     use nix::sys::signal::*;
+     use nix::sys::wait::*;
++    use crate::*;
+ 
+-    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    require_capability!(CAP_SYS_PTRACE);
++    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Pre-allocate memory in the child, since allocation isn't safe
+     // post-fork (~= async-signal-safe)
+     let mut vector = vec![1u8, 2, 3, 4, 5];
+ 
+     let (r, w) = pipe().unwrap();
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+         Parent { child } => {
+             close(w).unwrap();
+             // wait for child
+diff --git a/third_party/rust/nix/test/sys/test_wait.rs b/third_party/rust/nix/test/sys/test_wait.rs
+index d07d82f0d9075..5bb298eba4d29 100644
+--- a/third_party/rust/nix/test/sys/test_wait.rs
++++ b/third_party/rust/nix/test/sys/test_wait.rs
+@@ -6,11 +6,12 @@ use nix::sys::wait::*;
+ use libc::_exit;
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_wait_signal() {
+-    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+       Child => {
+           pause();
+           unsafe { _exit(123) }
+@@ -24,10 +25,10 @@ fn test_wait_signal() {
+ 
+ #[test]
+ fn test_wait_exit() {
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Safe: Child only calls `_exit`, which is async-signal-safe.
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+       Child => unsafe { _exit(12); },
+       Parent { child } => {
+           assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
+@@ -45,9 +46,9 @@ fn test_waitstatus_from_raw() {
+ 
+ #[test]
+ fn test_waitstatus_pid() {
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+-    match fork().unwrap() {
++    match unsafe{fork()}.unwrap() {
+         Child => unsafe { _exit(0) },
+         Parent { child } => {
+             let status = waitpid(child, None).unwrap();
+@@ -66,6 +67,7 @@ mod ptrace {
+     use nix::unistd::*;
+     use nix::unistd::ForkResult::*;
+     use libc::_exit;
++    use crate::*;
+ 
+     fn ptrace_child() -> ! {
+         ptrace::traceme().unwrap();
+@@ -82,7 +84,7 @@ mod ptrace {
+         assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
+ 
+         // First, stop on the next system call, which will be exit()
+-        assert!(ptrace::syscall(child).is_ok());
++        assert!(ptrace::syscall(child, None).is_ok());
+         assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
+         // Then get the ptrace event for the process exiting
+         assert!(ptrace::cont(child, None).is_ok());
+@@ -94,9 +96,10 @@ mod ptrace {
+ 
+     #[test]
+     fn test_wait_ptrace() {
+-        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++        require_capability!(CAP_SYS_PTRACE);
++        let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+-        match fork().expect("Error: Fork Failed") {
++        match unsafe{fork()}.expect("Error: Fork Failed") {
+             Child => ptrace_child(),
+             Parent { child } => ptrace_parent(child),
+         }
+diff --git a/third_party/rust/nix/test/test.rs b/third_party/rust/nix/test/test.rs
+index 6a71d261b5712..5a5330b7e4010 100644
+--- a/third_party/rust/nix/test/test.rs
++++ b/third_party/rust/nix/test/test.rs
+@@ -1,69 +1,13 @@
+-// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
+-#![allow(deprecated)]
+-extern crate bytes;
+-#[cfg(any(target_os = "android", target_os = "linux"))]
+-extern crate caps;
+ #[macro_use]
+ extern crate cfg_if;
+-#[macro_use]
++#[cfg_attr(not(target_os = "redox"), macro_use)]
+ extern crate nix;
+ #[macro_use]
+ extern crate lazy_static;
+-extern crate libc;
+-extern crate rand;
+-#[cfg(target_os = "freebsd")]
+-extern crate sysctl;
+-extern crate tempfile;
+-
+-#[cfg(any(target_os = "android", target_os = "linux"))]
+-macro_rules! require_capability {
+-    ($capname:ident) => {
+-        use ::caps::{Capability, CapSet, has_cap};
+-        use ::std::io::{self, Write};
+-
+-        if !has_cap(None, CapSet::Effective, Capability::$capname).unwrap() {
+-            let stderr = io::stderr();
+-            let mut handle = stderr.lock();
+-            writeln!(handle, "Insufficient capabilities. Skipping test.")
+-                .unwrap();
+-            return;
+-        }
+-    }
+-}
+-
+-#[cfg(target_os = "freebsd")]
+-macro_rules! skip_if_jailed {
+-    ($name:expr) => {
+-        use ::sysctl::CtlValue;
+-
+-        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
+-            .unwrap()
+-        {
+-            use ::std::io::Write;
+-            let stderr = ::std::io::stderr();
+-            let mut handle = stderr.lock();
+-            writeln!(handle, "{} cannot run in a jail. Skipping test.", $name)
+-                .unwrap();
+-            return;
+-        }
+-    }
+-}
+-
+-macro_rules! skip_if_not_root {
+-    ($name:expr) => {
+-        use nix::unistd::Uid;
+-
+-        if !Uid::current().is_root() {
+-            use ::std::io::Write;
+-            let stderr = ::std::io::stderr();
+-            let mut handle = stderr.lock();
+-            writeln!(handle, "{} requires root privileges. Skipping test.", $name).unwrap();
+-            return;
+-        }
+-    };
+-}
+ 
++mod common;
+ mod sys;
++#[cfg(not(target_os = "redox"))]
+ mod test_dir;
+ mod test_fcntl;
+ #[cfg(any(target_os = "android",
+@@ -75,10 +19,15 @@ mod test_kmod;
+           target_os = "linux",
+           target_os = "netbsd"))]
+ mod test_mq;
++#[cfg(not(target_os = "redox"))]
+ mod test_net;
+ mod test_nix_path;
+ mod test_poll;
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ mod test_pty;
++#[cfg(any(target_os = "android",
++          target_os = "linux"))]
++mod test_sched;
+ #[cfg(any(target_os = "android",
+           target_os = "freebsd",
+           target_os = "ios",
+@@ -86,6 +35,7 @@ mod test_pty;
+           target_os = "macos"))]
+ mod test_sendfile;
+ mod test_stat;
++mod test_time;
+ mod test_unistd;
+ 
+ use std::os::unix::io::RawFd;
+@@ -93,6 +43,7 @@ use std::path::PathBuf;
+ use std::sync::{Mutex, RwLock, RwLockWriteGuard};
+ use nix::unistd::{chdir, getcwd, read};
+ 
++
+ /// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
+ fn read_exact(f: RawFd, buf: &mut  [u8]) {
+     let mut len = 0;
+@@ -130,7 +81,7 @@ struct DirRestore<'a> {
+ 
+ impl<'a> DirRestore<'a> {
+     fn new() -> Self {
+-        let guard = ::CWD_LOCK.write()
++        let guard = crate::CWD_LOCK.write()
+             .expect("Lock got poisoned by another test");
+         DirRestore{
+             _g: guard,
+diff --git a/third_party/rust/nix/test/test_clearenv.rs b/third_party/rust/nix/test/test_clearenv.rs
+new file mode 100644
+index 0000000000000..28a77680498ca
+--- /dev/null
++++ b/third_party/rust/nix/test/test_clearenv.rs
+@@ -0,0 +1,9 @@
++use std::env;
++
++#[test]
++fn clearenv() {
++    env::set_var("FOO", "BAR");
++    unsafe { nix::env::clearenv() }.unwrap();
++    assert_eq!(env::var("FOO").unwrap_err(), env::VarError::NotPresent);
++    assert_eq!(env::vars().count(), 0);
++}
+diff --git a/third_party/rust/nix/test/test_dir.rs b/third_party/rust/nix/test/test_dir.rs
+index c42fbcd18a29d..505277e7143b7 100644
+--- a/third_party/rust/nix/test/test_dir.rs
++++ b/third_party/rust/nix/test/test_dir.rs
+@@ -1,11 +1,8 @@
+-extern crate nix;
+-extern crate tempfile;
+-
+ use nix::dir::{Dir, Type};
+ use nix::fcntl::OFlag;
+ use nix::sys::stat::Mode;
+ use std::fs::File;
+-use self::tempfile::tempdir;
++use tempfile::tempdir;
+ 
+ #[test]
+ fn read() {
+@@ -37,7 +34,9 @@ fn rewind() {
+                             Mode::empty()).unwrap();
+     let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
+     let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
++    let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect();
+     assert_eq!(entries1, entries2);
++    assert_eq!(entries2, entries3);
+ }
+ 
+ #[test]
+diff --git a/third_party/rust/nix/test/test_fcntl.rs b/third_party/rust/nix/test/test_fcntl.rs
+index 6b2bbd679fc31..5d1bafebe195f 100644
+--- a/third_party/rust/nix/test/test_fcntl.rs
++++ b/third_party/rust/nix/test/test_fcntl.rs
+@@ -1,14 +1,28 @@
++#[cfg(not(target_os = "redox"))]
+ use nix::Error;
++#[cfg(not(target_os = "redox"))]
+ use nix::errno::*;
+-use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
++#[cfg(not(target_os = "redox"))]
++use nix::fcntl::{open, OFlag, readlink};
++#[cfg(not(target_os = "redox"))]
++use nix::fcntl::{openat, readlinkat, renameat};
++#[cfg(not(target_os = "redox"))]
+ use nix::sys::stat::Mode;
++#[cfg(not(target_os = "redox"))]
+ use nix::unistd::{close, read};
++#[cfg(not(target_os = "redox"))]
+ use tempfile::{self, NamedTempFile};
++#[cfg(not(target_os = "redox"))]
+ use std::fs::File;
++#[cfg(not(target_os = "redox"))]
+ use std::io::prelude::*;
++#[cfg(not(target_os = "redox"))]
+ use std::os::unix::fs;
+ 
++use crate::*;
++
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_openat() {
+     const CONTENTS: &[u8] = b"abcd";
+     let mut tmp = NamedTempFile::new().unwrap();
+@@ -31,6 +45,7 @@ fn test_openat() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_renameat() {
+     let old_dir = tempfile::tempdir().unwrap();
+     let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
+@@ -47,6 +62,7 @@ fn test_renameat() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_readlink() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let src = tempdir.path().join("a");
+@@ -56,28 +72,31 @@ fn test_readlink() {
+     let dirfd = open(tempdir.path(),
+                      OFlag::empty(),
+                      Mode::empty()).unwrap();
++    let expected_dir = src.to_str().unwrap();
++
++    assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
++    assert_eq!(readlinkat(dirfd, "b").unwrap().to_str().unwrap(), expected_dir);
+ 
+-    let mut buf = vec![0; src.to_str().unwrap().len() + 1];
+-    assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
+-               src.to_str().unwrap());
+-    assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
+-               src.to_str().unwrap());
+ }
+ 
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+ mod linux_android {
++    use std::fs::File;
+     use std::io::prelude::*;
+-    use std::io::SeekFrom;
++    use std::io::{BufRead, BufReader, SeekFrom};
+     use std::os::unix::prelude::*;
+ 
+     use libc::loff_t;
+ 
+     use nix::fcntl::*;
++    use nix::sys::stat::fstat;
+     use nix::sys::uio::IoVec;
+     use nix::unistd::{close, pipe, read, write};
+ 
+     use tempfile::{tempfile, NamedTempFile};
+ 
++    use crate::*;
++
+     /// This test creates a temporary file containing the contents
+     /// 'foobarbaz' and uses the `copy_file_range` call to transfer
+     /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
+@@ -198,6 +217,113 @@ mod linux_android {
+         let mut buf = [0u8; 200];
+         assert_eq!(100, read(fd, &mut buf).unwrap());
+     }
++
++    // The tests below are disabled for the listed targets
++    // due to OFD locks not being available in the kernel/libc
++    // versions used in the CI environment, probably because
++    // they run under QEMU.
++
++    #[test]
++    #[cfg(not(any(target_arch = "aarch64",
++                  target_arch = "arm",
++                  target_arch = "armv7",
++                  target_arch = "x86",
++                  target_arch = "mips",
++                  target_arch = "mips64",
++                  target_arch = "mips64el",
++                  target_arch = "powerpc64",
++                  target_arch = "powerpc64le",
++                  target_env = "musl")))]
++    fn test_ofd_write_lock() {
++        let tmp = NamedTempFile::new().unwrap();
++
++        let fd = tmp.as_raw_fd();
++        let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
++        if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
++            // OverlayFS is a union file system.  It returns one inode value in
++            // stat(2), but a different one shows up in /proc/locks.  So we must
++            // skip the test.
++            skip!("/proc/locks does not work on overlayfs");
++        }
++        let inode = fstat(fd).expect("fstat failed").st_ino as usize;
++
++        let mut flock = libc::flock {
++            l_type: libc::F_WRLCK as libc::c_short,
++            l_whence: libc::SEEK_SET as libc::c_short,
++            l_start: 0,
++            l_len: 0,
++            l_pid: 0,
++        };
++        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
++        assert_eq!(
++            Some(("OFDLCK".to_string(), "WRITE".to_string())),
++            lock_info(inode)
++        );
++
++        flock.l_type = libc::F_UNLCK as libc::c_short;
++        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed");
++        assert_eq!(None, lock_info(inode));
++    }
++
++    #[test]
++    #[cfg(not(any(target_arch = "aarch64",
++                  target_arch = "arm",
++                  target_arch = "armv7",
++                  target_arch = "x86",
++                  target_arch = "mips",
++                  target_arch = "mips64",
++                  target_arch = "mips64el",
++                  target_arch = "powerpc64",
++                  target_arch = "powerpc64le",
++                  target_env = "musl")))]
++    fn test_ofd_read_lock() {
++        let tmp = NamedTempFile::new().unwrap();
++
++        let fd = tmp.as_raw_fd();
++        let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
++        if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
++            // OverlayFS is a union file system.  It returns one inode value in
++            // stat(2), but a different one shows up in /proc/locks.  So we must
++            // skip the test.
++            skip!("/proc/locks does not work on overlayfs");
++        }
++        let inode = fstat(fd).expect("fstat failed").st_ino as usize;
++
++        let mut flock = libc::flock {
++            l_type: libc::F_RDLCK as libc::c_short,
++            l_whence: libc::SEEK_SET as libc::c_short,
++            l_start: 0,
++            l_len: 0,
++            l_pid: 0,
++        };
++        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
++        assert_eq!(
++            Some(("OFDLCK".to_string(), "READ".to_string())),
++            lock_info(inode)
++        );
++
++        flock.l_type = libc::F_UNLCK as libc::c_short;
++        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed");
++        assert_eq!(None, lock_info(inode));
++    }
++
++    fn lock_info(inode: usize) -> Option<(String, String)> {
++        let file = File::open("/proc/locks").expect("open /proc/locks failed");
++        let buf = BufReader::new(file);
++
++        for line in buf.lines() {
++            let line = line.unwrap();
++            let parts: Vec<_> = line.split_whitespace().collect();
++            let lock_type = parts[1];
++            let lock_access = parts[3];
++            let ino_parts: Vec<_> = parts[5].split(':').collect();
++            let ino: usize = ino_parts[2].parse().unwrap();
++            if ino == inode {
++                return Some((lock_type.to_string(), lock_access.to_string()));
++            }
++        }
++        None
++    }
+ }
+ 
+ #[cfg(any(target_os = "linux",
+@@ -206,7 +332,7 @@ mod linux_android {
+           target_os = "fuchsia",
+           any(target_os = "wasi", target_env = "wasi"),
+           target_env = "uclibc",
+-          target_env = "freebsd"))]
++          target_os = "freebsd"))]
+ mod test_posix_fadvise {
+ 
+     use tempfile::NamedTempFile;
+@@ -232,3 +358,60 @@ mod test_posix_fadvise {
+         assert_eq!(errno, Errno::ESPIPE as i32);
+     }
+ }
++
++#[cfg(any(target_os = "linux",
++          target_os = "android",
++          target_os = "emscripten",
++          target_os = "fuchsia",
++          any(target_os = "wasi", target_env = "wasi"),
++          target_os = "freebsd"))]
++mod test_posix_fallocate {
++
++    use tempfile::NamedTempFile;
++    use std::{io::Read, os::unix::io::{RawFd, AsRawFd}};
++    use nix::errno::Errno;
++    use nix::fcntl::*;
++    use nix::unistd::pipe;
++
++    #[test]
++    fn success() {
++        const LEN: usize = 100;
++        let mut tmp = NamedTempFile::new().unwrap();
++        let fd = tmp.as_raw_fd();
++        let res = posix_fallocate(fd, 0, LEN as libc::off_t);
++        match res {
++            Ok(_) => {
++                let mut data = [1u8; LEN];
++                assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
++                assert_eq!(&data[..], &[0u8; LEN][..]);
++            }
++            Err(nix::Error::Sys(Errno::EINVAL)) => {
++                // POSIX requires posix_fallocate to return EINVAL both for
++                // invalid arguments (i.e. len < 0) and if the operation is not
++                // supported by the file system.
++                // There's no way to tell for sure whether the file system
++                // supports posix_fallocate, so we must pass the test if it
++                // returns EINVAL.
++            }
++            _ => res.unwrap(),
++        }
++    }
++
++    #[test]
++    fn errno() {
++        let (rd, _wr) = pipe().unwrap();
++        let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
++        use nix::Error::Sys;
++        match err {
++            Sys(Errno::EINVAL)
++                | Sys(Errno::ENODEV)
++                | Sys(Errno::ESPIPE)
++                | Sys(Errno::EBADF) => (),
++            errno =>
++                panic!(
++                    "unexpected errno {}",
++                    errno,
++                ),
++        }
++    }
++}
+diff --git a/third_party/rust/nix/test/test_kmod/mod.rs b/third_party/rust/nix/test/test_kmod/mod.rs
+index ad406357b06d2..fb7260ba9c9d9 100644
+--- a/third_party/rust/nix/test/test_kmod/mod.rs
++++ b/third_party/rust/nix/test/test_kmod/mod.rs
+@@ -2,9 +2,10 @@ use std::fs::copy;
+ use std::path::PathBuf;
+ use std::process::Command;
+ use tempfile::{tempdir, TempDir};
++use crate::*;
+ 
+ fn compile_kernel_module() -> (PathBuf, String, TempDir) {
+-    let _m = ::FORK_MTX
++    let _m = crate::FORK_MTX
+         .lock()
+         .expect("Mutex got poisoned by another test");
+ 
+@@ -41,8 +42,8 @@ use std::io::Read;
+ #[test]
+ fn test_finit_and_delete_module() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
+ 
+@@ -59,8 +60,8 @@ fn test_finit_and_delete_module() {
+ #[test]
+ fn test_finit_and_delete_modul_with_params() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
+ 
+@@ -80,8 +81,8 @@ fn test_finit_and_delete_modul_with_params() {
+ #[test]
+ fn test_init_and_delete_module() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
+ 
+@@ -100,8 +101,8 @@ fn test_init_and_delete_module() {
+ #[test]
+ fn test_init_and_delete_module_with_params() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
+ 
+@@ -121,8 +122,8 @@ fn test_init_and_delete_module_with_params() {
+ #[test]
+ fn test_finit_module_invalid() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let kmod_path = "/dev/zero";
+ 
+@@ -135,8 +136,8 @@ fn test_finit_module_invalid() {
+ #[test]
+ fn test_finit_module_twice_and_delete_module() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
+ 
+@@ -157,8 +158,8 @@ fn test_finit_module_twice_and_delete_module() {
+ #[test]
+ fn test_delete_module_not_loaded() {
+     require_capability!(CAP_SYS_MODULE);
+-    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
+-    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
+ 
+     let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
+ 
+diff --git a/third_party/rust/nix/test/test_mount.rs b/third_party/rust/nix/test/test_mount.rs
+index d2e08bc42855d..c1b6c8a3bf2d2 100644
+--- a/third_party/rust/nix/test/test_mount.rs
++++ b/third_party/rust/nix/test/test_mount.rs
+@@ -1,12 +1,10 @@
++mod common;
++
+ // Impelmentation note: to allow unprivileged users to run it, this test makes
+ // use of user and mount namespaces. On systems that allow unprivileged user
+ // namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
+ // without root.
+ 
+-extern crate libc;
+-extern crate nix;
+-extern crate tempfile;
+-
+ #[cfg(target_os = "linux")]
+ mod test_mount {
+     use std::fs::{self, File};
+@@ -226,6 +224,7 @@ fn main() {
+     use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx,
+                      test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec,
+                      test_mount_bind};
++    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1351");
+     setup_namespaces();
+ 
+     run_tests!(test_mount_tmpfs_without_flags_allows_rwx,
+diff --git a/third_party/rust/nix/test/test_mq.rs b/third_party/rust/nix/test/test_mq.rs
+index caac4fc261cd6..1667a35b1a04b 100644
+--- a/third_party/rust/nix/test/test_mq.rs
++++ b/third_party/rust/nix/test/test_mq.rs
+@@ -1,17 +1,15 @@
+-use libc::c_long;
+-
+ use std::ffi::CString;
+ use std::str;
+ 
+ use nix::errno::Errno::*;
+ use nix::Error::Sys;
+-use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive};
++use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
+ use nix::mqueue::{MqAttr, MQ_OFlag};
+ use nix::sys::stat::Mode;
+ 
+ #[test]
+ fn test_mq_send_and_receive() {
+-    const MSG_SIZE: c_long =  32;
++    const MSG_SIZE: mq_attr_member_t = 32;
+     let attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
+     let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
+ 
+@@ -31,7 +29,7 @@ fn test_mq_send_and_receive() {
+     let mut buf = [0u8; 32];
+     let mut prio = 0u32;
+     let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
+-    assert!(prio == 1);
++    assert_eq!(prio, 1);
+ 
+     mq_close(mqd1).unwrap();
+     mq_close(mqd0).unwrap();
+@@ -43,7 +41,7 @@ fn test_mq_send_and_receive() {
+ #[cfg(not(any(target_os = "netbsd")))]
+ fn test_mq_getattr() {
+     use nix::mqueue::mq_getattr;
+-    const MSG_SIZE: c_long =  32;
++    const MSG_SIZE: mq_attr_member_t = 32;
+     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
+     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
+     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
+@@ -66,7 +64,7 @@ fn test_mq_getattr() {
+ #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+ fn test_mq_setattr() {
+     use nix::mqueue::{mq_getattr, mq_setattr};
+-    const MSG_SIZE: c_long =  32;
++    const MSG_SIZE: mq_attr_member_t = 32;
+     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
+     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
+     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
+@@ -87,7 +85,7 @@ fn test_mq_setattr() {
+     // O_NONBLOCK can be set (see tests below)
+     assert_ne!(new_attr_get, new_attr);
+ 
+-    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0);
++    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0);
+     mq_setattr(mqd, &new_attr_non_blocking).unwrap();
+     let new_attr_get = mq_getattr(mqd).unwrap();
+ 
+@@ -103,7 +101,7 @@ fn test_mq_setattr() {
+ #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
+ fn test_mq_set_nonblocking() {
+     use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
+-    const MSG_SIZE: c_long =  32;
++    const MSG_SIZE: mq_attr_member_t = 32;
+     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
+     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
+     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
+@@ -116,10 +114,10 @@ fn test_mq_set_nonblocking() {
+     let mqd = r.unwrap();
+     mq_set_nonblock(mqd).unwrap();
+     let new_attr = mq_getattr(mqd);
+-    assert!(new_attr.unwrap().flags() == MQ_OFlag::O_NONBLOCK.bits() as c_long);
++    assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t);
+     mq_remove_nonblock(mqd).unwrap();
+     let new_attr = mq_getattr(mqd);
+-    assert!(new_attr.unwrap().flags() == 0);
++    assert_eq!(new_attr.unwrap().flags(), 0);
+     mq_close(mqd).unwrap();
+ }
+ 
+@@ -127,7 +125,7 @@ fn test_mq_set_nonblocking() {
+ #[cfg(not(any(target_os = "netbsd")))]
+ fn test_mq_unlink() {
+     use nix::mqueue::mq_unlink;
+-    const MSG_SIZE: c_long =  32;
++    const MSG_SIZE: mq_attr_member_t = 32;
+     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
+     let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
+     let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
+@@ -141,12 +139,12 @@ fn test_mq_unlink() {
+     let mqd = r.unwrap();
+ 
+     let res_unlink = mq_unlink(mq_name_opened);
+-    assert!(res_unlink == Ok(()) );
++    assert_eq!(res_unlink, Ok(()) );
+ 
+     let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
+-    assert!(res_unlink_not_opened == Err(Sys(ENOENT)) );
++    assert_eq!(res_unlink_not_opened, Err(Sys(ENOENT)) );
+ 
+     mq_close(mqd).unwrap();
+     let res_unlink_after_close = mq_unlink(mq_name_opened);
+-    assert!(res_unlink_after_close == Err(Sys(ENOENT)) );
++    assert_eq!(res_unlink_after_close, Err(Sys(ENOENT)) );
+ }
+diff --git a/third_party/rust/nix/test/test_poll.rs b/third_party/rust/nix/test/test_poll.rs
+index aef40e4792b5a..acfaad8bea6c0 100644
+--- a/third_party/rust/nix/test/test_poll.rs
++++ b/third_party/rust/nix/test/test_poll.rs
+@@ -1,5 +1,21 @@
+-use nix::poll::{PollFlags, poll, PollFd};
+-use nix::unistd::{write, pipe};
++use nix::{
++    Error,
++    errno::Errno,
++    poll::{PollFlags, poll, PollFd},
++    unistd::{write, pipe}
++};
++
++macro_rules! loop_while_eintr {
++    ($poll_expr: expr) => {
++        loop {
++            match $poll_expr {
++                Ok(nfds) => break nfds,
++                Err(Error::Sys(Errno::EINTR)) => (),
++                Err(e) => panic!("{}", e)
++            }
++        }
++    }
++}
+ 
+ #[test]
+ fn test_poll() {
+@@ -7,7 +23,7 @@ fn test_poll() {
+     let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
+ 
+     // Poll an idle pipe.  Should timeout
+-    let nfds = poll(&mut fds, 100).unwrap();
++    let nfds = loop_while_eintr!(poll(&mut fds, 100));
+     assert_eq!(nfds, 0);
+     assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
+ 
+@@ -37,14 +53,15 @@ fn test_ppoll() {
+     let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
+ 
+     // Poll an idle pipe.  Should timeout
+-    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
++    let sigset = SigSet::empty();
++    let nfds = loop_while_eintr!(ppoll(&mut fds, Some(timeout), sigset));
+     assert_eq!(nfds, 0);
+     assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
+ 
+     write(w, b".").unwrap();
+ 
+     // Poll a readable pipe.  Should return an event.
+-    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
++    let nfds = ppoll(&mut fds, Some(timeout), SigSet::empty()).unwrap();
+     assert_eq!(nfds, 1);
+     assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
+ }
+diff --git a/third_party/rust/nix/test/test_pty.rs b/third_party/rust/nix/test/test_pty.rs
+index 476b15c10128c..ab347bb040f5f 100644
+--- a/third_party/rust/nix/test/test_pty.rs
++++ b/third_party/rust/nix/test/test_pty.rs
+@@ -1,4 +1,5 @@
+-use std::io::Write;
++use std::fs::File;
++use std::io::{Read, Write};
+ use std::path::Path;
+ use std::os::unix::prelude::*;
+ use tempfile::tempfile;
+@@ -28,7 +29,7 @@ fn test_explicit_close() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptsname_equivalence() {
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open a new PTTY master
+     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
+@@ -45,7 +46,7 @@ fn test_ptsname_equivalence() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptsname_copy() {
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open a new PTTY master
+     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
+@@ -54,7 +55,7 @@ fn test_ptsname_copy() {
+     // Get the name of the slave
+     let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
+     let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
+-    assert!(slave_name1 == slave_name2);
++    assert_eq!(slave_name1, slave_name2);
+     // Also make sure that the string was actually copied and they point to different parts of
+     // memory.
+     assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
+@@ -71,7 +72,7 @@ fn test_ptsname_r_copy() {
+     // Get the name of the slave
+     let slave_name1 = ptsname_r(&master_fd).unwrap();
+     let slave_name2 = ptsname_r(&master_fd).unwrap();
+-    assert!(slave_name1 == slave_name2);
++    assert_eq!(slave_name1, slave_name2);
+     assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
+ }
+ 
+@@ -79,7 +80,7 @@ fn test_ptsname_r_copy() {
+ #[test]
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ fn test_ptsname_unique() {
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open a new PTTY master
+     let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
+@@ -95,35 +96,74 @@ fn test_ptsname_unique() {
+     assert!(slave_name1 != slave_name2);
+ }
+ 
+-/// Test opening a master/slave PTTY pair
+-///
+-/// This is a single larger test because much of these functions aren't useful by themselves. So for
+-/// this test we perform the basic act of getting a file handle for a connect master/slave PTTY
+-/// pair.
+-#[test]
+-fn test_open_ptty_pair() {
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++/// Common setup for testing PTTY pairs
++fn open_ptty_pair() -> (PtyMaster, File) {
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open a new PTTY master
+-    let master_fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
+-    assert!(master_fd.as_raw_fd() > 0);
++    let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
+ 
+     // Allow a slave to be generated for it
+-    grantpt(&master_fd).expect("grantpt failed");
+-    unlockpt(&master_fd).expect("unlockpt failed");
++    grantpt(&master).expect("grantpt failed");
++    unlockpt(&master).expect("unlockpt failed");
+ 
+     // Get the name of the slave
+-    let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed");
++    let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed");
+ 
+     // Open the slave device
+     let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
+-    assert!(slave_fd > 0);
++    let slave = unsafe { File::from_raw_fd(slave_fd) };
++
++    (master, slave)
++}
++
++/// Test opening a master/slave PTTY pair
++///
++/// This uses a common `open_ptty_pair` because much of these functions aren't useful by
++/// themselves. So for this test we perform the basic act of getting a file handle for a
++/// master/slave PTTY pair, then just sanity-check the raw values.
++#[test]
++fn test_open_ptty_pair() {
++    let (master, slave) = open_ptty_pair();
++    assert!(master.as_raw_fd() > 0);
++    assert!(slave.as_raw_fd() > 0);
++}
++
++/// Put the terminal in raw mode.
++fn make_raw(fd: RawFd) {
++    let mut termios = tcgetattr(fd).unwrap();
++    cfmakeraw(&mut termios);
++    tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap();
++}
++
++/// Test `io::Read` on the PTTY master
++#[test]
++fn test_read_ptty_pair() {
++    let (mut master, mut slave) = open_ptty_pair();
++    make_raw(slave.as_raw_fd());
++
++    let mut buf = [0u8; 5];
++    slave.write_all(b"hello").unwrap();
++    master.read_exact(&mut buf).unwrap();
++    assert_eq!(&buf, b"hello");
++}
++
++/// Test `io::Write` on the PTTY master
++#[test]
++fn test_write_ptty_pair() {
++    let (mut master, mut slave) = open_ptty_pair();
++    make_raw(slave.as_raw_fd());
++
++    let mut buf = [0u8; 5];
++    master.write_all(b"adios").unwrap();
++    slave.read_exact(&mut buf).unwrap();
++    assert_eq!(&buf, b"adios");
+ }
+ 
+ #[test]
+ fn test_openpty() {
+     // openpty uses ptname(3) internally
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     let pty = openpty(None, None).unwrap();
+     assert!(pty.master > 0);
+@@ -133,21 +173,21 @@ fn test_openpty() {
+     let string = "foofoofoo\n";
+     let mut buf = [0u8; 10];
+     write(pty.master, string.as_bytes()).unwrap();
+-    ::read_exact(pty.slave, &mut buf);
++    crate::read_exact(pty.slave, &mut buf);
+ 
+     assert_eq!(&buf, string.as_bytes());
+ 
+     // Read the echo as well
+     let echoed_string = "foofoofoo\r\n";
+     let mut buf = [0u8; 11];
+-    ::read_exact(pty.master, &mut buf);
++    crate::read_exact(pty.master, &mut buf);
+     assert_eq!(&buf, echoed_string.as_bytes());
+ 
+     let string2 = "barbarbarbar\n";
+     let echoed_string2 = "barbarbarbar\r\n";
+     let mut buf = [0u8; 14];
+     write(pty.slave, string2.as_bytes()).unwrap();
+-    ::read_exact(pty.master, &mut buf);
++    crate::read_exact(pty.master, &mut buf);
+ 
+     assert_eq!(&buf, echoed_string2.as_bytes());
+ 
+@@ -158,14 +198,14 @@ fn test_openpty() {
+ #[test]
+ fn test_openpty_with_termios() {
+     // openpty uses ptname(3) internally
+-    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Open one pty to get attributes for the second one
+     let mut termios = {
+         let pty = openpty(None, None).unwrap();
+         assert!(pty.master > 0);
+         assert!(pty.slave > 0);
+-        let termios = tcgetattr(pty.master).unwrap();
++        let termios = tcgetattr(pty.slave).unwrap();
+         close(pty.master).unwrap();
+         close(pty.slave).unwrap();
+         termios
+@@ -182,20 +222,20 @@ fn test_openpty_with_termios() {
+     let string = "foofoofoo\n";
+     let mut buf = [0u8; 10];
+     write(pty.master, string.as_bytes()).unwrap();
+-    ::read_exact(pty.slave, &mut buf);
++    crate::read_exact(pty.slave, &mut buf);
+ 
+     assert_eq!(&buf, string.as_bytes());
+ 
+     // read the echo as well
+     let echoed_string = "foofoofoo\n";
+-    ::read_exact(pty.master, &mut buf);
++    crate::read_exact(pty.master, &mut buf);
+     assert_eq!(&buf, echoed_string.as_bytes());
+ 
+     let string2 = "barbarbarbar\n";
+     let echoed_string2 = "barbarbarbar\n";
+     let mut buf = [0u8; 13];
+     write(pty.slave, string2.as_bytes()).unwrap();
+-    ::read_exact(pty.master, &mut buf);
++    crate::read_exact(pty.master, &mut buf);
+ 
+     assert_eq!(&buf, echoed_string2.as_bytes());
+ 
+@@ -209,9 +249,9 @@ fn test_forkpty() {
+     use nix::sys::signal::*;
+     use nix::sys::wait::wait;
+     // forkpty calls openpty which uses ptname(3) internally.
+-    let _m0 = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m0 = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
+     // forkpty spawns a child process
+-    let _m1 = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m1 = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     let string = "naninani\n";
+     let echoed_string = "naninani\r\n";
+@@ -225,7 +265,7 @@ fn test_forkpty() {
+         Parent { child } => {
+             let mut buf = [0u8; 10];
+             assert!(child.as_raw() > 0);
+-            ::read_exact(pty.master, &mut buf);
++            crate::read_exact(pty.master, &mut buf);
+             kill(child, SIGTERM).unwrap();
+             wait().unwrap(); // keep other tests using generic wait from getting our child
+             assert_eq!(&buf, echoed_string.as_bytes());
+diff --git a/third_party/rust/nix/test/test_ptymaster_drop.rs b/third_party/rust/nix/test/test_ptymaster_drop.rs
+index 9b59d66435ed0..ff939b9c63e76 100644
+--- a/third_party/rust/nix/test/test_ptymaster_drop.rs
++++ b/third_party/rust/nix/test/test_ptymaster_drop.rs
+@@ -1,21 +1,24 @@
+-extern crate nix;
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++mod t {
++    use nix::fcntl::OFlag;
++    use nix::pty::*;
++    use nix::unistd::close;
++    use std::os::unix::io::AsRawFd;
+ 
+-use nix::fcntl::OFlag;
+-use nix::pty::*;
+-use nix::unistd::close;
+-use std::os::unix::io::AsRawFd;
+-
+-/// Regression test for Issue #659
+-/// `PtyMaster` should panic rather than double close the file descriptor
+-/// This must run in its own test process because it deliberately creates a race
+-/// condition.
+-#[test]
+-#[should_panic(expected = "Closing an invalid file descriptor!")]
+-// In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't know
+-// why.  It doesn't happen on any other target, and it doesn't happen on my PC.
+-#[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
+-fn test_double_close() {
+-    let m = posix_openpt(OFlag::O_RDWR).unwrap();
+-    close(m.as_raw_fd()).unwrap();
+-    drop(m);            // should panic here
++    /// Regression test for Issue #659
++    ///
++    /// `PtyMaster` should panic rather than double close the file descriptor
++    /// This must run in its own test process because it deliberately creates a
++    /// race condition.
++    #[test]
++    #[should_panic(expected = "Closing an invalid file descriptor!")]
++    // In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't
++    // know why.  It doesn't happen on any other target, and it doesn't happen
++    // on my PC.
++    #[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
++    fn test_double_close() {
++        let m = posix_openpt(OFlag::O_RDWR).unwrap();
++        close(m.as_raw_fd()).unwrap();
++        drop(m);            // should panic here
++    }
+ }
+diff --git a/third_party/rust/nix/test/test_sched.rs b/third_party/rust/nix/test/test_sched.rs
+new file mode 100644
+index 0000000000000..922196a3dba73
+--- /dev/null
++++ b/third_party/rust/nix/test/test_sched.rs
+@@ -0,0 +1,32 @@
++use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet};
++use nix::unistd::Pid;
++
++#[test]
++fn test_sched_affinity() {
++    // If pid is zero, then the mask of the calling process is returned.
++    let initial_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
++    let mut at_least_one_cpu = false;
++    let mut last_valid_cpu = 0;
++    for field in 0..CpuSet::count() {
++        if initial_affinity.is_set(field).unwrap() {
++            at_least_one_cpu = true;
++            last_valid_cpu = field;
++        }
++    }
++    assert!(at_least_one_cpu);
++
++    // Now restrict the running CPU
++    let mut new_affinity = CpuSet::new();
++    new_affinity.set(last_valid_cpu).unwrap();
++    sched_setaffinity(Pid::from_raw(0), &new_affinity).unwrap();
++
++    // And now re-check the affinity which should be only the one we set.
++    let updated_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
++    for field in 0..CpuSet::count() {
++        // Should be set only for the CPU we set previously
++        assert_eq!(updated_affinity.is_set(field).unwrap(), field==last_valid_cpu)
++    }
++
++    // Finally, reset the initial CPU set
++    sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap();
++}
+diff --git a/third_party/rust/nix/test/test_stat.rs b/third_party/rust/nix/test/test_stat.rs
+index 1173455fae8db..0b9466685607b 100644
+--- a/third_party/rust/nix/test/test_stat.rs
++++ b/third_party/rust/nix/test/test_stat.rs
+@@ -1,15 +1,26 @@
+-use std::fs::{self, File};
++#[cfg(not(target_os = "redox"))]
++use std::fs;
++use std::fs::File;
++#[cfg(not(target_os = "redox"))]
+ use std::os::unix::fs::{symlink, PermissionsExt};
+ use std::os::unix::prelude::AsRawFd;
++#[cfg(not(target_os = "redox"))]
+ use std::time::{Duration, UNIX_EPOCH};
++#[cfg(not(target_os = "redox"))]
+ use std::path::Path;
+ 
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ use libc::{S_IFMT, S_IFLNK, mode_t};
+ 
++#[cfg(not(target_os = "redox"))]
+ use nix::{fcntl, Error};
+-use nix::errno::{Errno};
+-use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
++#[cfg(not(target_os = "redox"))]
++use nix::errno::Errno;
++#[cfg(not(target_os = "redox"))]
++use nix::sys::stat::{self, futimens, utimes};
++use nix::sys::stat::{fchmod, stat};
++#[cfg(not(target_os = "redox"))]
++use nix::sys::stat::{fchmodat, utimensat, mkdirat};
+ #[cfg(any(target_os = "linux",
+           target_os = "haiku",
+           target_os = "ios",
+@@ -17,15 +28,19 @@ use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat,
+           target_os = "freebsd",
+           target_os = "netbsd"))]
+ use nix::sys::stat::lutimes;
+-use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags};
++#[cfg(not(target_os = "redox"))]
++use nix::sys::stat::{FchmodatFlags, UtimensatFlags};
++use nix::sys::stat::Mode;
+ 
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ use nix::sys::stat::FileStat;
+ 
++#[cfg(not(target_os = "redox"))]
+ use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
++#[cfg(not(target_os = "redox"))]
+ use nix::unistd::chdir;
+ 
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ use nix::Result;
+ use tempfile;
+ 
+@@ -33,27 +48,27 @@ use tempfile;
+ // uid and gid are signed on Windows, but not on other platforms. This function
+ // allows warning free compiles on all platforms, and can be removed when
+ // expression-level #[allow] is available.
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn valid_uid_gid(stat: FileStat) -> bool {
+     // uid could be 0 for the `root` user. This quite possible when
+     // the tests are being run on a rooted Android device.
+     stat.st_uid >= 0 && stat.st_gid >= 0
+ }
+ 
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn assert_stat_results(stat_result: Result<FileStat>) {
+     let stats = stat_result.expect("stat call failed");
+     assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
+     assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
+     assert!(stats.st_mode > 0);     // must be positive integer
+-    assert!(stats.st_nlink == 1);   // there links created, must be 1
++    assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
+     assert!(valid_uid_gid(stats));  // must be positive integers
+-    assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
++    assert_eq!(stats.st_size, 0);    // size is 0 because we did not write anything to the file
+     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
+     assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
+ }
+ 
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn assert_lstat_results(stat_result: Result<FileStat>) {
+     let stats = stat_result.expect("stat call failed");
+     assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
+@@ -63,8 +78,8 @@ fn assert_lstat_results(stat_result: Result<FileStat>) {
+     // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
+     // (u16 on Android), and that will be a compile error.
+     // On other platforms they are the same (either both are u16 or u32).
+-    assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
+-    assert!(stats.st_nlink == 1);   // there links created, must be 1
++    assert_eq!((stats.st_mode as usize) & (S_IFMT as usize), S_IFLNK as usize); // should be a link
++    assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
+     assert!(valid_uid_gid(stats));  // must be positive integers
+     assert!(stats.st_size > 0);    // size is > 0 because it points to another file
+     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
+@@ -76,7 +91,7 @@ fn assert_lstat_results(stat_result: Result<FileStat>) {
+ }
+ 
+ #[test]
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn test_stat_and_fstat() {
+     use nix::sys::stat::fstat;
+ 
+@@ -92,7 +107,7 @@ fn test_stat_and_fstat() {
+ }
+ 
+ #[test]
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn test_fstatat() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let filename = tempdir.path().join("foo.txt");
+@@ -108,7 +123,7 @@ fn test_fstatat() {
+ }
+ 
+ #[test]
+-#[cfg(not(any(target_os = "netbsd")))]
++#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
+ fn test_stat_fstat_lstat() {
+     use nix::sys::stat::{fstat, lstat};
+ 
+@@ -155,8 +170,9 @@ fn test_fchmod() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_fchmodat() {
+-    let _dr = ::DirRestore::new();
++    let _dr = crate::DirRestore::new();
+     let tempdir = tempfile::tempdir().unwrap();
+     let filename = "foo.txt";
+     let fullpath = tempdir.path().join(filename);
+@@ -186,6 +202,7 @@ fn test_fchmodat() {
+ ///
+ /// The atime and mtime are expressed with a resolution of seconds because some file systems
+ /// (like macOS's HFS+) do not have higher granularity.
++#[cfg(not(target_os = "redox"))]
+ fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
+     assert_eq!(
+         Duration::new(exp_atime_sec, 0),
+@@ -196,6 +213,7 @@ fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata)
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_utimes() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let fullpath = tempdir.path().join("file");
+@@ -231,6 +249,7 @@ fn test_lutimes() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_futimens() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let fullpath = tempdir.path().join("file");
+@@ -243,8 +262,9 @@ fn test_futimens() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_utimensat() {
+-    let _dr = ::DirRestore::new();
++    let _dr = crate::DirRestore::new();
+     let tempdir = tempfile::tempdir().unwrap();
+     let filename = "foo.txt";
+     let fullpath = tempdir.path().join(filename);
+@@ -264,6 +284,7 @@ fn test_utimensat() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_mkdirat_success_path() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let filename = "example_subdir";
+@@ -273,6 +294,7 @@ fn test_mkdirat_success_path() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_mkdirat_success_mode() {
+     let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
+     let tempdir = tempfile::tempdir().unwrap();
+@@ -285,6 +307,7 @@ fn test_mkdirat_success_mode() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_mkdirat_fail() {
+     let tempdir = tempfile::tempdir().unwrap();
+     let not_dir_filename= "example_not_dir";
+diff --git a/third_party/rust/nix/test/test_time.rs b/third_party/rust/nix/test/test_time.rs
+new file mode 100644
+index 0000000000000..c321352d79c16
+--- /dev/null
++++ b/third_party/rust/nix/test/test_time.rs
+@@ -0,0 +1,56 @@
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "dragonfly",
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++))]
++use nix::time::clock_getcpuclockid;
++use nix::time::{clock_getres, clock_gettime, ClockId};
++
++#[test]
++pub fn test_clock_getres() {
++    assert!(clock_getres(ClockId::CLOCK_REALTIME).is_ok());
++}
++
++#[test]
++pub fn test_clock_gettime() {
++    assert!(clock_gettime(ClockId::CLOCK_REALTIME).is_ok());
++}
++
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "dragonfly",
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++))]
++#[test]
++pub fn test_clock_getcpuclockid() {
++    let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap();
++    assert!(clock_gettime(clock_id).is_ok());
++}
++
++#[test]
++pub fn test_clock_id_res() {
++    assert!(ClockId::CLOCK_REALTIME.res().is_ok());
++}
++
++#[test]
++pub fn test_clock_id_now() {
++    assert!(ClockId::CLOCK_REALTIME.now().is_ok());
++}
++
++#[cfg(any(
++    target_os = "freebsd",
++    target_os = "dragonfly",
++    target_os = "linux",
++    target_os = "android",
++    target_os = "emscripten",
++))]
++#[test]
++pub fn test_clock_id_pid_cpu_clock_id() {
++    assert!(ClockId::pid_cpu_clock_id(nix::unistd::Pid::this())
++        .map(ClockId::now)
++        .is_ok());
++}
+diff --git a/third_party/rust/nix/test/test_unistd.rs b/third_party/rust/nix/test/test_unistd.rs
+index 46196dec7ccce..16a8a05dd6d08 100644
+--- a/third_party/rust/nix/test/test_unistd.rs
++++ b/third_party/rust/nix/test/test_unistd.rs
+@@ -1,26 +1,39 @@
+-use nix::fcntl::{self, fcntl, FcntlArg, FdFlag, open, OFlag, readlink};
++#[cfg(not(target_os = "redox"))]
++use nix::fcntl::{self, open, readlink};
++use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
+ use nix::unistd::*;
+ use nix::unistd::ForkResult::*;
++#[cfg(not(target_os = "redox"))]
+ use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
+ use nix::sys::wait::*;
+ use nix::sys::stat::{self, Mode, SFlag};
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname};
+ use nix::errno::Errno;
++#[cfg(not(target_os = "redox"))]
+ use nix::Error;
+ use std::{env, iter};
++#[cfg(not(target_os = "redox"))]
+ use std::ffi::CString;
+-use std::fs::{self, DirBuilder, File};
++#[cfg(not(target_os = "redox"))]
++use std::fs::DirBuilder;
++use std::fs::{self, File};
+ use std::io::Write;
+ use std::os::unix::prelude::*;
+-use tempfile::{self, tempfile};
+-use libc::{self, _exit, off_t};
++#[cfg(not(target_os = "redox"))]
++use std::path::Path;
++use tempfile::{tempdir, tempfile};
++use libc::{_exit, off_t};
++
++use crate::*;
+ 
+ #[test]
+ #[cfg(not(any(target_os = "netbsd")))]
+ fn test_fork_and_waitpid() {
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Safe: Child only calls `_exit`, which is signal-safe
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+         Child => unsafe { _exit(0) },
+         Parent { child } => {
+             // assert that child was created and pid > 0
+@@ -29,7 +42,7 @@ fn test_fork_and_waitpid() {
+             let wait_status = waitpid(child, None);
+             match wait_status {
+                 // assert that waitpid returned correct status and the pid is the one of the child
+-                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),
++                Ok(WaitStatus::Exited(pid_t, _)) =>  assert_eq!(pid_t, child),
+ 
+                 // panic, must never happen
+                 s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
+@@ -45,10 +58,10 @@ fn test_fork_and_waitpid() {
+ #[test]
+ fn test_wait() {
+     // Grab FORK_MTX so wait doesn't reap a different test's child process
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Safe: Child only calls `_exit`, which is signal-safe
+-    match fork().expect("Error: Fork Failed") {
++    match unsafe{fork()}.expect("Error: Fork Failed") {
+         Child => unsafe { _exit(0) },
+         Parent { child } => {
+             let wait_status = wait();
+@@ -81,8 +94,9 @@ fn test_mkstemp_directory() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_mkfifo() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let mkfifo_fifo = tempdir.path().join("mkfifo_fifo");
+ 
+     mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
+@@ -93,11 +107,70 @@ fn test_mkfifo() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_mkfifo_directory() {
+     // mkfifo should fail if a directory is given
+     assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err());
+ }
+ 
++#[test]
++#[cfg(not(any(
++    target_os = "macos", target_os = "ios",
++    target_os = "android", target_os = "redox")))]
++fn test_mkfifoat_none() {
++    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let tempdir = tempdir().unwrap();
++    let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo");
++
++    mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap();
++
++    let stats = stat::stat(&mkfifoat_fifo).unwrap();
++    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
++    assert_eq!(typ, SFlag::S_IFIFO);
++}
++
++#[test]
++#[cfg(not(any(
++    target_os = "macos", target_os = "ios",
++    target_os = "android", target_os = "redox")))]
++fn test_mkfifoat() {
++    let tempdir = tempdir().unwrap();
++    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
++    let mkfifoat_name = "mkfifoat_name";
++
++    mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
++
++    let stats = stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
++    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
++    assert_eq!(typ, SFlag::S_IFIFO);
++}
++
++#[test]
++#[cfg(not(any(
++    target_os = "macos", target_os = "ios",
++    target_os = "android", target_os = "redox")))]
++fn test_mkfifoat_directory_none() {
++    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    // mkfifoat should fail if a directory is given
++    assert!(!mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_ok());
++}
++
++#[test]
++#[cfg(not(any(
++    target_os = "macos", target_os = "ios",
++    target_os = "android", target_os = "redox")))]
++fn test_mkfifoat_directory() {
++    // mkfifoat should fail if a directory is given
++    let tempdir = tempdir().unwrap();
++    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
++    let mkfifoat_dir = "mkfifoat_dir";
++    stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
++
++    assert!(!mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_ok());
++}
++
+ #[test]
+ fn test_getpid() {
+     let pid: ::libc::pid_t = getpid().into();
+@@ -107,11 +180,12 @@ fn test_getpid() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_getsid() {
+     let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
+     let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
+     assert!(none_sid > 0);
+-    assert!(none_sid == pid_sid);
++    assert_eq!(none_sid, pid_sid);
+ }
+ 
+ #[cfg(any(target_os = "linux", target_os = "android"))]
+@@ -127,12 +201,12 @@ mod linux_android {
+ 
+ #[test]
+ // `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
+-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
+ fn test_setgroups() {
+     // Skip this test when not run as root as `setgroups()` requires root.
+     skip_if_not_root!("test_setgroups");
+ 
+-    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Save the existing groups
+     let old_groups = getgroups().unwrap();
+@@ -150,13 +224,13 @@ fn test_setgroups() {
+ 
+ #[test]
+ // `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
+-#[cfg(not(any(target_os = "ios", target_os = "macos")))]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
+ fn test_initgroups() {
+     // Skip this test when not run as root as `initgroups()` and `setgroups()`
+     // require root.
+     skip_if_not_root!("test_initgroups");
+ 
+-    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     // Save the existing groups
+     let old_groups = getgroups().unwrap();
+@@ -180,11 +254,53 @@ fn test_initgroups() {
+     setgroups(&old_groups).unwrap();
+ }
+ 
++#[cfg(not(target_os = "redox"))]
+ macro_rules! execve_test_factory(
+     ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
+-    #[test]
+-    fn $test_name() {
+-        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++
++    #[cfg(test)]
++    mod $test_name {
++    use std::ffi::CStr;
++    use super::*;
++
++    const EMPTY: &'static [u8] = b"\0";
++    const DASH_C: &'static [u8] = b"-c\0";
++    const BIGARG: &'static [u8] = b"echo nix!!! && echo foo=$foo && echo baz=$baz\0";
++    const FOO: &'static [u8] = b"foo=bar\0";
++    const BAZ: &'static [u8] = b"baz=quux\0";
++
++    fn syscall_cstr_ref() -> Result<std::convert::Infallible, nix::Error> {
++        $syscall(
++            $exe,
++            $(CString::new($pathname).unwrap().as_c_str(), )*
++            &[CStr::from_bytes_with_nul(EMPTY).unwrap(),
++              CStr::from_bytes_with_nul(DASH_C).unwrap(),
++              CStr::from_bytes_with_nul(BIGARG).unwrap()],
++            &[CStr::from_bytes_with_nul(FOO).unwrap(),
++              CStr::from_bytes_with_nul(BAZ).unwrap()]
++            $(, $flags)*)
++    }
++
++    fn syscall_cstring() -> Result<std::convert::Infallible, nix::Error> {
++        $syscall(
++            $exe,
++            $(CString::new($pathname).unwrap().as_c_str(), )*
++            &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()),
++              CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()),
++              CString::from(CStr::from_bytes_with_nul(BIGARG).unwrap())],
++            &[CString::from(CStr::from_bytes_with_nul(FOO).unwrap()),
++              CString::from(CStr::from_bytes_with_nul(BAZ).unwrap())]
++            $(, $flags)*)
++    }
++
++    fn common_test(syscall: fn() -> Result<std::convert::Infallible, nix::Error>) {
++        if "execveat" == stringify!($syscall) {
++            // Though undocumented, Docker's default seccomp profile seems to
++            // block this syscall.  https://github.com/nix-rust/nix/issues/1122
++            skip_if_seccomp!($test_name);
++        }
++
++        let m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+         // The `exec`d process will write to `writer`, and we'll read that
+         // data from `reader`.
+         let (reader, writer) = pipe().unwrap();
+@@ -192,27 +308,21 @@ macro_rules! execve_test_factory(
+         // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
+         // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
+         //       The tests make sure not to do that, though.
+-        match fork().unwrap() {
++        match unsafe{fork()}.unwrap() {
+             Child => {
+-                // Close stdout.
+-                close(1).unwrap();
+                 // Make `writer` be the stdout of the new process.
+-                dup(writer).unwrap();
+-                // exec!
+-                $syscall(
+-                    $exe,
+-                    $(&CString::new($pathname).unwrap(), )*
+-                    &[CString::new(b"".as_ref()).unwrap(),
+-                      CString::new(b"-c".as_ref()).unwrap(),
+-                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
+-                                   .as_ref()).unwrap()],
+-                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
+-                      CString::new(b"baz=quux".as_ref()).unwrap()]
+-                    $(, $flags)*).unwrap();
++                dup2(writer, 1).unwrap();
++                let r = syscall();
++                let _ = std::io::stderr()
++                    .write_all(format!("{:?}", r).as_bytes());
++                // Should only get here in event of error
++                unsafe{ _exit(1) };
+             },
+             Parent { child } => {
+                 // Wait for the child to exit.
+-                waitpid(child, None).unwrap();
++                let ws = waitpid(child, None);
++                drop(m);
++                assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
+                 // Read 1024 bytes.
+                 let mut buf = [0u8; 1024];
+                 read(reader, &mut buf).unwrap();
+@@ -224,23 +334,43 @@ macro_rules! execve_test_factory(
+             }
+         }
+     }
++
++    // These tests frequently fail on musl, probably due to
++        // https://github.com/nix-rust/nix/issues/555
++    #[cfg_attr(target_env = "musl", ignore)]
++    #[test]
++    fn test_cstr_ref() {
++        common_test(syscall_cstr_ref);
++    }
++
++    // These tests frequently fail on musl, probably due to
++        // https://github.com/nix-rust/nix/issues/555
++    #[cfg_attr(target_env = "musl", ignore)]
++    #[test]
++    fn test_cstring() {
++        common_test(syscall_cstring);
++    }
++    }
++
+     )
+ );
+ 
+ cfg_if!{
+     if #[cfg(target_os = "android")] {
+-        execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
++        execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str());
+         execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
+     } else if #[cfg(any(target_os = "freebsd",
+                         target_os = "linux"))] {
+-        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
++        // These tests frequently fail on musl, probably due to
++        // https://github.com/nix-rust/nix/issues/555
++        execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
+         execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
+     } else if #[cfg(any(target_os = "dragonfly",
+                         target_os = "ios",
+                         target_os = "macos",
+                         target_os = "netbsd",
+                         target_os = "openbsd"))] {
+-        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
++        execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
+         // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
+         //
+         // Note for NetBSD and OpenBSD: although rust-lang/libc includes it
+@@ -255,13 +385,16 @@ execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
+ cfg_if!{
+     if #[cfg(target_os = "android")] {
+         use nix::fcntl::AtFlags;
+-        execve_test_factory!(test_execveat_empty, execveat, File::open("/system/bin/sh").unwrap().into_raw_fd(),
++        execve_test_factory!(test_execveat_empty, execveat,
++                             File::open("/system/bin/sh").unwrap().into_raw_fd(),
+                              "", AtFlags::AT_EMPTY_PATH);
+-        execve_test_factory!(test_execveat_relative, execveat, File::open("/system/bin/").unwrap().into_raw_fd(),
++        execve_test_factory!(test_execveat_relative, execveat,
++                             File::open("/system/bin/").unwrap().into_raw_fd(),
+                              "./sh", AtFlags::empty());
+-        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
++        execve_test_factory!(test_execveat_absolute, execveat,
++                             File::open("/").unwrap().into_raw_fd(),
+                              "/system/bin/sh", AtFlags::empty());
+-    } else if #[cfg(all(target_os = "linux"), any(target_arch ="x86_64", target_arch ="x86"))] {
++    } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
+         use nix::fcntl::AtFlags;
+         execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
+                              "", AtFlags::AT_EMPTY_PATH);
+@@ -273,11 +406,12 @@ cfg_if!{
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "fuchsia"))]
+ fn test_fchdir() {
+     // fchdir changes the process's cwd
+-    let _dr = ::DirRestore::new();
++    let _dr = crate::DirRestore::new();
+ 
+-    let tmpdir = tempfile::tempdir().unwrap();
++    let tmpdir = tempdir().unwrap();
+     let tmpdir_path = tmpdir.path().canonicalize().unwrap();
+     let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
+ 
+@@ -290,9 +424,9 @@ fn test_fchdir() {
+ #[test]
+ fn test_getcwd() {
+     // chdir changes the process's cwd
+-    let _dr = ::DirRestore::new();
++    let _dr = crate::DirRestore::new();
+ 
+-    let tmpdir = tempfile::tempdir().unwrap();
++    let tmpdir = tempdir().unwrap();
+     let tmpdir_path = tmpdir.path().canonicalize().unwrap();
+     assert!(chdir(&tmpdir_path).is_ok());
+     assert_eq!(getcwd().unwrap(), tmpdir_path);
+@@ -317,7 +451,7 @@ fn test_chown() {
+     let uid = Some(getuid());
+     let gid = Some(getgid());
+ 
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let path = tempdir.path().join("file");
+     {
+         File::create(&path).unwrap();
+@@ -332,13 +466,29 @@ fn test_chown() {
+ }
+ 
+ #[test]
++fn test_fchown() {
++    // Testing for anything other than our own UID/GID is hard.
++    let uid = Some(getuid());
++    let gid = Some(getgid());
++
++    let path = tempfile().unwrap();
++    let fd = path.as_raw_fd();
++
++    fchown(fd, uid, gid).unwrap();
++    fchown(fd, uid, None).unwrap();
++    fchown(fd, None, gid).unwrap();
++    fchown(999999999, uid, gid).unwrap_err();
++}
++
++#[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_fchownat() {
+-    let _dr = ::DirRestore::new();
++    let _dr = crate::DirRestore::new();
+     // Testing for anything other than our own UID/GID is hard.
+     let uid = Some(getuid());
+     let gid = Some(getgid());
+ 
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let path = tempdir.path().join("file");
+     {
+         File::create(&path).unwrap();
+@@ -366,7 +516,7 @@ fn test_lseek() {
+     lseek(tmpfd, offset, Whence::SeekSet).unwrap();
+ 
+     let mut buf = [0u8; 7];
+-    ::read_exact(tmpfd, &mut buf);
++    crate::read_exact(tmpfd, &mut buf);
+     assert_eq!(b"f123456", &buf);
+ 
+     close(tmpfd).unwrap();
+@@ -383,7 +533,7 @@ fn test_lseek64() {
+     lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
+ 
+     let mut buf = [0u8; 7];
+-    ::read_exact(tmpfd, &mut buf);
++    crate::read_exact(tmpfd, &mut buf);
+     assert_eq!(b"f123456", &buf);
+ 
+     close(tmpfd).unwrap();
+@@ -403,7 +553,7 @@ cfg_if!{
+                 skip_if_jailed!("test_acct");
+             }
+         }
+-    } else {
++    } else if #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] {
+         macro_rules! require_acct{
+             () => {
+                 skip_if_not_root!("test_acct");
+@@ -413,12 +563,13 @@ cfg_if!{
+ }
+ 
+ #[test]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ fn test_acct() {
+     use tempfile::NamedTempFile;
+     use std::process::Command;
+     use std::{thread, time};
+ 
+-    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
+     require_acct!();
+ 
+     let file = NamedTempFile::new().unwrap();
+@@ -481,6 +632,14 @@ fn test_pipe() {
+ 
+ // pipe2(2) is the same as pipe(2), except it allows setting some flags.  Check
+ // that we can set a flag.
++#[cfg(any(target_os = "android",
++          target_os = "dragonfly",
++          target_os = "emscripten",
++          target_os = "freebsd",
++          target_os = "linux",
++          target_os = "netbsd",
++          target_os = "openbsd",
++          target_os = "redox"))]
+ #[test]
+ fn test_pipe2() {
+     let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
+@@ -491,8 +650,9 @@ fn test_pipe2() {
+ }
+ 
+ #[test]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
+ fn test_truncate() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let path = tempdir.path().join("file");
+ 
+     {
+@@ -509,7 +669,7 @@ fn test_truncate() {
+ 
+ #[test]
+ fn test_ftruncate() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let path = tempdir.path().join("file");
+ 
+     let tmpfd = {
+@@ -527,17 +687,26 @@ fn test_ftruncate() {
+ }
+ 
+ // Used in `test_alarm`.
++#[cfg(not(target_os = "redox"))]
+ static mut ALARM_CALLED: bool = false;
+ 
+ // Used in `test_alarm`.
++#[cfg(not(target_os = "redox"))]
+ pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
+     assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
+     unsafe { ALARM_CALLED = true };
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_alarm() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    use std::{
++        time::{Duration, Instant,},
++        thread
++    };
++
++    // Maybe other tests that fork interfere with this one?
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     let handler = SigHandler::Handler(alarm_signal_handler);
+     let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
+@@ -554,8 +723,16 @@ fn test_alarm() {
+ 
+     // We should be woken up after 1 second by the alarm, so we'll sleep for 2
+     // seconds to be sure.
+-    sleep(2);
+-    assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");
++    let starttime = Instant::now();
++    loop {
++        thread::sleep(Duration::from_millis(100));
++        if unsafe { ALARM_CALLED} {
++            break;
++        }
++        if starttime.elapsed() > Duration::from_secs(3) {
++            panic!("Timeout waiting for SIGALRM");
++        }
++    }
+ 
+     // Reset the signal.
+     unsafe {
+@@ -565,8 +742,9 @@ fn test_alarm() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_canceling_alarm() {
+-    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
++    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
+ 
+     assert_eq!(alarm::cancel(), None);
+ 
+@@ -575,15 +753,17 @@ fn test_canceling_alarm() {
+ }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_symlinkat() {
+-    let mut buf = [0; 1024];
+-    let tempdir = tempfile::tempdir().unwrap();
++    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let tempdir = tempdir().unwrap();
+ 
+     let target = tempdir.path().join("a");
+     let linkpath = tempdir.path().join("b");
+     symlinkat(&target, None, &linkpath).unwrap();
+     assert_eq!(
+-        readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
++        readlink(&linkpath).unwrap().to_str().unwrap(),
+         target.to_str().unwrap()
+     );
+ 
+@@ -592,7 +772,7 @@ fn test_symlinkat() {
+     let linkpath = "d";
+     symlinkat(target, Some(dirfd), linkpath).unwrap();
+     assert_eq!(
+-        readlink(&tempdir.path().join(linkpath), &mut buf)
++        readlink(&tempdir.path().join(linkpath))
+             .unwrap()
+             .to_str()
+             .unwrap(),
+@@ -600,10 +780,154 @@ fn test_symlinkat() {
+     );
+ }
+ 
++#[test]
++#[cfg(not(target_os = "redox"))]
++fn test_linkat_file() {
++    let tempdir = tempdir().unwrap();
++    let oldfilename = "foo.txt";
++    let oldfilepath = tempdir.path().join(oldfilename);
++
++    let newfilename = "bar.txt";
++    let newfilepath = tempdir.path().join(newfilename);
++
++    // Create file
++    File::create(&oldfilepath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt hard link file at relative path
++    linkat(Some(dirfd), oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
++    assert!(newfilepath.exists());
++}
++
++#[test]
++#[cfg(not(target_os = "redox"))]
++fn test_linkat_olddirfd_none() {
++    let _dr = crate::DirRestore::new();
++
++    let tempdir_oldfile = tempdir().unwrap();
++    let oldfilename = "foo.txt";
++    let oldfilepath = tempdir_oldfile.path().join(oldfilename);
++
++    let tempdir_newfile = tempdir().unwrap();
++    let newfilename = "bar.txt";
++    let newfilepath = tempdir_newfile.path().join(newfilename);
++
++    // Create file
++    File::create(&oldfilepath).unwrap();
++
++    // Get file descriptor for base directory of new file
++    let dirfd = fcntl::open(tempdir_newfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt hard link file using curent working directory as relative path for old file path
++    chdir(tempdir_oldfile.path()).unwrap();
++    linkat(None, oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
++    assert!(newfilepath.exists());
++}
++
++#[test]
++#[cfg(not(target_os = "redox"))]
++fn test_linkat_newdirfd_none() {
++    let _dr = crate::DirRestore::new();
++
++    let tempdir_oldfile = tempdir().unwrap();
++    let oldfilename = "foo.txt";
++    let oldfilepath = tempdir_oldfile.path().join(oldfilename);
++
++    let tempdir_newfile = tempdir().unwrap();
++    let newfilename = "bar.txt";
++    let newfilepath = tempdir_newfile.path().join(newfilename);
++
++    // Create file
++    File::create(&oldfilepath).unwrap();
++
++    // Get file descriptor for base directory of old file
++    let dirfd = fcntl::open(tempdir_oldfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt hard link file using current working directory as relative path for new file path
++    chdir(tempdir_newfile.path()).unwrap();
++    linkat(Some(dirfd), oldfilename, None, newfilename, LinkatFlags::SymlinkFollow).unwrap();
++    assert!(newfilepath.exists());
++}
++
++#[test]
++#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
++fn test_linkat_no_follow_symlink() {
++    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let tempdir = tempdir().unwrap();
++    let oldfilename = "foo.txt";
++    let oldfilepath = tempdir.path().join(oldfilename);
++
++    let symoldfilename = "symfoo.txt";
++    let symoldfilepath = tempdir.path().join(symoldfilename);
++
++    let newfilename = "nofollowsymbar.txt";
++    let newfilepath = tempdir.path().join(newfilename);
++
++    // Create file
++    File::create(&oldfilepath).unwrap();
++
++    // Create symlink to file
++    symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt link symlink of file at relative path
++    linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::NoSymlinkFollow).unwrap();
++
++    // Assert newfile is actually a symlink to oldfile.
++    assert_eq!(
++        readlink(&newfilepath)
++            .unwrap()
++            .to_str()
++            .unwrap(),
++        oldfilepath.to_str().unwrap()
++    );
++}
++
++#[test]
++#[cfg(not(target_os = "redox"))]
++fn test_linkat_follow_symlink() {
++    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
++
++    let tempdir = tempdir().unwrap();
++    let oldfilename = "foo.txt";
++    let oldfilepath = tempdir.path().join(oldfilename);
++
++    let symoldfilename = "symfoo.txt";
++    let symoldfilepath = tempdir.path().join(symoldfilename);
++
++    let newfilename = "nofollowsymbar.txt";
++    let newfilepath = tempdir.path().join(newfilename);
++
++    // Create file
++    File::create(&oldfilepath).unwrap();
++
++    // Create symlink to file
++    symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
++
++    // Get file descriptor for base directory
++    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
++
++    // Attempt link target of symlink of file at relative path
++    linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
++
++    let newfilestat = stat::stat(&newfilepath).unwrap();
++
++    // Check the file type of the new link
++    assert!((stat::SFlag::from_bits_truncate(newfilestat.st_mode) & SFlag::S_IFMT) ==  SFlag::S_IFREG);
++
++    // Check the number of hard links to the original file
++    assert_eq!(newfilestat.st_nlink, 2);
++}
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_unlinkat_dir_noremovedir() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let dirname = "foo_dir";
+     let dirpath = tempdir.path().join(dirname);
+ 
+@@ -619,8 +943,9 @@ fn test_unlinkat_dir_noremovedir() {
+  }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_unlinkat_dir_removedir() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let dirname = "foo_dir";
+     let dirpath = tempdir.path().join(dirname);
+ 
+@@ -636,8 +961,9 @@ fn test_unlinkat_dir_removedir() {
+  }
+ 
+ #[test]
++#[cfg(not(target_os = "redox"))]
+ fn test_unlinkat_file() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let filename = "foo.txt";
+     let filepath = tempdir.path().join(filename);
+ 
+@@ -654,7 +980,7 @@ fn test_unlinkat_file() {
+ 
+ #[test]
+ fn test_access_not_existing() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let dir = tempdir.path().join("does_not_exist.txt");
+     assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
+                Errno::ENOENT);
+@@ -662,8 +988,123 @@ fn test_access_not_existing() {
+ 
+ #[test]
+ fn test_access_file_exists() {
+-    let tempdir = tempfile::tempdir().unwrap();
++    let tempdir = tempdir().unwrap();
+     let path  = tempdir.path().join("does_exist.txt");
+     let _file = File::create(path.clone()).unwrap();
+     assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
+ }
++
++/// Tests setting the filesystem UID with `setfsuid`.
++#[cfg(any(target_os = "linux", target_os = "android"))]
++#[test]
++fn test_setfsuid() {
++    use std::os::unix::fs::PermissionsExt;
++    use std::{fs, io, thread};
++    require_capability!(CAP_SETUID);
++
++    // get the UID of the "nobody" user
++    let nobody = User::from_name("nobody").unwrap().unwrap();
++
++    // create a temporary file with permissions '-rw-r-----'
++    let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap();
++    let temp_path = file.into_temp_path();
++    dbg!(&temp_path);
++    let temp_path_2 = (&temp_path).to_path_buf();
++    let mut permissions = fs::metadata(&temp_path).unwrap().permissions();
++    permissions.set_mode(640);
++
++    // spawn a new thread where to test setfsuid
++    thread::spawn(move || {
++        // set filesystem UID
++        let fuid = setfsuid(nobody.uid);
++        // trying to open the temporary file should fail with EACCES
++        let res = fs::File::open(&temp_path);
++        assert!(res.is_err());
++        assert_eq!(res.err().unwrap().kind(), io::ErrorKind::PermissionDenied);
++
++        // assert fuid actually changes
++        let prev_fuid = setfsuid(Uid::from_raw(-1i32 as u32));
++        assert_ne!(prev_fuid, fuid);
++    })
++    .join()
++    .unwrap();
++
++    // open the temporary file with the current thread filesystem UID
++    fs::File::open(temp_path_2).unwrap();
++}
++
++#[test]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++fn test_ttyname() {
++    let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
++    assert!(fd.as_raw_fd() > 0);
++
++    // on linux, we can just call ttyname on the pty master directly, but
++    // apparently osx requires that ttyname is called on a slave pty (can't
++    // find this documented anywhere, but it seems to empirically be the case)
++    grantpt(&fd).expect("grantpt failed");
++    unlockpt(&fd).expect("unlockpt failed");
++    let sname = unsafe { ptsname(&fd) }.expect("ptsname failed");
++    let fds = open(
++        Path::new(&sname),
++        OFlag::O_RDWR,
++        stat::Mode::empty(),
++    ).expect("open failed");
++    assert!(fds > 0);
++
++    let name = ttyname(fds).expect("ttyname failed");
++    assert!(name.starts_with("/dev"));
++}
++
++#[test]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++fn test_ttyname_not_pty() {
++    let fd = File::open("/dev/zero").unwrap();
++    assert!(fd.as_raw_fd() > 0);
++    assert_eq!(ttyname(fd.as_raw_fd()), Err(Error::Sys(Errno::ENOTTY)));
++}
++
++#[test]
++#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
++fn test_ttyname_invalid_fd() {
++    assert_eq!(ttyname(-1), Err(Error::Sys(Errno::EBADF)));
++}
++
++#[test]
++#[cfg(any(
++    target_os = "macos",
++    target_os = "ios",
++    target_os = "freebsd",
++    target_os = "openbsd",
++    target_os = "netbsd",
++    target_os = "dragonfly",
++))]
++fn test_getpeereid() {
++    use std::os::unix::net::UnixStream;
++    let (sock_a, sock_b) = UnixStream::pair().unwrap();
++
++    let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap();
++    let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap();
++
++    let uid = geteuid();
++    let gid = getegid();
++
++    assert_eq!(uid, uid_a);
++    assert_eq!(gid, gid_a);
++    assert_eq!(uid_a, uid_b);
++    assert_eq!(gid_a, gid_b);
++}
++
++#[test]
++#[cfg(any(
++    target_os = "macos",
++    target_os = "ios",
++    target_os = "freebsd",
++    target_os = "openbsd",
++    target_os = "netbsd",
++    target_os = "dragonfly",
++))]
++fn test_getpeereid_invalid_fd() {
++    // getpeereid is not POSIX, so error codes are inconsistent between different Unices.
++    assert!(getpeereid(-1).is_err());
++}

diff --git a/www-client/firefox/firefox-98.0.2.ebuild b/www-client/firefox/firefox-98.0.2.ebuild
index 4b45248..7eee8fb 100644
--- a/www-client/firefox/firefox-98.0.2.ebuild
+++ b/www-client/firefox/firefox-98.0.2.ebuild
@@ -51,6 +51,8 @@ PATCH_URIS=(
 	https://dev.gentoo.org/~{juippis,polynomial-c,whissi,slashbeast}/mozilla/patchsets/${FIREFOX_PATCHSET}
 )
 
+PATCHES=${FILESDIR}/makotokato-riscv64-support-and-zenithal-backported.patch
+
 SRC_URI="${MOZ_SRC_BASE_URI}/source/${MOZ_P}.source.tar.xz -> ${MOZ_P_DISTFILES}.source.tar.xz
 	${PATCH_URIS[@]}"
 
@@ -725,7 +727,7 @@ src_configure() {
 	# For future keywording: This is currently (97.0) only supported on:
 	# amd64, arm, arm64 & x86.
 	# Might want to flip the logic around if Firefox is to support more arches.
-	if use ppc64; then
+	if use ppc64 || use riscv; then
 		mozconfig_add_options_ac '' --disable-sandbox
 	else
 		mozconfig_add_options_ac '' --enable-sandbox


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [gentoo-commits] proj/riscv:master commit in: www-client/firefox/files/, www-client/firefox/
@ 2022-08-31  2:30 Yixun Lan
  0 siblings, 0 replies; 2+ messages in thread
From: Yixun Lan @ 2022-08-31  2:30 UTC (permalink / raw
  To: gentoo-commits

commit:     5183cfd4ccbd66fcf23f62c94dd359832eaa7006
Author:     Alex Fan <alex.fan.q <AT> gmail <DOT> com>
AuthorDate: Sun Aug 28 05:34:55 2022 +0000
Commit:     Yixun Lan <dlan <AT> gentoo <DOT> org>
CommitDate: Wed Aug 31 02:27:40 2022 +0000
URL:        https://gitweb.gentoo.org/proj/riscv.git/commit/?id=5183cfd4

www-client/firefox: bump to 103.0.1

update riscv support patch. To avoid huge patches of rust third party
libs, we have to download it on the fly. To do this, network-sandbox
is restricted and ./mach vendor rust is run before ./mach configure.
cargo-vet is disabled as mozbuild cannot pass correct PATH to it with
non-git firefox src and we don't audit libs anyway.

Signed-off-by: Alex Fan <alex.fan.q <AT> gmail.com>
Signed-off-by: Yixun Lan <dlan <AT> gentoo.org>

 .../firefox/files/firefox-riscv64-hack.patch       |   102 +
 .../firefox/files/firefox-riscv64-support.patch    |  3283 ++
 www-client/firefox/files/firefox-wayland.sh        |     7 -
 www-client/firefox/files/firefox-x11.sh            |     7 -
 www-client/firefox/files/firefox.sh                |   128 -
 .../firefox/files/gentoo-hwaccel-prefs.js-r2       |     5 +
 ...o-riscv64-support-and-zenithal-backported.patch | 47126 -------------------
 www-client/firefox/firefox-103.0.1.ebuild          |  1301 +
 8 files changed, 4691 insertions(+), 47268 deletions(-)

diff --git a/www-client/firefox/files/firefox-riscv64-hack.patch b/www-client/firefox/files/firefox-riscv64-hack.patch
new file mode 100644
index 0000000..b4fca4d
--- /dev/null
+++ b/www-client/firefox/files/firefox-riscv64-hack.patch
@@ -0,0 +1,102 @@
+Temporary hack to allow us to directly apply diff of matoko's branch.  Disable
+rust-vet to skip auditing third party libs in order to download/vendor rust
+deps on non-git firefox src.  Skip some style checks, as
+macroassembler support in js/src/jit/ is not complete yet
+
+diff --git a/python/mozbuild/mozbuild/vendor/vendor_rust.py b/python/mozbuild/mozbuild/vendor/vendor_rust.py
+index 7394ccaf40..491bd7fbdb 100644
+--- a/python/mozbuild/mozbuild/vendor/vendor_rust.py
++++ b/python/mozbuild/mozbuild/vendor/vendor_rust.py
+@@ -740,38 +740,40 @@ license file's hash.
+                     failed = True
+ 
+         # Only emit warnings for cargo-vet for now.
+-        env = os.environ.copy()
+-        env["PATH"] = os.pathsep.join(
+-            (
+-                str(Path(cargo).parent),
+-                os.environ["PATH"],
+-            )
+-        )
+-        flags = ["--output-format=json"]
+-        if "MOZ_AUTOMATION" in os.environ:
+-            flags.append("--locked")
+-            flags.append("--frozen")
+-        res = cargo_vet(
+-            self,
+-            flags,
+-            stdout=subprocess.PIPE,
+-            env=env,
+-        )
+-        if res.returncode:
+-            vet = json.loads(res.stdout)
+-            for failure in vet.get("failures", []):
+-                failure["crate"] = failure.pop("name")
+-                self.log(
+-                    logging.ERROR,
+-                    "cargo_vet_failed",
+-                    failure,
+-                    "Missing audit for {crate}:{version} (requires {missing_criteria})."
+-                    " Run `./mach cargo vet` for more information.",
+-                )
+-                failed = True
+-
+-        if failed:
+-            return False
++        #env = os.environ.copy()
++        #env["PATH"] = os.pathsep.join(
++        #    (
++        #        str(Path(cargo).parent),
++        #        os.environ["PATH"],
++        #    )
++        #)
++        #print(env["PATH"])
++        #print(self.topsrcdir)
++        #flags = ["--output-format=json"]
++        #if "MOZ_AUTOMATION" in os.environ:
++        #    flags.append("--locked")
++        #    flags.append("--frozen")
++        #res = cargo_vet(
++        #    self,
++        #    flags,
++        #    stdout=subprocess.PIPE,
++        #    env=env,
++        #)
++        #if res.returncode:
++        #    vet = json.loads(res.stdout)
++        #    for failure in vet.get("failures", []):
++        #        failure["crate"] = failure.pop("name")
++        #        self.log(
++        #            logging.ERROR,
++        #            "cargo_vet_failed",
++        #            failure,
++        #            "Missing audit for {crate}:{version} (requires {missing_criteria})."
++        #            " Run `./mach cargo vet` for more information.",
++        #        )
++        #        failed = True
++
++        #if failed:
++        #    return False
+ 
+         res = subprocess.run(
+             [cargo, "vendor", vendor_dir], cwd=self.topsrcdir, stdout=subprocess.PIPE
+@@ -848,6 +848,7 @@ license file's hash.
+                     directory=replace["directory"],
+                 )
+             )
++        return True
+ 
+         if not self._check_licenses(vendor_dir):
+             self.log(
+diff --git a/js/src/build/moz.build b/js/src/build/moz.build
+index 4c48a5c4ff..e68d79447e 100644
+--- a/js/src/build/moz.build
++++ b/js/src/build/moz.build
+@@ -101,7 +101,5 @@ GeneratedFile(
+     inputs=[
+         "!%sjs_static.%s" % (CONFIG["LIB_PREFIX"], CONFIG["LIB_SUFFIX"]),
+-        "/config/check_spidermonkey_style.py",
+-        "/config/check_macroassembler_style.py",
+         "/config/check_js_opcode.py",
+     ],
+ )

diff --git a/www-client/firefox/files/firefox-riscv64-support.patch b/www-client/firefox/files/firefox-riscv64-support.patch
new file mode 100644
index 0000000..7e9abfc
--- /dev/null
+++ b/www-client/firefox/files/firefox-riscv64-support.patch
@@ -0,0 +1,3283 @@
+patch generated directly from https://github.com/makotokato/gecko-dev by
+
+    git diff master..riscv64 -- . :^third_party
+
+:^third_party is a git feature to exclude third_party/ from diff
+
+diff --git a/.cargo/config.in b/.cargo/config.in
+index 20b8c3fad8..34c5f9a1f4 100644
+--- a/.cargo/config.in
++++ b/.cargo/config.in
+@@ -22,11 +22,6 @@ git = "https://github.com/mozilla/mp4parse-rust"
+ replace-with = "vendored-sources"
+ rev = "3bfc47d9a571d0842676043ba60716318e946c06"
+ 
+-[source."https://github.com/mozilla/midir.git"]
+-git = "https://github.com/mozilla/midir.git"
+-replace-with = "vendored-sources"
+-rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
+-
+ [source."https://github.com/mozilla/cubeb-pulse-rs"]
+ git = "https://github.com/mozilla/cubeb-pulse-rs"
+ replace-with = "vendored-sources"
+@@ -37,6 +32,11 @@ git = "https://github.com/mozilla/cubeb-coreaudio-rs"
+ replace-with = "vendored-sources"
+ rev = "44eca95823bb57e964cf7b6d9791ed2ccb4b2108"
+ 
++[source."https://github.com/mozilla/authenticator-rs"]
++git = "https://github.com/mozilla/authenticator-rs"
++replace-with = "vendored-sources"
++rev = "b85bccf0527e42c877573029e8d35ff13ef06f9d"
++
+ [source."https://github.com/mozilla/audioipc"]
+ git = "https://github.com/mozilla/audioipc"
+ replace-with = "vendored-sources"
+diff --git a/Cargo.lock b/Cargo.lock
+index 85a143565c..b4924869cb 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -30,14 +30,14 @@ dependencies = [
+ 
+ [[package]]
+ name = "alsa"
+-version = "0.4.3"
++version = "0.6.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"
++checksum = "5915f52fe2cf65e83924d037b6c5290b7cee097c6b5c8700746e6168a343fd6b"
+ dependencies = [
+  "alsa-sys",
+  "bitflags",
+  "libc",
+- "nix",
++ "nix 0.23.1",
+ ]
+ 
+ [[package]]
+@@ -359,9 +359,8 @@ dependencies = [
+ 
+ [[package]]
+ name = "authenticator"
+-version = "0.3.1"
+-source = "registry+https://github.com/rust-lang/crates.io-index"
+-checksum = "08cee7a0952628fde958e149507c2bb321ab4fccfafd225da0b20adc956ef88a"
++version = "0.3.2"
++source = "git+https://github.com/mozilla/authenticator-rs?rev=b85bccf0527e42c877573029e8d35ff13ef06f9d#b85bccf0527e42c877573029e8d35ff13ef06f9d"
+ dependencies = [
+  "bitflags",
+  "core-foundation",
+@@ -369,7 +368,7 @@ dependencies = [
+  "libc",
+  "libudev",
+  "log",
+- "rand 0.7.999",
++ "rand 0.8.5",
+  "runloop",
+  "winapi",
+ ]
+@@ -2204,6 +2203,7 @@ dependencies = [
+  "log",
+  "mapped_hyph",
+  "mdns_service",
++ "midir",
+  "midir_impl",
+  "mio 0.8.0",
+  "moz_asserts",
+@@ -3274,8 +3274,9 @@ dependencies = [
+ 
+ [[package]]
+ name = "midir"
+-version = "0.7.0"
+-source = "git+https://github.com/mozilla/midir.git?rev=4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f#4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
++version = "0.8.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "2c1c68e2b589cce71b14a10d7d1599a845673f9decde80fa9e8500fdccd50dca"
+ dependencies = [
+  "alsa",
+  "bitflags",
+@@ -3283,10 +3284,9 @@ dependencies = [
+  "js-sys",
+  "libc",
+  "memalloc",
+- "nix",
+  "wasm-bindgen",
+  "web-sys",
+- "winapi",
++ "windows",
+ ]
+ 
+ [[package]]
+@@ -3325,7 +3325,7 @@ dependencies = [
+  "libc",
+  "memmap2 0.2.999",
+  "memoffset 0.5.6",
+- "nix",
++ "nix 0.15.0",
+  "tempfile",
+  "thiserror",
+ ]
+@@ -3735,6 +3735,19 @@ dependencies = [
+  "void",
+ ]
+ 
++[[package]]
++name = "nix"
++version = "0.23.1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
++dependencies = [
++ "bitflags",
++ "cc",
++ "cfg-if 1.0.0",
++ "libc",
++ "memoffset 0.6.5",
++]
++
+ [[package]]
+ name = "nom"
+ version = "5.999.999"
+@@ -6218,6 +6231,49 @@ version = "0.4.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+ 
++[[package]]
++name = "windows"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "fbedf6db9096bc2364adce0ae0aa636dcd89f3c3f2cd67947062aaf0ca2a10ec"
++dependencies = [
++ "windows_aarch64_msvc",
++ "windows_i686_gnu",
++ "windows_i686_msvc",
++ "windows_x86_64_gnu",
++ "windows_x86_64_msvc",
++]
++
++[[package]]
++name = "windows_aarch64_msvc"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
++
++[[package]]
++name = "windows_i686_gnu"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
++
++[[package]]
++name = "windows_i686_msvc"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
++
++[[package]]
++name = "windows_x86_64_gnu"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
++
++[[package]]
++name = "windows_x86_64_msvc"
++version = "0.32.0"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
++
+ [[package]]
+ name = "wineventlog"
+ version = "0.1.0"
+diff --git a/Cargo.toml b/Cargo.toml
+index 2b499a0841..dcf1e401d7 100644
+--- a/Cargo.toml
++++ b/Cargo.toml
+@@ -153,7 +153,6 @@ coremidi = { git = "https://github.com/chris-zen/coremidi.git", rev="fc68464b544
+ fog = { path = "toolkit/components/glean/api" }
+ libudev-sys = { path = "dom/webauthn/libudev-sys" }
+ packed_simd = { package = "packed_simd_2", git = "https://github.com/hsivonen/packed_simd", rev="c149d0a519bf878567c7630096737669ec2ff15f" }
+-midir = { git = "https://github.com/mozilla/midir.git", rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f" }
+ minidump_writer_linux = { git = "https://github.com/rust-minidump/minidump-writer.git", rev = "75ada456c92a429704691a85e1cb42fef8cafc0d" }
+ 
+ # application-services overrides to make updating them all simpler.
+diff --git a/README.riscv64.md b/README.riscv64.md
+new file mode 100644
+index 0000000000..705099a3db
+--- /dev/null
++++ b/README.riscv64.md
+@@ -0,0 +1,69 @@
++## Cross building
++I recommend you should use docker environment
++
++#### Dockerfile
++```dockerfile
++FROM ubuntu:21.04
++MAINTAINER Makoto Kato <m_kato@ga2.so-net.ne.jp>
++
++ADD sources.list /etc/apt/
++ENV DEBIAN_FRONTEND=noninteractive
++RUN dpkg --add-architecture riscv64 && \
++    apt-get update && \
++    apt-get install -y clang g++ mercurial g++-riscv64-linux-gnu curl gyp ninja-build make python-is-python3 libssl-dev zlib1g-dev nodejs build-essential libpython3-dev m4 unzip zip uuid git python3-pip && \
++    apt-get install -y zlib1g-dev:riscv64 libssl-dev:riscv64 libffi-dev:riscv64 libasound2-dev:riscv64 libcurl4-openssl-dev:riscv64 libdbus-1-dev:riscv64 libdbus-glib-1-dev:riscv64 libdrm-dev:riscv64 libgtk-3-dev:riscv64 libpulse-dev:riscv64 libx11-xcb-dev:riscv64 libxt-dev:riscv64 xvfb:riscv64 libstdc++-10-dev:riscv64 && \
++    apt-get clean
++WORKDIR /root
++ENV PATH="/root/.cargo/bin:${PATH}"
++RUN curl https://sh.rustup.rs -s -o install.sh && sh install.sh -y && rm install.sh && rustup target add riscv64gc-unknown-linux-gnu
++RUN cargo install cbindgen
++```
++
++#### sources.list
++```
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute main restricted
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute-updates main restricted
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute universe
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute-updates universe
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute multiverse
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute-updates multiverse
++deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ hirsute-backports main restricted universe multiverse
++deb [arch=amd64] http://security.ubuntu.com/ubuntu/ hirsute-security main restricted
++deb [arch=amd64] http://security.ubuntu.com/ubuntu/ hirsute-security universe
++deb [arch=amd64] http://security.ubuntu.com/ubuntu/ hirsute-security multiverse
++
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute main restricted
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-updates main restricted
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute universe
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-updates universe
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute multiverse
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-updates multiverse
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-backports main restricted universe multiverse
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-security main restricted
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-security universe
++deb [arch=riscv64] http://ports.ubuntu.com/ubuntu-ports hirsute-security multiverse
++```
++
++## mozconfig
++```
++mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/objdir
++mk_add_options AUTOCLOBBER=1
++
++ac_add_options --disable-debug
++ac_add_options --enable-optimize
++
++ac_add_options --target=riscv64
++export CC=riscv64-linux-gnu-gcc
++export CXX=riscv64-linux-gnu-g++
++export HOST_CC=gcc
++export HOST_CXX=g++
++ac_add_options --disable-bootstrap
++ac_add_options --without-wasm-sandboxed-libraries
++ac_add_options --enable-webrtc
++ac_add_options --disable-crashreporter
++ac_add_options --disable-jit
++```
++
++## How to build
++1. `./mach build`
++2. `./mach package`
+diff --git a/dom/bindings/moz.build b/dom/bindings/moz.build
+index cf3a8d5017..5e1388cfe5 100644
+--- a/dom/bindings/moz.build
++++ b/dom/bindings/moz.build
+@@ -96,12 +96,16 @@ LOCAL_INCLUDES += [
+     "/layout/xul/tree",
+     "/media/webrtc/",
+     "/netwerk/base/",
+-    "/third_party/libwebrtc",
+-    "/third_party/libwebrtc/third_party/abseil-cpp",
+ ]
+ 
+ LOCAL_INCLUDES += ["/third_party/msgpack/include"]
+ 
++if CONFIG["MOZ_WEBRTC"]:
++    LOCAL_INCLUDES += [
++        "/third_party/libwebrtc",
++        "/third_party/libwebrtc/third_party/abseil-cpp",
++    ]
++
+ DEFINES["GOOGLE_PROTOBUF_NO_RTTI"] = True
+ DEFINES["GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER"] = True
+ 
+diff --git a/dom/media/gtest/moz.build b/dom/media/gtest/moz.build
+index 05803392cb..d689c7bd77 100644
+--- a/dom/media/gtest/moz.build
++++ b/dom/media/gtest/moz.build
+@@ -13,10 +13,14 @@ LOCAL_INCLUDES += [
+     "/dom/media/systemservices",
+     "/dom/media/webrtc",
+     "/dom/media/webrtc/common",
+-    "/third_party/libwebrtc",
+-    "/third_party/libwebrtc/third_party/abseil-cpp",
+ ]
+ 
++if CONFIG["MOZ_WEBRTC"]:
++    LOCAL_INCLUDES += [
++        "/third_party/libwebrtc",
++        "/third_party/libwebrtc/third_party/abseil-cpp",
++    ]
++
+ UNIFIED_SOURCES += [
+     "MockCubeb.cpp",
+     "MockMediaResource.cpp",
+diff --git a/dom/midi/midir_impl/Cargo.toml b/dom/midi/midir_impl/Cargo.toml
+index 7628fb4a68..a918ff2227 100644
+--- a/dom/midi/midir_impl/Cargo.toml
++++ b/dom/midi/midir_impl/Cargo.toml
+@@ -7,7 +7,7 @@ edition = "2018"
+ # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+ 
+ [dependencies]
+-midir = "0.7.0"
++midir = "0.8.0"
+ nsstring = { path = "../../../xpcom/rust/nsstring/" }
+ uuid = { version = "0.8", features = ["v4"] }
+ thin-vec = { version = "0.2.1", features = ["gecko-ffi"] }
+diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build
+index c4b7c1d69e..775f553d05 100644
+--- a/ipc/glue/moz.build
++++ b/ipc/glue/moz.build
+@@ -220,6 +220,12 @@ LOCAL_INCLUDES += [
+     "/xpcom/build",
+ ]
+ 
++if CONFIG["MOZ_WEBRTC"]:
++    LOCAL_INCLUDES += [
++        "/third_party/libwebrtc",
++        "/third_party/libwebrtc/third_party/abseil-cpp",
++    ]
++
+ PREPROCESSED_IPDL_SOURCES = [
+     "PUtilityProcess.ipdl",
+ ]
+diff --git a/js/moz.configure b/js/moz.configure
+index 4f9bb8992f..d53c672aa0 100644
+--- a/js/moz.configure
++++ b/js/moz.configure
+@@ -184,7 +184,7 @@ def report_deprecated(value):
+ # =======================================================
+ option(
+     "--enable-simulator",
+-    choices=("arm", "arm64", "mips32", "mips64", "loong64"),
++    choices=("arm", "arm64", "mips32", "mips64", "loong64", "riscv64"),
+     nargs=1,
+     help="Enable a JIT code simulator for the specified architecture",
+ )
+@@ -201,7 +201,7 @@ def simulator(jit_enabled, simulator_enabled, target):
+         if target.cpu != "x86":
+             die("The %s simulator only works on x86." % sim_cpu)
+ 
+-    if sim_cpu in ("arm64", "mips64", "loong64"):
++    if sim_cpu in ("arm64", "mips64", "loong64", "riscv64"):
+         if target.cpu != "x86_64" and target.cpu != "aarch64":
+             die("The %s simulator only works on x86-64 or arm64." % sim_cpu)
+ 
+@@ -214,12 +214,14 @@ set_config("JS_SIMULATOR_ARM64", simulator.arm64)
+ set_config("JS_SIMULATOR_MIPS32", simulator.mips32)
+ set_config("JS_SIMULATOR_MIPS64", simulator.mips64)
+ set_config("JS_SIMULATOR_LOONG64", simulator.loong64)
++set_config("JS_SIMULATOR_RISCV64", simulator.riscv64)
+ set_define("JS_SIMULATOR", depends_if(simulator)(lambda x: True))
+ set_define("JS_SIMULATOR_ARM", simulator.arm)
+ set_define("JS_SIMULATOR_ARM64", simulator.arm64)
+ set_define("JS_SIMULATOR_MIPS32", simulator.mips32)
+ set_define("JS_SIMULATOR_MIPS64", simulator.mips64)
+ set_define("JS_SIMULATOR_LOONG64", simulator.loong64)
++set_define("JS_SIMULATOR_RISCV64", simulator.riscv64)
+ 
+ 
+ @depends("--enable-jit", simulator, target)
+@@ -244,6 +246,7 @@ set_config("JS_CODEGEN_ARM64", jit_codegen.arm64)
+ set_config("JS_CODEGEN_MIPS32", jit_codegen.mips32)
+ set_config("JS_CODEGEN_MIPS64", jit_codegen.mips64)
+ set_config("JS_CODEGEN_LOONG64", jit_codegen.loong64)
++set_config("JS_CODEGEN_RISCV64", jit_codegen.riscv64)
+ set_config("JS_CODEGEN_X86", jit_codegen.x86)
+ set_config("JS_CODEGEN_X64", jit_codegen.x64)
+ set_define("JS_CODEGEN_NONE", jit_codegen.none)
+@@ -252,6 +255,7 @@ set_define("JS_CODEGEN_ARM64", jit_codegen.arm64)
+ set_define("JS_CODEGEN_MIPS32", jit_codegen.mips32)
+ set_define("JS_CODEGEN_MIPS64", jit_codegen.mips64)
+ set_define("JS_CODEGEN_LOONG64", jit_codegen.loong64)
++set_define("JS_CODEGEN_RISCV64", jit_codegen.riscv64)
+ set_define("JS_CODEGEN_X86", jit_codegen.x86)
+ set_define("JS_CODEGEN_X64", jit_codegen.x64)
+ 
+diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp
+index 2b8de6284f..1b9b4b62c7 100644
+--- a/js/src/builtin/TestingFunctions.cpp
++++ b/js/src/builtin/TestingFunctions.cpp
+@@ -426,6 +426,24 @@ static bool GetBuildConfiguration(JSContext* cx, unsigned argc, Value* vp) {
+     return false;
+   }
+ 
++#ifdef JS_CODEGEN_RISCV64
++  value = BooleanValue(true);
++#else
++  value = BooleanValue(false);
++#endif
++  if (!JS_SetProperty(cx, info, "riscv64", value)) {
++    return false;
++  }
++
++#ifdef JS_SIMULATOR_RISCV64
++  value = BooleanValue(true);
++#else
++  value = BooleanValue(false);
++#endif
++  if (!JS_SetProperty(cx, info, "riscv64-simulator", value)) {
++    return false;
++  }
++
+ #ifdef JS_SIMULATOR
+   value = BooleanValue(true);
+ #else
+diff --git a/js/src/jit/Assembler.h b/js/src/jit/Assembler.h
+index 04dcdc647e..2081f254b0 100644
+--- a/js/src/jit/Assembler.h
++++ b/js/src/jit/Assembler.h
+@@ -19,6 +19,8 @@
+ #  include "jit/mips32/Assembler-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/Assembler-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/Assembler-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/Assembler-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/CodeGenerator.h b/js/src/jit/CodeGenerator.h
+index 67453d3cd3..82e58d2a16 100644
+--- a/js/src/jit/CodeGenerator.h
++++ b/js/src/jit/CodeGenerator.h
+@@ -26,6 +26,8 @@
+ #  include "jit/mips64/CodeGenerator-mips64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/CodeGenerator-loong64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/CodeGenerator-riscv64.h"
+ #elif defined(JS_CODEGEN_NONE)
+ #  include "jit/none/CodeGenerator-none.h"
+ #else
+diff --git a/js/src/jit/FlushICache.h b/js/src/jit/FlushICache.h
+index 42b1fb045c..feeae3c793 100644
+--- a/js/src/jit/FlushICache.h
++++ b/js/src/jit/FlushICache.h
+@@ -25,7 +25,7 @@ inline void FlushICache(void* code, size_t size,
+ 
+ #elif (defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64)) ||   \
+     (defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)) || \
+-    defined(JS_CODEGEN_LOONG64)
++    defined(JS_CODEGEN_LOONG64) || defined(JS_CODEGEN_RISCV64)
+ 
+ extern void FlushICache(void* code, size_t size, bool codeIsThreadLocal = true);
+ 
+diff --git a/js/src/jit/LIR.h b/js/src/jit/LIR.h
+index 66c665b5ba..016c8246f7 100644
+--- a/js/src/jit/LIR.h
++++ b/js/src/jit/LIR.h
+@@ -1933,6 +1933,8 @@ AnyRegister LAllocation::toRegister() const {
+ #    include "jit/mips64/LIR-mips64.h"
+ #  endif
+ #  include "jit/mips-shared/LIR-mips-shared.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/LIR-riscv64.h"
+ #elif defined(JS_CODEGEN_NONE)
+ #  include "jit/none/LIR-none.h"
+ #else
+diff --git a/js/src/jit/Lowering.h b/js/src/jit/Lowering.h
+index a04d09c446..21094a616e 100644
+--- a/js/src/jit/Lowering.h
++++ b/js/src/jit/Lowering.h
+@@ -23,6 +23,8 @@
+ #  include "jit/mips32/Lowering-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/Lowering-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/Lowering-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/Lowering-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/MacroAssembler-inl.h b/js/src/jit/MacroAssembler-inl.h
+index 5ed4ac7458..1c208e676d 100644
+--- a/js/src/jit/MacroAssembler-inl.h
++++ b/js/src/jit/MacroAssembler-inl.h
+@@ -39,6 +39,8 @@
+ #  include "jit/mips64/MacroAssembler-mips64-inl.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/MacroAssembler-loong64-inl.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/MacroAssembler-riscv64-inl.h"
+ #elif !defined(JS_CODEGEN_NONE)
+ #  error "Unknown architecture!"
+ #endif
+diff --git a/js/src/jit/MacroAssembler.cpp b/js/src/jit/MacroAssembler.cpp
+index 3abc601bec..0665601509 100644
+--- a/js/src/jit/MacroAssembler.cpp
++++ b/js/src/jit/MacroAssembler.cpp
+@@ -4145,6 +4145,8 @@ void MacroAssembler::emitPreBarrierFastPath(JSRuntime* rt, MIRType type,
+   ma_dsll(temp1, temp1, temp3);
+ #elif JS_CODEGEN_LOONG64
+   as_sll_d(temp1, temp1, temp3);
++#elif JS_CODEGEN_RISCV64
++  MOZ_CRASH();
+ #elif JS_CODEGEN_NONE
+   MOZ_CRASH();
+ #else
+diff --git a/js/src/jit/MacroAssembler.h b/js/src/jit/MacroAssembler.h
+index 5fa8f40bd1..3395a139d3 100644
+--- a/js/src/jit/MacroAssembler.h
++++ b/js/src/jit/MacroAssembler.h
+@@ -25,6 +25,8 @@
+ #  include "jit/mips32/MacroAssembler-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/MacroAssembler-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/MacroAssembler-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/MacroAssembler-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+@@ -94,8 +96,8 @@
+ //   }
+ //   ////}}} check_macroassembler_style
+ 
+-#define ALL_ARCH mips32, mips64, arm, arm64, x86, x64, loong64
+-#define ALL_SHARED_ARCH arm, arm64, loong64, x86_shared, mips_shared
++#define ALL_ARCH mips32, mips64, arm, arm64, x86, x64, loong64, riscv64
++#define ALL_SHARED_ARCH arm, arm64, loong64, riscv64, x86_shared, mips_shared
+ 
+ // * How this macro works:
+ //
+@@ -142,6 +144,7 @@
+ #define DEFINED_ON_mips64
+ #define DEFINED_ON_mips_shared
+ #define DEFINED_ON_loong64
++#define DEFINED_ON_riscv64
+ #define DEFINED_ON_none
+ 
+ // Specialize for each architecture.
+@@ -174,6 +177,9 @@
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  undef DEFINED_ON_loong64
+ #  define DEFINED_ON_loong64 define
++#elif defined(JS_CODEGEN_RISCV64)
++#  undef DEFINED_ON_riscv64
++#  define DEFINED_ON_riscv64 define
+ #elif defined(JS_CODEGEN_NONE)
+ #  undef DEFINED_ON_none
+ #  define DEFINED_ON_none crash
+@@ -491,10 +497,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   // The size of the area used by PushRegsInMask.
+   size_t PushRegsInMaskSizeInBytes(LiveRegisterSet set)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   void PushRegsInMask(LiveRegisterSet set)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+   void PushRegsInMask(LiveGeneralRegisterSet set);
+ 
+   // Like PushRegsInMask, but instead of pushing the registers, store them to
+@@ -505,12 +511,12 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // must point to either the lowest address in the save area, or some address
+   // below that.
+   void storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   void PopRegsInMask(LiveRegisterSet set);
+   void PopRegsInMask(LiveGeneralRegisterSet set);
+   void PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   // ===============================================================
+   // Stack manipulation functions -- single registers/values.
+@@ -543,7 +549,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   void Pop(FloatRegister t) PER_SHARED_ARCH;
+   void Pop(const ValueOperand& val) PER_SHARED_ARCH;
+   void PopFlags() DEFINED_ON(x86_shared);
+-  void PopStackPtr() DEFINED_ON(arm, mips_shared, x86_shared, loong64);
++  void PopStackPtr() DEFINED_ON(arm, mips_shared, x86_shared, loong64, riscv64);
+   void popRooted(VMFunctionData::RootType rootType, Register cellReg,
+                  const ValueOperand& valueReg);
+ 
+@@ -601,8 +607,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   void callAndPushReturnAddress(Label* label) DEFINED_ON(x86_shared);
+ 
+   // These do not adjust framePushed().
+-  void pushReturnAddress() DEFINED_ON(mips_shared, arm, arm64, loong64);
+-  void popReturnAddress() DEFINED_ON(mips_shared, arm, arm64, loong64);
++  void pushReturnAddress()
++      DEFINED_ON(mips_shared, arm, arm64, loong64, riscv64);
++  void popReturnAddress() DEFINED_ON(mips_shared, arm, arm64, loong64, riscv64);
+ 
+   // Useful for dealing with two-valued returns.
+   void moveRegPair(Register src0, Register src1, Register dst0, Register dst1,
+@@ -633,10 +640,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // Note: "Near" applies to ARM64 where the target must be within 1 MB (this is
+   // release-asserted).
+   CodeOffset moveNearAddressWithPatch(Register dest)
+-      DEFINED_ON(x86, x64, arm, arm64, loong64, mips_shared);
++      DEFINED_ON(x86, x64, arm, arm64, loong64, mips_shared, riscv64);
+   static void patchNearAddressMove(CodeLocationLabel loc,
+                                    CodeLocationLabel target)
+-      DEFINED_ON(x86, x64, arm, arm64, loong64, mips_shared);
++      DEFINED_ON(x86, x64, arm, arm64, loong64, mips_shared, riscv64);
+ 
+  public:
+   // ===============================================================
+@@ -1045,17 +1052,17 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   inline void addPtr(ImmWord imm, Register dest) PER_ARCH;
+   inline void addPtr(ImmPtr imm, Register dest);
+   inline void addPtr(Imm32 imm, const Address& dest)
+-      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64, riscv64);
+   inline void addPtr(Imm32 imm, const AbsoluteAddress& dest)
+       DEFINED_ON(x86, x64);
+   inline void addPtr(const Address& src, Register dest)
+-      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64, riscv64);
+ 
+   inline void add64(Register64 src, Register64 dest) PER_ARCH;
+   inline void add64(Imm32 imm, Register64 dest) PER_ARCH;
+   inline void add64(Imm64 imm, Register64 dest) PER_ARCH;
+   inline void add64(const Operand& src, Register64 dest)
+-      DEFINED_ON(x64, mips64, loong64);
++      DEFINED_ON(x64, mips64, loong64, riscv64);
+ 
+   inline void addFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
+ 
+@@ -1074,16 +1081,16 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void subPtr(Register src, Register dest) PER_ARCH;
+   inline void subPtr(Register src, const Address& dest)
+-      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64, riscv64);
+   inline void subPtr(Imm32 imm, Register dest) PER_ARCH;
+   inline void subPtr(ImmWord imm, Register dest) DEFINED_ON(x64);
+   inline void subPtr(const Address& addr, Register dest)
+-      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64, riscv64);
+ 
+   inline void sub64(Register64 src, Register64 dest) PER_ARCH;
+   inline void sub64(Imm64 imm, Register64 dest) PER_ARCH;
+   inline void sub64(const Operand& src, Register64 dest)
+-      DEFINED_ON(x64, mips64, loong64);
++      DEFINED_ON(x64, mips64, loong64, riscv64);
+ 
+   inline void subFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
+ 
+@@ -1099,10 +1106,11 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void mul64(const Operand& src, const Register64& dest) DEFINED_ON(x64);
+   inline void mul64(const Operand& src, const Register64& dest,
+-                    const Register temp) DEFINED_ON(x64, mips64, loong64);
++                    const Register temp)
++      DEFINED_ON(x64, mips64, loong64, riscv64);
+   inline void mul64(Imm64 imm, const Register64& dest) PER_ARCH;
+   inline void mul64(Imm64 imm, const Register64& dest, const Register temp)
+-      DEFINED_ON(x86, x64, arm, mips32, mips64, loong64);
++      DEFINED_ON(x86, x64, arm, mips32, mips64, loong64, riscv64);
+   inline void mul64(const Register64& src, const Register64& dest,
+                     const Register temp) PER_ARCH;
+   inline void mul64(const Register64& src1, const Register64& src2,
+@@ -1116,14 +1124,14 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   inline void mulDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
+ 
+   inline void mulDoublePtr(ImmPtr imm, Register temp, FloatRegister dest)
+-      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86, x64, loong64, riscv64);
+ 
+   // Perform an integer division, returning the integer part rounded toward
+   // zero. rhs must not be zero, and the division must not overflow.
+   //
+   // On ARM, the chip must have hardware division instructions.
+   inline void quotient32(Register rhs, Register srcDest, bool isUnsigned)
+-      DEFINED_ON(mips_shared, arm, arm64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, loong64, riscv64);
+ 
+   // As above, but srcDest must be eax and tempEdx must be edx.
+   inline void quotient32(Register rhs, Register srcDest, Register tempEdx,
+@@ -1134,7 +1142,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   //
+   // On ARM, the chip must have hardware division instructions.
+   inline void remainder32(Register rhs, Register srcDest, bool isUnsigned)
+-      DEFINED_ON(mips_shared, arm, arm64, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, loong64, riscv64);
+ 
+   // As above, but srcDest must be eax and tempEdx must be edx.
+   inline void remainder32(Register rhs, Register srcDest, Register tempEdx,
+@@ -1149,7 +1157,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // rhs is preserved, srdDest is clobbered.
+   void flexibleRemainder32(Register rhs, Register srcDest, bool isUnsigned,
+                            const LiveRegisterSet& volatileLiveRegs)
+-      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64, riscv64);
+ 
+   // Perform an integer division, returning the integer part rounded toward
+   // zero. rhs must not be zero, and the division must not overflow.
+@@ -1160,7 +1168,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // rhs is preserved, srdDest is clobbered.
+   void flexibleQuotient32(Register rhs, Register srcDest, bool isUnsigned,
+                           const LiveRegisterSet& volatileLiveRegs)
+-      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64, riscv64);
+ 
+   // Perform an integer division, returning the integer part rounded toward
+   // zero. rhs must not be zero, and the division must not overflow. The
+@@ -1173,7 +1181,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   void flexibleDivMod32(Register rhs, Register srcDest, Register remOutput,
+                         bool isUnsigned,
+                         const LiveRegisterSet& volatileLiveRegs)
+-      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64);
++      DEFINED_ON(mips_shared, arm, arm64, x86_shared, loong64, riscv64);
+ 
+   inline void divFloat32(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
+   inline void divDouble(FloatRegister src, FloatRegister dest) PER_SHARED_ARCH;
+@@ -1380,7 +1388,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   template <typename T1, typename T2>
+   inline void cmp32Set(Condition cond, T1 lhs, T2 rhs, Register dest)
+-      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64);
++      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64, riscv64);
+ 
+   // Only the NotEqual and Equal conditions are allowed.
+   inline void cmp64Set(Condition cond, Address lhs, Imm64 rhs,
+@@ -1415,10 +1423,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void branch32(Condition cond, const AbsoluteAddress& lhs, Register rhs,
+                        Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void branch32(Condition cond, const AbsoluteAddress& lhs, Imm32 rhs,
+                        Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   inline void branch32(Condition cond, const BaseIndex& lhs, Register rhs,
+                        Label* label) DEFINED_ON(arm, x86_shared);
+@@ -1432,7 +1440,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void branch32(Condition cond, wasm::SymbolicAddress lhs, Imm32 rhs,
+                        Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   // The supported condition are Equal, NotEqual, LessThan(orEqual),
+   // GreaterThan(orEqual), Below(orEqual) and Above(orEqual). When a fail label
+@@ -1483,14 +1491,14 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void branchPtr(Condition cond, const AbsoluteAddress& lhs,
+                         Register rhs, Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void branchPtr(Condition cond, const AbsoluteAddress& lhs, ImmWord rhs,
+                         Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   inline void branchPtr(Condition cond, wasm::SymbolicAddress lhs, Register rhs,
+                         Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   // Given a pointer to a GC Cell, retrieve the StoreBuffer pointer from its
+   // chunk header, or nullptr if it is in the tenured heap.
+@@ -1498,7 +1506,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   void branchPtrInNurseryChunk(Condition cond, Register ptr, Register temp,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   void branchPtrInNurseryChunk(Condition cond, const Address& address,
+                                Register temp, Label* label) DEFINED_ON(x86);
+   void branchValueIsNurseryCell(Condition cond, const Address& address,
+@@ -1520,10 +1528,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // x64 variants will do this only in the int64_t range.
+   inline void branchTruncateFloat32MaybeModUint32(FloatRegister src,
+                                                   Register dest, Label* fail)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void branchTruncateDoubleMaybeModUint32(FloatRegister src,
+                                                  Register dest, Label* fail)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   // Truncate a double/float32 to intptr and when it doesn't fit jump to the
+   // failure label.
+@@ -1536,10 +1544,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // failure label.
+   inline void branchTruncateFloat32ToInt32(FloatRegister src, Register dest,
+                                            Label* fail)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void branchTruncateDoubleToInt32(FloatRegister src, Register dest,
+                                           Label* fail)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   inline void branchDouble(DoubleCondition cond, FloatRegister lhs,
+                            FloatRegister rhs, Label* label) PER_SHARED_ARCH;
+@@ -1596,7 +1604,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                            Label* label) PER_SHARED_ARCH;
+   inline void branchTest32(Condition cond, const AbsoluteAddress& lhs,
+                            Imm32 rhs, Label* label)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   template <class L>
+   inline void branchTestPtr(Condition cond, Register lhs, Register rhs,
+@@ -1757,7 +1765,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   inline void branchTestInt32(Condition cond, Register tag,
+                               Label* label) PER_SHARED_ARCH;
+   inline void branchTestDouble(Condition cond, Register tag, Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+   inline void branchTestNumber(Condition cond, Register tag,
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestBoolean(Condition cond, Register tag,
+@@ -1789,7 +1797,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                   Label* label) PER_SHARED_ARCH;
+   inline void branchTestUndefined(Condition cond, const ValueOperand& value,
+                                   Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestInt32(Condition cond, const Address& address,
+                               Label* label) PER_SHARED_ARCH;
+@@ -1797,7 +1805,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                               Label* label) PER_SHARED_ARCH;
+   inline void branchTestInt32(Condition cond, const ValueOperand& value,
+                               Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestDouble(Condition cond, const Address& address,
+                                Label* label) PER_SHARED_ARCH;
+@@ -1805,11 +1813,11 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestDouble(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestNumber(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestBoolean(Condition cond, const Address& address,
+                                 Label* label) PER_SHARED_ARCH;
+@@ -1817,7 +1825,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                 Label* label) PER_SHARED_ARCH;
+   inline void branchTestBoolean(Condition cond, const ValueOperand& value,
+                                 Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestString(Condition cond, const Address& address,
+                                Label* label) PER_SHARED_ARCH;
+@@ -1825,7 +1833,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestString(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestSymbol(Condition cond, const Address& address,
+                                Label* label) PER_SHARED_ARCH;
+@@ -1833,7 +1841,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestSymbol(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestBigInt(Condition cond, const Address& address,
+                                Label* label) PER_SHARED_ARCH;
+@@ -1841,7 +1849,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestBigInt(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestNull(Condition cond, const Address& address,
+                              Label* label) PER_SHARED_ARCH;
+@@ -1849,7 +1857,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                              Label* label) PER_SHARED_ARCH;
+   inline void branchTestNull(Condition cond, const ValueOperand& value,
+                              Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   // Clobbers the ScratchReg on x64.
+   inline void branchTestObject(Condition cond, const Address& address,
+@@ -1858,7 +1866,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+                                Label* label) PER_SHARED_ARCH;
+   inline void branchTestObject(Condition cond, const ValueOperand& value,
+                                Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestGCThing(Condition cond, const Address& address,
+                                 Label* label) PER_SHARED_ARCH;
+@@ -1869,7 +1877,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void branchTestPrimitive(Condition cond, const ValueOperand& value,
+                                   Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestMagic(Condition cond, const Address& address,
+                               Label* label) PER_SHARED_ARCH;
+@@ -1878,7 +1886,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   template <class L>
+   inline void branchTestMagic(Condition cond, const ValueOperand& value,
+                               L label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   inline void branchTestMagic(Condition cond, const Address& valaddr,
+                               JSWhyMagic why, Label* label) PER_ARCH;
+@@ -1896,17 +1904,17 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // The type of the value should match the type of the method.
+   inline void branchTestInt32Truthy(bool truthy, const ValueOperand& value,
+                                     Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+   inline void branchTestDoubleTruthy(bool truthy, FloatRegister reg,
+                                      Label* label) PER_SHARED_ARCH;
+   inline void branchTestBooleanTruthy(bool truthy, const ValueOperand& value,
+                                       Label* label) PER_ARCH;
+   inline void branchTestStringTruthy(bool truthy, const ValueOperand& value,
+                                      Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+   inline void branchTestBigIntTruthy(bool truthy, const ValueOperand& value,
+                                      Label* label)
+-      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared);
++      DEFINED_ON(arm, arm64, mips32, mips64, loong64, x86_shared, riscv64);
+ 
+   // Create an unconditional branch to the address given as argument.
+   inline void branchToComputedAddress(const BaseIndex& address) PER_ARCH;
+@@ -2008,11 +2016,11 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void cmp32Move32(Condition cond, Register lhs, Register rhs,
+                           Register src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared, riscv64);
+ 
+   inline void cmp32Move32(Condition cond, Register lhs, const Address& rhs,
+                           Register src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared, riscv64);
+ 
+   inline void cmpPtrMovePtr(Condition cond, Register lhs, Register rhs,
+                             Register src, Register dest) PER_ARCH;
+@@ -2022,36 +2030,36 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void cmp32Load32(Condition cond, Register lhs, const Address& rhs,
+                           const Address& src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared, riscv64);
+ 
+   inline void cmp32Load32(Condition cond, Register lhs, Register rhs,
+                           const Address& src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86_shared, riscv64);
+ 
+   inline void cmp32LoadPtr(Condition cond, const Address& lhs, Imm32 rhs,
+                            const Address& src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64, riscv64);
+ 
+   inline void cmp32MovePtr(Condition cond, Register lhs, Imm32 rhs,
+                            Register src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64, riscv64);
+ 
+   inline void test32LoadPtr(Condition cond, const Address& addr, Imm32 mask,
+                             const Address& src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64, riscv64);
+ 
+   inline void test32MovePtr(Condition cond, const Address& addr, Imm32 mask,
+                             Register src, Register dest)
+-      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64);
++      DEFINED_ON(arm, arm64, loong64, mips_shared, x86, x64, riscv64);
+ 
+   // Conditional move for Spectre mitigations.
+   inline void spectreMovePtr(Condition cond, Register src, Register dest)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   // Zeroes dest if the condition is true.
+   inline void spectreZeroRegister(Condition cond, Register scratch,
+                                   Register dest)
+-      DEFINED_ON(arm, arm64, mips_shared, x86_shared, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86_shared, loong64, riscv64);
+ 
+   // Performs a bounds check and zeroes the index register if out-of-bounds
+   // (to mitigate Spectre).
+@@ -2063,17 +2071,17 @@ class MacroAssembler : public MacroAssemblerSpecific {
+  public:
+   inline void spectreBoundsCheck32(Register index, Register length,
+                                    Register maybeScratch, Label* failure)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void spectreBoundsCheck32(Register index, const Address& length,
+                                    Register maybeScratch, Label* failure)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   inline void spectreBoundsCheckPtr(Register index, Register length,
+                                     Register maybeScratch, Label* failure)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+   inline void spectreBoundsCheckPtr(Register index, const Address& length,
+                                     Register maybeScratch, Label* failure)
+-      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64);
++      DEFINED_ON(arm, arm64, mips_shared, x86, x64, loong64, riscv64);
+ 
+   // ========================================================================
+   // Canonicalization primitives.
+@@ -2087,10 +2095,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // ========================================================================
+   // Memory access primitives.
+   inline void storeUncanonicalizedDouble(FloatRegister src, const Address& dest)
+-      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64);
++      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64, riscv64);
+   inline void storeUncanonicalizedDouble(FloatRegister src,
+                                          const BaseIndex& dest)
+-      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64);
++      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64, riscv64);
+   inline void storeUncanonicalizedDouble(FloatRegister src, const Operand& dest)
+       DEFINED_ON(x86_shared);
+ 
+@@ -2104,10 +2112,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   inline void storeUncanonicalizedFloat32(FloatRegister src,
+                                           const Address& dest)
+-      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64);
++      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64, riscv64);
+   inline void storeUncanonicalizedFloat32(FloatRegister src,
+                                           const BaseIndex& dest)
+-      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64);
++      DEFINED_ON(x86_shared, arm, arm64, mips32, mips64, loong64, riscv64);
+   inline void storeUncanonicalizedFloat32(FloatRegister src,
+                                           const Operand& dest)
+       DEFINED_ON(x86_shared);
+@@ -3508,10 +3516,10 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   // temp required on x86 and x64; must be undefined on mips64 and loong64.
+   void convertUInt64ToFloat32(Register64 src, FloatRegister dest, Register temp)
+-      DEFINED_ON(arm64, mips64, loong64, x64, x86);
++      DEFINED_ON(arm64, mips64, loong64, x64, x86, riscv64);
+ 
+   void convertInt64ToFloat32(Register64 src, FloatRegister dest)
+-      DEFINED_ON(arm64, mips64, loong64, x64, x86);
++      DEFINED_ON(arm64, mips64, loong64, x64, x86, riscv64);
+ 
+   bool convertUInt64ToDoubleNeedsTemp() PER_ARCH;
+ 
+@@ -3563,19 +3571,19 @@ class MacroAssembler : public MacroAssemblerSpecific {
+ 
+   void wasmBoundsCheck32(Condition cond, Register index,
+                          Register boundsCheckLimit, Label* ok)
+-      DEFINED_ON(arm, arm64, mips32, mips64, x86_shared, loong64);
++      DEFINED_ON(arm, arm64, mips32, mips64, x86_shared, loong64, riscv64);
+ 
+   void wasmBoundsCheck32(Condition cond, Register index,
+                          Address boundsCheckLimit, Label* ok)
+-      DEFINED_ON(arm, arm64, mips32, mips64, x86_shared, loong64);
++      DEFINED_ON(arm, arm64, mips32, mips64, x86_shared, loong64, riscv64);
+ 
+   void wasmBoundsCheck64(Condition cond, Register64 index,
+                          Register64 boundsCheckLimit, Label* ok)
+-      DEFINED_ON(arm64, mips64, x64, x86, arm, loong64);
++      DEFINED_ON(arm64, mips64, x64, x86, arm, loong64, riscv64);
+ 
+   void wasmBoundsCheck64(Condition cond, Register64 index,
+                          Address boundsCheckLimit, Label* ok)
+-      DEFINED_ON(arm64, mips64, x64, x86, arm, loong64);
++      DEFINED_ON(arm64, mips64, x64, x86, arm, loong64, riscv64);
+ 
+   // Each wasm load/store instruction appends its own wasm::Trap::OutOfBounds.
+   void wasmLoad(const wasm::MemoryAccessDesc& access, Operand srcAddr,
+@@ -3668,7 +3676,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   void oolWasmTruncateCheckF64ToI32(FloatRegister input, Register output,
+                                     TruncFlags flags, wasm::BytecodeOffset off,
+                                     Label* rejoin)
+-      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64);
++      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64, riscv64);
+ 
+   void wasmTruncateFloat32ToUInt32(FloatRegister input, Register output,
+                                    bool isSaturating, Label* oolEntry) PER_ARCH;
+@@ -3678,35 +3686,35 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   void oolWasmTruncateCheckF32ToI32(FloatRegister input, Register output,
+                                     TruncFlags flags, wasm::BytecodeOffset off,
+                                     Label* rejoin)
+-      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64);
++      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64, riscv64);
+ 
+   // The truncate-to-int64 methods will always bind the `oolRejoin` label
+   // after the last emitted instruction.
+   void wasmTruncateDoubleToInt64(FloatRegister input, Register64 output,
+                                  bool isSaturating, Label* oolEntry,
+                                  Label* oolRejoin, FloatRegister tempDouble)
+-      DEFINED_ON(arm64, x86, x64, mips64, loong64);
++      DEFINED_ON(arm64, x86, x64, mips64, loong64, riscv64);
+   void wasmTruncateDoubleToUInt64(FloatRegister input, Register64 output,
+                                   bool isSaturating, Label* oolEntry,
+                                   Label* oolRejoin, FloatRegister tempDouble)
+-      DEFINED_ON(arm64, x86, x64, mips64, loong64);
++      DEFINED_ON(arm64, x86, x64, mips64, loong64, riscv64);
+   void oolWasmTruncateCheckF64ToI64(FloatRegister input, Register64 output,
+                                     TruncFlags flags, wasm::BytecodeOffset off,
+                                     Label* rejoin)
+-      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64);
++      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64, riscv64);
+ 
+   void wasmTruncateFloat32ToInt64(FloatRegister input, Register64 output,
+                                   bool isSaturating, Label* oolEntry,
+                                   Label* oolRejoin, FloatRegister tempDouble)
+-      DEFINED_ON(arm64, x86, x64, mips64, loong64);
++      DEFINED_ON(arm64, x86, x64, mips64, loong64, riscv64);
+   void wasmTruncateFloat32ToUInt64(FloatRegister input, Register64 output,
+                                    bool isSaturating, Label* oolEntry,
+                                    Label* oolRejoin, FloatRegister tempDouble)
+-      DEFINED_ON(arm64, x86, x64, mips64, loong64);
++      DEFINED_ON(arm64, x86, x64, mips64, loong64, riscv64);
+   void oolWasmTruncateCheckF32ToI64(FloatRegister input, Register64 output,
+                                     TruncFlags flags, wasm::BytecodeOffset off,
+                                     Label* rejoin)
+-      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64);
++      DEFINED_ON(arm, arm64, x86_shared, mips_shared, loong64, riscv64);
+ 
+   void loadWasmGlobalPtr(uint32_t globalDataOffset, Register dest);
+ 
+@@ -3764,7 +3772,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   // convention, which requires predictable high bits.  In practice, this means
+   // that the 32-bit value will be zero-extended or sign-extended to 64 bits as
+   // appropriate for the platform.
+-  void widenInt32(Register r) DEFINED_ON(arm64, x64, mips64, loong64);
++  void widenInt32(Register r) DEFINED_ON(arm64, x64, mips64, loong64, riscv64);
+ 
+   // As enterFakeExitFrame(), but using register conventions appropriate for
+   // wasm stubs.
+@@ -5006,7 +5014,7 @@ class MacroAssembler : public MacroAssemblerSpecific {
+   inline void addStackPtrTo(T t);
+ 
+   void subFromStackPtr(Imm32 imm32)
+-      DEFINED_ON(mips32, mips64, loong64, arm, x86, x64);
++      DEFINED_ON(mips32, mips64, loong64, arm, x86, x64, riscv64);
+   void subFromStackPtr(Register reg);
+ 
+   template <typename T>
+diff --git a/js/src/jit/MoveEmitter.h b/js/src/jit/MoveEmitter.h
+index a51cbc100a..ea4d92bedc 100644
+--- a/js/src/jit/MoveEmitter.h
++++ b/js/src/jit/MoveEmitter.h
+@@ -17,6 +17,8 @@
+ #  include "jit/mips32/MoveEmitter-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/MoveEmitter-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/MoveEmitter-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/MoveEmitter-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/Registers.h b/js/src/jit/Registers.h
+index 2c1cec0771..baf0630e07 100644
+--- a/js/src/jit/Registers.h
++++ b/js/src/jit/Registers.h
+@@ -20,6 +20,8 @@
+ #  include "jit/mips32/Architecture-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/Architecture-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/Architecture-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/Architecture-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/SharedICHelpers-inl.h b/js/src/jit/SharedICHelpers-inl.h
+index 60a77956f0..242f5d3f27 100644
+--- a/js/src/jit/SharedICHelpers-inl.h
++++ b/js/src/jit/SharedICHelpers-inl.h
+@@ -17,6 +17,8 @@
+ #  include "jit/arm64/SharedICHelpers-arm64-inl.h"
+ #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips-shared/SharedICHelpers-mips-shared-inl.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/SharedICHelpers-riscv64-inl.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/SharedICHelpers-loong64-inl.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/SharedICHelpers.h b/js/src/jit/SharedICHelpers.h
+index da8378ebae..bfe4a1b672 100644
+--- a/js/src/jit/SharedICHelpers.h
++++ b/js/src/jit/SharedICHelpers.h
+@@ -17,6 +17,8 @@
+ #  include "jit/arm64/SharedICHelpers-arm64.h"
+ #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips-shared/SharedICHelpers-mips-shared.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/SharedICHelpers-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/SharedICHelpers-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/SharedICRegisters.h b/js/src/jit/SharedICRegisters.h
+index e29f21c28d..4091d9f595 100644
+--- a/js/src/jit/SharedICRegisters.h
++++ b/js/src/jit/SharedICRegisters.h
+@@ -19,6 +19,8 @@
+ #  include "jit/mips32/SharedICRegisters-mips32.h"
+ #elif defined(JS_CODEGEN_MIPS64)
+ #  include "jit/mips64/SharedICRegisters-mips64.h"
++#elif defined(JS_CODEGEN_RISCV64)
++#  include "jit/riscv64/SharedICRegisters-riscv64.h"
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  include "jit/loong64/SharedICRegisters-loong64.h"
+ #elif defined(JS_CODEGEN_NONE)
+diff --git a/js/src/jit/moz.build b/js/src/jit/moz.build
+index 967146e32f..1519351bbb 100644
+--- a/js/src/jit/moz.build
++++ b/js/src/jit/moz.build
+@@ -212,6 +212,13 @@ elif CONFIG["JS_CODEGEN_MIPS32"] or CONFIG["JS_CODEGEN_MIPS64"]:
+         ]
+         if CONFIG["JS_SIMULATOR_MIPS64"]:
+             UNIFIED_SOURCES += ["mips64/Simulator-mips64.cpp"]
++elif CONFIG["JS_CODEGEN_RISCV64"]:
++    UNIFIED_SOURCES += [
++        "riscv64/Assembler-riscv64.cpp",
++        "riscv64/Trampoline-riscv64.cpp",
++    ]
++    if CONFIG["JS_SIMULATOR_RISC64"]:
++        UNIFIED_SOURCES += ["riscv64/Simulator-riscv64.cpp"]
+ elif CONFIG["JS_CODEGEN_LOONG64"]:
+     UNIFIED_SOURCES += [
+         "loong64/Architecture-loong64.cpp",
+@@ -225,7 +232,6 @@ elif CONFIG["JS_CODEGEN_LOONG64"]:
+     if CONFIG["JS_SIMULATOR_LOONG64"]:
+         UNIFIED_SOURCES += ["loong64/Simulator-loong64.cpp"]
+ 
+-
+ # Generate jit/MIROpsGenerated.h from jit/MIROps.yaml
+ GeneratedFile(
+     "MIROpsGenerated.h",
+diff --git a/js/src/jit/riscv64/Architecture-riscv64.h b/js/src/jit/riscv64/Architecture-riscv64.h
+new file mode 100644
+index 0000000000..a676dc142e
+--- /dev/null
++++ b/js/src/jit/riscv64/Architecture-riscv64.h
+@@ -0,0 +1,404 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_Architecture_riscv64_h
++#define jit_riscv64_Architecture_riscv64_h
++
++// JitSpewer.h is included through MacroAssembler implementations for other
++// platforms, so include it here to avoid inadvertent build bustage.
++#include "jit/JitSpewer.h"
++
++#include "jit/shared/Architecture-shared.h"
++
++namespace js {
++namespace jit {
++
++static const uint32_t SimdMemoryAlignment =
++    4;  // Make it 4 to avoid a bunch of div-by-zero warnings
++static const uint32_t WasmStackAlignment = 8;
++static const uint32_t WasmTrapInstructionLength = 0;
++
++// See comments in wasm::GenerateFunctionPrologue.
++static constexpr uint32_t WasmCheckedCallEntryOffset = 0u;
++static constexpr uint32_t WasmCheckedTailEntryOffset = 1u;
++
++class Registers {
++ public:
++  enum RegisterID {
++    x0 = 0,
++    zero = 0,
++    x1 = 1,
++    ra = 1,
++    x2 = 2,
++    sp = 2,
++    x3 = 3,
++    gp = 3,
++    x4 = 4,
++    tp = 4,
++    x5 = 5,
++    t0 = 5,
++    x6 = 6,
++    t1 = 6,
++    x7 = 7,
++    t2 = 7,
++    x8 = 8,
++    fp = 8,
++    s0 = 8,
++    x9 = 9,
++    s1 = 9,
++    x10 = 10,
++    a0 = 10,
++    x11 = 11,
++    a1 = 11,
++    x12 = 12,
++    a2 = 12,
++    x13 = 13,
++    a3 = 13,
++    x14 = 14,
++    a4 = 14,
++    x15 = 15,
++    a5 = 15,
++    x16 = 16,
++    a6 = 16,
++    x17 = 17,
++    a7 = 17,
++    x18 = 18,
++    s2 = 18,
++    x19 = 19,
++    s3 = 19,
++    x20 = 20,
++    s4 = 20,
++    x21 = 21,
++    s5 = 21,
++    x22 = 22,
++    s6 = 22,
++    x23 = 23,
++    s7 = 23,
++    x24 = 24,
++    s8 = 24,
++    x25 = 25,
++    s9 = 25,
++    x26 = 26,
++    s10 = 26,
++    x27 = 27,
++    s11 = 27,
++    x28 = 28,
++    t3 = 28,
++    x29 = 29,
++    t4 = 29,
++    x30 = 30,
++    t5 = 30,
++    x31 = 31,
++    t6 = 31,
++    invalid_reg
++  };
++  typedef uint8_t Code;
++  typedef RegisterID Encoding;
++  union RegisterContent {
++    uintptr_t r;
++  };
++
++  typedef uint32_t SetType;
++
++  static uint32_t SetSize(SetType x) {
++    static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
++    return mozilla::CountPopulation32(x);
++  }
++  static uint32_t FirstBit(SetType x) {
++    return mozilla::CountTrailingZeroes32(x);
++  }
++  static uint32_t LastBit(SetType x) {
++    return 31 - mozilla::CountLeadingZeroes32(x);
++  }
++
++  static const char* GetName(uint32_t code) {
++    // clang-format off
++    static const char* const Names[] = {
++        "zero", "ra", "sp",  "gp",  "tp", "t0", "t1", "t2",
++        "fp",   "s1", "a0",  "a1",  "a2", "a3", "a4", "a5",
++        "a6",   "a7", "s2",  "s3",  "s4", "s5", "s6", "s7",
++        "s8",   "s9", "s10", "s11", "t3", "t4", "t5", "t6"};
++    // clang-format on
++    static_assert(Total == sizeof(Names) / sizeof(Names[0]),
++                  "Table is the correct size");
++    if (code >= Total) {
++      return "invalid";
++    }
++    return Names[code];
++  }
++
++  static Code FromName(const char* name) {
++    for (size_t i = 0; i < Total; i++) {
++      if (strcmp(GetName(Code(i)), name) == 0) {
++        return Code(i);
++      }
++    }
++    return Invalid;
++  }
++
++  static const Encoding StackPointer = sp;
++  static const Encoding Invalid = invalid_reg;
++  static const uint32_t Total = 32;
++  static const uint32_t TotalPhys = 32;
++  static const uint32_t Allocatable = 28;
++  static const SetType AllMask = 0xffffffff;
++  static const SetType ArgRegMask =
++      (1 << Registers::a0) | (1 << Registers::a1) | (1 << Registers::a2) |
++      (1 << Registers::a3) | (1 << Registers::a4) | (1 << Registers::a5) |
++      (1 << Registers::a6) | (1 << Registers::a7);
++  static const SetType VolatileMask =
++      (1 << Registers::a0) | (1 << Registers::a1) | (1 << Registers::a2) |
++      (1 << Registers::a3) | (1 << Registers::a4) | (1 << Registers::a5) |
++      (1 << Registers::a6) | (1 << Registers::a7) | (1 << Registers::t0) |
++      (1 << Registers::t1) | (1 << Registers::t2) | (1 << Registers::t3) |
++      (1 << Registers::t4) | (1 << Registers::t5) | (1 << Registers::t6);
++  static const SetType NonVolatileMask =
++      (1 << Registers::s0) | (1 << Registers::s1) | (1 << Registers::s2) |
++      (1 << Registers::s3) | (1 << Registers::s4) | (1 << Registers::s5) |
++      (1 << Registers::s6) | (1 << Registers::s7) | (1 << Registers::s8) |
++      (1 << Registers::s9) | (1 << Registers::s10) | (1 << Registers::s11);
++  static const SetType NonAllocatableMask =
++      (1 << Registers::zero) | (1 << Registers::sp) | (1 << Registers::tp) |
++      (1 << Registers::gp);
++  static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
++  static const SetType JSCallMask = 0;
++  static const SetType CallMask = 0;
++};
++
++typedef uint8_t PackedRegisterMask;
++
++class FloatRegisters {
++ public:
++  enum FPRegisterID {
++    f0 = 0,
++    ft0 = 0,
++    f1 = 1,
++    ft1 = 1,
++    f2 = 2,
++    ft2 = 2,
++    f3 = 3,
++    ft3 = 3,
++    f4 = 4,
++    ft4 = 4,
++    f5 = 5,
++    ft5 = 5,
++    f6 = 6,
++    ft6 = 6,
++    f7 = 7,
++    ft7 = 7,
++    f8 = 8,
++    fs0 = 8,
++    f9 = 9,
++    fs1 = 9,
++    f10 = 10,
++    fa0 = 10,
++    f11 = 11,
++    fa1 = 11,
++    f12 = 12,
++    fa2 = 12,
++    f13 = 13,
++    fa3 = 13,
++    f14 = 14,
++    fa4 = 14,
++    f15 = 15,
++    fa5 = 15,
++    f16 = 16,
++    fa6 = 16,
++    f17 = 17,
++    fa7 = 17,
++    f18 = 18,
++    fs2 = 18,
++    f19 = 19,
++    fs3 = 19,
++    f20 = 20,
++    fs4 = 20,
++    f21 = 21,
++    fs5 = 21,
++    f22 = 22,
++    fs6 = 22,
++    f23 = 23,
++    fs7 = 23,
++    f24 = 24,
++    fs8 = 24,
++    f25 = 25,
++    fs9 = 25,
++    f26 = 26,
++    fs10 = 26,
++    f27 = 27,
++    fs11 = 27,
++    f28 = 28,
++    ft8 = 28,
++    f29 = 29,
++    ft9 = 29,
++    f30 = 30,
++    ft10 = 30,
++    f31 = 31,
++    ft11 = 31,
++    invalid_reg
++  };
++
++  typedef uint8_t Code;
++  typedef FPRegisterID Encoding;
++  typedef uint32_t SetType;
++
++  enum Kind : uint8_t { Double, Single };
++
++  union RegisterContent {
++    float s;
++    double d;
++  };
++
++  static const char* GetName(uint32_t code) {
++    // clang-format off
++    static const char* const Names[] = {
++        "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
++        "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
++        "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
++        "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
++    };
++    // clang-format on
++    static_assert(Total == sizeof(Names) / sizeof(Names[0]),
++                  "Table is the correct size");
++    if (code >= Total) {
++      return "invalid";
++    }
++    return Names[code];
++  }
++  static Code FromName(const char* name) {
++    for (size_t i = 0; i < Total; i++) {
++      if (strcmp(GetName(i), name) == 0) {
++        return Code(i);
++      }
++    }
++
++    return Invalid;
++  }
++
++  static constexpr Encoding encoding(Code c) { return Encoding(c & 31); }
++
++  static const Encoding Invalid = invalid_reg;
++  static const uint32_t Total = 32;
++  static const uint32_t TotalPhys = 32;
++  static const uint32_t Allocatable = 32;
++  static const SetType AllMask = 0xffffffff;
++  static const SetType AllDoubleMask = 0;
++  static const SetType AllSingleMask = 0;
++  static const SetType VolatileMask =
++      (1 << FloatRegisters::ft0) | (1 << FloatRegisters::ft1) |
++      (1 << FloatRegisters::ft2) | (1 << FloatRegisters::ft3) |
++      (1 << FloatRegisters::ft4) | (1 << FloatRegisters::ft5) |
++      (1 << FloatRegisters::ft6) | (1 << FloatRegisters::ft7) |
++      (1 << FloatRegisters::ft8) | (1 << FloatRegisters::ft9) |
++      (1 << FloatRegisters::ft10) | (1 << FloatRegisters::ft11) |
++      (1 << FloatRegisters::fa0) | (1 << FloatRegisters::fa1) |
++      (1 << FloatRegisters::fa2) | (1 << FloatRegisters::fa3) |
++      (1 << FloatRegisters::fa4) | (1 << FloatRegisters::fa5) |
++      (1 << FloatRegisters::fa6) | (1 << FloatRegisters::fa7);
++  static const SetType NonVolatileMask =
++      (1 << FloatRegisters::fs0) | (1 << FloatRegisters::fs1) |
++      (1 << FloatRegisters::fs2) | (1 << FloatRegisters::fs3) |
++      (1 << FloatRegisters::fs4) | (1 << FloatRegisters::fs5) |
++      (1 << FloatRegisters::fs6) | (1 << FloatRegisters::fs7) |
++      (1 << FloatRegisters::fs8) | (1 << FloatRegisters::fs9) |
++      (1 << FloatRegisters::fs10) | (1 << FloatRegisters::fs11);
++  static const SetType NonAllocatableMask = 0;
++  static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
++};
++
++template <typename T>
++class TypedRegisterSet;
++
++struct FloatRegister {
++  typedef FloatRegisters Codes;
++  typedef size_t Code;
++  typedef Codes::Encoding Encoding;
++  typedef Codes::SetType SetType;
++  typedef Codes::Kind Kind;
++
++ private:
++  uint8_t encoding_;
++  uint8_t kind_;
++  bool invalid_;
++
++ public:
++  constexpr FloatRegister(Encoding encoding)
++      : encoding_(encoding), kind_(FloatRegisters::Double), invalid_(false) {}
++  constexpr FloatRegister(Encoding encoding, Kind kind)
++      : encoding_(encoding), kind_(kind), invalid_(false) {}
++  constexpr FloatRegister()
++      : encoding_(0), kind_(FloatRegisters::Double), invalid_(true) {}
++
++  static uint32_t FirstBit(SetType) { MOZ_CRASH(); }
++  static uint32_t LastBit(SetType) { MOZ_CRASH(); }
++  static FloatRegister FromCode(uint32_t i) {
++    return FloatRegister(FloatRegisters::encoding(i), FloatRegisters::Double);
++  }
++  bool isSingle() const { return kind_ == FloatRegisters::Single; }
++  bool isDouble() const { return kind_ == FloatRegisters::Double; }
++  bool isSimd128() const { return false; }
++  bool isInvalid() const { return invalid_; }
++  FloatRegister asSingle() const { MOZ_CRASH(); }
++  FloatRegister asDouble() const { MOZ_CRASH(); }
++  FloatRegister asSimd128() const { MOZ_CRASH(); }
++  Code code() const { MOZ_CRASH(); }
++  Encoding encoding() const { return Encoding(encoding_); }
++  const char* name() const { return FloatRegisters::GetName(code()); }
++  bool volatile_() const { MOZ_CRASH(); }
++  bool operator!=(FloatRegister) const { MOZ_CRASH(); }
++  bool operator==(FloatRegister) const { MOZ_CRASH(); }
++  bool aliases(FloatRegister) const { MOZ_CRASH(); }
++  uint32_t numAliased() const { MOZ_CRASH(); }
++  FloatRegister aliased(uint32_t) { MOZ_CRASH(); }
++  bool equiv(FloatRegister) const { MOZ_CRASH(); }
++  uint32_t size() const { MOZ_CRASH(); }
++  uint32_t numAlignedAliased() const { MOZ_CRASH(); }
++  FloatRegister alignedAliased(uint32_t) { MOZ_CRASH(); }
++  SetType alignedOrDominatedAliasedSet() const { MOZ_CRASH(); }
++
++  static constexpr RegTypeName DefaultType = RegTypeName::Float64;
++
++  template <RegTypeName = DefaultType>
++  static SetType LiveAsIndexableSet(SetType s) {
++    return SetType(0);
++  }
++
++  template <RegTypeName Name = DefaultType>
++  static SetType AllocatableAsIndexableSet(SetType s) {
++    static_assert(Name != RegTypeName::Any, "Allocatable set are not iterable");
++    return SetType(0);
++  }
++
++  template <typename T>
++  static T ReduceSetForPush(T) {
++    MOZ_CRASH();
++  }
++  uint32_t getRegisterDumpOffsetInBytes() {
++    MOZ_CRASH();
++    return 0;
++  }
++  static uint32_t SetSize(SetType x) {
++    MOZ_CRASH();
++    return 0;
++  }
++  static Code FromName(const char* name) { return 0; }
++
++  // This is used in static initializers, so produce a bogus value instead of
++  // crashing.
++  static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>&) {
++    return 0;
++  }
++};
++
++inline bool hasUnaliasedDouble() { MOZ_CRASH(); }
++inline bool hasMultiAlias() { MOZ_CRASH(); }
++
++static const uint32_t ShadowStackSpace = 0;
++static const uint32_t JumpImmediateRange = INT32_MAX;
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_Architecture_riscv64_h */
+diff --git a/js/src/jit/riscv64/Assembler-riscv64.cpp b/js/src/jit/riscv64/Assembler-riscv64.cpp
+new file mode 100644
+index 0000000000..90fa6d87a8
+--- /dev/null
++++ b/js/src/jit/riscv64/Assembler-riscv64.cpp
+@@ -0,0 +1,47 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "jit/riscv64/Assembler-riscv64.h"
++
++using namespace js;
++using namespace js::jit;
++
++ABIArg ABIArgGenerator::next(MIRType type) {
++  switch (type) {
++    case MIRType::Int32:
++    case MIRType::Int64:
++    case MIRType::Pointer:
++    case MIRType::RefOrNull:
++    case MIRType::StackResults:
++      if (intRegIndex_ == NumIntArgRegs) {
++        current_ = ABIArg(stackOffset_);
++        stackOffset_ += sizeof(uintptr_t);
++        break;
++      }
++      current_ = ABIArg(Register::FromCode(intRegIndex_));
++      intRegIndex_++;
++      break;
++
++    case MIRType::Float32:
++    case MIRType::Double:
++      if (floatRegIndex_ == NumFloatArgRegs) {
++        current_ = ABIArg(stackOffset_);
++        stackOffset_ += sizeof(double);
++        break;
++      }
++      current_ = ABIArg(FloatRegister(FloatRegisters::Encoding(floatRegIndex_),
++                                      type == MIRType::Double
++                                          ? FloatRegisters::Double
++                                          : FloatRegisters::Single));
++      floatRegIndex_++;
++      break;
++
++    case MIRType::Simd128:
++    default:
++      MOZ_CRASH("Unexpected argument type");
++  }
++  return current_;
++}
+diff --git a/js/src/jit/riscv64/Assembler-riscv64.h b/js/src/jit/riscv64/Assembler-riscv64.h
+new file mode 100644
+index 0000000000..a58e6c4aff
+--- /dev/null
++++ b/js/src/jit/riscv64/Assembler-riscv64.h
+@@ -0,0 +1,303 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_Assembler_riscv64_h
++#define jit_riscv64_Assembler_riscv64_h
++
++#include "mozilla/Sprintf.h"
++#include <iterator>
++
++#include "jit/CompactBuffer.h"
++#include "jit/JitCode.h"
++#include "jit/JitSpewer.h"
++#include "jit/riscv64/Architecture-riscv64.h"
++#include "jit/shared/Assembler-shared.h"
++#include "jit/shared/Disassembler-shared.h"
++#include "jit/shared/IonAssemblerBuffer.h"
++#include "wasm/WasmTypeDecls.h"
++
++namespace js {
++namespace jit {
++
++class MacroAssembler;
++
++static constexpr Register t0{Registers::t0};
++static constexpr Register t1{Registers::t1};
++static constexpr Register t2{Registers::t2};
++static constexpr Register t3{Registers::t3};
++static constexpr Register t4{Registers::t4};
++static constexpr Register t5{Registers::t5};
++static constexpr Register t6{Registers::t6};
++static constexpr Register s0{Registers::s0};
++static constexpr Register s4{Registers::s4};
++
++static constexpr Register StackPointer{Registers::sp};
++static constexpr Register FramePointer{Registers::fp};
++static constexpr Register ReturnReg{Registers::a0};
++static constexpr FloatRegister InvalidFloatReg;
++static constexpr FloatRegister ReturnFloat32Reg{FloatRegisters::fa0,
++                                                FloatRegisters::Single};
++static constexpr FloatRegister ReturnDoubleReg{FloatRegisters::fa0,
++                                               FloatRegisters::Double};
++static constexpr FloatRegister ReturnSimd128Reg = InvalidFloatReg;
++static constexpr FloatRegister ScratchSimd128Reg = InvalidFloatReg;
++static constexpr FloatRegister ScratchFloat32Reg_ = InvalidFloatReg;
++static constexpr FloatRegister ScratchDoubleReg_ = InvalidFloatReg;
++
++static constexpr Register ScratchRegister = t6;
++
++// Helper class for ScratchRegister usage. Asserts that only one piece
++// of code thinks it has exclusive ownership of the scratch register.
++struct ScratchRegisterScope : public AutoRegisterScope {
++  explicit ScratchRegisterScope(MacroAssembler& masm)
++      : AutoRegisterScope(masm, ScratchRegister) {}
++};
++
++struct SecondScratchRegisterScope : public AutoRegisterScope {
++  explicit SecondScratchRegisterScope(MacroAssembler& masm);
++};
++
++struct ScratchFloat32Scope : AutoFloatRegisterScope {
++  explicit ScratchFloat32Scope(MacroAssembler& masm)
++      : AutoFloatRegisterScope(masm, ScratchFloat32Reg_) {}
++};
++
++struct ScratchDoubleScope : AutoFloatRegisterScope {
++  explicit ScratchDoubleScope(MacroAssembler& masm)
++      : AutoFloatRegisterScope(masm, ScratchDoubleReg_) {}
++};
++
++static constexpr Register OsrFrameReg{Registers::invalid_reg};
++static constexpr Register PreBarrierReg{Registers::invalid_reg};
++static constexpr Register InterpreterPCReg{Registers::invalid_reg};
++static constexpr Register CallTempReg0 = t0;
++static constexpr Register CallTempReg1 = t1;
++static constexpr Register CallTempReg2 = t2;
++static constexpr Register CallTempReg3 = t3;
++static constexpr Register CallTempReg4 = t4;
++static constexpr Register CallTempReg5 = t5;
++static constexpr Register InvalidReg{Registers::invalid_reg};
++static constexpr Register CallTempNonArgRegs[] = {t0, t1, t2, t3, t4, t5, t6};
++static const uint32_t NumCallTempNonArgRegs = std::size(CallTempNonArgRegs);
++
++static constexpr Register IntArgReg0{Registers::a0};
++static constexpr Register IntArgReg1{Registers::a1};
++static constexpr Register IntArgReg2{Registers::a2};
++static constexpr Register IntArgReg3{Registers::a3};
++static constexpr Register IntArgReg4{Registers::a4};
++static constexpr Register IntArgReg5{Registers::a5};
++static constexpr Register IntArgReg6{Registers::a6};
++static constexpr Register IntArgReg7{Registers::a7};
++static constexpr Register HeapReg{Registers::invalid_reg};
++
++// Registerd used in RegExpTester instruction (do not use ReturnReg).
++static constexpr Register RegExpTesterRegExpReg = CallTempReg0;
++static constexpr Register RegExpTesterStringReg = CallTempReg1;
++static constexpr Register RegExpTesterLastIndexReg = CallTempReg2;
++
++// Registerd used in RegExpMatcher instruction (do not use JSReturnOperand).
++static constexpr Register RegExpMatcherRegExpReg = CallTempReg0;
++static constexpr Register RegExpMatcherStringReg = CallTempReg1;
++static constexpr Register RegExpMatcherLastIndexReg = CallTempReg2;
++
++static constexpr Register JSReturnReg_Type{Registers::a3};
++static constexpr Register JSReturnReg_Data{Registers::a2};
++static constexpr Register JSReturnReg{Registers::a2};
++
++static constexpr Register64 ReturnReg64(ReturnReg);
++
++static constexpr Register ABINonArgReg0{Registers::s0};
++static constexpr Register ABINonArgReg1{Registers::s1};
++static constexpr Register ABINonArgReg2{Registers::s2};
++static constexpr Register ABINonArgReg3{Registers::s3};
++static constexpr Register ABINonArgReturnReg0{Registers::s0};
++static constexpr Register ABINonArgReturnReg1{Registers::s1};
++static constexpr Register ABINonVolatileReg{Registers::fp};
++static constexpr Register ABINonArgReturnVolatileReg{Registers::ra};
++
++static constexpr FloatRegister ABINonArgDoubleReg = InvalidFloatReg;
++
++// Instance pointer argument register for WebAssembly functions. This must not
++// alias any other register used for passing function arguments or return
++// values. Preserved by WebAssembly functions.
++static constexpr Register InstanceReg = s4;
++
++static constexpr Register WasmTableCallScratchReg0{Registers::invalid_reg};
++static constexpr Register WasmTableCallScratchReg1{Registers::invalid_reg};
++static constexpr Register WasmTableCallSigReg{Registers::invalid_reg};
++static constexpr Register WasmTableCallIndexReg{Registers::invalid_reg};
++static constexpr Register WasmTlsReg{Registers::invalid_reg};
++static constexpr Register WasmJitEntryReturnScratch{Registers::invalid_reg};
++
++static constexpr uint32_t ABIStackAlignment = 16;
++static constexpr uint32_t CodeAlignment = 16;
++static constexpr uint32_t JitStackAlignment = 8;
++static constexpr uint32_t JitStackValueAlignment =
++    JitStackAlignment / sizeof(Value);
++
++static const Scale ScalePointer = TimesOne;
++
++class Instruction;
++typedef js::jit::AssemblerBuffer<1024, Instruction> RISCVBuffer;
++
++class Assembler : public AssemblerShared {
++ public:
++  enum RISCVCondition : uint32_t {
++    EQ = 0b000,
++    NE = 0b001,
++    LT = 0b100,
++    GE = 0b101,
++    LTU = 0b110,
++    GEU = 0b111,
++  };
++
++  enum Condition {
++    Equal,
++    NotEqual,
++    Above,
++    AboveOrEqual,
++    Below,
++    BelowOrEqual,
++    GreaterThan,
++    GreaterThanOrEqual,
++    LessThan,
++    LessThanOrEqual,
++    Overflow,
++    CarrySet,
++    CarryClear,
++    Signed,
++    NotSigned,
++    Zero,
++    NonZero,
++    Always,
++  };
++
++  enum DoubleCondition {
++    DoubleOrdered,
++    DoubleEqual,
++    DoubleNotEqual,
++    DoubleGreaterThan,
++    DoubleGreaterThanOrEqual,
++    DoubleLessThan,
++    DoubleLessThanOrEqual,
++    DoubleUnordered,
++    DoubleEqualOrUnordered,
++    DoubleNotEqualOrUnordered,
++    DoubleGreaterThanOrUnordered,
++    DoubleGreaterThanOrEqualOrUnordered,
++    DoubleLessThanOrUnordered,
++    DoubleLessThanOrEqualOrUnordered
++  };
++
++  RISCVBuffer m_buffer;
++
++  BufferOffset nextOffset() { return m_buffer.nextOffset(); }
++
++  static Condition InvertCondition(Condition) { MOZ_CRASH(); }
++
++  static DoubleCondition InvertCondition(DoubleCondition) { MOZ_CRASH(); }
++
++  static void TraceJumpRelocations(JSTracer* trc, JitCode* code,
++                                   CompactBufferReader& reader);
++  static void TraceDataRelocations(JSTracer* trc, JitCode* code,
++                                   CompactBufferReader& reader);
++
++  template <typename T, typename S>
++  static void PatchDataWithValueCheck(CodeLocationLabel, T, S) {
++    MOZ_CRASH();
++  }
++  static void PatchWrite_Imm32(CodeLocationLabel, Imm32) { MOZ_CRASH(); }
++
++  static void PatchWrite_NearCall(CodeLocationLabel, CodeLocationLabel) {
++    MOZ_CRASH();
++  }
++  static uint32_t PatchWrite_NearCallSize() { MOZ_CRASH(); }
++
++  static void ToggleToJmp(CodeLocationLabel) { MOZ_CRASH(); }
++  static void ToggleToCmp(CodeLocationLabel) { MOZ_CRASH(); }
++  static void ToggleCall(CodeLocationLabel, bool) { MOZ_CRASH(); }
++
++  static void Bind(uint8_t* rawCode, const CodeLabel& label) { MOZ_CRASH(); }
++
++  static uintptr_t GetPointer(uint8_t*) { MOZ_CRASH(); }
++
++  static bool HasRoundInstruction(RoundingMode) { return false; }
++
++  void verifyHeapAccessDisassembly(uint32_t begin, uint32_t end,
++                                   const Disassembler::HeapAccess& heapAccess) {
++    MOZ_CRASH();
++  }
++
++  void setUnlimitedBuffer() { MOZ_CRASH(); }
++
++  MOZ_ALWAYS_INLINE BufferOffset writeInst(uint32_t x) {
++    MOZ_ASSERT(hasCreator());
++    return m_buffer.putInt(x);
++  }
++};
++
++class Instruction {
++ protected:
++  uint32_t data;
++
++  // Standard constructor
++  Instruction(uint32_t data_) : data(data_) {}
++
++ public:
++  uint32_t encode() const { return data; }
++
++  void setData(uint32_t data) { this->data = data; }
++  Instruction* next();
++  const uint32_t* raw() const { return &data; }
++  uint32_t size() const { return sizeof(data); }
++};
++
++class Operand {
++ public:
++  enum Kind { REG };
++
++ private:
++  Kind kind_ : 4;
++  uint32_t reg_ : 5;
++  int32_t offset_;
++
++ public:
++  explicit Operand(const Register reg)
++      : kind_(REG), reg_(reg.code()), offset_(0) {}
++  explicit Operand(const FloatRegister) { MOZ_CRASH(); }
++  explicit Operand(const Address& adress) { MOZ_CRASH(); }
++  explicit Operand(Register reg, Imm32 offset)
++      : kind_(REG), reg_(reg.code()), offset_(offset.value) {}
++  explicit Operand(Register reg, int32_t offset)
++      : kind_(REG), reg_(reg.code()), offset_(offset) {}
++
++  Kind kind() const { return kind_; }
++};
++
++static const uint32_t NumIntArgRegs = 8;
++static const uint32_t NumFloatArgRegs = 8;
++
++class ABIArgGenerator {
++ public:
++  ABIArgGenerator()
++      : intRegIndex_(0), floatRegIndex_(0), stackOffset_(0), current_() {}
++
++  ABIArg next(MIRType);
++  ABIArg& current() { return current_; }
++  uint32_t stackBytesConsumedSoFar() const { return stackOffset_; }
++  void increaseStackOffset(uint32_t bytes) { stackOffset_ += bytes; }
++
++ private:
++  unsigned intRegIndex_;
++  unsigned floatRegIndex_;
++  uint32_t stackOffset_;
++  ABIArg current_;
++};
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_Assembler_riscv64_h */
+diff --git a/js/src/jit/riscv64/CodeGenerator-riscv64.h b/js/src/jit/riscv64/CodeGenerator-riscv64.h
+new file mode 100644
+index 0000000000..db30b32283
+--- /dev/null
++++ b/js/src/jit/riscv64/CodeGenerator-riscv64.h
+@@ -0,0 +1,78 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_CodeGenerator_riscv64_h
++#define jit_riscv64_CodeGenerator_riscv64_h
++
++#include "jit/shared/CodeGenerator-shared.h"
++
++namespace js {
++namespace jit {
++
++class CodeGeneratorRiscv64 : public CodeGeneratorShared {
++ protected:
++  CodeGeneratorRiscv64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm)
++      : CodeGeneratorShared(gen, graph, masm) {
++    MOZ_CRASH();
++  }
++
++  MoveOperand toMoveOperand(LAllocation) const { MOZ_CRASH(); }
++  template <typename T1, typename T2>
++  void bailoutCmp32(Assembler::Condition, T1, T2, LSnapshot*) {
++    MOZ_CRASH();
++  }
++  template <typename T1, typename T2>
++  void bailoutTest32(Assembler::Condition, T1, T2, LSnapshot*) {
++    MOZ_CRASH();
++  }
++  template <typename T1, typename T2>
++  void bailoutCmpPtr(Assembler::Condition, T1, T2, LSnapshot*) {
++    MOZ_CRASH();
++  }
++  void bailoutTestPtr(Assembler::Condition, Register, Register, LSnapshot*) {
++    MOZ_CRASH();
++  }
++  void bailoutIfFalseBool(Register, LSnapshot*) { MOZ_CRASH(); }
++  void bailoutFrom(Label*, LSnapshot*) { MOZ_CRASH(); }
++  void bailout(LSnapshot*) { MOZ_CRASH(); }
++  void bailoutIf(Assembler::Condition, LSnapshot*) { MOZ_CRASH(); }
++  bool generateOutOfLineCode() { MOZ_CRASH(); }
++  void testNullEmitBranch(Assembler::Condition, ValueOperand, MBasicBlock*,
++                          MBasicBlock*) {
++    MOZ_CRASH();
++  }
++  void testUndefinedEmitBranch(Assembler::Condition, ValueOperand, MBasicBlock*,
++                               MBasicBlock*) {
++    MOZ_CRASH();
++  }
++  void testObjectEmitBranch(Assembler::Condition, ValueOperand, MBasicBlock*,
++                            MBasicBlock*) {
++    MOZ_CRASH();
++  }
++  void testZeroEmitBranch(Assembler::Condition, Register, MBasicBlock*,
++                          MBasicBlock*) {
++    MOZ_CRASH();
++  }
++  void emitTableSwitchDispatch(MTableSwitch*, Register, Register) {
++    MOZ_CRASH();
++  }
++  void emitBigIntDiv(LBigIntDiv*, Register, Register, Register, Label*) {
++    MOZ_CRASH();
++  }
++  void emitBigIntMod(LBigIntMod*, Register, Register, Register, Label*) {
++    MOZ_CRASH();
++  }
++  ValueOperand ToValue(LInstruction*, size_t) { MOZ_CRASH(); }
++  ValueOperand ToTempValue(LInstruction*, size_t) { MOZ_CRASH(); }
++  void generateInvalidateEpilogue() { MOZ_CRASH(); }
++};
++
++typedef CodeGeneratorRiscv64 CodeGeneratorSpecific;
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_CodeGenerator_riscv64_h */
+diff --git a/js/src/jit/riscv64/LIR-riscv64.h b/js/src/jit/riscv64/LIR-riscv64.h
+new file mode 100644
+index 0000000000..59d42c6c75
+--- /dev/null
++++ b/js/src/jit/riscv64/LIR-riscv64.h
+@@ -0,0 +1,111 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_LIR_riscv64_h
++#define jit_riscv64_LIR_riscv64_h
++
++namespace js {
++namespace jit {
++
++class LUnboxFloatingPoint : public LInstruction {
++ public:
++  LIR_HEADER(UnboxFloatingPoint)
++  static const size_t Input = 0;
++
++  MUnbox* mir() const { MOZ_CRASH(); }
++
++  const LDefinition* output() const { MOZ_CRASH(); }
++  MIRType type() const { MOZ_CRASH(); }
++};
++
++class LTableSwitch : public LInstruction {
++ public:
++  LIR_HEADER(TableSwitch)
++  MTableSwitch* mir() { MOZ_CRASH(); }
++
++  const LAllocation* index() { MOZ_CRASH(); }
++  const LDefinition* tempInt() { MOZ_CRASH(); }
++  const LDefinition* tempPointer() { MOZ_CRASH(); }
++};
++
++class LTableSwitchV : public LInstruction {
++ public:
++  LIR_HEADER(TableSwitchV)
++  MTableSwitch* mir() { MOZ_CRASH(); }
++
++  const LDefinition* tempInt() { MOZ_CRASH(); }
++  const LDefinition* tempFloat() { MOZ_CRASH(); }
++  const LDefinition* tempPointer() { MOZ_CRASH(); }
++
++  static const size_t InputValue = 0;
++};
++
++class LWasmUint32ToFloat32 : public LInstructionHelper<1, 1, 0> {
++ public:
++  explicit LWasmUint32ToFloat32(const LAllocation&)
++      : LInstructionHelper(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++};
++
++class LUnbox : public LInstructionHelper<1, 2, 0> {
++ public:
++  MUnbox* mir() const { MOZ_CRASH(); }
++  const LAllocation* payload() { MOZ_CRASH(); }
++  const LAllocation* type() { MOZ_CRASH(); }
++  const char* extraName() const { MOZ_CRASH(); }
++};
++class LDivI : public LBinaryMath<1> {
++ public:
++  LDivI(const LAllocation&, const LAllocation&, const LDefinition&)
++      : LBinaryMath(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++  MDiv* mir() const { MOZ_CRASH(); }
++};
++class LDivPowTwoI : public LInstructionHelper<1, 1, 0> {
++ public:
++  LDivPowTwoI(const LAllocation&, int32_t)
++      : LInstructionHelper(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++  const LAllocation* numerator() { MOZ_CRASH(); }
++  int32_t shift() { MOZ_CRASH(); }
++  MDiv* mir() const { MOZ_CRASH(); }
++};
++class LModI : public LBinaryMath<1> {
++ public:
++  LModI(const LAllocation&, const LAllocation&, const LDefinition&)
++      : LBinaryMath(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++
++  const LDefinition* callTemp() { MOZ_CRASH(); }
++  MMod* mir() const { MOZ_CRASH(); }
++};
++class LWasmUint32ToDouble : public LInstructionHelper<1, 1, 0> {
++ public:
++  explicit LWasmUint32ToDouble(const LAllocation&)
++      : LInstructionHelper(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++};
++class LModPowTwoI : public LInstructionHelper<1, 1, 0> {
++ public:
++  int32_t shift() { MOZ_CRASH(); }
++  LModPowTwoI(const LAllocation& lhs, int32_t shift)
++      : LInstructionHelper(Opcode::Invalid) {
++    MOZ_CRASH();
++  }
++  MMod* mir() const { MOZ_CRASH(); }
++};
++
++class LMulI : public LInstruction {};
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_LIR_riscv64_h */
+diff --git a/js/src/jit/riscv64/Lowering-riscv64.h b/js/src/jit/riscv64/Lowering-riscv64.h
+new file mode 100644
+index 0000000000..a68e52b872
+--- /dev/null
++++ b/js/src/jit/riscv64/Lowering-riscv64.h
+@@ -0,0 +1,130 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_Lowering_riscv64_h
++#define jit_riscv64_Lowering_riscv64_h
++
++#include "jit/shared/Lowering-shared.h"
++
++namespace js {
++namespace jit {
++
++class LIRGeneratorRiscv64 : public LIRGeneratorShared {
++ protected:
++  LIRGeneratorRiscv64(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph)
++      : LIRGeneratorShared(gen, graph, lirGraph) {
++    MOZ_CRASH();
++  }
++
++  LBoxAllocation useBoxFixed(MDefinition*, Register, Register,
++                             bool useAtStart = false) {
++    MOZ_CRASH();
++  }
++
++  LAllocation useByteOpRegister(MDefinition*) { MOZ_CRASH(); }
++  LAllocation useByteOpRegisterAtStart(MDefinition*) { MOZ_CRASH(); }
++  LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition*) {
++    MOZ_CRASH();
++  }
++  LDefinition tempByteOpRegister() { MOZ_CRASH(); }
++  LDefinition tempToUnbox() { MOZ_CRASH(); }
++  bool needTempForPostBarrier() { MOZ_CRASH(); }
++  void lowerUntypedPhiInput(MPhi*, uint32_t, LBlock*, size_t) { MOZ_CRASH(); }
++  void lowerInt64PhiInput(MPhi*, uint32_t, LBlock*, size_t) { MOZ_CRASH(); }
++  void defineInt64Phi(MPhi*, size_t) { MOZ_CRASH(); }
++  void lowerForShift(LInstructionHelper<1, 2, 0>*, MDefinition*, MDefinition*,
++                     MDefinition*) {
++    MOZ_CRASH();
++  }
++  void lowerUrshD(MUrsh*) { MOZ_CRASH(); }
++  void lowerPowOfTwoI(MPow*) { MOZ_CRASH(); }
++  template <typename T>
++  void lowerForALU(T, MDefinition*, MDefinition*, MDefinition* v = nullptr) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void lowerForFPU(T, MDefinition*, MDefinition*, MDefinition* v = nullptr) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void lowerForALUInt64(T, MDefinition*, MDefinition*,
++                        MDefinition* v = nullptr) {
++    MOZ_CRASH();
++  }
++  void lowerForMulInt64(LMulI64*, MMul*, MDefinition*,
++                        MDefinition* v = nullptr) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void lowerForShiftInt64(T, MDefinition*, MDefinition*,
++                          MDefinition* v = nullptr) {
++    MOZ_CRASH();
++  }
++  void lowerForBitAndAndBranch(LBitAndAndBranch*, MInstruction*, MDefinition*,
++                               MDefinition*) {
++    MOZ_CRASH();
++  }
++  void lowerForCompareI64AndBranch(MTest*, MCompare*, JSOp, MDefinition*,
++                                   MDefinition*, MBasicBlock*, MBasicBlock*) {
++    MOZ_CRASH();
++  }
++
++  void lowerConstantDouble(double, MInstruction*) { MOZ_CRASH(); }
++  void lowerConstantFloat32(float, MInstruction*) { MOZ_CRASH(); }
++  void lowerTruncateDToInt32(MTruncateToInt32*) { MOZ_CRASH(); }
++  void lowerTruncateFToInt32(MTruncateToInt32*) { MOZ_CRASH(); }
++  void lowerBuiltinInt64ToFloatingPoint(MBuiltinInt64ToFloatingPoint* ins) {
++    MOZ_CRASH();
++  }
++  void lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64* ins) {
++    MOZ_CRASH();
++  }
++  void lowerWasmBuiltinTruncateToInt32(MWasmBuiltinTruncateToInt32* ins) {
++    MOZ_CRASH();
++  }
++  void lowerDivI(MDiv*) { MOZ_CRASH(); }
++  void lowerModI(MMod*) { MOZ_CRASH(); }
++  void lowerDivI64(MDiv*) { MOZ_CRASH(); }
++  void lowerWasmBuiltinDivI64(MWasmBuiltinDivI64* div) { MOZ_CRASH(); }
++  void lowerModI64(MMod*) { MOZ_CRASH(); }
++  void lowerWasmBuiltinModI64(MWasmBuiltinModI64* mod) { MOZ_CRASH(); }
++  void lowerNegI(MInstruction*, MDefinition*) { MOZ_CRASH(); }
++  void lowerNegI64(MInstruction*, MDefinition*) { MOZ_CRASH(); }
++  void lowerMulI(MMul*, MDefinition*, MDefinition*) { MOZ_CRASH(); }
++  void lowerUDiv(MDiv*) { MOZ_CRASH(); }
++  void lowerUMod(MMod*) { MOZ_CRASH(); }
++  void lowerWasmSelectI(MWasmSelect* select) { MOZ_CRASH(); }
++  void lowerWasmSelectI64(MWasmSelect* select) { MOZ_CRASH(); }
++  void lowerWasmCompareAndSelect(MWasmSelect* ins, MDefinition* lhs,
++                                 MDefinition* rhs, MCompare::CompareType compTy,
++                                 JSOp jsop) {
++    MOZ_CRASH();
++  }
++  bool canSpecializeWasmCompareAndSelect(MCompare::CompareType compTy,
++                                         MIRType insTy) {
++    MOZ_CRASH();
++  }
++
++  void lowerBigIntLsh(MBigIntLsh*) { MOZ_CRASH(); }
++  void lowerBigIntRsh(MBigIntRsh*) { MOZ_CRASH(); }
++  void lowerBigIntDiv(MBigIntDiv*) { MOZ_CRASH(); }
++  void lowerBigIntMod(MBigIntMod*) { MOZ_CRASH(); }
++
++  void lowerAtomicLoad64(MLoadUnboxedScalar*) { MOZ_CRASH(); }
++  void lowerAtomicStore64(MStoreUnboxedScalar*) { MOZ_CRASH(); }
++
++  LTableSwitch* newLTableSwitch(LAllocation, LDefinition, MTableSwitch*) {
++    MOZ_CRASH();
++  }
++  LTableSwitchV* newLTableSwitchV(MTableSwitch*) { MOZ_CRASH(); }
++};
++
++typedef LIRGeneratorRiscv64 LIRGeneratorSpecific;
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_Lowering_riscv64_h */
+diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h b/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h
+new file mode 100644
+index 0000000000..3dd6273d0f
+--- /dev/null
++++ b/js/src/jit/riscv64/MacroAssembler-riscv64-inl.h
+@@ -0,0 +1,18 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_MacroAssembler_riscv64_inl_h
++#define jit_riscv64_MacroAssembler_riscv64_inl_h
++
++#include "jit/riscv64/MacroAssembler-riscv64.h"
++
++namespace js {
++namespace jit {
++
++}  // namespace jit
++}  // namespace js
++
++#endif
+diff --git a/js/src/jit/riscv64/MacroAssembler-riscv64.h b/js/src/jit/riscv64/MacroAssembler-riscv64.h
+new file mode 100644
+index 0000000000..30ca17d359
+--- /dev/null
++++ b/js/src/jit/riscv64/MacroAssembler-riscv64.h
+@@ -0,0 +1,458 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_MacroAssembler_riscv64_h
++#define jit_riscv64_MacroAssembler_riscv64_h
++
++#include "jit/riscv64/Assembler-riscv64.h"
++#include "jit/MoveResolver.h"
++#include "wasm/WasmBuiltins.h"
++
++namespace js {
++namespace jit {
++
++static constexpr ValueOperand JSReturnOperand{JSReturnReg};
++
++class ScratchTagScope : public SecondScratchRegisterScope {
++ public:
++  ScratchTagScope(MacroAssembler& masm, const js::jit::ValueOperand&)
++      : SecondScratchRegisterScope(masm) {}
++};
++
++class ScratchTagScopeRelease {
++  ScratchTagScope* ts_;
++
++ public:
++  explicit ScratchTagScopeRelease(ScratchTagScope* ts) : ts_(ts) {
++    ts_->release();
++  }
++
++  ~ScratchTagScopeRelease() { ts_->reacquire(); }
++};
++
++class MacroAssemblerRiscv64 : public Assembler {
++ protected:
++  // Perform a downcast. Should be removed by Bug 996602.
++  MacroAssembler& asMasm();
++  const MacroAssembler& asMasm() const;
++
++ public:
++  MacroAssemblerRiscv64() { MOZ_CRASH(); }
++
++  MoveResolver moveResolver_;
++
++  size_t size() const { MOZ_CRASH(); }
++  size_t bytesNeeded() const { MOZ_CRASH(); }
++  size_t jumpRelocationTableBytes() const { MOZ_CRASH(); }
++  size_t dataRelocationTableBytes() const { MOZ_CRASH(); }
++  size_t preBarrierTableBytes() const { MOZ_CRASH(); }
++
++  size_t numCodeLabels() const { MOZ_CRASH(); }
++  CodeLabel codeLabel(size_t) { MOZ_CRASH(); }
++
++  bool reserve(size_t size) { MOZ_CRASH(); }
++  bool appendRawCode(const uint8_t* code, size_t numBytes) { MOZ_CRASH(); }
++  bool swapBuffer(wasm::Bytes& bytes) { MOZ_CRASH(); }
++
++  void assertNoGCThings() const { MOZ_CRASH(); }
++
++  static bool SupportsFloatingPoint() { return false; }
++  static bool SupportsUnalignedAccesses() { return false; }
++  static bool SupportsFastUnalignedFPAccesses() { return false; }
++
++  void executableCopy(void*, bool = true) { MOZ_CRASH(); }
++  void copyJumpRelocationTable(uint8_t*) { MOZ_CRASH(); }
++  void copyDataRelocationTable(uint8_t*) { MOZ_CRASH(); }
++  void copyPreBarrierTable(uint8_t*) { MOZ_CRASH(); }
++  void processCodeLabels(uint8_t*) { MOZ_CRASH(); }
++
++  void flushBuffer() {}
++
++  template <typename T>
++  void bind(T) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void j(Condition, T) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void jump(T) {
++    MOZ_CRASH();
++  }
++  void writeCodePointer(CodeLabel* label) {
++    MOZ_CRASH();
++  }
++  void haltingAlign(size_t) { MOZ_CRASH(); }
++  void nopAlign(size_t) { MOZ_CRASH(); }
++  void checkStackAlignment() { MOZ_CRASH(); }
++  uint32_t currentOffset() { return nextOffset().getOffset(); }
++
++  void nop() { MOZ_CRASH(); }
++  void breakpoint() { MOZ_CRASH(); }
++  void abiret() { MOZ_CRASH(); }
++  void ret() { MOZ_CRASH(); }
++
++  CodeOffset toggledJump(Label*) { MOZ_CRASH(); }
++  CodeOffset toggledCall(JitCode*, bool) { MOZ_CRASH(); }
++  static size_t ToggledCallSize(uint8_t*) { MOZ_CRASH(); }
++
++  void finish() { MOZ_CRASH(); }
++
++  template <typename T, typename S>
++  void moveValue(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S, typename U>
++  void moveValue(T, S, U) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void storeValue(const T&, const S&) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S, typename U>
++  void storeValue(T, S, U) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void storePrivateValue(const T&, const S&) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void loadValue(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void loadUnalignedValue(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void pushValue(const T&) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void pushValue(T, S) {
++    MOZ_CRASH();
++  }
++  void popValue(ValueOperand) { MOZ_CRASH(); }
++  void tagValue(JSValueType, Register, ValueOperand) { MOZ_CRASH(); }
++  void retn(Imm32 n) { MOZ_CRASH(); }
++  template <typename T>
++  void push(const T&) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void Push(T) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void pop(T) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void Pop(T) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  CodeOffset pushWithPatch(T) {
++    MOZ_CRASH();
++  }
++
++  void testNullSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
++  void testObjectSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
++  void testUndefinedSet(Condition, ValueOperand, Register) { MOZ_CRASH(); }
++
++  template <typename T, typename S>
++  void cmpPtrSet(Condition, T, S, Register) {
++    MOZ_CRASH();
++  }
++  void cmp8Set(Condition, Address, Imm32, Register) { MOZ_CRASH(); }
++  void cmp16Set(Condition, Address, Imm32, Register) { MOZ_CRASH(); }
++  template <typename T, typename S>
++  void cmp32Set(Condition, T, S, Register) {
++    MOZ_CRASH();
++  }
++  void cmp64Set(Condition, Address, Imm64, Register) { MOZ_CRASH(); }
++
++  template <typename T>
++  void mov(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void movePtr(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void move32(const T&, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void movq(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void moveFloat32(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void moveDouble(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void move64(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  CodeOffset movWithPatch(T, Register) {
++    MOZ_CRASH();
++  }
++
++  template <typename T>
++  void loadPtr(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load32(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load32Unaligned(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void loadFloat32(T, FloatRegister) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void loadDouble(T, FloatRegister) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void loadPrivate(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load8SignExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load8ZeroExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load16SignExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load16UnalignedSignExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load16ZeroExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load16UnalignedZeroExtend(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load64(T, Register64) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void load64Unaligned(T, Register64) {
++    MOZ_CRASH();
++  }
++
++  template <typename T, typename S>
++  void storePtr(const T&, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store32(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store32_NoSecondScratch(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store32Unaligned(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void storeFloat32(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void storeDouble(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store8(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store16(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store16Unaligned(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store64(T, S) {
++    MOZ_CRASH();
++  }
++  template <typename T, typename S>
++  void store64Unaligned(T, S) {
++    MOZ_CRASH();
++  }
++
++  template <typename T>
++  void computeEffectiveAddress(T, Register) {
++    MOZ_CRASH();
++  }
++
++  void splitTagForTest(ValueOperand, ScratchTagScope&) { MOZ_CRASH(); }
++
++  void boxDouble(FloatRegister, ValueOperand, FloatRegister) { MOZ_CRASH(); }
++  void boxNonDouble(JSValueType, Register, ValueOperand) { MOZ_CRASH(); }
++  template <typename T>
++  void boxDouble(FloatRegister src, const T& dest) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxInt32(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxBoolean(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxString(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxSymbol(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxBigInt(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxObject(T, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxDouble(T, FloatRegister) {
++    MOZ_CRASH();
++  }
++  void unboxValue(const ValueOperand&, AnyRegister, JSValueType) {
++    MOZ_CRASH();
++  }
++  void unboxNonDouble(const ValueOperand&, Register, JSValueType) {
++    MOZ_CRASH();
++  }
++  void unboxNonDouble(const Address&, Register, JSValueType) { MOZ_CRASH(); }
++  template <typename T>
++  void unboxGCThingForGCBarrier(const T&, Register) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void unboxObjectOrNull(const T& src, Register dest) {
++    MOZ_CRASH();
++  }
++  void notBoolean(ValueOperand) { MOZ_CRASH(); }
++  [[nodiscard]] Register extractObject(Address, Register) { MOZ_CRASH(); }
++  [[nodiscard]] Register extractObject(ValueOperand, Register) { MOZ_CRASH(); }
++  [[nodiscard]] Register extractSymbol(ValueOperand, Register) { MOZ_CRASH(); }
++  [[nodiscard]] Register extractInt32(ValueOperand, Register) { MOZ_CRASH(); }
++  [[nodiscard]] Register extractBoolean(ValueOperand, Register) { MOZ_CRASH(); }
++  template <typename T>
++  [[nodiscard]] Register extractTag(T, Register) {
++    MOZ_CRASH();
++  }
++
++  void convertFloat32ToInt32(FloatRegister, Register, Label*, bool v = true) {
++    MOZ_CRASH();
++  }
++  void convertDoubleToInt32(FloatRegister, Register, Label*, bool v = true) {
++    MOZ_CRASH();
++  }
++  void convertDoubleToPtr(FloatRegister, Register, Label*, bool v = true) {
++    MOZ_CRASH();
++  }
++  void convertBoolToInt32(Register, Register) { MOZ_CRASH(); }
++
++  void convertDoubleToFloat32(FloatRegister, FloatRegister) { MOZ_CRASH(); }
++  void convertInt32ToFloat32(Register, FloatRegister) { MOZ_CRASH(); }
++
++  template <typename T>
++  void convertInt32ToDouble(T, FloatRegister) {
++    MOZ_CRASH();
++  }
++  void convertFloat32ToDouble(FloatRegister, FloatRegister) { MOZ_CRASH(); }
++
++  void boolValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
++  void boolValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
++  void int32ValueToDouble(ValueOperand, FloatRegister) { MOZ_CRASH(); }
++  void int32ValueToFloat32(ValueOperand, FloatRegister) { MOZ_CRASH(); }
++
++  void loadConstantDouble(double, FloatRegister) { MOZ_CRASH(); }
++  void loadConstantFloat32(float, FloatRegister) { MOZ_CRASH(); }
++  Condition testInt32Truthy(bool, ValueOperand) { MOZ_CRASH(); }
++  Condition testStringTruthy(bool, ValueOperand) { MOZ_CRASH(); }
++  Condition testBigIntTruthy(bool, ValueOperand) { MOZ_CRASH(); }
++
++  template <typename T>
++  void loadUnboxedValue(T, MIRType, AnyRegister) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void storeUnboxedValue(const ConstantOrRegister&, MIRType, T, MIRType) {
++    MOZ_CRASH();
++  }
++  template <typename T>
++  void storeUnboxedPayload(ValueOperand value, T, size_t, JSValueType) {
++    MOZ_CRASH();
++  }
++
++  void convertUInt32ToDouble(Register, FloatRegister) { MOZ_CRASH(); }
++  void convertUInt32ToFloat32(Register, FloatRegister) { MOZ_CRASH(); }
++  void incrementInt32Value(Address) { MOZ_CRASH(); }
++  void ensureDouble(ValueOperand, FloatRegister, Label*) { MOZ_CRASH(); }
++
++  void buildFakeExitFrame(Register, uint32_t*) { MOZ_CRASH(); }
++  bool buildOOLFakeExitFrame(void*) { MOZ_CRASH(); }
++
++  void setPrinter(Sprinter*) { MOZ_CRASH(); }
++  Operand ToPayload(Operand base) { MOZ_CRASH(); }
++  Address ToPayload(Address) { MOZ_CRASH(); }
++
++  Register getStackPointer() const { MOZ_CRASH(); }
++
++  void handleFailureWithHandlerTail(Label* profilerExitTail,
++                                    Label* bailoutTail) { MOZ_CRASH(); }
++
++  // Instrumentation for entering and leaving the profiler.
++  void profilerEnterFrame(Register, Register) { MOZ_CRASH(); }
++  void profilerExitFrame() { MOZ_CRASH(); }
++};
++
++typedef MacroAssemblerRiscv64 MacroAssemblerSpecific;
++
++static inline bool GetTempRegForIntArg(uint32_t, uint32_t, Register*) {
++  MOZ_CRASH();
++}
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_MacroAssembler_riscv64_h */
+diff --git a/js/src/jit/riscv64/MoveEmitter-riscv64.h b/js/src/jit/riscv64/MoveEmitter-riscv64.h
+new file mode 100644
+index 0000000000..24ca3aebb2
+--- /dev/null
++++ b/js/src/jit/riscv64/MoveEmitter-riscv64.h
+@@ -0,0 +1,32 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_MoveEmitter_riscv64_h
++#define jit_riscv64_MoveEmitter_riscv64_h
++
++#include "mozilla/Assertions.h"
++
++namespace js {
++namespace jit {
++
++class MacroAssemblerRiscv64;
++class MoveResolver;
++struct Register;
++
++class MoveEmitterRiscv64 {
++ public:
++  explicit MoveEmitterRiscv64(MacroAssemblerRiscv64&) { MOZ_CRASH(); }
++  void emit(const MoveResolver&) { MOZ_CRASH(); }
++  void finish() { MOZ_CRASH(); }
++  void setScratchRegister(Register) { MOZ_CRASH(); }
++};
++
++typedef MoveEmitterRiscv64 MoveEmitter;
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_MoveEmitter_riscv64_h */
+diff --git a/js/src/jit/riscv64/SharedICHelpers-riscv64-inl.h b/js/src/jit/riscv64/SharedICHelpers-riscv64-inl.h
+new file mode 100644
+index 0000000000..7c6f7b7c20
+--- /dev/null
++++ b/js/src/jit/riscv64/SharedICHelpers-riscv64-inl.h
+@@ -0,0 +1,34 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_SharedICHelpers_riscv64_inl_h
++#define jit_riscv64_SharedICHelpers_riscv64_inl_h
++
++#include "jit/SharedICHelpers.h"
++
++namespace js {
++namespace jit {
++
++inline void EmitBaselineTailCallVM(TrampolinePtr, MacroAssembler&, uint32_t) {
++  MOZ_CRASH();
++}
++inline void EmitBaselineCreateStubFrameDescriptor(MacroAssembler&, Register,
++                                                  uint32_t) {
++  MOZ_CRASH();
++}
++inline void EmitBaselineCallVM(TrampolinePtr, MacroAssembler&) { MOZ_CRASH(); }
++
++static const uint32_t STUB_FRAME_SIZE = 0;
++static const uint32_t STUB_FRAME_SAVED_STUB_OFFSET = 0;
++
++inline void EmitBaselineEnterStubFrame(MacroAssembler&, Register) {
++  MOZ_CRASH();
++}
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_SharedICHelpers_riscv64_inl_h */
+diff --git a/js/src/jit/riscv64/SharedICHelpers-riscv64.h b/js/src/jit/riscv64/SharedICHelpers-riscv64.h
+new file mode 100644
+index 0000000000..205b6615da
+--- /dev/null
++++ b/js/src/jit/riscv64/SharedICHelpers-riscv64.h
+@@ -0,0 +1,35 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_SharedICHelpers_riscv64_h
++#define jit_riscv64_SharedICHelpers_riscv64_h
++
++#include "jit/MacroAssembler.h"
++#include "jit/SharedICRegisters.h"
++
++namespace js {
++namespace jit {
++
++static const size_t ICStackValueOffset = 0;
++
++inline void EmitRestoreTailCallReg(MacroAssembler&) { MOZ_CRASH(); }
++inline void EmitRepushTailCallReg(MacroAssembler&) { MOZ_CRASH(); }
++inline void EmitCallIC(MacroAssembler&, CodeOffset*) { MOZ_CRASH(); }
++inline void EmitReturnFromIC(MacroAssembler&) { MOZ_CRASH(); }
++inline void EmitBaselineLeaveStubFrame(MacroAssembler&, bool v = false) {
++  MOZ_CRASH();
++}
++inline void EmitStubGuardFailure(MacroAssembler&) { MOZ_CRASH(); }
++
++template <typename T>
++inline void EmitPreBarrier(MacroAssembler&, T, MIRType) {
++  MOZ_CRASH();
++}
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_SharedICHelpers_riscv64_h */
+diff --git a/js/src/jit/riscv64/SharedICRegisters-riscv64.h b/js/src/jit/riscv64/SharedICRegisters-riscv64.h
+new file mode 100644
+index 0000000000..f1d5f165d8
+--- /dev/null
++++ b/js/src/jit/riscv64/SharedICRegisters-riscv64.h
+@@ -0,0 +1,38 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#ifndef jit_riscv64_SharedICRegisters_riscv64_h
++#define jit_riscv64_SharedICRegisters_riscv64_h
++
++#include "jit/riscv64/Assembler-riscv64.h"
++#include "jit/Registers.h"
++#include "jit/RegisterSets.h"
++
++namespace js {
++namespace jit {
++
++static constexpr Register BaselineFrameReg{Registers::invalid_reg};
++static constexpr Register BaselineStackReg{Registers::invalid_reg};
++
++static constexpr ValueOperand R0 = JSReturnOperand;
++static constexpr ValueOperand R1 = JSReturnOperand;
++static constexpr ValueOperand R2 = JSReturnOperand;
++
++static constexpr Register ICTailCallReg{Registers::invalid_reg};
++static constexpr Register ICStubReg{Registers::invalid_reg};
++
++static constexpr Register ExtractTemp0{Registers::invalid_reg};
++static constexpr Register ExtractTemp1{Registers::invalid_reg};
++
++static constexpr FloatRegister FloatReg0;
++static constexpr FloatRegister FloatReg1;
++static constexpr FloatRegister FloatReg2;
++static constexpr FloatRegister FloatReg3;
++
++}  // namespace jit
++}  // namespace js
++
++#endif /* jit_riscv64_SharedICRegisters_riscv64_h */
+diff --git a/js/src/jit/riscv64/Trampoline-riscv64.cpp b/js/src/jit/riscv64/Trampoline-riscv64.cpp
+new file mode 100644
+index 0000000000..0774254cf4
+--- /dev/null
++++ b/js/src/jit/riscv64/Trampoline-riscv64.cpp
+@@ -0,0 +1,67 @@
++/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
++ * vim: set ts=8 sts=2 et sw=2 tw=80:
++ * This Source Code Form is subject to the terms of the Mozilla Public
++ * License, v. 2.0. If a copy of the MPL was not distributed with this
++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
++
++#include "jit/Bailouts.h"
++#include "jit/BaselineIC.h"
++#include "jit/JitRuntime.h"
++#include "vm/Realm.h"
++
++using namespace js;
++using namespace js::jit;
++
++// This file includes stubs for generating the JIT trampolines when there is no
++// JIT backend, and also includes implementations for assorted random things
++// which can't be implemented in headers.
++
++void JitRuntime::generateEnterJIT(JSContext*, MacroAssembler&) { MOZ_CRASH(); }
++// static
++mozilla::Maybe<::JS::ProfilingFrameIterator::RegisterState>
++JitRuntime::getCppEntryRegisters(JitFrameLayout* frameStackAddress) {
++  return mozilla::Nothing{};
++}
++void JitRuntime::generateInvalidator(MacroAssembler&, Label*) { MOZ_CRASH(); }
++void JitRuntime::generateArgumentsRectifier(MacroAssembler&,
++                                            ArgumentsRectifierKind kind) {
++  MOZ_CRASH();
++}
++JitRuntime::BailoutTable JitRuntime::generateBailoutTable(MacroAssembler&,
++                                                          Label*, uint32_t) {
++  MOZ_CRASH();
++}
++void JitRuntime::generateBailoutHandler(MacroAssembler&, Label*) {
++  MOZ_CRASH();
++}
++uint32_t JitRuntime::generatePreBarrier(JSContext*, MacroAssembler&, MIRType) {
++  MOZ_CRASH();
++}
++void JitRuntime::generateExceptionTailStub(MacroAssembler&, Label*) {
++  MOZ_CRASH();
++}
++void JitRuntime::generateBailoutTailStub(MacroAssembler&, Label*) {
++  MOZ_CRASH();
++}
++void JitRuntime::generateProfilerExitFrameTailStub(MacroAssembler&, Label*) {
++  MOZ_CRASH();
++}
++
++bool JitRuntime::generateVMWrapper(JSContext*, MacroAssembler&,
++                                   const VMFunctionData&, DynFn, uint32_t*) {
++  MOZ_CRASH();
++}
++
++FrameSizeClass FrameSizeClass::FromDepth(uint32_t) { MOZ_CRASH(); }
++FrameSizeClass FrameSizeClass::ClassLimit() { MOZ_CRASH(); }
++uint32_t FrameSizeClass::frameSize() const { MOZ_CRASH(); }
++
++BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& iter,
++                                   BailoutStack* bailout) {
++  MOZ_CRASH();
++}
++
++BailoutFrameInfo::BailoutFrameInfo(const JitActivationIterator& iter,
++                                   InvalidationBailoutStack* bailout) {
++  MOZ_CRASH();
++}
+diff --git a/js/src/jit/shared/Assembler-shared.h b/js/src/jit/shared/Assembler-shared.h
+index fcabddd98b..19cf397df1 100644
+--- a/js/src/jit/shared/Assembler-shared.h
++++ b/js/src/jit/shared/Assembler-shared.h
+@@ -26,13 +26,14 @@
+ 
+ #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_ARM64) ||     \
+     defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
+-    defined(JS_CODEGEN_LOONG64)
++    defined(JS_CODEGEN_LOONG64) || defined(JS_CODEGEN_RISCV64)
+ // Push return addresses callee-side.
+ #  define JS_USE_LINK_REGISTER
+ #endif
+ 
+ #if defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64) || \
+-    defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_LOONG64)
++    defined(JS_CODEGEN_ARM64) || defined(JS_CODEGEN_LOONG64) || \
++    defined(JS_CODEGEN_RISCV64)
+ // JS_CODELABEL_LINKMODE gives labels additional metadata
+ // describing how Bind() should patch them.
+ #  define JS_CODELABEL_LINKMODE
+diff --git a/js/src/util/Poison.h b/js/src/util/Poison.h
+index cb8e1abc64..a6a2d2f12b 100644
+--- a/js/src/util/Poison.h
++++ b/js/src/util/Poison.h
+@@ -95,6 +95,8 @@ const uint8_t JS_SCOPE_DATA_TRAILING_NAMES_PATTERN = 0xCC;
+ #  define JS_SWEPT_CODE_PATTERN 0x01  // undefined instruction
+ #elif defined(JS_CODEGEN_LOONG64)
+ #  define JS_SWEPT_CODE_PATTERN 0x01  // undefined instruction
++#elif defined(JS_CODEGEN_RISCV64)
++#  define JS_SWEPT_CODE_PATTERN 0x01  // undefined instruction
+ #else
+ #  error "JS_SWEPT_CODE_PATTERN not defined for this platform"
+ #endif
+diff --git a/js/src/wasm/WasmBCMemory.cpp b/js/src/wasm/WasmBCMemory.cpp
+index 94e739090b..2c226dadd5 100644
+--- a/js/src/wasm/WasmBCMemory.cpp
++++ b/js/src/wasm/WasmBCMemory.cpp
+@@ -1214,6 +1214,22 @@ static void Deallocate(BaseCompiler* bc, RegI32 rv, const Temps& temps) {
+   bc->maybeFree(temps.t2);
+ }
+ 
++#elif defined(JS_CODEGEN_RISCV64)
++
++struct Temps {
++  RegI32 t0;
++};
++
++static void PopAndAllocate(BaseCompiler* bc, ValType type,
++                           Scalar::Type viewType, AtomicOp op, RegI32* rd,
++                           RegI32* rv, Temps* temps) {}
++
++static void Perform(BaseCompiler* bc, const MemoryAccessDesc& access,
++                    BaseIndex srcAddr, AtomicOp op, RegI32 rv, RegI32 rd,
++                    const Temps& temps) {}
++
++static void Deallocate(BaseCompiler*, RegI32, const Temps&) {}
++
+ #elif defined(JS_CODEGEN_NONE)
+ 
+ using Temps = Nothing;
+@@ -1375,6 +1391,17 @@ static void Deallocate(BaseCompiler* bc, AtomicOp op, RegI64 rv, RegI64 temp) {
+   bc->freeI64(temp);
+ }
+ 
++#elif defined(JS_CODEGEN_RISCV64)
++
++static void PopAndAllocate(BaseCompiler* bc, AtomicOp op, RegI64* rd,
++                           RegI64* rv, RegI64* temp) {}
++
++static void Perform(BaseCompiler* bc, const MemoryAccessDesc& access,
++                    BaseIndex srcAddr, AtomicOp op, RegI64 rv, RegI64 temp,
++                    RegI64 rd) {}
++
++static void Deallocate(BaseCompiler* bc, AtomicOp op, RegI64 rv, RegI64 temp) {}
++
+ #elif defined(JS_CODEGEN_NONE)
+ 
+ static void PopAndAllocate(BaseCompiler*, AtomicOp, RegI64*, RegI64*, RegI64*) {
+diff --git a/js/src/wasm/WasmCompile.cpp b/js/src/wasm/WasmCompile.cpp
+index 26534bca4e..403e26414b 100644
+--- a/js/src/wasm/WasmCompile.cpp
++++ b/js/src/wasm/WasmCompile.cpp
+@@ -74,6 +74,8 @@ uint32_t wasm::ObservedCPUFeatures() {
+ #elif defined(JS_CODEGEN_LOONG64)
+   MOZ_ASSERT(jit::GetLOONG64Flags() <= (UINT32_MAX >> ARCH_BITS));
+   return LOONG64 | (jit::GetLOONG64Flags() << ARCH_BITS);
++#elif defined(JS_CODEGEN_RISCV64)
++  return 0;
+ #elif defined(JS_CODEGEN_NONE)
+   return 0;
+ #else
+diff --git a/js/src/wasm/WasmFrameIter.cpp b/js/src/wasm/WasmFrameIter.cpp
+index e612e05704..0ce3453287 100644
+--- a/js/src/wasm/WasmFrameIter.cpp
++++ b/js/src/wasm/WasmFrameIter.cpp
+@@ -384,6 +384,12 @@ static const unsigned PushedFP = 16;
+ static const unsigned SetFP = 20;
+ static const unsigned PoppedFP = 4;
+ static const unsigned PoppedFPJitEntry = 0;
++#elif defined(JS_CODEGEN_RISCV64)
++static const unsigned PushedRetAddr = 0;
++static const unsigned PushedFP = 1;
++static const unsigned SetFP = 2;
++static const unsigned PoppedFP = 3;
++static const unsigned PoppedFPJitEntry = 4;
+ #elif defined(JS_CODEGEN_NONE)
+ // Synthetic values to satisfy asserts and avoid compiler warnings.
+ static const unsigned PushedRetAddr = 0;
+diff --git a/js/src/wasm/WasmSignalHandlers.cpp b/js/src/wasm/WasmSignalHandlers.cpp
+index f74368b954..9521441f02 100644
+--- a/js/src/wasm/WasmSignalHandlers.cpp
++++ b/js/src/wasm/WasmSignalHandlers.cpp
+@@ -157,6 +157,11 @@ using mozilla::DebugOnly;
+ #      define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
+ #      define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
+ #    endif
++#    if defined(__linux__) && defined(__riscv) && __riscv_xlen == 64
++#      define EPC_sig(p) ((p)->uc_mcontext.__gregs[0])
++#      define X02_sig(p) ((p)->uc_mcontext.__gregs[2])
++#      define X08_sig(p) ((p)->uc_mcontext.__gregs[8])
++#    endif
+ #    if defined(__linux__) && defined(__loongarch__)
+ #      define EPC_sig(p) ((p)->uc_mcontext.pc)
+ #      define RRA_sig(p) ((p)->uc_mcontext.gregs[1])
+@@ -405,6 +410,10 @@ struct macos_aarch64_context {
+ #    define FP_sig(p) RFP_sig(p)
+ #    define SP_sig(p) RSP_sig(p)
+ #    define LR_sig(p) RRA_sig(p)
++#  elif defined(__riscv) && __riscv_xlen == 64
++#    define PC_sig(p) EPC_sig(p)
++#    define SP_sig(p) X02_sig(p)
++#    define FP_sig(p) X08_sig(p)
+ #  endif
+ 
+ static void SetContextPC(CONTEXT* context, uint8_t* pc) {
+diff --git a/python/mozbuild/mozbuild/vendor/vendor_rust.py b/python/mozbuild/mozbuild/vendor/vendor_rust.py
+index 31baea4290..7394ccaf40 100644
+--- a/python/mozbuild/mozbuild/vendor/vendor_rust.py
++++ b/python/mozbuild/mozbuild/vendor/vendor_rust.py
+@@ -98,6 +98,7 @@ TOLERATED_DUPES = {
+     "libloading": 2,
+     "memoffset": 2,
+     "mio": 2,
++    "nix": 2,
+     # Transition from time 0.1 to 0.3 underway, but chrono is stuck on 0.1
+     # and hasn't been updated in 1.5 years (an hypothetical update is
+     # expected to remove the dependency on time altogether).
+diff --git a/supply-chain/config.toml b/supply-chain/config.toml
+index bb3dd733e8..371cbca809 100644
+--- a/supply-chain/config.toml
++++ b/supply-chain/config.toml
+@@ -1,6 +1,10 @@
+ 
+ # cargo-vet config file
+ 
++[policy.viaduct]
++audit-as-crates-io = true
++notes = "I don't know, do as what rust-vet tells me to do"
++
+ [policy.async-task]
+ audit-as-crates-io = true
+ notes = "This is the upstream code plus an extra fix that hasn't been released yet, see bug 1746533."
+diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml
+index dbd7770326..ffbadcb14c 100644
+--- a/toolkit/library/rust/shared/Cargo.toml
++++ b/toolkit/library/rust/shared/Cargo.toml
+@@ -38,7 +38,7 @@ tokio-reactor = { version = "=0.1.3", optional = true }
+ # audioipc2-client and audioipc2-server.
+ tokio-threadpool = { version = "=0.1.17", optional = true }
+ encoding_glue = { path = "../../../../intl/encoding_glue" }
+-authenticator = "0.3.1"
++authenticator = { git = "https://github.com/mozilla/authenticator-rs", rev = "b85bccf0527e42c877573029e8d35ff13ef06f9d" }
+ gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
+ gecko_logger = { path = "../../../../xpcom/rust/gecko_logger" }
+ rsdparsa_capi = { path = "../../../../dom/media/webrtc/sdp/rsdparsa_capi" }
+@@ -72,6 +72,7 @@ midir_impl = { path = "../../../../dom/midi/midir_impl", optional = true }
+ dom = { path = "../../../../dom/base/rust" }
+ origin-trials-ffi = { path = "../../../../dom/origin-trials/ffi" }
+ jog = { path = "../../../components/glean/bindings/jog" }
++midir = { version = "0.8.0" }
+ 
+ # Note: `modern_sqlite` means rusqlite's bindings file be for a sqlite with
+ # version less than or equal to what we link to. This isn't a problem because we

diff --git a/www-client/firefox/files/firefox-wayland.sh b/www-client/firefox/files/firefox-wayland.sh
deleted file mode 100644
index 4428025..0000000
--- a/www-client/firefox/files/firefox-wayland.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-#
-# Run Mozilla Firefox under Wayland
-#
-export MOZ_ENABLE_WAYLAND=1
-exec @PREFIX@/bin/firefox "$@"

diff --git a/www-client/firefox/files/firefox-x11.sh b/www-client/firefox/files/firefox-x11.sh
deleted file mode 100644
index 7565566..0000000
--- a/www-client/firefox/files/firefox-x11.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-
-#
-# Run Mozilla Firefox on X11
-#
-export MOZ_DISABLE_WAYLAND=1
-exec @PREFIX@/bin/firefox "$@"

diff --git a/www-client/firefox/files/firefox.sh b/www-client/firefox/files/firefox.sh
deleted file mode 100644
index c08d555..0000000
--- a/www-client/firefox/files/firefox.sh
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/bin/bash
-
-##
-## Usage:
-##
-## $ firefox
-##
-## This script is meant to run Mozilla Firefox in Gentoo.
-
-cmdname=$(basename "$0")
-
-##
-## Variables
-##
-MOZ_ARCH=$(uname -m)
-case ${MOZ_ARCH} in
-	x86_64|s390x|sparc64)
-		MOZ_LIB_DIR="@PREFIX@/lib64"
-		SECONDARY_LIB_DIR="@PREFIX@/lib"
-		;;
-	*)
-		MOZ_LIB_DIR="@PREFIX@/lib"
-		SECONDARY_LIB_DIR="@PREFIX@/lib64"
-		;;
-esac
-
-MOZ_FIREFOX_FILE="firefox"
-
-if [[ ! -r ${MOZ_LIB_DIR}/firefox/${MOZ_FIREFOX_FILE} ]]; then
-	if [[ ! -r ${SECONDARY_LIB_DIR}/firefox/${MOZ_FIREFOX_FILE} ]]; then
-		echo "Error: ${MOZ_LIB_DIR}/firefox/${MOZ_FIREFOX_FILE} not found" >&2
-		if [[ -d $SECONDARY_LIB_DIR ]]; then
-			echo "       ${SECONDARY_LIB_DIR}/firefox/${MOZ_FIREFOX_FILE} not found" >&2
-		fi
-		exit 1
-	fi
-	MOZ_LIB_DIR="$SECONDARY_LIB_DIR"
-fi
-MOZILLA_FIVE_HOME="${MOZ_LIB_DIR}/firefox"
-MOZ_EXTENSIONS_PROFILE_DIR="${HOME}/.mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
-MOZ_PROGRAM="${MOZILLA_FIVE_HOME}/${MOZ_FIREFOX_FILE}"
-DESKTOP_FILE="firefox"
-
-##
-## Enable Wayland backend?
-##
-if @DEFAULT_WAYLAND@ && [[ -z ${MOZ_DISABLE_WAYLAND} ]]; then
-	if [[ -n "$WAYLAND_DISPLAY" ]]; then
-		DESKTOP_FILE="firefox-wayland"
-		export MOZ_ENABLE_WAYLAND=1
-	fi
-elif [[ -n ${MOZ_DISABLE_WAYLAND} ]]; then
-	DESKTOP_FILE="firefox-x11"
-fi
-
-##
-## Use D-Bus remote exclusively when there's Wayland display.
-##
-if [[ -n "${WAYLAND_DISPLAY}" ]]; then
-	export MOZ_DBUS_REMOTE=1
-fi
-
-##
-## Make sure that we set the plugin path
-##
-MOZ_PLUGIN_DIR="plugins"
-
-if [[ -n "${MOZ_PLUGIN_PATH}" ]]; then
-	MOZ_PLUGIN_PATH=${MOZ_PLUGIN_PATH}:${MOZ_LIB_DIR}/mozilla/${MOZ_PLUGIN_DIR}
-else
-	MOZ_PLUGIN_PATH=${MOZ_LIB_DIR}/mozilla/${MOZ_PLUGIN_DIR}
-fi
-
-if [[ -d "${SECONDARY_LIB_DIR}/mozilla/${MOZ_PLUGIN_DIR}" ]]; then
-	MOZ_PLUGIN_PATH=${MOZ_PLUGIN_PATH}:${SECONDARY_LIB_DIR}/mozilla/${MOZ_PLUGIN_DIR}
-fi
-
-export MOZ_PLUGIN_PATH
-
-##
-## Set MOZ_APP_LAUNCHER for gnome-session
-##
-export MOZ_APP_LAUNCHER="@PREFIX@/bin/${cmdname}"
-
-##
-## Disable the GNOME crash dialog, Moz has it's own
-##
-if [[ "$XDG_CURRENT_DESKTOP" == "GNOME" ]]; then
-	GNOME_DISABLE_CRASH_DIALOG=1
-	export GNOME_DISABLE_CRASH_DIALOG
-fi
-
-##
-## Enable Xinput2 (#617344)
-##
-
-# respect user settings
-MOZ_USE_XINPUT2=${MOZ_USE_XINPUT2:-auto}
-
-if [[ ${MOZ_USE_XINPUT2} == auto && -n ${WAYLAND_DISPLAY} ]]; then
-	# enabling XINPUT2 should be safe for all wayland users
-	MOZ_USE_XINPUT2=1
-elif [[ ${MOZ_USE_XINPUT2} == auto && ${XDG_CURRENT_DESKTOP^^} == KDE ]]; then
-	# XINPUT2 is known to cause problems for KWin users
-	MOZ_USE_XINPUT2=0
-elif [[ ${MOZ_USE_XINPUT2} == auto && ${XDG_CURRENT_DESKTOP^^} == LXQT ]]; then
-	# LXQt uses KWin
-	MOZ_USE_XINPUT2=0
-elif [[ ${MOZ_USE_XINPUT2} == auto ]]; then
-	# should work on Mate, Xfce, FluxBox, OpenBox and all the others ...
-	MOZ_USE_XINPUT2=1
-fi
-
-[[ ${MOZ_USE_XINPUT2} != 0 ]] && export MOZ_USE_XINPUT2=${MOZ_USE_XINPUT2}
-
-# Don't throw "old profile" dialog box.
-export MOZ_ALLOW_DOWNGRADE=1
-
-##
-## Route to the correct .desktop file to get proper
-## name and actions
-##
-if [[ $@ != *"--name "* ]]; then
-	set -- --name "${DESKTOP_FILE}" "$@"
-fi
-
-# Run the browser
-exec ${MOZ_PROGRAM} "$@"

diff --git a/www-client/firefox/files/gentoo-hwaccel-prefs.js-r2 b/www-client/firefox/files/gentoo-hwaccel-prefs.js-r2
new file mode 100644
index 0000000..48025ca
--- /dev/null
+++ b/www-client/firefox/files/gentoo-hwaccel-prefs.js-r2
@@ -0,0 +1,5 @@
+/* Force hardware accelerated rendering due to USE=hwaccel */
+pref("gfx.webrender.all",                  true);
+pref("layers.acceleration.force-enabled",  true);
+pref("media.hardware-video-decoding.enabled", true);
+pref("webgl.force-enabled",                true);

diff --git a/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch b/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch
deleted file mode 100644
index 39ebd6a..0000000
--- a/www-client/firefox/files/makotokato-riscv64-support-and-zenithal-backported.patch
+++ /dev/null
@@ -1,47126 +0,0 @@
-From: Zenithal <i@zenithal.me>
-
-Some changes would be rejected/ignored when patching firefox 92 src,
-so I commented out some blocks, see these #-leading block below
-
-From be9cbd86b4c121dbdb626f8c373fd809f25bc23e Mon Sep 17 00:00:00 2001
-From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
-Date: Sun, 13 Jun 2021 04:06:39 +0000
-Subject: [PATCH] Update authenticator-rs
-
----
- .cargo/config.in                              |    5 +
- Cargo.lock                                    |    3 +-
- .../rust/authenticator/.cargo-checksum.json   |    2 +-
- third_party/rust/authenticator/.clippy.toml   |    2 +
- third_party/rust/authenticator/.flake8        |    4 +
- .../authenticator/.pre-commit-config.yaml     |   42 +
- third_party/rust/authenticator/.travis.yml    |   42 +
- third_party/rust/authenticator/Cargo.lock     | 1603 -----------------
- third_party/rust/authenticator/Cargo.toml     |  131 +-
- third_party/rust/authenticator/build.rs       |    2 +
- .../authenticator/src/linux/hidwrapper.rs     |    3 +
- .../authenticator/src/linux/ioctl_riscv64.rs  |    5 +
- toolkit/library/rust/shared/Cargo.toml        |    2 +-
- 13 files changed, 154 insertions(+), 1692 deletions(-)
- create mode 100644 third_party/rust/authenticator/.clippy.toml
- create mode 100644 third_party/rust/authenticator/.flake8
- create mode 100644 third_party/rust/authenticator/.pre-commit-config.yaml
- create mode 100644 third_party/rust/authenticator/.travis.yml
- delete mode 100644 third_party/rust/authenticator/Cargo.lock
- create mode 100644 third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
-
-diff --unified --recursive --text a/.cargo/config.in b/.cargo/config.in
---- a/.cargo/config.in  2022-03-10 14:19:43.020478706 +0800
-+++ b/.cargo/config.in  2022-03-10 14:21:21.873044017 +0800
-@@ -22,11 +22,6 @@
- replace-with = "vendored-sources"
- rev = "3bfc47d9a571d0842676043ba60716318e946c06"
- 
--[source."https://github.com/mozilla/midir.git"]
--git = "https://github.com/mozilla/midir.git"
--replace-with = "vendored-sources"
--rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
--
- [source."https://github.com/mozilla/l10nregistry-rs.git"]
- git = "https://github.com/mozilla/l10nregistry-rs.git"
- replace-with = "vendored-sources"
-@@ -57,6 +52,16 @@
- replace-with = "vendored-sources"
- rev = "a1a6ba41f0c610ebe751639f25f037474ca52941"
- 
-+[source."https://github.com/makotokato/midir.git"]
-+git = "https://github.com/makotokato/midir.git"
-+replace-with = "vendored-sources"
-+rev = "6140b2825dd4dc2b40e49e154ca7596e7b9a131a"
-+
-+[source."https://github.com/makotokato/authenticator-rs"]
-+git = "https://github.com/makotokato/authenticator-rs"
-+replace-with = "vendored-sources"
-+rev = "eed8919d50559f4959e2d7d2af7b4d48869b5366"
-+
- [source."https://github.com/kinetiknz/mio-named-pipes"]
- git = "https://github.com/kinetiknz/mio-named-pipes"
- replace-with = "vendored-sources"
-diff --git a/Cargo.lock b/Cargo.lock
-index 7e17939fad48b..8519d3d0e95a6 100644
---- a/Cargo.lock
-+++ b/Cargo.lock
-@@ -316,8 +316,7 @@ dependencies = [
- [[package]]
- name = "authenticator"
- version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "08cee7a0952628fde958e149507c2bb321ab4fccfafd225da0b20adc956ef88a"
-+source = "git+https://github.com/makotokato/authenticator-rs?rev=eed8919d50559f4959e2d7d2af7b4d48869b5366#eed8919d50559f4959e2d7d2af7b4d48869b5366"
- dependencies = [
-  "bitflags",
-  "core-foundation",
-diff --git a/third_party/rust/authenticator/.cargo-checksum.json b/third_party/rust/authenticator/.cargo-checksum.json
-index ce451ad09df4f..9791345c9de54 100644
---- a/third_party/rust/authenticator/.cargo-checksum.json
-+++ b/third_party/rust/authenticator/.cargo-checksum.json
-@@ -1 +1 @@
--{"files":{"Cargo.lock":"abaed4932db2206e5fdb7cb73a8c100f6c91fc84a8f33e8763677040ae8ea9bf","Cargo.toml":"9b56d5495021e7cd8ab7e019cceda45e906a2a3629a68e9019c6e5cb682dbc43","Cross.toml":"8d132da818d48492aa9f4b78a348f0df3adfae45d988d42ebd6be8a5adadb6c3","LICENSE":"e866c8f5864d4cacfe403820e722e9dc03fe3c7565efa5e4dad9051d827bb92a","README.md":"c87d9c7cc44f1dd4ef861a3a9f8cd2eb68aedd3814768871f5fb63c2070806cd","build.rs":"bc308b771ae9741d775370e3efe45e9cca166fd1d0335f4214b00497042ccc55","examples/main.rs":"d899646fa396776d0bb66efb86099ffb195566ecdb6fc4c1765ae3d54d696a8d","rustfmt.toml":"ceb6615363d6fff16426eb56f5727f98a7f7ed459ba9af735b1d8b672e2c3b9b","src/authenticatorservice.rs":"9fc5bcdd1e4f32e58ae920f96f40619a870b0a1b8d05db650803b2402a37fbf9","src/capi.rs":"1d3145ce81293bec697b0d385357fb1b0b495b0c356e2da5e6f15d028d328c70","src/consts.rs":"3dbcdfced6241822062e1aa2e6c8628af5f539ea18ee41edab51a3d33ebb77c6","src/errors.rs":"de89e57435ed1f9ff10f1f2d997a5b29d61cb215551e0ab40861a08ca52d1447",
 "src/freebsd/device.rs":"595df4b3f66b90dd73f8df67e1a2ba9a20c0b5fd893afbadbec564aa34f89981","src/freebsd/mod.rs":"42dcb57fbeb00140003a8ad39acac9b547062b8f281a3fa5deb5f92a6169dde6","src/freebsd/monitor.rs":"c10b154632fbedc3dca27197f7fc890c3d50ac1744b927e9f1e44a9e8a13506e","src/freebsd/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/freebsd/uhid.rs":"84f564d337637c1cd107ccc536b8fce2230628e144e4031e8db4d7163c9c0cb3","src/hidproto.rs":"362fc8e24b94ba431aad5ee0002f5a3364badd937c706c0ae119a5a7a2abc7c2","src/lib.rs":"12f62285a3d33347f95236b71341462a76ea1ded67651fc96ba25d7bd1dd8298","src/linux/device.rs":"d27c5f877cf96b97668579ac5db0f2685f7c969e7a5d0ddc68043eb16bfcddb8","src/linux/hidraw.rs":"ed55caa40fd518d67bb67d5af08f9adcab34f89e0ca591142d45b87f172926dd","src/linux/hidwrapper.h":"72785db3a9b27ea72b6cf13a958fee032af54304522d002f56322473978a20f9","src/linux/hidwrapper.rs":"4be65676cf3220929700bf4906938dcbd1538ba53d40c60b08f9ba8890c910f6","src/linux/io
 ctl_aarch64le.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_armle.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_mips64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsle.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64be.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpcbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_s390xbe.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86_64.rs":"2d8b265cd39a9f46
 816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/mod.rs":"446e435126d2a58f167f648dd95cba28e8ac9c17f1f799e1eaeab80ea800fc57","src/linux/monitor.rs":"9ef4e22fdcf005dd5201b42595d958ea462998c75dbfc68c8a403e7be64328e4","src/linux/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/macos/device.rs":"cc97b773254a89526164987e4b8e4181910fc3decb32acf51ca86c596ad0147b","src/macos/iokit.rs":"7dc4e7bbf8e42e2fcde0cee8e48d14d6234a5a910bd5d3c4e966d8ba6b73992f","src/macos/mod.rs":"333e561554fc901d4f6092f6e4c85823e2b0c4ff31c9188d0e6d542b71a0a07c","src/macos/monitor.rs":"d059861b4739c9272fa305b6dd91ebeb08530bd0e70a013dd999565d6f06fb30","src/macos/transaction.rs":"935b4bc79b0e50a984604a1ada96a7ef723cc283b7d33ca07f3150b1752b99f7","src/manager.rs":"5a4cdc26b9fde20e1a3dc2389f15d38d9153109bfee5119c092fbfdbd19bad8d","src/netbsd/device.rs":"3a99a989a7a8411ddb9893c371644076662a3b488d40b436601c27fd92fdf159","src/netbsd/fd.rs":"260f1a8ae04896c0eb35ab0914e11ca9291e
 7317a086c94328aa219c0e1fc1d2","src/netbsd/mod.rs":"b1c52aa29537330cebe67427062d6c94871cab2a9b0c04b2305d686f07e88fd5","src/netbsd/monitor.rs":"dfd68e026c52271b68a3a9263837c793127e9d54ed19b748ef6d13ab4c44e09a","src/netbsd/transaction.rs":"9334a832a57e717a981c13c364ed4ee80ce9798460fc6c8954723d2fcf20585a","src/netbsd/uhid.rs":"154a4587767f151e3f846cc0b79f615d5137de67afed84f19176f27ac9097908","src/openbsd/device.rs":"ae1c8de90bb515a12d571372a30322fadb5122bc69ab71caf154452caa8a644f","src/openbsd/mod.rs":"514274d414042ff84b3667a41a736e78581e22fda87ccc97c2bc05617e381a30","src/openbsd/monitor.rs":"5eb071dd3719ea305eac21ec20596463f63790f8cd1f908a59e3f9cb0b71b5ad","src/openbsd/transaction.rs":"2380c9430f4c95a1fefaaab729d8ece0d149674708d705a71dd5d2513d9e1a4c","src/statecallback.rs":"6b16f97176db1ae3fc3851fe8394e4ffc324bc6fe59313845ac3a88132fd52f1","src/statemachine.rs":"27e2655411ebc1077c200f0aa2ba429ca656fc7dd6f90e08b51492b59ec72e61","src/stub/device.rs":"5e378147e113e20160a45d395b717bd3deecb3
 27247c24b6735035f7d50861b7","src/stub/mod.rs":"6a7fec504a52d403b0241b18cd8b95088a31807571f4c0a67e4055afc74f4453","src/stub/transaction.rs":"4a2ccb2d72070a8bc61442254e063278c68212d5565ba5bfe4d47cacebf5bd1c","src/u2fhid-capi.h":"10f2658df774bb7f7f197a9f217b9e20d67b232b60a554e8ee3c3f71480ea1f6","src/u2fprotocol.rs":"72120773a948ffd667b5976c26ae27a4327769d97b0eef7a3b1e6b2b4bbb46a9","src/u2ftypes.rs":"a02d2c29790c5edfec9af320b1d4bcb93be0bbf02b881fa5aa403cfb687a25ae","src/util.rs":"d2042b2db4864f2b1192606c3251709361de7fb7521e1519190ef26a77de8e64","src/virtualdevices/mod.rs":"2c7df7691d5c150757304241351612aed4260d65b70ab0f483edbc1a5cfb5674","src/virtualdevices/software_u2f.rs":"1b86b94c6eadec6a22dffdd2b003c5324247c6412eeddb28a6094feb1c523f8e","src/virtualdevices/webdriver/mod.rs":"4a36e6dfa9f45f941d863b4039bfbcfa8eaca660bd6ed78aeb1a2962db64be5a","src/virtualdevices/webdriver/testtoken.rs":"7146e02f1a5dad2c8827dd11c12ee408c0e42a0706ac65f139998feffd42570f","src/virtualdevices/webdriver/virtu
 almanager.rs":"a55a28995c81b5affb0a74207b6dd556d272086a554676df2e675fe991d730a9","src/virtualdevices/webdriver/web_api.rs":"27206ee09c83fe25b34cad62174e42383defd8c8a5e917d30691412aacdae08f","src/windows/device.rs":"bc3f9587677c185a624c0aae7537baf9f780484ab8337929db994800b9064ba9","src/windows/mod.rs":"218e7f2fe91ecb390c12bba5a5ffdad2c1f0b22861c937f4d386262e5b3dd617","src/windows/monitor.rs":"3804dc67de46a1a6b7925c83e0df95d94ddfa1aa53a88fc845f4ff26aede57f8","src/windows/transaction.rs":"ee639f28b2dcdb7e00c922d8762fe6aa33def8c7aaeb46ec93e3a772407a9d86","src/windows/winapi.rs":"de92afb17df26216161138f18eb3b9162f3fb2cdeb74aa78173afe804ba02e00","testing/cross/powerpc64le-unknown-linux-gnu.Dockerfile":"d7463ff4376e3e0ca3fed879fab4aa975c4c0a3e7924c5b88aef9381a5d013de","testing/cross/x86_64-unknown-linux-gnu.Dockerfile":"11c79c04b07a171b0c9b63ef75fa75f33263ce76e3c1eda0879a3e723ebd0c24","testing/run_cross.sh":"cc2a7e0359f210eba2e7121f81eb8ab0125cea6e0d0f2698177b0fe2ad0c33d8","webdriver-tools
 /requirements.txt":"8236aa3dedad886f213c9b778fec80b037212d30e640b458984110211d546005","webdriver-tools/webdriver-driver.py":"82327c26ba271d1689acc87b612ab8436cb5475f0a3c0dba7baa06e7f6f5e19c"},"package":"08cee7a0952628fde958e149507c2bb321ab4fccfafd225da0b20adc956ef88a"}
-\ No newline at end of file
-+{"files":{".clippy.toml":"86011295a6e2cea043b8002238f9c96b39f17aa8241aa079f44bb6e71eb62421",".flake8":"04f55f4a3c02b50dfa568ce4f7c6a47a9374b6483256811f8be702d1382576cd",".pre-commit-config.yaml":"b7920a17d5a378c7702f9c39bf5156bb8c4ea15d8691217e0a5a8e8f571b4cf7",".travis.yml":"883be088379477e7fa6f3d06b1c8d59dc41da61b6c15d2675c62113341e7b2d5","Cargo.toml":"e7334212220a6d8ca01996888275cc0d11d098e36db1bf4c5b7429051897bf3f","Cross.toml":"8d132da818d48492aa9f4b78a348f0df3adfae45d988d42ebd6be8a5adadb6c3","LICENSE":"e866c8f5864d4cacfe403820e722e9dc03fe3c7565efa5e4dad9051d827bb92a","README.md":"c87d9c7cc44f1dd4ef861a3a9f8cd2eb68aedd3814768871f5fb63c2070806cd","build.rs":"a459ee1ace052f9692817b15c702cb6e5a6dac7c7dfe74fa075662dbcf808dbe","examples/main.rs":"d899646fa396776d0bb66efb86099ffb195566ecdb6fc4c1765ae3d54d696a8d","rustfmt.toml":"ceb6615363d6fff16426eb56f5727f98a7f7ed459ba9af735b1d8b672e2c3b9b","src/authenticatorservice.rs":"9fc5bcdd1e4f32e58ae920f96f40619a870b0a1b8d05db650803b2402a37
 fbf9","src/capi.rs":"1d3145ce81293bec697b0d385357fb1b0b495b0c356e2da5e6f15d028d328c70","src/consts.rs":"3dbcdfced6241822062e1aa2e6c8628af5f539ea18ee41edab51a3d33ebb77c6","src/errors.rs":"de89e57435ed1f9ff10f1f2d997a5b29d61cb215551e0ab40861a08ca52d1447","src/freebsd/device.rs":"595df4b3f66b90dd73f8df67e1a2ba9a20c0b5fd893afbadbec564aa34f89981","src/freebsd/mod.rs":"42dcb57fbeb00140003a8ad39acac9b547062b8f281a3fa5deb5f92a6169dde6","src/freebsd/monitor.rs":"c10b154632fbedc3dca27197f7fc890c3d50ac1744b927e9f1e44a9e8a13506e","src/freebsd/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/freebsd/uhid.rs":"84f564d337637c1cd107ccc536b8fce2230628e144e4031e8db4d7163c9c0cb3","src/hidproto.rs":"362fc8e24b94ba431aad5ee0002f5a3364badd937c706c0ae119a5a7a2abc7c2","src/lib.rs":"12f62285a3d33347f95236b71341462a76ea1ded67651fc96ba25d7bd1dd8298","src/linux/device.rs":"d27c5f877cf96b97668579ac5db0f2685f7c969e7a5d0ddc68043eb16bfcddb8","src/linux/hidraw.rs":"ed55caa40fd
 518d67bb67d5af08f9adcab34f89e0ca591142d45b87f172926dd","src/linux/hidwrapper.h":"72785db3a9b27ea72b6cf13a958fee032af54304522d002f56322473978a20f9","src/linux/hidwrapper.rs":"753c7459dbb73befdd186b6269ac33f7a4537b4c935928f50f2b2131756e787d","src/linux/ioctl_aarch64le.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_armle.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_mips64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_mipsle.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64be.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpc64le.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9d5a5322c3047d474fd","src/linux/ioctl_powerpcbe.rs":"fbda309934ad8bda689cd4fb5c0ca696fe26dedb493fe9
 d5a5322c3047d474fd","src/linux/ioctl_riscv64.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_s390xbe.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/ioctl_x86_64.rs":"2d8b265cd39a9f46816f83d5a5df0701c13eb842bc609325bad42ce50add3bf0","src/linux/mod.rs":"446e435126d2a58f167f648dd95cba28e8ac9c17f1f799e1eaeab80ea800fc57","src/linux/monitor.rs":"9ef4e22fdcf005dd5201b42595d958ea462998c75dbfc68c8a403e7be64328e4","src/linux/transaction.rs":"bfb92dcf2edeb5d620a019907fff1025eb36ef322055e78649a3055b074fa851","src/macos/device.rs":"cc97b773254a89526164987e4b8e4181910fc3decb32acf51ca86c596ad0147b","src/macos/iokit.rs":"7dc4e7bbf8e42e2fcde0cee8e48d14d6234a5a910bd5d3c4e966d8ba6b73992f","src/macos/mod.rs":"333e561554fc901d4f6092f6e4c85823e2b0c4ff31c9188d0e6d542b71a0a07c","src/macos/monitor.rs":"d059861b4739c9272fa305b6dd91ebeb08530bd0e
 70a013dd999565d6f06fb30","src/macos/transaction.rs":"935b4bc79b0e50a984604a1ada96a7ef723cc283b7d33ca07f3150b1752b99f7","src/manager.rs":"5a4cdc26b9fde20e1a3dc2389f15d38d9153109bfee5119c092fbfdbd19bad8d","src/netbsd/device.rs":"3a99a989a7a8411ddb9893c371644076662a3b488d40b436601c27fd92fdf159","src/netbsd/fd.rs":"260f1a8ae04896c0eb35ab0914e11ca9291e7317a086c94328aa219c0e1fc1d2","src/netbsd/mod.rs":"b1c52aa29537330cebe67427062d6c94871cab2a9b0c04b2305d686f07e88fd5","src/netbsd/monitor.rs":"dfd68e026c52271b68a3a9263837c793127e9d54ed19b748ef6d13ab4c44e09a","src/netbsd/transaction.rs":"9334a832a57e717a981c13c364ed4ee80ce9798460fc6c8954723d2fcf20585a","src/netbsd/uhid.rs":"154a4587767f151e3f846cc0b79f615d5137de67afed84f19176f27ac9097908","src/openbsd/device.rs":"ae1c8de90bb515a12d571372a30322fadb5122bc69ab71caf154452caa8a644f","src/openbsd/mod.rs":"514274d414042ff84b3667a41a736e78581e22fda87ccc97c2bc05617e381a30","src/openbsd/monitor.rs":"5eb071dd3719ea305eac21ec20596463f63790f8cd1f908a59e3
 f9cb0b71b5ad","src/openbsd/transaction.rs":"2380c9430f4c95a1fefaaab729d8ece0d149674708d705a71dd5d2513d9e1a4c","src/statecallback.rs":"6b16f97176db1ae3fc3851fe8394e4ffc324bc6fe59313845ac3a88132fd52f1","src/statemachine.rs":"27e2655411ebc1077c200f0aa2ba429ca656fc7dd6f90e08b51492b59ec72e61","src/stub/device.rs":"5e378147e113e20160a45d395b717bd3deecb327247c24b6735035f7d50861b7","src/stub/mod.rs":"6a7fec504a52d403b0241b18cd8b95088a31807571f4c0a67e4055afc74f4453","src/stub/transaction.rs":"4a2ccb2d72070a8bc61442254e063278c68212d5565ba5bfe4d47cacebf5bd1c","src/u2fhid-capi.h":"10f2658df774bb7f7f197a9f217b9e20d67b232b60a554e8ee3c3f71480ea1f6","src/u2fprotocol.rs":"72120773a948ffd667b5976c26ae27a4327769d97b0eef7a3b1e6b2b4bbb46a9","src/u2ftypes.rs":"a02d2c29790c5edfec9af320b1d4bcb93be0bbf02b881fa5aa403cfb687a25ae","src/util.rs":"d2042b2db4864f2b1192606c3251709361de7fb7521e1519190ef26a77de8e64","src/virtualdevices/mod.rs":"2c7df7691d5c150757304241351612aed4260d65b70ab0f483edbc1a5cfb5674","src/v
 irtualdevices/software_u2f.rs":"1b86b94c6eadec6a22dffdd2b003c5324247c6412eeddb28a6094feb1c523f8e","src/virtualdevices/webdriver/mod.rs":"4a36e6dfa9f45f941d863b4039bfbcfa8eaca660bd6ed78aeb1a2962db64be5a","src/virtualdevices/webdriver/testtoken.rs":"7146e02f1a5dad2c8827dd11c12ee408c0e42a0706ac65f139998feffd42570f","src/virtualdevices/webdriver/virtualmanager.rs":"a55a28995c81b5affb0a74207b6dd556d272086a554676df2e675fe991d730a9","src/virtualdevices/webdriver/web_api.rs":"27206ee09c83fe25b34cad62174e42383defd8c8a5e917d30691412aacdae08f","src/windows/device.rs":"bc3f9587677c185a624c0aae7537baf9f780484ab8337929db994800b9064ba9","src/windows/mod.rs":"218e7f2fe91ecb390c12bba5a5ffdad2c1f0b22861c937f4d386262e5b3dd617","src/windows/monitor.rs":"3804dc67de46a1a6b7925c83e0df95d94ddfa1aa53a88fc845f4ff26aede57f8","src/windows/transaction.rs":"ee639f28b2dcdb7e00c922d8762fe6aa33def8c7aaeb46ec93e3a772407a9d86","src/windows/winapi.rs":"de92afb17df26216161138f18eb3b9162f3fb2cdeb74aa78173afe804ba02e00",
 "testing/cross/powerpc64le-unknown-linux-gnu.Dockerfile":"d7463ff4376e3e0ca3fed879fab4aa975c4c0a3e7924c5b88aef9381a5d013de","testing/cross/x86_64-unknown-linux-gnu.Dockerfile":"11c79c04b07a171b0c9b63ef75fa75f33263ce76e3c1eda0879a3e723ebd0c24","testing/run_cross.sh":"cc2a7e0359f210eba2e7121f81eb8ab0125cea6e0d0f2698177b0fe2ad0c33d8","webdriver-tools/requirements.txt":"8236aa3dedad886f213c9b778fec80b037212d30e640b458984110211d546005","webdriver-tools/webdriver-driver.py":"82327c26ba271d1689acc87b612ab8436cb5475f0a3c0dba7baa06e7f6f5e19c"},"package":null}
-\ No newline at end of file
-diff --git a/third_party/rust/authenticator/.clippy.toml b/third_party/rust/authenticator/.clippy.toml
-new file mode 100644
-index 0000000000000..844d0757e91f4
---- /dev/null
-+++ b/third_party/rust/authenticator/.clippy.toml
-@@ -0,0 +1,2 @@
-+type-complexity-threshold = 384
-+too-many-arguments-threshold = 8
-diff --git a/third_party/rust/authenticator/.flake8 b/third_party/rust/authenticator/.flake8
-new file mode 100644
-index 0000000000000..5a725c9b4ce65
---- /dev/null
-+++ b/third_party/rust/authenticator/.flake8
-@@ -0,0 +1,4 @@
-+[flake8]
-+# See http://pep8.readthedocs.io/en/latest/intro.html#configuration
-+ignore = E121, E123, E126, E129, E133, E203, E226, E241, E242, E704, W503, E402, E741
-+max-line-length = 99
-diff --git a/third_party/rust/authenticator/.pre-commit-config.yaml b/third_party/rust/authenticator/.pre-commit-config.yaml
-new file mode 100644
-index 0000000000000..e0ceb8ea5473c
---- /dev/null
-+++ b/third_party/rust/authenticator/.pre-commit-config.yaml
-@@ -0,0 +1,42 @@
-+- repo: git://github.com/pre-commit/pre-commit-hooks
-+  rev: HEAD
-+  hooks:
-+    - id: flake8
-+    - id: check-ast
-+    - id: detect-private-key
-+    - id: detect-aws-credentials
-+    - id: check-merge-conflict
-+    - id: end-of-file-fixer
-+    - id: requirements-txt-fixer
-+    - id: trailing-whitespace
-+- repo: local
-+  hooks:
-+    - id: rustfmt
-+      name: Check rustfmt
-+      language: system
-+      entry: cargo fmt -- --check
-+      pass_filenames: false
-+      files: '.rs$'
-+- repo: local
-+  hooks:
-+    - id: tests
-+      name: Run tests
-+      language: system
-+      entry: cargo test --all-targets --all-features
-+      pass_filenames: false
-+      files: '.rs$'
-+- repo: local
-+  hooks:
-+    - id: clippy
-+      name: Check clippy
-+      language: system
-+      entry: cargo clippy --all-targets -- -A renamed_and_removed_lints -A clippy::new-ret-no-self -D warnings
-+      pass_filenames: false
-+      files: '.rs$'
-+- repo: local
-+  hooks:
-+    - id: black
-+      name: Check black
-+      language: system
-+      entry: black
-+      files: '.py$'
-diff --git a/third_party/rust/authenticator/.travis.yml b/third_party/rust/authenticator/.travis.yml
-new file mode 100644
-index 0000000000000..70ea5c5581af2
---- /dev/null
-+++ b/third_party/rust/authenticator/.travis.yml
-@@ -0,0 +1,42 @@
-+os:
-+  - linux
-+  - windows
-+
-+language: rust
-+rust:
-+  - stable
-+  - nightly
-+cache: cargo
-+
-+jobs:
-+  allow_failures:
-+    - rust: nightly
-+
-+addons:
-+  apt:
-+    packages:
-+      - build-essential
-+      - libudev-dev
-+
-+install:
-+  - rustup component add rustfmt
-+  - rustup component add clippy
-+
-+script:
-+- |
-+  if [ "$TRAVIS_RUST_VERSION" == "nightly" ] && [ "$TRAVIS_OS_NAME" == "linux" ] ; then
-+    export ASAN_OPTIONS="detect_odr_violation=1:leak_check_at_exit=0:detect_leaks=0"
-+    export RUSTFLAGS="-Z sanitizer=address"
-+  fi
-+- |
-+  if [ "$TRAVIS_RUST_VERSION" == "stable" ] && [ "$TRAVIS_OS_NAME" == "linux" ] ; then
-+    echo "Running rustfmt"
-+    cargo fmt --all -- --check
-+    echo "Running clippy"
-+    cargo clippy --all-targets --all-features -- -A renamed_and_removed_lints -A clippy::new-ret-no-self -D warnings
-+
-+    rustup install nightly
-+    cargo install cargo-fuzz
-+    cargo +nightly fuzz build
-+  fi
-+- cargo test --all-targets --all-features
-diff --git a/third_party/rust/authenticator/Cargo.lock b/third_party/rust/authenticator/Cargo.lock
-deleted file mode 100644
-index 9f284b468deaa..0000000000000
---- a/third_party/rust/authenticator/Cargo.lock
-+++ /dev/null
-@@ -1,1603 +0,0 @@
--# This file is automatically @generated by Cargo.
--# It is not intended for manual editing.
--[[package]]
--name = "aho-corasick"
--version = "0.7.13"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "ansi_term"
--version = "0.11.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "assert_matches"
--version = "1.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "atty"
--version = "0.2.14"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "authenticator"
--version = "0.3.1"
--dependencies = [
-- "assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "core-foundation 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "devd-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
-- "sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "warp 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "autocfg"
--version = "0.1.7"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "autocfg"
--version = "1.0.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "base64"
--version = "0.10.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "base64"
--version = "0.12.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "bindgen"
--version = "0.51.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "bitflags"
--version = "1.2.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "block-buffer"
--version = "0.7.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "block-buffer"
--version = "0.9.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "block-padding"
--version = "0.1.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "buf_redux"
--version = "0.8.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "byte-tools"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "byteorder"
--version = "1.3.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "bytes"
--version = "0.5.6"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "cc"
--version = "1.0.58"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "cexpr"
--version = "0.3.6"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "cfg-if"
--version = "0.1.10"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "clang-sys"
--version = "0.28.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "clap"
--version = "2.33.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "cloudabi"
--version = "0.0.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "core-foundation"
--version = "0.9.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "core-foundation-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "core-foundation-sys"
--version = "0.8.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "cpuid-bool"
--version = "0.1.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "devd-rs"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "digest"
--version = "0.8.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "digest"
--version = "0.9.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "dtoa"
--version = "0.4.6"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "env_logger"
--version = "0.6.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
-- "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
-- "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "fake-simd"
--version = "0.1.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "fnv"
--version = "1.0.7"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "fuchsia-cprng"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "fuchsia-zircon"
--version = "0.3.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "fuchsia-zircon-sys"
--version = "0.3.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "futures"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "futures-channel"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "futures-core"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "futures-io"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "futures-sink"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "futures-task"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "futures-util"
--version = "0.3.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "generic-array"
--version = "0.12.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "generic-array"
--version = "0.14.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "getopts"
--version = "0.2.21"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "getrandom"
--version = "0.1.14"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "glob"
--version = "0.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "h2"
--version = "0.2.6"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "hashbrown"
--version = "0.9.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "headers"
--version = "0.3.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "headers-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
-- "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "headers-core"
--version = "0.2.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "hermit-abi"
--version = "0.1.15"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "http"
--version = "0.2.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "http-body"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "httparse"
--version = "1.3.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "humantime"
--version = "1.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "hyper"
--version = "0.13.7"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
-- "socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
-- "time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "idna"
--version = "0.2.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "indexmap"
--version = "1.6.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "input_buffer"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "iovec"
--version = "0.1.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "itoa"
--version = "0.4.6"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "kernel32-sys"
--version = "0.2.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "lazy_static"
--version = "1.4.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "libc"
--version = "0.2.73"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "libloading"
--version = "0.5.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "libudev"
--version = "0.2.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libudev-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "libudev-sys"
--version = "0.1.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "log"
--version = "0.4.11"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "matches"
--version = "0.1.8"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "memchr"
--version = "2.3.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "mime"
--version = "0.3.16"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "mime_guess"
--version = "2.0.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
-- "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "mio"
--version = "0.6.22"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
-- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "miow"
--version = "0.2.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "multipart"
--version = "0.17.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "net2"
--version = "0.2.35"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "nom"
--version = "4.2.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "nom"
--version = "5.1.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "once_cell"
--version = "1.4.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "opaque-debug"
--version = "0.2.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "opaque-debug"
--version = "0.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "peeking_take_while"
--version = "0.1.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "percent-encoding"
--version = "2.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "pin-project"
--version = "0.4.23"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "pin-project-internal"
--version = "0.4.23"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "pin-project-lite"
--version = "0.1.7"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "pin-utils"
--version = "0.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "pkg-config"
--version = "0.3.18"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "ppv-lite86"
--version = "0.2.8"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "proc-macro2"
--version = "1.0.19"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "quick-error"
--version = "1.2.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "quote"
--version = "1.0.7"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand"
--version = "0.6.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand"
--version = "0.7.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_chacha"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_chacha"
--version = "0.2.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_core"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_core"
--version = "0.4.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "rand_core"
--version = "0.5.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_hc"
--version = "0.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_hc"
--version = "0.2.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_isaac"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_jitter"
--version = "0.1.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_os"
--version = "0.1.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_pcg"
--version = "0.1.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rand_xorshift"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "rdrand"
--version = "0.4.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "redox_syscall"
--version = "0.1.57"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "regex"
--version = "1.3.9"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)",
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)",
-- "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "regex-syntax"
--version = "0.6.18"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "remove_dir_all"
--version = "0.5.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "runloop"
--version = "0.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "rustc-hash"
--version = "1.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "ryu"
--version = "1.0.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "safemem"
--version = "0.3.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "scoped-tls"
--version = "1.0.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "serde"
--version = "1.0.116"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "serde_derive"
--version = "1.0.116"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "serde_json"
--version = "1.0.57"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "serde_urlencoded"
--version = "0.6.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
-- "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "sha-1"
--version = "0.8.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "sha-1"
--version = "0.9.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "sha2"
--version = "0.8.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "shlex"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "slab"
--version = "0.4.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "socket2"
--version = "0.3.15"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "strsim"
--version = "0.8.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "syn"
--version = "1.0.41"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tempfile"
--version = "3.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)",
-- "remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "termcolor"
--version = "1.1.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "textwrap"
--version = "0.11.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "thread_local"
--version = "1.0.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "time"
--version = "0.1.44"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
-- "wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tinyvec"
--version = "0.3.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "tokio"
--version = "0.2.22"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tokio-macros"
--version = "0.2.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tokio-tungstenite"
--version = "0.11.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tungstenite 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tokio-util"
--version = "0.3.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tower-service"
--version = "0.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "tracing"
--version = "0.1.19"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tracing-core"
--version = "0.1.16"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "tracing-futures"
--version = "0.2.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "try-lock"
--version = "0.2.3"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "tungstenite"
--version = "0.11.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "input_buffer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "twoway"
--version = "0.1.8"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "typenum"
--version = "1.12.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "unicase"
--version = "2.6.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "unicode-bidi"
--version = "0.3.4"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "unicode-normalization"
--version = "0.1.13"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "unicode-width"
--version = "0.1.8"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "unicode-xid"
--version = "0.2.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "url"
--version = "2.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "urlencoding"
--version = "1.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "utf-8"
--version = "0.7.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "vec_map"
--version = "0.8.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "version_check"
--version = "0.1.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "version_check"
--version = "0.9.2"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "want"
--version = "0.3.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "warp"
--version = "0.2.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
-- "futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
-- "headers 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
-- "http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)",
-- "log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
-- "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
-- "multipart 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)",
-- "scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)",
-- "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tokio-tungstenite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
-- "tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
-- "urlencoding 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "wasi"
--version = "0.9.0+wasi-snapshot-preview1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "wasi"
--version = "0.10.0+wasi-snapshot-preview1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "which"
--version = "3.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "winapi"
--version = "0.2.8"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "winapi"
--version = "0.3.9"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "winapi-build"
--version = "0.1.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "winapi-i686-pc-windows-gnu"
--version = "0.4.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "winapi-util"
--version = "0.1.5"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[[package]]
--name = "winapi-x86_64-pc-windows-gnu"
--version = "0.4.0"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--
--[[package]]
--name = "ws2_32-sys"
--version = "0.2.1"
--source = "registry+https://github.com/rust-lang/crates.io-index"
--dependencies = [
-- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
-- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
--]
--
--[metadata]
--"checksum aho-corasick 0.7.13 (registry+https://github.com/rust-lang/crates.io-index)" = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86"
--"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
--"checksum assert_matches 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7deb0a829ca7bcfaf5da70b073a8d128619259a7be8216a355e23f00763059e5"
--"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
--"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
--"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
--"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
--"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
--"checksum bindgen 0.51.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebd71393f1ec0509b553aa012b9b58e81dadbdff7130bd3b8cba576e69b32f75"
--"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
--"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
--"checksum block-buffer 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
--"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
--"checksum buf_redux 0.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
--"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
--"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
--"checksum bytes 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
--"checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
--"checksum cexpr 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d"
--"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
--"checksum clang-sys 0.28.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81de550971c976f176130da4b2978d3b524eaa0fd9ac31f3ceb5ae1231fb4853"
--"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
--"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
--"checksum core-foundation 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3b5ed8e7e76c45974e15e41bfa8d5b0483cd90191639e01d8f5f1e606299d3fb"
--"checksum core-foundation-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6"
--"checksum cpuid-bool 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
--"checksum devd-rs 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1945ccb7caedabdfb9347766ead740fb1e0582b7425598325f546adbd832cce1"
--"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
--"checksum digest 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
--"checksum dtoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b"
--"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3"
--"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
--"checksum fnv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
--"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
--"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
--"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
--"checksum futures 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613"
--"checksum futures-channel 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5"
--"checksum futures-core 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399"
--"checksum futures-io 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789"
--"checksum futures-sink 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc"
--"checksum futures-task 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626"
--"checksum futures-util 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6"
--"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
--"checksum generic-array 0.14.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
--"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
--"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb"
--"checksum glob 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
--"checksum h2 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "993f9e0baeed60001cf565546b0d3dbe6a6ad23f2bd31644a133c641eccf6d53"
--"checksum hashbrown 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
--"checksum headers 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f"
--"checksum headers-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
--"checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
--"checksum http 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9"
--"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
--"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
--"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f"
--"checksum hyper 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3e68a8dd9716185d9e64ea473ea6ef63529252e3e27623295a0378a19665d5eb"
--"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
--"checksum indexmap 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
--"checksum input_buffer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754"
--"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
--"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
--"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
--"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
--"checksum libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
--"checksum libloading 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753"
--"checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
--"checksum libudev-sys 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3c8469b4a23b962c1396b9b451dda50ef5b283e8dd309d69033475fa9b334324"
--"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
--"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
--"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
--"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
--"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
--"checksum mio 0.6.22 (registry+https://github.com/rust-lang/crates.io-index)" = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
--"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
--"checksum multipart 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8209c33c951f07387a8497841122fc6f712165e3f9bda3e6be4645b58188f676"
--"checksum net2 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
--"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
--"checksum nom 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
--"checksum once_cell 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
--"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
--"checksum opaque-debug 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
--"checksum peeking_take_while 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
--"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
--"checksum pin-project 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "ca4433fff2ae79342e497d9f8ee990d174071408f28f726d6d83af93e58e48aa"
--"checksum pin-project-internal 0.4.23 (registry+https://github.com/rust-lang/crates.io-index)" = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f"
--"checksum pin-project-lite 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715"
--"checksum pin-utils 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
--"checksum pkg-config 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
--"checksum ppv-lite86 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
--"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
--"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
--"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
--"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
--"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
--"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
--"checksum rand_chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
--"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
--"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
--"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
--"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
--"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
--"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
--"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
--"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
--"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
--"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
--"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
--"checksum redox_syscall 0.1.57 (registry+https://github.com/rust-lang/crates.io-index)" = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
--"checksum regex 1.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
--"checksum regex-syntax 0.6.18 (registry+https://github.com/rust-lang/crates.io-index)" = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
--"checksum remove_dir_all 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
--"checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd"
--"checksum rustc-hash 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
--"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
--"checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
--"checksum scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
--"checksum serde 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
--"checksum serde_derive 1.0.116 (registry+https://github.com/rust-lang/crates.io-index)" = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
--"checksum serde_json 1.0.57 (registry+https://github.com/rust-lang/crates.io-index)" = "164eacbdb13512ec2745fb09d51fd5b22b0d65ed294a1dcf7285a360c80a675c"
--"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97"
--"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
--"checksum sha-1 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "170a36ea86c864a3f16dd2687712dd6646f7019f301e57537c7f4dc9f5916770"
--"checksum sha2 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69"
--"checksum shlex 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2"
--"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
--"checksum socket2 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "b1fa70dc5c8104ec096f4fe7ede7a221d35ae13dcd19ba1ad9a81d2cab9a1c44"
--"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
--"checksum syn 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b"
--"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
--"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
--"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
--"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
--"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
--"checksum tinyvec 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117"
--"checksum tokio 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5d34ca54d84bf2b5b4d7d31e901a8464f7b60ac145a284fba25ceb801f2ddccd"
--"checksum tokio-macros 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389"
--"checksum tokio-tungstenite 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d9e878ad426ca286e4dcae09cbd4e1973a7f8987d97570e2469703dd7f5720c"
--"checksum tokio-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
--"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860"
--"checksum tracing 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6d79ca061b032d6ce30c660fded31189ca0b9922bf483cd70759f13a2d86786c"
--"checksum tracing-core 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5bcf46c1f1f06aeea2d6b81f3c863d0930a596c86ad1920d4e5bad6dd1d7119a"
--"checksum tracing-futures 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ab7bb6f14721aa00656086e9335d363c5c8747bae02ebe32ea2c7dece5689b4c"
--"checksum try-lock 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
--"checksum tungstenite 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23"
--"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
--"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
--"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
--"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
--"checksum unicode-normalization 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977"
--"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
--"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
--"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
--"checksum urlencoding 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c9232eb53352b4442e40d7900465dfc534e8cb2dc8f18656fcb2ac16112b5593"
--"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
--"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
--"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
--"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
--"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
--"checksum warp 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f41be6df54c97904af01aa23e613d4521eed7ab23537cede692d4058f6449407"
--"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
--"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
--"checksum which 3.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724"
--"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
--"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
--"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
--"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
--"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
--"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
--"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
-diff --git a/third_party/rust/authenticator/Cargo.toml b/third_party/rust/authenticator/Cargo.toml
-index 57d24bd66b948..c49befae2178c 100644
---- a/third_party/rust/authenticator/Cargo.toml
-+++ b/third_party/rust/authenticator/Cargo.toml
-@@ -1,99 +1,60 @@
--# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
--#
--# When uploading crates to the registry Cargo will automatically
--# "normalize" Cargo.toml files for maximal compatibility
--# with all versions of Cargo and also rewrite `path` dependencies
--# to registry (e.g., crates.io) dependencies
--#
--# If you believe there's an error in this file please file an
--# issue against the rust-lang/cargo repository. If you're
--# editing this file be aware that the upstream Cargo.toml
--# will likely look very different (and much more reasonable)
--
- [package]
--edition = "2018"
- name = "authenticator"
- version = "0.3.1"
- authors = ["J.C. Jones <jc@mozilla.com>", "Tim Taubert <ttaubert@mozilla.com>", "Kyle Machulis <kyle@nonpolynomial.com>"]
--description = "Library for interacting with CTAP1/2 security keys for Web Authentication. Used by Firefox."
- keywords = ["ctap2", "u2f", "fido", "webauthn"]
- categories = ["cryptography", "hardware-support", "os"]
--license = "MPL-2.0"
- repository = "https://github.com/mozilla/authenticator-rs/"
--[dependencies.base64]
--version = "^0.10"
--optional = true
--
--[dependencies.bitflags]
--version = "1.0"
--
--[dependencies.bytes]
--version = "0.5"
--features = ["serde"]
--optional = true
--
--[dependencies.libc]
--version = "0.2"
--
--[dependencies.log]
--version = "0.4"
--
--[dependencies.rand]
--version = "0.7"
--
--[dependencies.runloop]
--version = "0.1.0"
--
--[dependencies.serde]
--version = "1.0"
--features = ["derive"]
--optional = true
--
--[dependencies.serde_json]
--version = "1.0"
--optional = true
--
--[dependencies.tokio]
--version = "0.2"
--features = ["macros"]
--optional = true
-+license = "MPL-2.0"
-+description = "Library for interacting with CTAP1/2 security keys for Web Authentication. Used by Firefox."
-+edition = "2018"
- 
--[dependencies.warp]
--version = "0.2.4"
--optional = true
--[dev-dependencies.assert_matches]
--version = "1.2"
-+[badges]
-+travis-ci = { repository = "mozilla/authenticator-rs", branch = "master" }
-+maintenance = { status = "actively-developed" }
- 
--[dev-dependencies.base64]
--version = "^0.10"
-+[features]
-+binding-recompile = ["bindgen"]
-+webdriver = ["base64", "bytes", "warp", "tokio", "serde", "serde_json"]
- 
--[dev-dependencies.env_logger]
--version = "^0.6"
-+[target.'cfg(target_os = "linux")'.dependencies]
-+libudev = "^0.2"
- 
--[dev-dependencies.getopts]
--version = "^0.2"
-+[target.'cfg(target_os = "freebsd")'.dependencies]
-+devd-rs = "0.3"
- 
--[dev-dependencies.sha2]
--version = "^0.8.2"
--[build-dependencies.bindgen]
--version = "^0.51"
--optional = true
-+[target.'cfg(target_os = "macos")'.dependencies]
-+core-foundation = "0.9"
- 
--[features]
--binding-recompile = ["bindgen"]
--webdriver = ["base64", "bytes", "warp", "tokio", "serde", "serde_json"]
--[target."cfg(target_os = \"freebsd\")".dependencies.devd-rs]
--version = "0.3"
--[target."cfg(target_os = \"linux\")".dependencies.libudev]
--version = "^0.2"
--[target."cfg(target_os = \"macos\")".dependencies.core-foundation]
--version = "0.9"
--[target."cfg(target_os = \"windows\")".dependencies.winapi]
-+[target.'cfg(target_os = "windows")'.dependencies.winapi]
- version = "^0.3"
--features = ["handleapi", "hidclass", "hidpi", "hidusage", "setupapi"]
--[badges.maintenance]
--status = "actively-developed"
--
--[badges.travis-ci]
--branch = "master"
--repository = "mozilla/authenticator-rs"
-+features = [
-+    "handleapi",
-+    "hidclass",
-+    "hidpi",
-+    "hidusage",
-+    "setupapi",
-+]
-+
-+[build-dependencies]
-+bindgen = { version = "^0.58.1", optional = true }
-+
-+[dependencies]
-+rand = "0.7"
-+log = "0.4"
-+libc = "0.2"
-+runloop = "0.1.0"
-+bitflags = "1.0"
-+tokio = { version = "0.2", optional = true, features = ["macros"] }
-+warp = { version = "0.2.4", optional = true }
-+serde = { version = "1.0", optional = true, features = ["derive"] }
-+serde_json = { version = "1.0", optional = true }
-+bytes = { version = "0.5", optional = true, features = ["serde"] }
-+base64 = { version = "^0.10", optional = true }
-+
-+[dev-dependencies]
-+sha2 = "^0.8.2"
-+base64 = "^0.10"
-+env_logger = "^0.6"
-+getopts = "^0.2"
-+assert_matches = "1.2"
-diff --git a/third_party/rust/authenticator/build.rs b/third_party/rust/authenticator/build.rs
-index 299e4df6d7331..c972d85b898ea 100644
---- a/third_party/rust/authenticator/build.rs
-+++ b/third_party/rust/authenticator/build.rs
-@@ -45,6 +45,8 @@ fn main() {
-         "ioctl_aarch64be.rs"
-     } else if cfg!(all(target_arch = "s390x", target_endian = "big")) {
-         "ioctl_s390xbe.rs"
-+    } else if cfg!(all(target_arch = "riscv64", target_endian = "little")) {
-+        "ioctl_riscv64.rs"
-     } else {
-         panic!("architecture not supported");
-     };
-diff --git a/third_party/rust/authenticator/src/linux/hidwrapper.rs b/third_party/rust/authenticator/src/linux/hidwrapper.rs
-index ea1a39051b63a..82aabc6301017 100644
---- a/third_party/rust/authenticator/src/linux/hidwrapper.rs
-+++ b/third_party/rust/authenticator/src/linux/hidwrapper.rs
-@@ -46,3 +46,6 @@ include!("ioctl_aarch64be.rs");
- 
- #[cfg(all(target_arch = "s390x", target_endian = "big"))]
- include!("ioctl_s390xbe.rs");
-+
-+#[cfg(all(target_arch = "riscv64", target_endian = "little"))]
-+include!("ioctl_riscv64.rs");
-diff --git a/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs b/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
-new file mode 100644
-index 0000000000000..a784e9bf4600b
---- /dev/null
-+++ b/third_party/rust/authenticator/src/linux/ioctl_riscv64.rs
-@@ -0,0 +1,5 @@
-+/* automatically generated by rust-bindgen */
-+
-+pub type __u32 = ::std::os::raw::c_uint;
-+pub const _HIDIOCGRDESCSIZE: __u32 = 2147764225;
-+pub const _HIDIOCGRDESC: __u32 = 2416199682;
---- a/toolkit/library/rust/shared/Cargo.toml    2022-02-10 20:41:52.387673027 +0800
-+++ b/toolkit/library/rust/shared/Cargo.toml    2022-02-12 17:34:42.861720793 +0800
-@@ -24,7 +24,7 @@
- cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="f2456201dbfdc467b80f0ff6bbb1b8a6faf7df02", optional = true, features=["pulse-dlopen"] }
- cubeb-sys = { version = "0.9", optional = true, features=["gecko-in-tree"] }
- encoding_glue = { path = "../../../../intl/encoding_glue" }
--authenticator = "0.3.1"
-+authenticator = { git = "https://github.com/makotokato/authenticator-rs", rev = "eed8919d50559f4959e2d7d2af7b4d48869b5366" }
- gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
- gecko_logger = { path = "../../../../xpcom/rust/gecko_logger" }
- rsdparsa_capi = { path = "../../../../dom/media/webrtc/sdp/rsdparsa_capi" }
-From a418c651c88cd2682c4cfe61e9f57b5389078c09 Mon Sep 17 00:00:00 2001
-From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
-Date: Thu, 17 Jun 2021 21:50:49 +0900
-Subject: [PATCH] signal handler
-
----
- js/src/wasm/WasmSignalHandlers.cpp | 9 +++++++++
- 1 file changed, 9 insertions(+)
---- a/js/src/wasm/WasmSignalHandlers.cpp        2022-02-12 19:29:33.566924464 +0800
-+++ b/js/src/wasm/WasmSignalHandlers.cpp        2022-02-12 19:50:29.499985612 +0800
-@@ -156,6 +156,11 @@
- #      define R01_sig(p) ((p)->uc_mcontext.gp_regs[1])
- #      define R32_sig(p) ((p)->uc_mcontext.gp_regs[32])
- #    endif
-+#  if defined(__linux__) && defined(__riscv) && __riscv_xlen == 64
-+#    define EPC_sig(p) ((p)->uc_mcontext.__gregs[0])
-+#    define X02_sig(p) ((p)->uc_mcontext.__gregs[2])
-+#    define X08_sig(p) ((p)->uc_mcontext.__gregs[8])
-+#  endif
- #  elif defined(__NetBSD__)
- #    define EIP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EIP])
- #    define EBP_sig(p) ((p)->uc_mcontext.__gregs[_REG_EBP])
-@@ -376,6 +381,10 @@
- #    define PC_sig(p) R32_sig(p)
- #    define SP_sig(p) R01_sig(p)
- #    define FP_sig(p) R01_sig(p)
-+#elif defined(__riscv) && __riscv_xlen == 64
-+#  define PC_sig(p) EPC_sig(p)
-+#  define SP_sig(p) X02_sig(p)
-+#  define FP_sig(p) X08_sig(p)
- #  endif
- 
- static void SetContextPC(CONTEXT* context, uint8_t* pc) {
-From b6be52755af09f55e78d86bdd02a99efa0d16f9f Mon Sep 17 00:00:00 2001
-From: Makoto Kato <m_kato@ga2.so-net.ne.jp>
-Date: Fri, 28 Jan 2022 12:21:06 +0900
-Subject: [PATCH] mach vendor rust
-
----
- .cargo/config.in                              |   10 +-
- Cargo.lock                                    |   29 +-
- Cargo.toml                                    |    3 +-
- .../mozbuild/mozbuild/vendor/vendor_rust.py   |    1 +
- third_party/rust/alsa/.cargo-checksum.json    |    2 +-
- third_party/rust/alsa/Cargo.toml              |    8 +-
- third_party/rust/alsa/src/direct/pcm.rs       |    2 +-
- third_party/rust/alsa/src/error.rs            |    1 -
- third_party/rust/alsa/src/lib.rs              |    8 +-
- third_party/rust/alsa/src/mixer.rs            |    8 +
- third_party/rust/alsa/src/pcm.rs              |   78 +-
- .../rust/bitflags/.cargo-checksum.json        |    2 +-
- third_party/rust/bitflags/CHANGELOG.md        |   57 -
- third_party/rust/bitflags/Cargo.toml          |   34 +-
- third_party/rust/bitflags/README.md           |   12 +-
- third_party/rust/bitflags/build.rs            |   44 +
- third_party/rust/bitflags/src/lib.rs          |  873 ++----
- third_party/rust/bitflags/tests/basic.rs      |   20 -
- .../bitflags/tests/compile-fail/impls/copy.rs |   10 -
- .../tests/compile-fail/impls/copy.stderr.beta |   27 -
- .../bitflags/tests/compile-fail/impls/eq.rs   |   10 -
- .../tests/compile-fail/impls/eq.stderr.beta   |   55 -
- .../non_integer_base/all_defined.rs           |  123 -
- .../non_integer_base/all_defined.stderr.beta  |   27 -
- .../non_integer_base/all_missing.rs           |   13 -
- .../non_integer_base/all_missing.stderr.beta  |   13 -
- .../compile-fail/visibility/private_field.rs  |   13 -
- .../visibility/private_field.stderr.beta      |   10 -
- .../compile-fail/visibility/private_flags.rs  |   18 -
- .../visibility/private_flags.stderr.beta      |   18 -
- .../compile-fail/visibility/pub_const.rs      |    9 -
- .../visibility/pub_const.stderr.beta          |    5 -
- .../tests/compile-pass/impls/convert.rs       |   17 -
- .../tests/compile-pass/impls/default.rs       |   10 -
- .../compile-pass/impls/inherent_methods.rs    |   15 -
- .../tests/compile-pass/redefinition/core.rs   |   14 -
- .../compile-pass/redefinition/stringify.rs    |   19 -
- .../bitflags/tests/compile-pass/repr/c.rs     |   10 -
- .../tests/compile-pass/repr/transparent.rs    |   10 -
- .../compile-pass/visibility/bits_field.rs     |   11 -
- .../tests/compile-pass/visibility/pub_in.rs   |   19 -
- third_party/rust/bitflags/tests/compile.rs    |   63 -
- third_party/rust/midir/.cargo-checksum.json   |    2 +-
- third_party/rust/midir/Cargo.toml             |    4 +-
- .../rust/nix-0.15.0/.cargo-checksum.json      |    1 +
- third_party/rust/nix-0.15.0/CHANGELOG.md      |  742 +++++
- third_party/rust/nix-0.15.0/CONTRIBUTING.md   |  114 +
- third_party/rust/nix-0.15.0/CONVENTIONS.md    |   87 +
- third_party/rust/nix-0.15.0/Cargo.toml        |   71 +
- third_party/rust/nix-0.15.0/LICENSE           |   21 +
- third_party/rust/nix-0.15.0/README.md         |  111 +
- third_party/rust/{nix => nix-0.15.0}/build.rs |    0
- third_party/rust/nix-0.15.0/src/dir.rs        |  193 ++
- third_party/rust/nix-0.15.0/src/errno.rs      | 1963 ++++++++++++++
- .../{nix => nix-0.15.0}/src/errno_dragonfly.c |    0
- third_party/rust/nix-0.15.0/src/fcntl.rs      |  506 ++++
- third_party/rust/nix-0.15.0/src/features.rs   |  103 +
- third_party/rust/nix-0.15.0/src/ifaddrs.rs    |  146 +
- third_party/rust/nix-0.15.0/src/kmod.rs       |  123 +
- third_party/rust/nix-0.15.0/src/lib.rs        |  284 ++
- third_party/rust/nix-0.15.0/src/macros.rs     |  264 ++
- third_party/rust/nix-0.15.0/src/mount.rs      |   98 +
- third_party/rust/nix-0.15.0/src/mqueue.rs     |  162 ++
- third_party/rust/nix-0.15.0/src/net/if_.rs    |  268 ++
- third_party/rust/nix-0.15.0/src/net/mod.rs    |    4 +
- third_party/rust/nix-0.15.0/src/poll.rs       |  143 +
- third_party/rust/nix-0.15.0/src/pty.rs        |  326 +++
- third_party/rust/nix-0.15.0/src/sched.rs      |  147 +
- third_party/rust/nix-0.15.0/src/sys/aio.rs    | 1280 +++++++++
- third_party/rust/nix-0.15.0/src/sys/epoll.rs  |  109 +
- third_party/rust/nix-0.15.0/src/sys/event.rs  |  351 +++
- .../rust/nix-0.15.0/src/sys/eventfd.rs        |   18 +
- .../rust/nix-0.15.0/src/sys/inotify.rs        |  230 ++
- .../rust/nix-0.15.0/src/sys/ioctl/bsd.rs      |  102 +
- .../rust/nix-0.15.0/src/sys/ioctl/linux.rs    |  140 +
- .../rust/nix-0.15.0/src/sys/ioctl/mod.rs      |  778 ++++++
- third_party/rust/nix-0.15.0/src/sys/memfd.rs  |   20 +
- third_party/rust/nix-0.15.0/src/sys/mman.rs   |  325 +++
- third_party/rust/nix-0.15.0/src/sys/mod.rs    |  100 +
- .../rust/nix-0.15.0/src/sys/pthread.rs        |   13 +
- .../rust/nix-0.15.0/src/sys/ptrace/bsd.rs     |  170 ++
- .../rust/nix-0.15.0/src/sys/ptrace/linux.rs   |  402 +++
- .../rust/nix-0.15.0/src/sys/ptrace/mod.rs     |   22 +
- third_party/rust/nix-0.15.0/src/sys/quota.rs  |  273 ++
- third_party/rust/nix-0.15.0/src/sys/reboot.rs |   45 +
- third_party/rust/nix-0.15.0/src/sys/select.rs |  334 +++
- .../rust/nix-0.15.0/src/sys/sendfile.rs       |  200 ++
- third_party/rust/nix-0.15.0/src/sys/signal.rs |  966 +++++++
- .../rust/nix-0.15.0/src/sys/signalfd.rs       |  170 ++
- .../rust/nix-0.15.0/src/sys/socket/addr.rs    | 1278 +++++++++
- .../rust/nix-0.15.0/src/sys/socket/mod.rs     | 1294 +++++++++
- .../rust/nix-0.15.0/src/sys/socket/sockopt.rs |  680 +++++
- third_party/rust/nix-0.15.0/src/sys/stat.rs   |  294 ++
- third_party/rust/nix-0.15.0/src/sys/statfs.rs |  548 ++++
- .../rust/nix-0.15.0/src/sys/statvfs.rs        |  160 ++
- .../rust/nix-0.15.0/src/sys/sysinfo.rs        |   72 +
- .../rust/nix-0.15.0/src/sys/termios.rs        | 1107 ++++++++
- third_party/rust/nix-0.15.0/src/sys/time.rs   |  542 ++++
- third_party/rust/nix-0.15.0/src/sys/uio.rs    |  194 ++
- .../rust/nix-0.15.0/src/sys/utsname.rs        |   67 +
- third_party/rust/nix-0.15.0/src/sys/wait.rs   |  239 ++
- third_party/rust/nix-0.15.0/src/ucontext.rs   |   39 +
- third_party/rust/nix-0.15.0/src/unistd.rs     | 2394 +++++++++++++++++
- third_party/rust/nix-0.15.0/test/sys/mod.rs   |   38 +
- .../rust/nix-0.15.0/test/sys/test_aio.rs      |  654 +++++
- .../rust/nix-0.15.0/test/sys/test_aio_drop.rs |   32 +
- .../rust/nix-0.15.0/test/sys/test_epoll.rs    |   24 +
- .../rust/nix-0.15.0/test/sys/test_inotify.rs  |   65 +
- .../rust/nix-0.15.0/test/sys/test_ioctl.rs    |  334 +++
- .../test/sys/test_lio_listio_resubmit.rs      |  111 +
- .../rust/nix-0.15.0/test/sys/test_pthread.rs  |   15 +
- .../rust/nix-0.15.0/test/sys/test_ptrace.rs   |  107 +
- .../rust/nix-0.15.0/test/sys/test_select.rs   |   54 +
- .../rust/nix-0.15.0/test/sys/test_signal.rs   |  104 +
- .../rust/nix-0.15.0/test/sys/test_signalfd.rs |   25 +
- .../rust/nix-0.15.0/test/sys/test_socket.rs   | 1066 ++++++++
- .../rust/nix-0.15.0/test/sys/test_sockopt.rs  |   53 +
- .../rust/nix-0.15.0/test/sys/test_sysinfo.rs  |   18 +
- .../rust/nix-0.15.0/test/sys/test_termios.rs  |  136 +
- .../rust/nix-0.15.0/test/sys/test_uio.rs      |  241 ++
- .../rust/nix-0.15.0/test/sys/test_wait.rs     |  104 +
- third_party/rust/nix-0.15.0/test/test.rs      |  149 +
- third_party/rust/nix-0.15.0/test/test_dir.rs  |   46 +
- .../rust/nix-0.15.0/test/test_fcntl.rs        |  234 ++
- .../test/test_kmod/hello_mod/Makefile         |    7 +
- .../test/test_kmod/hello_mod/hello.c          |   26 +
- .../rust/nix-0.15.0/test/test_kmod/mod.rs     |  166 ++
- .../rust/nix-0.15.0/test/test_mount.rs        |  238 ++
- third_party/rust/nix-0.15.0/test/test_mq.rs   |  152 ++
- third_party/rust/nix-0.15.0/test/test_net.rs  |   12 +
- .../rust/nix-0.15.0/test/test_nix_path.rs     |    0
- third_party/rust/nix-0.15.0/test/test_poll.rs |   50 +
- third_party/rust/nix-0.15.0/test/test_pty.rs  |  235 ++
- .../nix-0.15.0/test/test_ptymaster_drop.rs    |   21 +
- .../rust/nix-0.15.0/test/test_sendfile.rs     |  129 +
- third_party/rust/nix-0.15.0/test/test_stat.rs |  296 ++
- .../rust/nix-0.15.0/test/test_unistd.rs       |  669 +++++
- third_party/rust/nix/.cargo-checksum.json     |    2 +-
- third_party/rust/nix/CHANGELOG.md             |  306 ++-
- third_party/rust/nix/CONTRIBUTING.md          |   10 +-
- third_party/rust/nix/CONVENTIONS.md           |    9 +-
- third_party/rust/nix/Cargo.toml               |   40 +-
- third_party/rust/nix/README.md                |   22 +-
- third_party/rust/nix/src/dir.rs               |   99 +-
- third_party/rust/nix/src/env.rs               |   53 +
- third_party/rust/nix/src/errno.rs             |  480 +++-
- third_party/rust/nix/src/fcntl.rs             |  268 +-
- third_party/rust/nix/src/features.rs          |    7 +-
- third_party/rust/nix/src/ifaddrs.rs           |   29 +-
- third_party/rust/nix/src/kmod.rs              |    4 +-
- third_party/rust/nix/src/lib.rs               |   74 +-
- third_party/rust/nix/src/macros.rs            |   79 +-
- third_party/rust/nix/src/mount.rs             |   43 +-
- third_party/rust/nix/src/mqueue.rs            |   65 +-
- third_party/rust/nix/src/net/if_.rs           |    3 +-
- third_party/rust/nix/src/poll.rs              |   29 +-
- third_party/rust/nix/src/pty.rs               |   80 +-
- third_party/rust/nix/src/sched.rs             |  104 +-
- third_party/rust/nix/src/sys/aio.rs           |   44 +-
- third_party/rust/nix/src/sys/epoll.rs         |    8 +-
- third_party/rust/nix/src/sys/event.rs         |   45 +-
- third_party/rust/nix/src/sys/eventfd.rs       |    4 +-
- third_party/rust/nix/src/sys/inotify.rs       |   37 +-
- third_party/rust/nix/src/sys/ioctl/bsd.rs     |    4 +-
- third_party/rust/nix/src/sys/ioctl/linux.rs   |    3 +-
- third_party/rust/nix/src/sys/ioctl/mod.rs     |   12 +-
- third_party/rust/nix/src/sys/memfd.rs         |    4 +-
- third_party/rust/nix/src/sys/mman.rs          |  136 +-
- third_party/rust/nix/src/sys/mod.rs           |   10 +
- third_party/rust/nix/src/sys/personality.rs   |   70 +
- third_party/rust/nix/src/sys/ptrace/bsd.rs    |   25 +-
- third_party/rust/nix/src/sys/ptrace/linux.rs  |  164 +-
- third_party/rust/nix/src/sys/quota.rs         |   16 +-
- third_party/rust/nix/src/sys/reboot.rs        |    8 +-
- third_party/rust/nix/src/sys/select.rs        |  140 +-
- third_party/rust/nix/src/sys/sendfile.rs      |   11 +-
- third_party/rust/nix/src/sys/signal.rs        |  300 ++-
- third_party/rust/nix/src/sys/signalfd.rs      |   28 +-
- third_party/rust/nix/src/sys/socket/addr.rs   |  205 +-
- third_party/rust/nix/src/sys/socket/mod.rs    |  930 +++++--
- .../rust/nix/src/sys/socket/sockopt.rs        |  117 +-
- third_party/rust/nix/src/sys/stat.rs          |   39 +-
- third_party/rust/nix/src/sys/statfs.rs        |  216 +-
- third_party/rust/nix/src/sys/statvfs.rs       |   21 +-
- third_party/rust/nix/src/sys/sysinfo.rs       |   19 +-
- third_party/rust/nix/src/sys/termios.rs       |  217 +-
- third_party/rust/nix/src/sys/time.rs          |   79 +-
- third_party/rust/nix/src/sys/timerfd.rs       |  285 ++
- third_party/rust/nix/src/sys/uio.rs           |   18 +-
- third_party/rust/nix/src/sys/utsname.rs       |    8 +-
- third_party/rust/nix/src/sys/wait.rs          |   43 +-
- third_party/rust/nix/src/time.rs              |  260 ++
- third_party/rust/nix/src/ucontext.rs          |   25 +-
- third_party/rust/nix/src/unistd.rs            |  809 ++++--
- third_party/rust/nix/test/common/mod.rs       |  127 +
- third_party/rust/nix/test/sys/mod.rs          |    7 +
- third_party/rust/nix/test/sys/test_aio.rs     |  104 +-
- .../rust/nix/test/sys/test_aio_drop.rs        |    4 +-
- third_party/rust/nix/test/sys/test_ioctl.rs   |   55 +-
- .../nix/test/sys/test_lio_listio_resubmit.rs  |    4 -
- third_party/rust/nix/test/sys/test_mman.rs    |   80 +
- third_party/rust/nix/test/sys/test_pthread.rs |    4 +-
- third_party/rust/nix/test/sys/test_ptrace.rs  |   79 +-
- third_party/rust/nix/test/sys/test_select.rs  |    2 +-
- third_party/rust/nix/test/sys/test_signal.rs  |   25 +-
- .../rust/nix/test/sys/test_signalfd.rs        |    6 +-
- third_party/rust/nix/test/sys/test_socket.rs  |  555 +++-
- third_party/rust/nix/test/sys/test_sockopt.rs |   43 +
- third_party/rust/nix/test/sys/test_termios.rs |   22 +-
- third_party/rust/nix/test/sys/test_timerfd.rs |   61 +
- third_party/rust/nix/test/sys/test_uio.rs     |   12 +-
- third_party/rust/nix/test/sys/test_wait.rs    |   21 +-
- third_party/rust/nix/test/test.rs             |   71 +-
- third_party/rust/nix/test/test_clearenv.rs    |    9 +
- third_party/rust/nix/test/test_dir.rs         |    7 +-
- third_party/rust/nix/test/test_fcntl.rs       |  199 +-
- third_party/rust/nix/test/test_kmod/mod.rs    |   31 +-
- third_party/rust/nix/test/test_mount.rs       |    7 +-
- third_party/rust/nix/test/test_mq.rs          |   28 +-
- third_party/rust/nix/test/test_poll.rs        |   27 +-
- third_party/rust/nix/test/test_pty.rs         |  104 +-
- .../rust/nix/test/test_ptymaster_drop.rs      |   41 +-
- third_party/rust/nix/test/test_sched.rs       |   32 +
- third_party/rust/nix/test/test_stat.rs        |   61 +-
- third_party/rust/nix/test/test_time.rs        |   56 +
- third_party/rust/nix/test/test_unistd.rs      |  575 +++-
- 226 files changed, 33484 insertions(+), 3322 deletions(-)
- create mode 100644 third_party/rust/bitflags/build.rs
- delete mode 100644 third_party/rust/bitflags/tests/basic.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/default.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/repr/c.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
- delete mode 100644 third_party/rust/bitflags/tests/compile.rs
- create mode 100644 third_party/rust/nix-0.15.0/.cargo-checksum.json
- create mode 100644 third_party/rust/nix-0.15.0/CHANGELOG.md
- create mode 100644 third_party/rust/nix-0.15.0/CONTRIBUTING.md
- create mode 100644 third_party/rust/nix-0.15.0/CONVENTIONS.md
- create mode 100644 third_party/rust/nix-0.15.0/Cargo.toml
- create mode 100644 third_party/rust/nix-0.15.0/LICENSE
- create mode 100644 third_party/rust/nix-0.15.0/README.md
- rename third_party/rust/{nix => nix-0.15.0}/build.rs (100%)
- create mode 100644 third_party/rust/nix-0.15.0/src/dir.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/errno.rs
- rename third_party/rust/{nix => nix-0.15.0}/src/errno_dragonfly.c (100%)
- create mode 100644 third_party/rust/nix-0.15.0/src/fcntl.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/features.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/ifaddrs.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/kmod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/lib.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/macros.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/mount.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/mqueue.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/net/if_.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/net/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/poll.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/pty.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sched.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/aio.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/epoll.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/event.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/eventfd.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/inotify.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/memfd.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/mman.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/pthread.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/quota.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/reboot.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/select.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/sendfile.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/signal.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/signalfd.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/stat.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/statfs.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/statvfs.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/termios.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/time.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/uio.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/utsname.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/sys/wait.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/ucontext.rs
- create mode 100644 third_party/rust/nix-0.15.0/src/unistd.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_aio.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_select.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_signal.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_socket.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_termios.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_uio.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/sys/test_wait.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_dir.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_fcntl.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
- create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
- create mode 100644 third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_mount.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_mq.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_net.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_nix_path.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_poll.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_pty.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_sendfile.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_stat.rs
- create mode 100644 third_party/rust/nix-0.15.0/test/test_unistd.rs
- create mode 100644 third_party/rust/nix/src/env.rs
- create mode 100644 third_party/rust/nix/src/sys/personality.rs
- create mode 100644 third_party/rust/nix/src/sys/timerfd.rs
- create mode 100644 third_party/rust/nix/src/time.rs
- create mode 100644 third_party/rust/nix/test/common/mod.rs
- create mode 100644 third_party/rust/nix/test/sys/test_mman.rs
- create mode 100644 third_party/rust/nix/test/sys/test_timerfd.rs
- create mode 100644 third_party/rust/nix/test/test_clearenv.rs
- create mode 100644 third_party/rust/nix/test/test_sched.rs
- create mode 100644 third_party/rust/nix/test/test_time.rs
-
-diff --git a/Cargo.lock b/Cargo.lock
-index edc5ef5ff2d98..f6240163e1440 100644
---- a/Cargo.lock
-+++ b/Cargo.lock
-@@ -25,14 +25,14 @@ dependencies = [
- 
- [[package]]
- name = "alsa"
--version = "0.4.3"
-+version = "0.5.0"
- source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"
-+checksum = "75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18"
- dependencies = [
-  "alsa-sys",
-  "bitflags",
-  "libc",
-- "nix",
-+ "nix 0.20.2",
- ]
- 
- [[package]]
-@@ -427,9 +427,9 @@ checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
- 
- [[package]]
- name = "bitflags"
--version = "1.3.2"
-+version = "1.2.1"
- source = "registry+https://github.com/rust-lang/crates.io-index"
--checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
-+checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
- 
- [[package]]
- name = "bitflags_serde_shim"
-@@ -3073,7 +3073,7 @@ dependencies = [
- [[package]]
- name = "midir"
- version = "0.7.0"
--source = "git+https://github.com/mozilla/midir.git?rev=4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f#4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
-+source = "git+https://github.com/makotokato/midir.git?rev=6140b2825dd4dc2b40e49e154ca7596e7b9a131a#6140b2825dd4dc2b40e49e154ca7596e7b9a131a"
- dependencies = [
-  "alsa",
-  "bitflags",
-@@ -3081,7 +3081,7 @@ dependencies = [
-  "js-sys",
-  "libc",
-  "memalloc",
-- "nix",
-+ "nix 0.20.2",
-  "wasm-bindgen",
-  "web-sys",
-  "winapi",
-@@ -3123,7 +3123,7 @@ dependencies = [
-  "libc",
-  "memmap2 0.2.3",
-  "memoffset 0.5.6",
-- "nix",
-+ "nix 0.15.0",
-  "tempfile",
-  "thiserror",
- ]
-@@ -3535,6 +3535,19 @@ dependencies = [
-  "void",
- ]
- 
-+[[package]]
-+name = "nix"
-+version = "0.20.2"
-+source = "registry+https://github.com/rust-lang/crates.io-index"
-+checksum = "f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"
-+dependencies = [
-+ "bitflags",
-+ "cc",
-+ "cfg-if 1.0.0",
-+ "libc",
-+ "memoffset 0.6.5",
-+]
-+
- [[package]]
- name = "nom"
- version = "5.1.2"
-diff --git a/Cargo.toml b/Cargo.toml
-index 1c2437f1f5675..2923c7e5ea9bf 100644
---- a/Cargo.toml        2022-03-10 14:19:47.963772765 +0800
-+++ b/Cargo.toml        2022-03-10 14:33:46.354649188 +0800
-@@ -103,13 +103,14 @@
- moz_asserts = { path = "mozglue/static/rust/moz_asserts" }
- 
- # Other overrides
-+authenticator = { git = "https://github.com/makotokato/authenticator-rs", rev="eed8919d50559f4959e2d7d2af7b4d48869b5366" }
- async-task = { git = "https://github.com/smol-rs/async-task", rev="f6488e35beccb26eb6e85847b02aa78a42cd3d0e" }
- chardetng = { git = "https://github.com/hsivonen/chardetng", rev="3484d3e3ebdc8931493aa5df4d7ee9360a90e76b" }
- chardetng_c = { git = "https://github.com/hsivonen/chardetng_c", rev="ed8a4c6f900a90d4dbc1d64b856e61490a1c3570" }
- coremidi = { git = "https://github.com/chris-zen/coremidi.git", rev="fc68464b5445caf111e41f643a2e69ccce0b4f83" }
- libudev-sys = { path = "dom/webauthn/libudev-sys" }
- packed_simd = { git = "https://github.com/hsivonen/packed_simd", rev="8b4bd7d8229660a749dbe419a57ea01df9de5453" }
--midir = { git = "https://github.com/mozilla/midir.git", rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f" }
-+midir = { git = "https://github.com/makotokato/midir.git", rev = "6140b2825dd4dc2b40e49e154ca7596e7b9a131a" }
- minidump_writer_linux = { git = "https://github.com/msirringhaus/minidump_writer_linux.git", rev = "029ac0d54b237f27dc7d8d4e51bc0fb076e5e852" }
- 
- # Patch mio 0.6 to use winapi 0.3 and miow 0.3, getting rid of winapi 0.2.
-
-diff --git a/third_party/rust/alsa/.cargo-checksum.json b/third_party/rust/alsa/.cargo-checksum.json
-index 17227c0a74d16..2bd6b2e2ce47b 100644
---- a/third_party/rust/alsa/.cargo-checksum.json
-+++ b/third_party/rust/alsa/.cargo-checksum.json
-@@ -1 +1 @@
--{"files":{"Cargo.toml":"5c7a276dd872b47ff86f892e5d8991f38fbe3d61b64eb7138a4ee7ed43d437b7","README.md":"4ccf86e184eda628989919a15560c1ada2c00808cf34740f6e8de466338a1d48","src/card.rs":"f49c6cd6afb83848d34ce7a2e71ede2741ef60262d073be631347871c2768401","src/chmap.rs":"c639f9018fe7d49179a64b73d4f7ef418483c7b150b7edba61d81963c4056770","src/ctl_int.rs":"ebff40ad723a62632ed59840c15c4ec8e4cea2053e4f61d49bdae95e7a74da70","src/device_name.rs":"1e8ad5efbca9c4f062289213e3de8c3429d97a4acf6312c2016553b06e7fa57b","src/direct.rs":"fbd40addd2458bb0b3e856e5b0225fd24dc0ad46ce3662aef12635cf34ef7f55","src/direct/asound_ioctl.rs":"27c8935a0e7bd6e1925d947411c37ca81befba60468a6f2206da9fb08805be89","src/direct/ffi.rs":"aeb0871bd764198558557b5af1a1f6038efe8c8a400d77b4ddfc91143029ac90","src/direct/pcm.rs":"a258e7ba908ef6a2d7d0851ce5279ccc9f7b1579511f48550927fbe4306edaae","src/error.rs":"c8e9839123d760d49b58f46574445550c2c48b90c738b4daaf48aab8dd9a205f","src/hctl.rs":"cc33947cb0810d3edeec7b71686f0231d06c88b421
 4994605de7f4fd0f6de1a1","src/io.rs":"a6e21b94a265b7de56388e035b104877c8b6a0f5d10002c5931dacc90dd577fd","src/lib.rs":"df35e75bb2d83ddddcc90f4ed76e4bcef6843b3b2be09d9b8197c9ede564fbdf","src/mixer.rs":"d6610712f80eb4fd292d5b6e1d10723dfb245be4d85d0370a675034d83010e75","src/pcm.rs":"4259a5b33421e0b144de59da938af1ff1f70a1a3f6e0d2ab665dda4b94441d8c","src/poll.rs":"a6472dbcc96bcbdcc574563f305550df66870e48820d5e90609b0f105d12bb07","src/rawmidi.rs":"ca891bf1cd43ad59b1657efd58356f78ea476d5de999ed756eba74b729f0c184","src/seq.rs":"d229b36f12bf0161c87e0820fd4a3313f19718790e38e0b6294b7e6b1123c611"},"package":"eb213f6b3e4b1480a60931ca2035794aa67b73103d254715b1db7b70dcb3c934"}
-\ No newline at end of file
-+{"files":{"Cargo.toml":"e057013b541a2bcf1d2b7aa79a2860fec402dad4ae434a66ad2cf1f4e40d31b9","README.md":"4ccf86e184eda628989919a15560c1ada2c00808cf34740f6e8de466338a1d48","src/card.rs":"f49c6cd6afb83848d34ce7a2e71ede2741ef60262d073be631347871c2768401","src/chmap.rs":"c639f9018fe7d49179a64b73d4f7ef418483c7b150b7edba61d81963c4056770","src/ctl_int.rs":"ebff40ad723a62632ed59840c15c4ec8e4cea2053e4f61d49bdae95e7a74da70","src/device_name.rs":"1e8ad5efbca9c4f062289213e3de8c3429d97a4acf6312c2016553b06e7fa57b","src/direct.rs":"fbd40addd2458bb0b3e856e5b0225fd24dc0ad46ce3662aef12635cf34ef7f55","src/direct/asound_ioctl.rs":"27c8935a0e7bd6e1925d947411c37ca81befba60468a6f2206da9fb08805be89","src/direct/ffi.rs":"aeb0871bd764198558557b5af1a1f6038efe8c8a400d77b4ddfc91143029ac90","src/direct/pcm.rs":"e8d464f08405e4edfc35be12d715012b3c765093794dd8fafc8991a5f4367c67","src/error.rs":"b37d9958dd200362c44d7015d1b03813efec183c9c76168f2608d1e798035ea1","src/hctl.rs":"cc33947cb0810d3edeec7b71686f0231d06c88b421
 4994605de7f4fd0f6de1a1","src/io.rs":"a6e21b94a265b7de56388e035b104877c8b6a0f5d10002c5931dacc90dd577fd","src/lib.rs":"b1235da87167b3a329b5a1a1d8670db0ab411676c0cdb2bfd1b8884bca34f469","src/mixer.rs":"a358bb2ad1db787348c29cdfeda339c4cd16c5a85f5cea8d7e0e9dda8335cbbd","src/pcm.rs":"6c5c87c9d959626d717c6e0e6f13248a56297a0cb390ab0e58d27ca7ad901cac","src/poll.rs":"a6472dbcc96bcbdcc574563f305550df66870e48820d5e90609b0f105d12bb07","src/rawmidi.rs":"ca891bf1cd43ad59b1657efd58356f78ea476d5de999ed756eba74b729f0c184","src/seq.rs":"d229b36f12bf0161c87e0820fd4a3313f19718790e38e0b6294b7e6b1123c611"},"package":"75c4da790adcb2ce5e758c064b4f3ec17a30349f9961d3e5e6c9688b052a9e18"}
-\ No newline at end of file
-diff --git a/third_party/rust/alsa/Cargo.toml b/third_party/rust/alsa/Cargo.toml
-index c7578fb0785b9..b4af1a6dae284 100644
---- a/third_party/rust/alsa/Cargo.toml
-+++ b/third_party/rust/alsa/Cargo.toml
-@@ -13,7 +13,7 @@
- [package]
- edition = "2018"
- name = "alsa"
--version = "0.4.3"
-+version = "0.5.0"
- authors = ["David Henningsson <diwic@ubuntu.com>"]
- description = "Thin but safe wrappers for ALSA (Linux sound API)"
- documentation = "http://docs.rs/alsa"
-@@ -23,16 +23,16 @@ categories = ["multimedia::audio", "api-bindings"]
- license = "Apache-2.0/MIT"
- repository = "https://github.com/diwic/alsa-rs"
- [dependencies.alsa-sys]
--version = "0.3.0"
-+version = "0.3.1"
- 
- [dependencies.bitflags]
- version = "1.2.1"
- 
- [dependencies.libc]
--version = "0.2.65"
-+version = "0.2.88"
- 
- [dependencies.nix]
--version = "0.15"
-+version = "0.20"
- [badges.is-it-maintained-issue-resolution]
- repository = "diwic/alsa-rs"
- 
-diff --git a/third_party/rust/alsa/src/direct/pcm.rs b/third_party/rust/alsa/src/direct/pcm.rs
-index 13a16a993b030..f248a70c67031 100644
---- a/third_party/rust/alsa/src/direct/pcm.rs
-+++ b/third_party/rust/alsa/src/direct/pcm.rs
-@@ -19,7 +19,7 @@ don't expect it to work with, e g, the PulseAudio plugin or so.
- For an example of how to use this mode, look in the "synth-example" directory.
- */
- 
--use {libc, nix};
-+use libc;
- use std::{mem, ptr, fmt, cmp};
- use crate::error::{Error, Result};
- use std::os::unix::io::RawFd;
-diff --git a/third_party/rust/alsa/src/error.rs b/third_party/rust/alsa/src/error.rs
-index 4711b0fd2016d..25089c4cbd1d7 100644
---- a/third_party/rust/alsa/src/error.rs
-+++ b/third_party/rust/alsa/src/error.rs
-@@ -3,7 +3,6 @@
- use libc::{c_void, c_int, c_char, free};
- use std::{fmt, ptr, str};
- use std::ffi::CStr;
--use nix;
- use std::error::Error as StdError;
- 
- /// ALSA error
-diff --git a/third_party/rust/alsa/src/lib.rs b/third_party/rust/alsa/src/lib.rs
-index cf172cb6c60c6..b1a98df7804f3 100644
---- a/third_party/rust/alsa/src/lib.rs
-+++ b/third_party/rust/alsa/src/lib.rs
-@@ -18,7 +18,7 @@ extern crate libc;
- #[macro_use]
- extern crate bitflags;
- #[macro_use]
--extern crate nix;
-+extern crate nix as nix_the_crate;
- 
- macro_rules! alsa_enum {
-  ($(#[$attr:meta])+ $name:ident, $static_name:ident [$count:expr], $( $a:ident = $b:ident),* ,) =>
-@@ -125,3 +125,9 @@ pub use crate::io::Output;
- mod chmap;
- 
- pub mod direct;
-+
-+/// Re-exports from the nix crate.
-+pub mod nix {
-+    pub use nix_the_crate::Error;
-+    pub use nix_the_crate::errno;
-+}
-diff --git a/third_party/rust/alsa/src/mixer.rs b/third_party/rust/alsa/src/mixer.rs
-index cb16247a85b62..834aafaf35c18 100644
---- a/third_party/rust/alsa/src/mixer.rs
-+++ b/third_party/rust/alsa/src/mixer.rs
-@@ -112,11 +112,19 @@ impl ops::Add for MilliBel {
-     fn add(self, rhs: Self) -> Self { MilliBel(self.0 + rhs.0) }
- }
- 
-+impl ops::AddAssign for MilliBel {
-+    fn add_assign(&mut self, rhs: Self) { self.0 += rhs.0 }
-+}
-+
- impl ops::Sub for MilliBel {
-     type Output = MilliBel;
-     fn sub(self, rhs: Self) -> Self { MilliBel(self.0 - rhs.0) }
- }
- 
-+impl ops::SubAssign for MilliBel {
-+    fn sub_assign(&mut self, rhs: Self) { self.0 -= rhs.0 }
-+}
-+
- /// Wraps [snd_mixer_elem_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___mixer.html)
- #[derive(Copy, Clone, Debug)]
- pub struct Elem<'a>{
-diff --git a/third_party/rust/alsa/src/pcm.rs b/third_party/rust/alsa/src/pcm.rs
-index 359b44c6db2cb..5696df9dc691e 100644
---- a/third_party/rust/alsa/src/pcm.rs
-+++ b/third_party/rust/alsa/src/pcm.rs
-@@ -174,8 +174,7 @@ impl PCM {
-     }
- 
-     pub fn status(&self) -> Result<Status> {
--        let z = Status::new();
--        acheck!(snd_pcm_status(self.0, z.ptr())).map(|_| z)
-+        StatusBuilder::new().build(self)
-     }
- 
-     fn verify_format(&self, f: Format) -> Result<()> {
-@@ -416,6 +415,7 @@ alsa_enum!(
- );
- 
- alsa_enum!(
-+    #[non_exhaustive]
-     /// [SND_PCM_FORMAT_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
-     Format, ALL_FORMATS[48],
- 
-@@ -470,21 +470,21 @@ alsa_enum!(
- );
- 
- impl Format {
--    pub fn s16() -> Format { <i16 as IoFormat>::FORMAT }
--    pub fn u16() -> Format { <u16 as IoFormat>::FORMAT }
--    pub fn s32() -> Format { <i32 as IoFormat>::FORMAT }
--    pub fn u32() -> Format { <u32 as IoFormat>::FORMAT }
--    pub fn float() -> Format { <f32 as IoFormat>::FORMAT }
--    pub fn float64() -> Format { <f64 as IoFormat>::FORMAT }
-+    pub const fn s16() -> Format { <i16 as IoFormat>::FORMAT }
-+    pub const fn u16() -> Format { <u16 as IoFormat>::FORMAT }
-+    pub const fn s32() -> Format { <i32 as IoFormat>::FORMAT }
-+    pub const fn u32() -> Format { <u32 as IoFormat>::FORMAT }
-+    pub const fn float() -> Format { <f32 as IoFormat>::FORMAT }
-+    pub const fn float64() -> Format { <f64 as IoFormat>::FORMAT }
- 
--    #[cfg(target_endian = "little")] pub fn s24() -> Format { Format::S24LE }
--    #[cfg(target_endian = "big")] pub fn s24() -> Format { Format::S24BE }
-+    #[cfg(target_endian = "little")] pub const fn s24() -> Format { Format::S24LE }
-+    #[cfg(target_endian = "big")] pub const fn s24() -> Format { Format::S24BE }
- 
--    #[cfg(target_endian = "little")] pub fn u24() -> Format { Format::U24LE }
--    #[cfg(target_endian = "big")] pub fn u24() -> Format { Format::U24BE }
-+    #[cfg(target_endian = "little")] pub const fn u24() -> Format { Format::U24LE }
-+    #[cfg(target_endian = "big")] pub const fn u24() -> Format { Format::U24BE }
- 
--    #[cfg(target_endian = "little")] pub fn iec958_subframe() -> Format { Format::IEC958SubframeLE }
--    #[cfg(target_endian = "big")] pub fn iec958_subframe() -> Format { Format::IEC958SubframeBE }
-+    #[cfg(target_endian = "little")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeLE }
-+    #[cfg(target_endian = "big")] pub const fn iec958_subframe() -> Format { Format::IEC958SubframeBE }
- }
- 
- 
-@@ -769,6 +769,15 @@ impl<'a> HwParams<'a> {
-         unsafe { alsa::snd_pcm_hw_params_can_resume(self.0) != 0 }
-     }
- 
-+    /// Returns true if the alsa stream supports the provided `AudioTstampType`, false if not.
-+    ///
-+    /// This function should only be called when the configuration space contains a single
-+    /// configuration. Call `PCM::hw_params` to choose a single configuration from the
-+    /// configuration space.
-+    pub fn supports_audio_ts_type(&self, type_: AudioTstampType) -> bool {
-+        unsafe { alsa::snd_pcm_hw_params_supports_audio_ts_type(self.0, type_ as libc::c_int) != 0 }
-+    }
-+
-     pub fn dump(&self, o: &mut Output) -> Result<()> {
-         acheck!(snd_pcm_hw_params_dump(self.0, super::io::output_handle(o))).map(|_| ())
-     }
-@@ -923,6 +932,47 @@ impl Status {
-     }
- }
- 
-+/// Builder for [`Status`].
-+///
-+/// Allows setting the audio timestamp configuration before retrieving the
-+/// status from the stream.
-+pub struct StatusBuilder(Status);
-+
-+impl StatusBuilder {
-+    pub fn new() -> Self {
-+        StatusBuilder(Status::new())
-+    }
-+
-+    pub fn audio_htstamp_config(
-+        self,
-+        type_requested: AudioTstampType,
-+        report_delay: bool,
-+    ) -> Self {
-+        let mut cfg: alsa::snd_pcm_audio_tstamp_config_t = unsafe { std::mem::zeroed() };
-+        cfg.set_type_requested(type_requested as _);
-+        cfg.set_report_delay(report_delay as _);
-+        unsafe { alsa::snd_pcm_status_set_audio_htstamp_config(self.0.ptr(), &mut cfg) };
-+        self
-+    }
-+
-+    pub fn build(self, pcm: &PCM) -> Result<Status> {
-+        acheck!(snd_pcm_status(pcm.0, self.0.ptr())).map(|_| self.0)
-+    }
-+}
-+
-+alsa_enum!(
-+    #[non_exhaustive]
-+    /// [SND_PCM_AUDIO_TSTAMP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
-+    AudioTstampType, ALL_AUDIO_TSTAMP_TYPES[6],
-+
-+    Compat = SND_PCM_AUDIO_TSTAMP_TYPE_COMPAT,
-+    Default = SND_PCM_AUDIO_TSTAMP_TYPE_DEFAULT,
-+    Link = SND_PCM_AUDIO_TSTAMP_TYPE_LINK,
-+    LinkAbsolute = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ABSOLUTE,
-+    LinkEstimated = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_ESTIMATED,
-+    LinkSynchronized = SND_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED,
-+);
-+
- #[test]
- fn info_from_default() {
-     use std::ffi::CString;
-diff --git a/third_party/rust/bitflags/.cargo-checksum.json b/third_party/rust/bitflags/.cargo-checksum.json
-index 7e8d470b53a37..a8b031c6517a2 100644
---- a/third_party/rust/bitflags/.cargo-checksum.json
-+++ b/third_party/rust/bitflags/.cargo-checksum.json
-@@ -1 +1 @@
--{"files":{"CHANGELOG.md":"d362fc1fccaaf4d421bcf0fe8b80ddb4f625dade0c1ee52d08bd0b95509a49d1","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"87aced7532a7974eb37ab5fe6037f0abafc36d6b2d74891ecd2bf2f14f50d11e","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"baa8604f8afb34fd93b9c79729daafb884dedcaf34023e4af8ad037d916061fd","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"e6477688535ee326d27238aeedc9cb4320ac35b9d17a4deda09e0587b0ccdbd4","tests/basic.rs":"146f1cbf6279bc609242cd3349f29cb21b41294f5e4921875f5ec95bd83529a2","tests/compile-fail/impls/copy.rs":"b791371237ddc75a7c04d2130e03b462c9c00a80dca08bd45aa97433d9c0d13a","tests/compile-fail/impls/copy.stderr.beta":"77d83484ce221d4b6ff2f7de843929a452d779fcfff428122710dd8218c298e3","tests/compile-fail/i
 mpls/eq.rs":"0cee8b9e07d537890e0189710293b53972d0fab63c09366f33c391065afafa99","tests/compile-fail/impls/eq.stderr.beta":"381fc6143d45ce76d7cecc47aa59cb69fe5e79c0b60a4a85d5c6163b400b3cc7","tests/compile-fail/non_integer_base/all_defined.rs":"95e14cad9e94560262f2862c3c01865ac30369b69da1001b0e7285cb55e6cb75","tests/compile-fail/non_integer_base/all_defined.stderr.beta":"1760739a276690903bb03844025587d37939f5dfcbfab309db3c86f32bdbf748","tests/compile-fail/non_integer_base/all_missing.rs":"b3d9da619d23213731ba2581aa7999c796c3c79aaf4f0ee6b11ceec08a11537f","tests/compile-fail/non_integer_base/all_missing.stderr.beta":"37e102290d3867e175b21976be798939f294efb17580d5b51e7b17b590d55132","tests/compile-fail/visibility/private_field.rs":"38e4d3fe6471829360d12c8d09b097f6a21aa93fb51eac3b215d96bdae23316b","tests/compile-fail/visibility/private_field.stderr.beta":"5aa24a3ebb39326f31927721c5017b8beb66c3e501fb865a3fa814c9763bfa0f","tests/compile-fail/visibility/private_flags.rs":"2ce4235802aa4e9c96c4
 e77d9e31d8401ef58dcda4741325184f0764ab1fe393","tests/compile-fail/visibility/private_flags.stderr.beta":"f3eb9f7baf2689258f3519ff7ee5c6ec3c237264ebcfe63f40c40f2023e5022f","tests/compile-fail/visibility/pub_const.rs":"8f813a97ac518c5ea8ac65b184101912452384afaf7b8d6c5e62f8370eca3c0a","tests/compile-fail/visibility/pub_const.stderr.beta":"823976ae1794d7f5372e2ec9aabba497e7bb88004722904c38da342ed98e8962","tests/compile-pass/impls/convert.rs":"88fe80bfb9cd5779f0e1d92c9ec02a8b6bb67e334c07f2309e9c0ba5ef776eb0","tests/compile-pass/impls/default.rs":"c508f9a461691f44b45142fa5ad599f02326e1de4c0cbca6c0593f4652eba109","tests/compile-pass/impls/inherent_methods.rs":"ecc26388e9a394bfa7a5bb69a5d621ab3d4d1e53f28f657bb8e78fe79f437913","tests/compile-pass/redefinition/core.rs":"ff5b6e72f87acc6ebb12405d3c0f6e3fa62e669933656a454bb63b30ea44179c","tests/compile-pass/redefinition/stringify.rs":"1edbce42b900c14425d7ffa14e83e165ebe452d7dccd8c0a8a821bdec64f5c93","tests/compile-pass/repr/c.rs":"6fda17f7c2edfc
 d155314579e83d0fc8a16209e400f1f9a5ca77bd9a799041f2","tests/compile-pass/repr/transparent.rs":"6cdc87a2137d8a4e0c8ce9b6cba83c82255f8ea125951bf614418685600489ce","tests/compile-pass/visibility/bits_field.rs":"1f3e5ba5a047440066a9f6bf7b7af33f5b06f6b1da3dd9af6886168199a7ea0a","tests/compile-pass/visibility/pub_in.rs":"e95312ff60966d42ec4bc00225507895a9b8ec24056ce6a9edd9145be35d730f","tests/compile.rs":"f27c67a7dd183ca30efea1b6e0880e3469a6dd63b92b1fd711c082df182c9eec"},"package":"bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"}
-\ No newline at end of file
-+{"files":{"CHANGELOG.md":"00224cc8d292567bdd212c36db66a1f662cd2e6c58e947900680234937e288a9","CODE_OF_CONDUCT.md":"42634d0f6d922f49857175af991802822f7f920487aefa2ee250a50d12251a66","Cargo.toml":"abacd42e33056c16008ab8eefd16eb2403cbc3393f8a6ed352a9a39d945ad3a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"6b236f8b62c82f189fabce0756e01a2c0ab1f32cb84cad9ff3c96b2ce5282bda","build.rs":"8923f38056f859b30aa9022980bb517755cbef57e1b09c34b33b27eb03b0626c","src/example_generated.rs":"e43eb59e90f317f38d436670a6067d2fd9eb35fb319fe716184e4a04e24ed1b2","src/lib.rs":"bd4e44ac35831c75af8815ba3a11ee1659afe0f72ce9c5f638a66bf50aa23d2a"},"package":"cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"}
-\ No newline at end of file
-diff --git a/third_party/rust/bitflags/CHANGELOG.md b/third_party/rust/bitflags/CHANGELOG.md
-index 12fea1673ac30..0d4910153d909 100644
---- a/third_party/rust/bitflags/CHANGELOG.md
-+++ b/third_party/rust/bitflags/CHANGELOG.md
-@@ -1,60 +1,3 @@
--# 1.3.2
--
--- Allow `non_snake_case` in generated flags types ([#256])
--
--[#252]: https://github.com/bitflags/bitflags/pull/256
--
--# 1.3.1
--
--- Revert unconditional `#[repr(transparent)]` ([#252])
--
--[#252]: https://github.com/bitflags/bitflags/pull/252
--
--# 1.3.0 (yanked)
--
--- Add `#[repr(transparent)]` ([#187])
--
--- End `empty` doc comment with full stop ([#202])
--
--- Fix typo in crate root docs ([#206])
--
--- Document from_bits_unchecked unsafety ([#207])
--
--- Let `is_all` ignore extra bits ([#211])
--
--- Allows empty flag definition ([#225])
--
--- Making crate accessible from std ([#227])
--
--- Make `from_bits` a const fn ([#229])
--
--- Allow multiple bitflags structs in one macro invocation ([#235])
--
--- Add named functions to perform set operations ([#244])
--
--- Fix typos in method docs ([#245])
--
--- Modernization of the `bitflags` macro to take advantage of newer features and 2018 idioms ([#246])
--
--- Fix regression (in an unreleased feature) and simplify tests ([#247])
--
--- Use `Self` and fix bug when overriding `stringify!` ([#249])
--
--[#187]: https://github.com/bitflags/bitflags/pull/187
--[#202]: https://github.com/bitflags/bitflags/pull/202
--[#206]: https://github.com/bitflags/bitflags/pull/206
--[#207]: https://github.com/bitflags/bitflags/pull/207
--[#211]: https://github.com/bitflags/bitflags/pull/211
--[#225]: https://github.com/bitflags/bitflags/pull/225
--[#227]: https://github.com/bitflags/bitflags/pull/227
--[#229]: https://github.com/bitflags/bitflags/pull/229
--[#235]: https://github.com/bitflags/bitflags/pull/235
--[#244]: https://github.com/bitflags/bitflags/pull/244
--[#245]: https://github.com/bitflags/bitflags/pull/245
--[#246]: https://github.com/bitflags/bitflags/pull/246
--[#247]: https://github.com/bitflags/bitflags/pull/247
--[#249]: https://github.com/bitflags/bitflags/pull/249
--
- # 1.2.1
- 
- - Remove extraneous `#[inline]` attributes ([#194])
-diff --git a/third_party/rust/bitflags/Cargo.toml b/third_party/rust/bitflags/Cargo.toml
-index 9d54c725a1c5d..b803644d44753 100644
---- a/third_party/rust/bitflags/Cargo.toml
-+++ b/third_party/rust/bitflags/Cargo.toml
-@@ -11,11 +11,11 @@
- # will likely look very different (and much more reasonable)
- 
- [package]
--edition = "2018"
- name = "bitflags"
--version = "1.3.2"
-+version = "1.2.1"
- authors = ["The Rust Project Developers"]
--exclude = ["bors.toml"]
-+build = "build.rs"
-+exclude = [".travis.yml", "appveyor.yml", "bors.toml"]
- description = "A macro to generate structures which behave like bitflags.\n"
- homepage = "https://github.com/bitflags/bitflags"
- documentation = "https://docs.rs/bitflags"
-@@ -26,33 +26,9 @@ license = "MIT/Apache-2.0"
- repository = "https://github.com/bitflags/bitflags"
- [package.metadata.docs.rs]
- features = ["example_generated"]
--[dependencies.compiler_builtins]
--version = "0.1.2"
--optional = true
--
--[dependencies.core]
--version = "1.0.0"
--optional = true
--package = "rustc-std-workspace-core"
--[dev-dependencies.rustversion]
--version = "1.0"
--
--[dev-dependencies.serde]
--version = "1.0"
--
--[dev-dependencies.serde_derive]
--version = "1.0"
--
--[dev-dependencies.serde_json]
--version = "1.0"
--
--[dev-dependencies.trybuild]
--version = "1.0"
--
--[dev-dependencies.walkdir]
--version = "2.3"
- 
- [features]
- default = []
- example_generated = []
--rustc-dep-of-std = ["core", "compiler_builtins"]
-+[badges.travis-ci]
-+repository = "bitflags/bitflags"
-diff --git a/third_party/rust/bitflags/README.md b/third_party/rust/bitflags/README.md
-index 0da0f853661b0..df12934c3e28a 100644
---- a/third_party/rust/bitflags/README.md
-+++ b/third_party/rust/bitflags/README.md
-@@ -1,10 +1,11 @@
- bitflags
- ========
- 
--[![Rust](https://github.com/bitflags/bitflags/workflows/Rust/badge.svg)](https://github.com/bitflags/bitflags/actions)
-+[![Build Status](https://travis-ci.com/bitflags/bitflags.svg?branch=master)](https://travis-ci.com/bitflags/bitflags)
- [![Join the chat at https://gitter.im/bitflags/Lobby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bitflags/Lobby?utm_source=badge&utm_medium=badge&utm_content=badge)
- [![Latest version](https://img.shields.io/crates/v/bitflags.svg)](https://crates.io/crates/bitflags)
- [![Documentation](https://docs.rs/bitflags/badge.svg)](https://docs.rs/bitflags)
-+![Minimum rustc version](https://img.shields.io/badge/rustc-1.20+-yellow.svg)
- ![License](https://img.shields.io/crates/l/bitflags.svg)
- 
- A Rust macro to generate structures which behave like a set of bitflags
-@@ -18,15 +19,16 @@ Add this to your `Cargo.toml`:
- 
- ```toml
- [dependencies]
--bitflags = "1.3"
-+bitflags = "1.0"
- ```
- 
--and this to your source code:
-+and this to your crate root:
- 
- ```rust
--use bitflags::bitflags;
-+#[macro_use]
-+extern crate bitflags;
- ```
- 
- ## Rust Version Support
- 
--The minimum supported Rust version is 1.46 due to use of associated constants and const functions.
-+The minimum supported Rust version is 1.20 due to use of associated constants.
-diff --git a/third_party/rust/bitflags/build.rs b/third_party/rust/bitflags/build.rs
-new file mode 100644
-index 0000000000000..985757a6f6126
---- /dev/null
-+++ b/third_party/rust/bitflags/build.rs
-@@ -0,0 +1,44 @@
-+use std::env;
-+use std::process::Command;
-+use std::str::{self, FromStr};
-+
-+fn main(){
-+    let minor = match rustc_minor_version() {
-+        Some(minor) => minor,
-+        None => return,
-+    };
-+
-+    // const fn stabilized in Rust 1.31:
-+    if minor >= 31 {
-+        println!("cargo:rustc-cfg=bitflags_const_fn");
-+    }
-+}
-+
-+fn rustc_minor_version() -> Option<u32> {
-+    let rustc = match env::var_os("RUSTC") {
-+        Some(rustc) => rustc,
-+        None => return None,
-+    };
-+
-+    let output = match Command::new(rustc).arg("--version").output() {
-+        Ok(output) => output,
-+        Err(_) => return None,
-+    };
-+
-+    let version = match str::from_utf8(&output.stdout) {
-+        Ok(version) => version,
-+        Err(_) => return None,
-+    };
-+
-+    let mut pieces = version.split('.');
-+    if pieces.next() != Some("rustc 1") {
-+        return None;
-+    }
-+
-+    let next = match pieces.next() {
-+        Some(next) => next,
-+        None => return None,
-+    };
-+
-+    u32::from_str(next).ok()
-+}
-\ No newline at end of file
-diff --git a/third_party/rust/bitflags/src/lib.rs b/third_party/rust/bitflags/src/lib.rs
-index 935e432f1701e..3929b02ac10d7 100644
---- a/third_party/rust/bitflags/src/lib.rs
-+++ b/third_party/rust/bitflags/src/lib.rs
-@@ -11,14 +11,15 @@
- //! A typesafe bitmask flag generator useful for sets of C-style bitmask flags.
- //! It can be used for creating typesafe wrappers around C APIs.
- //!
--//! The `bitflags!` macro generates `struct`s that manage a set of flags. The
-+//! The `bitflags!` macro generates a `struct` that manages a set of flags. The
- //! flags should only be defined for integer types, otherwise unexpected type
- //! errors may occur at compile time.
- //!
- //! # Example
- //!
- //! ```
--//! use bitflags::bitflags;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
- //! bitflags! {
- //!     struct Flags: u32 {
-@@ -46,9 +47,10 @@
- //! implementations:
- //!
- //! ```
--//! use std::fmt;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
--//! use bitflags::bitflags;
-+//! use std::fmt;
- //!
- //! bitflags! {
- //!     struct Flags: u32 {
-@@ -82,19 +84,21 @@
- //!
- //! # Visibility
- //!
--//! The generated structs and their associated flag constants are not exported
-+//! The generated struct and its associated flag constants are not exported
- //! out of the current module by default. A definition can be exported out of
--//! the current module by adding `pub` before `struct`:
-+//! the current module by adding `pub` before `flags`:
- //!
- //! ```
--//! mod example {
--//!     use bitflags::bitflags;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
-+//! mod example {
- //!     bitflags! {
- //!         pub struct Flags1: u32 {
- //!             const A = 0b00000001;
- //!         }
--//!
-+//!     }
-+//!     bitflags! {
- //! #       pub
- //!         struct Flags2: u32 {
- //!             const B = 0b00000010;
-@@ -110,44 +114,26 @@
- //!
- //! # Attributes
- //!
--//! Attributes can be attached to the generated `struct`s by placing them
--//! before the `struct` keyword.
--//!
--//! ## Representations
--//!
--//! It's valid to add a `#[repr(C)]` or `#[repr(transparent)]` attribute to a type
--//! generated by `bitflags!`. In these cases, the type is guaranteed to be a newtype.
--//!
--//! ```
--//! use bitflags::bitflags;
--//!
--//! bitflags! {
--//!     #[repr(transparent)]
--//!     struct Flags: u32 {
--//!         const A = 0b00000001;
--//!         const B = 0b00000010;
--//!         const C = 0b00000100;
--//!     }
--//! }
--//! ```
-+//! Attributes can be attached to the generated `struct` by placing them
-+//! before the `flags` keyword.
- //!
- //! # Trait implementations
- //!
- //! The `Copy`, `Clone`, `PartialEq`, `Eq`, `PartialOrd`, `Ord` and `Hash`
--//! traits are automatically derived for the `struct`s using the `derive` attribute.
-+//! traits automatically derived for the `struct` using the `derive` attribute.
- //! Additional traits can be derived by providing an explicit `derive`
--//! attribute on `struct`.
-+//! attribute on `flags`.
- //!
--//! The `Extend` and `FromIterator` traits are implemented for the `struct`s,
-+//! The `Extend` and `FromIterator` traits are implemented for the `struct`,
- //! too: `Extend` adds the union of the instances of the `struct` iterated over,
- //! while `FromIterator` calculates the union.
- //!
--//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` traits are also
-+//! The `Binary`, `Debug`, `LowerHex`, `Octal` and `UpperHex` trait is also
- //! implemented by displaying the bits value of the internal struct.
- //!
- //! ## Operators
- //!
--//! The following operator traits are implemented for the generated `struct`s:
-+//! The following operator traits are implemented for the generated `struct`:
- //!
- //! - `BitOr` and `BitOrAssign`: union
- //! - `BitAnd` and `BitAndAssign`: intersection
-@@ -157,7 +143,7 @@
- //!
- //! # Methods
- //!
--//! The following methods are defined for the generated `struct`s:
-+//! The following methods are defined for the generated `struct`:
- //!
- //! - `empty`: an empty set of flags
- //! - `all`: the set of all defined flags
-@@ -173,34 +159,23 @@
- //! - `is_empty`: `true` if no flags are currently stored
- //! - `is_all`: `true` if currently set flags exactly equal all defined flags
- //! - `intersects`: `true` if there are flags common to both `self` and `other`
--//! - `contains`: `true` if all of the flags in `other` are contained within `self`
-+//! - `contains`: `true` all of the flags in `other` are contained within `self`
- //! - `insert`: inserts the specified flags in-place
- //! - `remove`: removes the specified flags in-place
- //! - `toggle`: the specified flags will be inserted if not present, and removed
- //!             if they are.
- //! - `set`: inserts or removes the specified flags depending on the passed value
--//! - `intersection`: returns a new set of flags, containing only the flags present
--//!                   in both `self` and `other` (the argument to the function).
--//! - `union`: returns a new set of flags, containing any flags present in
--//!            either `self` or `other` (the argument to the function).
--//! - `difference`: returns a new set of flags, containing all flags present in
--//!                 `self` without any of the flags present in `other` (the
--//!                 argument to the function).
--//! - `symmetric_difference`: returns a new set of flags, containing all flags
--//!                           present in either `self` or `other` (the argument
--//!                           to the function), but not both.
--//! - `complement`: returns a new set of flags, containing all flags which are
--//!                 not set in `self`, but which are allowed for this type.
- //!
- //! ## Default
- //!
--//! The `Default` trait is not automatically implemented for the generated structs.
-+//! The `Default` trait is not automatically implemented for the generated struct.
- //!
- //! If your default value is equal to `0` (which is the same value as calling `empty()`
- //! on the generated struct), you can simply derive `Default`:
- //!
- //! ```
--//! use bitflags::bitflags;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
- //! bitflags! {
- //!     // Results in default value with bits: 0
-@@ -221,7 +196,8 @@
- //! If your default value is not equal to `0` you need to implement `Default` yourself:
- //!
- //! ```
--//! use bitflags::bitflags;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
- //! bitflags! {
- //!     struct Flags: u32 {
-@@ -249,7 +225,8 @@
- //! Flags with a value equal to zero will have some strange behavior that one should be aware of.
- //!
- //! ```
--//! use bitflags::bitflags;
-+//! #[macro_use]
-+//! extern crate bitflags;
- //!
- //! bitflags! {
- //!     struct Flags: u32 {
-@@ -272,23 +249,28 @@
- //!     assert!(none.is_empty());
- //! }
- //! ```
--//!
--//! Users should generally avoid defining a flag with a value of zero.
- 
--#![cfg_attr(not(test), no_std)]
--#![doc(html_root_url = "https://docs.rs/bitflags/1.3.2")]
-+#![no_std]
-+#![doc(html_root_url = "https://docs.rs/bitflags/1.2.1")]
-+
-+#[cfg(test)]
-+#[macro_use]
-+extern crate std;
- 
-+// Re-export libcore using an alias so that the macros can work without
-+// requiring `extern crate core` downstream.
- #[doc(hidden)]
- pub extern crate core as _core;
- 
--/// The macro used to generate the flag structures.
-+/// The macro used to generate the flag structure.
- ///
- /// See the [crate level docs](../bitflags/index.html) for complete documentation.
- ///
- /// # Example
- ///
- /// ```
--/// use bitflags::bitflags;
-+/// #[macro_use]
-+/// extern crate bitflags;
- ///
- /// bitflags! {
- ///     struct Flags: u32 {
-@@ -313,9 +295,10 @@ pub extern crate core as _core;
- /// implementations:
- ///
- /// ```
--/// use std::fmt;
-+/// #[macro_use]
-+/// extern crate bitflags;
- ///
--/// use bitflags::bitflags;
-+/// use std::fmt;
- ///
- /// bitflags! {
- ///     struct Flags: u32 {
-@@ -350,18 +333,78 @@ pub extern crate core as _core;
- macro_rules! bitflags {
-     (
-         $(#[$outer:meta])*
--        $vis:vis struct $BitFlags:ident: $T:ty {
-+        pub struct $BitFlags:ident: $T:ty {
-+            $(
-+                $(#[$inner:ident $($args:tt)*])*
-+                const $Flag:ident = $value:expr;
-+            )+
-+        }
-+    ) => {
-+        __bitflags! {
-+            $(#[$outer])*
-+            (pub) $BitFlags: $T {
-+                $(
-+                    $(#[$inner $($args)*])*
-+                    $Flag = $value;
-+                )+
-+            }
-+        }
-+    };
-+    (
-+        $(#[$outer:meta])*
-+        struct $BitFlags:ident: $T:ty {
-+            $(
-+                $(#[$inner:ident $($args:tt)*])*
-+                const $Flag:ident = $value:expr;
-+            )+
-+        }
-+    ) => {
-+        __bitflags! {
-+            $(#[$outer])*
-+            () $BitFlags: $T {
-+                $(
-+                    $(#[$inner $($args)*])*
-+                    $Flag = $value;
-+                )+
-+            }
-+        }
-+    };
-+    (
-+        $(#[$outer:meta])*
-+        pub ($($vis:tt)+) struct $BitFlags:ident: $T:ty {
-             $(
-                 $(#[$inner:ident $($args:tt)*])*
-                 const $Flag:ident = $value:expr;
--            )*
-+            )+
-+        }
-+    ) => {
-+        __bitflags! {
-+            $(#[$outer])*
-+            (pub ($($vis)+)) $BitFlags: $T {
-+                $(
-+                    $(#[$inner $($args)*])*
-+                    $Flag = $value;
-+                )+
-+            }
-         }
-+    };
-+}
- 
--        $($t:tt)*
-+#[macro_export(local_inner_macros)]
-+#[doc(hidden)]
-+macro_rules! __bitflags {
-+    (
-+        $(#[$outer:meta])*
-+        ($($vis:tt)*) $BitFlags:ident: $T:ty {
-+            $(
-+                $(#[$inner:ident $($args:tt)*])*
-+                $Flag:ident = $value:expr;
-+            )+
-+        }
-     ) => {
-         $(#[$outer])*
-         #[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
--        $vis struct $BitFlags {
-+        $($vis)* struct $BitFlags {
-             bits: $T,
-         }
- 
-@@ -370,52 +413,63 @@ macro_rules! bitflags {
-                 $(
-                     $(#[$inner $($args)*])*
-                     $Flag = $value;
--                )*
-+                )+
-             }
-         }
-+    };
-+}
- 
--        bitflags! {
--            $($t)*
--        }
-+#[macro_export(local_inner_macros)]
-+#[doc(hidden)]
-+#[cfg(bitflags_const_fn)]
-+macro_rules! __fn_bitflags {
-+    (
-+        $(# $attr_args:tt)*
-+        const fn $($item:tt)*
-+    ) => {
-+        $(# $attr_args)*
-+        const fn $($item)*
-+    };
-+    (
-+        $(# $attr_args:tt)*
-+        pub const fn $($item:tt)*
-+    ) => {
-+        $(# $attr_args)*
-+        pub const fn $($item)*
-+    };
-+    (
-+        $(# $attr_args:tt)*
-+        pub const unsafe fn $($item:tt)*
-+    ) => {
-+        $(# $attr_args)*
-+        pub const unsafe fn $($item)*
-     };
--    () => {};
- }
- 
--// A helper macro to implement the `all` function.
- #[macro_export(local_inner_macros)]
- #[doc(hidden)]
--macro_rules! __impl_all_bitflags {
-+#[cfg(not(bitflags_const_fn))]
-+macro_rules! __fn_bitflags {
-     (
--        $BitFlags:ident: $T:ty {
--            $(
--                $(#[$attr:ident $($args:tt)*])*
--                $Flag:ident = $value:expr;
--            )+
--        }
-+        $(# $attr_args:tt)*
-+        const fn $($item:tt)*
-     ) => {
--        // See `Debug::fmt` for why this approach is taken.
--        #[allow(non_snake_case)]
--        trait __BitFlags {
--            $(
--                const $Flag: $T = 0;
--            )+
--        }
--        #[allow(non_snake_case)]
--        impl __BitFlags for $BitFlags {
--            $(
--                __impl_bitflags! {
--                    #[allow(deprecated)]
--                    $(? #[$attr $($args)*])*
--                    const $Flag: $T = Self::$Flag.bits;
--                }
--            )+
--        }
--        Self { bits: $(<Self as __BitFlags>::$Flag)|+ }
-+        $(# $attr_args)*
-+        fn $($item)*
-+    };
-+    (
-+        $(# $attr_args:tt)*
-+        pub const fn $($item:tt)*
-+    ) => {
-+        $(# $attr_args)*
-+        pub fn $($item)*
-     };
-     (
--        $BitFlags:ident: $T:ty { }
-+        $(# $attr_args:tt)*
-+        pub const unsafe fn $($item:tt)*
-     ) => {
--        Self { bits: 0 }
-+        $(# $attr_args)*
-+        pub unsafe fn $($item)*
-     };
- }
- 
-@@ -427,7 +481,7 @@ macro_rules! __impl_bitflags {
-             $(
-                 $(#[$attr:ident $($args:tt)*])*
-                 $Flag:ident = $value:expr;
--            )*
-+            )+
-         }
-     ) => {
-         impl $crate::_core::fmt::Debug for $BitFlags {
-@@ -445,12 +499,11 @@ macro_rules! __impl_bitflags {
-                     $(
-                         #[inline]
-                         fn $Flag(&self) -> bool { false }
--                    )*
-+                    )+
-                 }
- 
-                 // Conditionally override the check for just those flags that
-                 // are not #[cfg]ed away.
--                #[allow(non_snake_case)]
-                 impl __BitFlags for $BitFlags {
-                     $(
-                         __impl_bitflags! {
-@@ -465,20 +518,20 @@ macro_rules! __impl_bitflags {
-                                 }
-                             }
-                         }
--                    )*
-+                    )+
-                 }
- 
-                 let mut first = true;
-                 $(
--                    if <Self as __BitFlags>::$Flag(self) {
-+                    if <$BitFlags as __BitFlags>::$Flag(self) {
-                         if !first {
-                             f.write_str(" | ")?;
-                         }
-                         first = false;
--                        f.write_str($crate::_core::stringify!($Flag))?;
-+                        f.write_str(__bitflags_stringify!($Flag))?;
-                     }
--                )*
--                let extra_bits = self.bits & !Self::all().bits();
-+                )+
-+                let extra_bits = self.bits & !$BitFlags::all().bits();
-                 if extra_bits != 0 {
-                     if !first {
-                         f.write_str(" | ")?;
-@@ -518,295 +571,227 @@ macro_rules! __impl_bitflags {
-         impl $BitFlags {
-             $(
-                 $(#[$attr $($args)*])*
--                pub const $Flag: Self = Self { bits: $value };
--            )*
-+                pub const $Flag: $BitFlags = $BitFlags { bits: $value };
-+            )+
- 
--            /// Returns an empty set of flags.
--            #[inline]
--            pub const fn empty() -> Self {
--                Self { bits: 0 }
-+            __fn_bitflags! {
-+                /// Returns an empty set of flags
-+                #[inline]
-+                pub const fn empty() -> $BitFlags {
-+                    $BitFlags { bits: 0 }
-+                }
-             }
- 
--            /// Returns the set containing all flags.
--            #[inline]
--            pub const fn all() -> Self {
--                __impl_all_bitflags! {
--                    $BitFlags: $T {
-+            __fn_bitflags! {
-+                /// Returns the set containing all flags.
-+                #[inline]
-+                pub const fn all() -> $BitFlags {
-+                    // See `Debug::fmt` for why this approach is taken.
-+                    #[allow(non_snake_case)]
-+                    trait __BitFlags {
-                         $(
--                            $(#[$attr $($args)*])*
--                            $Flag = $value;
--                        )*
-+                            const $Flag: $T = 0;
-+                        )+
-                     }
-+                    impl __BitFlags for $BitFlags {
-+                        $(
-+                            __impl_bitflags! {
-+                                #[allow(deprecated)]
-+                                $(? #[$attr $($args)*])*
-+                                const $Flag: $T = Self::$Flag.bits;
-+                            }
-+                        )+
-+                    }
-+                    $BitFlags { bits: $(<$BitFlags as __BitFlags>::$Flag)|+ }
-                 }
-             }
- 
--            /// Returns the raw value of the flags currently stored.
--            #[inline]
--            pub const fn bits(&self) -> $T {
--                self.bits
-+            __fn_bitflags! {
-+                /// Returns the raw value of the flags currently stored.
-+                #[inline]
-+                pub const fn bits(&self) -> $T {
-+                    self.bits
-+                }
-             }
- 
-             /// Convert from underlying bit representation, unless that
-             /// representation contains bits that do not correspond to a flag.
-             #[inline]
--            pub const fn from_bits(bits: $T) -> $crate::_core::option::Option<Self> {
--                if (bits & !Self::all().bits()) == 0 {
--                    $crate::_core::option::Option::Some(Self { bits })
-+            pub fn from_bits(bits: $T) -> $crate::_core::option::Option<$BitFlags> {
-+                if (bits & !$BitFlags::all().bits()) == 0 {
-+                    $crate::_core::option::Option::Some($BitFlags { bits })
-                 } else {
-                     $crate::_core::option::Option::None
-                 }
-             }
- 
--            /// Convert from underlying bit representation, dropping any bits
--            /// that do not correspond to flags.
--            #[inline]
--            pub const fn from_bits_truncate(bits: $T) -> Self {
--                Self { bits: bits & Self::all().bits }
-+            __fn_bitflags! {
-+                /// Convert from underlying bit representation, dropping any bits
-+                /// that do not correspond to flags.
-+                #[inline]
-+                pub const fn from_bits_truncate(bits: $T) -> $BitFlags {
-+                    $BitFlags { bits: bits & $BitFlags::all().bits }
-+                }
-             }
- 
--            /// Convert from underlying bit representation, preserving all
--            /// bits (even those not corresponding to a defined flag).
--            ///
--            /// # Safety
--            ///
--            /// The caller of the `bitflags!` macro can chose to allow or
--            /// disallow extra bits for their bitflags type.
--            ///
--            /// The caller of `from_bits_unchecked()` has to ensure that
--            /// all bits correspond to a defined flag or that extra bits
--            /// are valid for this bitflags type.
--            #[inline]
--            pub const unsafe fn from_bits_unchecked(bits: $T) -> Self {
--                Self { bits }
-+            __fn_bitflags! {
-+                /// Convert from underlying bit representation, preserving all
-+                /// bits (even those not corresponding to a defined flag).
-+                #[inline]
-+                pub const unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
-+                    $BitFlags { bits }
-+                }
-             }
- 
--            /// Returns `true` if no flags are currently stored.
--            #[inline]
--            pub const fn is_empty(&self) -> bool {
--                self.bits() == Self::empty().bits()
-+            __fn_bitflags! {
-+                /// Returns `true` if no flags are currently stored.
-+                #[inline]
-+                pub const fn is_empty(&self) -> bool {
-+                    self.bits() == $BitFlags::empty().bits()
-+                }
-             }
- 
--            /// Returns `true` if all flags are currently set.
--            #[inline]
--            pub const fn is_all(&self) -> bool {
--                Self::all().bits | self.bits == self.bits
-+            __fn_bitflags! {
-+                /// Returns `true` if all flags are currently set.
-+                #[inline]
-+                pub const fn is_all(&self) -> bool {
-+                    self.bits == $BitFlags::all().bits
-+                }
-             }
- 
--            /// Returns `true` if there are flags common to both `self` and `other`.
--            #[inline]
--            pub const fn intersects(&self, other: Self) -> bool {
--                !(Self { bits: self.bits & other.bits}).is_empty()
-+            __fn_bitflags! {
-+                /// Returns `true` if there are flags common to both `self` and `other`.
-+                #[inline]
-+                pub const fn intersects(&self, other: $BitFlags) -> bool {
-+                    !$BitFlags{ bits: self.bits & other.bits}.is_empty()
-+                }
-             }
- 
--            /// Returns `true` if all of the flags in `other` are contained within `self`.
--            #[inline]
--            pub const fn contains(&self, other: Self) -> bool {
--                (self.bits & other.bits) == other.bits
-+            __fn_bitflags! {
-+                /// Returns `true` all of the flags in `other` are contained within `self`.
-+                #[inline]
-+                pub const fn contains(&self, other: $BitFlags) -> bool {
-+                    (self.bits & other.bits) == other.bits
-+                }
-             }
- 
-             /// Inserts the specified flags in-place.
-             #[inline]
--            pub fn insert(&mut self, other: Self) {
-+            pub fn insert(&mut self, other: $BitFlags) {
-                 self.bits |= other.bits;
-             }
- 
-             /// Removes the specified flags in-place.
-             #[inline]
--            pub fn remove(&mut self, other: Self) {
-+            pub fn remove(&mut self, other: $BitFlags) {
-                 self.bits &= !other.bits;
-             }
- 
-             /// Toggles the specified flags in-place.
-             #[inline]
--            pub fn toggle(&mut self, other: Self) {
-+            pub fn toggle(&mut self, other: $BitFlags) {
-                 self.bits ^= other.bits;
-             }
- 
-             /// Inserts or removes the specified flags depending on the passed value.
-             #[inline]
--            pub fn set(&mut self, other: Self, value: bool) {
-+            pub fn set(&mut self, other: $BitFlags, value: bool) {
-                 if value {
-                     self.insert(other);
-                 } else {
-                     self.remove(other);
-                 }
-             }
--
--            /// Returns the intersection between the flags in `self` and
--            /// `other`.
--            ///
--            /// Specifically, the returned set contains only the flags which are
--            /// present in *both* `self` *and* `other`.
--            ///
--            /// This is equivalent to using the `&` operator (e.g.
--            /// [`ops::BitAnd`]), as in `flags & other`.
--            ///
--            /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
--            #[inline]
--            #[must_use]
--            pub const fn intersection(self, other: Self) -> Self {
--                Self { bits: self.bits & other.bits }
--            }
--
--            /// Returns the union of between the flags in `self` and `other`.
--            ///
--            /// Specifically, the returned set contains all flags which are
--            /// present in *either* `self` *or* `other`, including any which are
--            /// present in both (see [`Self::symmetric_difference`] if that
--            /// is undesirable).
--            ///
--            /// This is equivalent to using the `|` operator (e.g.
--            /// [`ops::BitOr`]), as in `flags | other`.
--            ///
--            /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
--            #[inline]
--            #[must_use]
--            pub const fn union(self, other: Self) -> Self {
--                Self { bits: self.bits | other.bits }
--            }
--
--            /// Returns the difference between the flags in `self` and `other`.
--            ///
--            /// Specifically, the returned set contains all flags present in
--            /// `self`, except for the ones present in `other`.
--            ///
--            /// It is also conceptually equivalent to the "bit-clear" operation:
--            /// `flags & !other` (and this syntax is also supported).
--            ///
--            /// This is equivalent to using the `-` operator (e.g.
--            /// [`ops::Sub`]), as in `flags - other`.
--            ///
--            /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
--            #[inline]
--            #[must_use]
--            pub const fn difference(self, other: Self) -> Self {
--                Self { bits: self.bits & !other.bits }
--            }
--
--            /// Returns the [symmetric difference][sym-diff] between the flags
--            /// in `self` and `other`.
--            ///
--            /// Specifically, the returned set contains the flags present which
--            /// are present in `self` or `other`, but that are not present in
--            /// both. Equivalently, it contains the flags present in *exactly
--            /// one* of the sets `self` and `other`.
--            ///
--            /// This is equivalent to using the `^` operator (e.g.
--            /// [`ops::BitXor`]), as in `flags ^ other`.
--            ///
--            /// [sym-diff]: https://en.wikipedia.org/wiki/Symmetric_difference
--            /// [`ops::BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
--            #[inline]
--            #[must_use]
--            pub const fn symmetric_difference(self, other: Self) -> Self {
--                Self { bits: self.bits ^ other.bits }
--            }
--
--            /// Returns the complement of this set of flags.
--            ///
--            /// Specifically, the returned set contains all the flags which are
--            /// not set in `self`, but which are allowed for this type.
--            ///
--            /// Alternatively, it can be thought of as the set difference
--            /// between [`Self::all()`] and `self` (e.g. `Self::all() - self`)
--            ///
--            /// This is equivalent to using the `!` operator (e.g.
--            /// [`ops::Not`]), as in `!flags`.
--            ///
--            /// [`Self::all()`]: Self::all
--            /// [`ops::Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
--            #[inline]
--            #[must_use]
--            pub const fn complement(self) -> Self {
--                Self::from_bits_truncate(!self.bits)
--            }
--
-         }
- 
-         impl $crate::_core::ops::BitOr for $BitFlags {
--            type Output = Self;
-+            type Output = $BitFlags;
- 
-             /// Returns the union of the two sets of flags.
-             #[inline]
--            fn bitor(self, other: $BitFlags) -> Self {
--                Self { bits: self.bits | other.bits }
-+            fn bitor(self, other: $BitFlags) -> $BitFlags {
-+                $BitFlags { bits: self.bits | other.bits }
-             }
-         }
- 
-         impl $crate::_core::ops::BitOrAssign for $BitFlags {
-+
-             /// Adds the set of flags.
-             #[inline]
--            fn bitor_assign(&mut self, other: Self) {
-+            fn bitor_assign(&mut self, other: $BitFlags) {
-                 self.bits |= other.bits;
-             }
-         }
- 
-         impl $crate::_core::ops::BitXor for $BitFlags {
--            type Output = Self;
-+            type Output = $BitFlags;
- 
-             /// Returns the left flags, but with all the right flags toggled.
-             #[inline]
--            fn bitxor(self, other: Self) -> Self {
--                Self { bits: self.bits ^ other.bits }
-+            fn bitxor(self, other: $BitFlags) -> $BitFlags {
-+                $BitFlags { bits: self.bits ^ other.bits }
-             }
-         }
- 
-         impl $crate::_core::ops::BitXorAssign for $BitFlags {
-+
-             /// Toggles the set of flags.
-             #[inline]
--            fn bitxor_assign(&mut self, other: Self) {
-+            fn bitxor_assign(&mut self, other: $BitFlags) {
-                 self.bits ^= other.bits;
-             }
-         }
- 
-         impl $crate::_core::ops::BitAnd for $BitFlags {
--            type Output = Self;
-+            type Output = $BitFlags;
- 
-             /// Returns the intersection between the two sets of flags.
-             #[inline]
--            fn bitand(self, other: Self) -> Self {
--                Self { bits: self.bits & other.bits }
-+            fn bitand(self, other: $BitFlags) -> $BitFlags {
-+                $BitFlags { bits: self.bits & other.bits }
-             }
-         }
- 
-         impl $crate::_core::ops::BitAndAssign for $BitFlags {
-+
-             /// Disables all flags disabled in the set.
-             #[inline]
--            fn bitand_assign(&mut self, other: Self) {
-+            fn bitand_assign(&mut self, other: $BitFlags) {
-                 self.bits &= other.bits;
-             }
-         }
- 
-         impl $crate::_core::ops::Sub for $BitFlags {
--            type Output = Self;
-+            type Output = $BitFlags;
- 
-             /// Returns the set difference of the two sets of flags.
-             #[inline]
--            fn sub(self, other: Self) -> Self {
--                Self { bits: self.bits & !other.bits }
-+            fn sub(self, other: $BitFlags) -> $BitFlags {
-+                $BitFlags { bits: self.bits & !other.bits }
-             }
-         }
- 
-         impl $crate::_core::ops::SubAssign for $BitFlags {
-+
-             /// Disables all flags enabled in the set.
-             #[inline]
--            fn sub_assign(&mut self, other: Self) {
-+            fn sub_assign(&mut self, other: $BitFlags) {
-                 self.bits &= !other.bits;
-             }
-         }
- 
-         impl $crate::_core::ops::Not for $BitFlags {
--            type Output = Self;
-+            type Output = $BitFlags;
- 
-             /// Returns the complement of this set of flags.
-             #[inline]
--            fn not(self) -> Self {
--                Self { bits: !self.bits } & Self::all()
-+            fn not(self) -> $BitFlags {
-+                $BitFlags { bits: !self.bits } & $BitFlags::all()
-             }
-         }
- 
-         impl $crate::_core::iter::Extend<$BitFlags> for $BitFlags {
--            fn extend<T: $crate::_core::iter::IntoIterator<Item=Self>>(&mut self, iterator: T) {
-+            fn extend<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(&mut self, iterator: T) {
-                 for item in iterator {
-                     self.insert(item)
-                 }
-@@ -814,7 +799,7 @@ macro_rules! __impl_bitflags {
-         }
- 
-         impl $crate::_core::iter::FromIterator<$BitFlags> for $BitFlags {
--            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=Self>>(iterator: T) -> Self {
-+            fn from_iter<T: $crate::_core::iter::IntoIterator<Item=$BitFlags>>(iterator: T) -> $BitFlags {
-                 let mut result = Self::empty();
-                 result.extend(iterator);
-                 result
-@@ -832,7 +817,7 @@ macro_rules! __impl_bitflags {
-     // Input:
-     //
-     //     ? #[cfg(feature = "advanced")]
--    //     ? #[deprecated(note = "Use something else.")]
-+    //     ? #[deprecated(note = "Use somthing else.")]
-     //     ? #[doc = r"High quality documentation."]
-     //     fn f() -> i32 { /* ... */ }
-     //
-@@ -887,7 +872,7 @@ macro_rules! __impl_bitflags {
-     // Input:
-     //
-     //     ? #[cfg(feature = "advanced")]
--    //     ? #[deprecated(note = "Use something else.")]
-+    //     ? #[deprecated(note = "Use somthing else.")]
-     //     ? #[doc = r"High quality documentation."]
-     //     const f: i32 { /* ... */ }
-     //
-@@ -931,6 +916,16 @@ macro_rules! __impl_bitflags {
-     };
- }
- 
-+// Same as std::stringify but callable from __impl_bitflags, which needs to use
-+// local_inner_macros so can only directly call macros from this crate.
-+#[macro_export]
-+#[doc(hidden)]
-+macro_rules! __bitflags_stringify {
-+    ($s:ident) => {
-+        stringify!($s)
-+    };
-+}
-+
- #[cfg(feature = "example_generated")]
- pub mod example_generated;
- 
-@@ -944,7 +939,6 @@ mod tests {
-         #[doc = "> you are the easiest person to fool."]
-         #[doc = "> "]
-         #[doc = "> - Richard Feynman"]
--        #[derive(Default)]
-         struct Flags: u32 {
-             const A = 0b00000001;
-             #[doc = "<pcwalton> macros are way better at generating code than trans is"]
-@@ -955,7 +949,9 @@ mod tests {
-             #[doc = "<strcat> wait what?"]
-             const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
-         }
-+    }
- 
-+    bitflags! {
-         struct _CfgFlags: u32 {
-             #[cfg(unix)]
-             const _CFG_A = 0b01;
-@@ -964,18 +960,17 @@ mod tests {
-             #[cfg(unix)]
-             const _CFG_C = Self::_CFG_A.bits | 0b10;
-         }
-+    }
- 
-+    bitflags! {
-         struct AnotherSetOfFlags: i8 {
-             const ANOTHER_FLAG = -1_i8;
-         }
--
--        struct LongFlags: u32 {
--            const LONG_A = 0b1111111111111111;
--        }
-     }
- 
-     bitflags! {
--        struct EmptyFlags: u32 {
-+        struct LongFlags: u32 {
-+            const LONG_A = 0b1111111111111111;
-         }
-     }
- 
-@@ -987,8 +982,6 @@ mod tests {
- 
-         assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
-         assert_eq!(AnotherSetOfFlags::ANOTHER_FLAG.bits(), !0_i8);
--
--        assert_eq!(EmptyFlags::empty().bits(), 0b00000000);
-     }
- 
-     #[test]
-@@ -1003,9 +996,6 @@ mod tests {
-             AnotherSetOfFlags::from_bits(!0_i8),
-             Some(AnotherSetOfFlags::ANOTHER_FLAG)
-         );
--
--        assert_eq!(EmptyFlags::from_bits(0), Some(EmptyFlags::empty()));
--        assert_eq!(EmptyFlags::from_bits(0b1), None);
-     }
- 
-     #[test]
-@@ -1021,9 +1011,6 @@ mod tests {
-             AnotherSetOfFlags::from_bits_truncate(0_i8),
-             AnotherSetOfFlags::empty()
-         );
--
--        assert_eq!(EmptyFlags::from_bits_truncate(0), EmptyFlags::empty());
--        assert_eq!(EmptyFlags::from_bits_truncate(0b1), EmptyFlags::empty());
-     }
- 
-     #[test]
-@@ -1032,25 +1019,9 @@ mod tests {
-         assert_eq!(unsafe { Flags::from_bits_unchecked(0) }, Flags::empty());
-         assert_eq!(unsafe { Flags::from_bits_unchecked(0b1) }, Flags::A);
-         assert_eq!(unsafe { Flags::from_bits_unchecked(0b10) }, Flags::B);
--
--        assert_eq!(
--            unsafe { Flags::from_bits_unchecked(0b11) },
--            (Flags::A | Flags::B)
--        );
--        assert_eq!(
--            unsafe { Flags::from_bits_unchecked(0b1000) },
--            (extra | Flags::empty())
--        );
--        assert_eq!(
--            unsafe { Flags::from_bits_unchecked(0b1001) },
--            (extra | Flags::A)
--        );
--
--        let extra = unsafe { EmptyFlags::from_bits_unchecked(0b1000) };
--        assert_eq!(
--            unsafe { EmptyFlags::from_bits_unchecked(0b1000) },
--            (extra | EmptyFlags::empty())
--        );
-+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b11) }, (Flags::A | Flags::B));
-+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1000) }, (extra | Flags::empty()));
-+        assert_eq!(unsafe { Flags::from_bits_unchecked(0b1001) }, (extra | Flags::A));
-     }
- 
-     #[test]
-@@ -1060,9 +1031,6 @@ mod tests {
-         assert!(!Flags::ABC.is_empty());
- 
-         assert!(!AnotherSetOfFlags::ANOTHER_FLAG.is_empty());
--
--        assert!(EmptyFlags::empty().is_empty());
--        assert!(EmptyFlags::all().is_empty());
-     }
- 
-     #[test]
-@@ -1071,15 +1039,7 @@ mod tests {
-         assert!(!Flags::A.is_all());
-         assert!(Flags::ABC.is_all());
- 
--        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
--        assert!(!extra.is_all());
--        assert!(!(Flags::A | extra).is_all());
--        assert!((Flags::ABC | extra).is_all());
--
-         assert!(AnotherSetOfFlags::ANOTHER_FLAG.is_all());
--
--        assert!(EmptyFlags::all().is_all());
--        assert!(EmptyFlags::empty().is_all());
-     }
- 
-     #[test]
-@@ -1121,8 +1081,6 @@ mod tests {
-         assert!(Flags::ABC.contains(e2));
- 
-         assert!(AnotherSetOfFlags::ANOTHER_FLAG.contains(AnotherSetOfFlags::ANOTHER_FLAG));
--
--        assert!(EmptyFlags::empty().contains(EmptyFlags::empty()));
-     }
- 
-     #[test]
-@@ -1183,188 +1141,6 @@ mod tests {
-         assert_eq!(e3, Flags::A | Flags::B | extra);
-     }
- 
--    #[test]
--    fn test_set_ops_basic() {
--        let ab = Flags::A.union(Flags::B);
--        let ac = Flags::A.union(Flags::C);
--        let bc = Flags::B.union(Flags::C);
--        assert_eq!(ab.bits, 0b011);
--        assert_eq!(bc.bits, 0b110);
--        assert_eq!(ac.bits, 0b101);
--
--        assert_eq!(ab, Flags::B.union(Flags::A));
--        assert_eq!(ac, Flags::C.union(Flags::A));
--        assert_eq!(bc, Flags::C.union(Flags::B));
--
--        assert_eq!(ac, Flags::A | Flags::C);
--        assert_eq!(bc, Flags::B | Flags::C);
--        assert_eq!(ab.union(bc), Flags::ABC);
--
--        assert_eq!(ac, Flags::A | Flags::C);
--        assert_eq!(bc, Flags::B | Flags::C);
--
--        assert_eq!(ac.union(bc), ac | bc);
--        assert_eq!(ac.union(bc), Flags::ABC);
--        assert_eq!(bc.union(ac), Flags::ABC);
--
--        assert_eq!(ac.intersection(bc), ac & bc);
--        assert_eq!(ac.intersection(bc), Flags::C);
--        assert_eq!(bc.intersection(ac), Flags::C);
--
--        assert_eq!(ac.difference(bc), ac - bc);
--        assert_eq!(bc.difference(ac), bc - ac);
--        assert_eq!(ac.difference(bc), Flags::A);
--        assert_eq!(bc.difference(ac), Flags::B);
--
--        assert_eq!(bc.complement(), !bc);
--        assert_eq!(bc.complement(), Flags::A);
--        assert_eq!(ac.symmetric_difference(bc), Flags::A.union(Flags::B));
--        assert_eq!(bc.symmetric_difference(ac), Flags::A.union(Flags::B));
--    }
--
--    #[test]
--    fn test_set_ops_const() {
--        // These just test that these compile and don't cause use-site panics
--        // (would be possible if we had some sort of UB)
--        const INTERSECT: Flags = Flags::all().intersection(Flags::C);
--        const UNION: Flags = Flags::A.union(Flags::C);
--        const DIFFERENCE: Flags = Flags::all().difference(Flags::A);
--        const COMPLEMENT: Flags = Flags::C.complement();
--        const SYM_DIFFERENCE: Flags = UNION.symmetric_difference(DIFFERENCE);
--        assert_eq!(INTERSECT, Flags::C);
--        assert_eq!(UNION, Flags::A | Flags::C);
--        assert_eq!(DIFFERENCE, Flags::all() - Flags::A);
--        assert_eq!(COMPLEMENT, !Flags::C);
--        assert_eq!(SYM_DIFFERENCE, (Flags::A | Flags::C) ^ (Flags::all() - Flags::A));
--    }
--
--    #[test]
--    fn test_set_ops_unchecked() {
--        let extra = unsafe { Flags::from_bits_unchecked(0b1000) };
--        let e1 = Flags::A.union(Flags::C).union(extra);
--        let e2 = Flags::B.union(Flags::C);
--        assert_eq!(e1.bits, 0b1101);
--        assert_eq!(e1.union(e2), (Flags::ABC | extra));
--        assert_eq!(e1.intersection(e2), Flags::C);
--        assert_eq!(e1.difference(e2), Flags::A | extra);
--        assert_eq!(e2.difference(e1), Flags::B);
--        assert_eq!(e2.complement(), Flags::A);
--        assert_eq!(e1.complement(), Flags::B);
--        assert_eq!(e1.symmetric_difference(e2), Flags::A | Flags::B | extra); // toggle
--    }
--
--    #[test]
--    fn test_set_ops_exhaustive() {
--        // Define a flag that contains gaps to help exercise edge-cases,
--        // especially around "unknown" flags (e.g. ones outside of `all()`
--        // `from_bits_unchecked`).
--        // - when lhs and rhs both have different sets of unknown flags.
--        // - unknown flags at both ends, and in the middle
--        // - cases with "gaps".
--        bitflags! {
--            struct Test: u16 {
--                // Intentionally no `A`
--                const B = 0b000000010;
--                // Intentionally no `C`
--                const D = 0b000001000;
--                const E = 0b000010000;
--                const F = 0b000100000;
--                const G = 0b001000000;
--                // Intentionally no `H`
--                const I = 0b100000000;
--            }
--        }
--        let iter_test_flags =
--            || (0..=0b111_1111_1111).map(|bits| unsafe { Test::from_bits_unchecked(bits) });
--
--        for a in iter_test_flags() {
--            assert_eq!(
--                a.complement(),
--                Test::from_bits_truncate(!a.bits),
--                "wrong result: !({:?})",
--                a,
--            );
--            assert_eq!(a.complement(), !a, "named != op: !({:?})", a);
--            for b in iter_test_flags() {
--                // Check that the named operations produce the expected bitwise
--                // values.
--                assert_eq!(
--                    a.union(b).bits,
--                    a.bits | b.bits,
--                    "wrong result: `{:?}` | `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(
--                    a.intersection(b).bits,
--                    a.bits & b.bits,
--                    "wrong result: `{:?}` & `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(
--                    a.symmetric_difference(b).bits,
--                    a.bits ^ b.bits,
--                    "wrong result: `{:?}` ^ `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(
--                    a.difference(b).bits,
--                    a.bits & !b.bits,
--                    "wrong result: `{:?}` - `{:?}`",
--                    a,
--                    b,
--                );
--                // Note: Difference is checked as both `a - b` and `b - a`
--                assert_eq!(
--                    b.difference(a).bits,
--                    b.bits & !a.bits,
--                    "wrong result: `{:?}` - `{:?}`",
--                    b,
--                    a,
--                );
--                // Check that the named set operations are equivalent to the
--                // bitwise equivalents
--                assert_eq!(a.union(b), a | b, "named != op: `{:?}` | `{:?}`", a, b,);
--                assert_eq!(
--                    a.intersection(b),
--                    a & b,
--                    "named != op: `{:?}` & `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(
--                    a.symmetric_difference(b),
--                    a ^ b,
--                    "named != op: `{:?}` ^ `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(a.difference(b), a - b, "named != op: `{:?}` - `{:?}`", a, b,);
--                // Note: Difference is checked as both `a - b` and `b - a`
--                assert_eq!(b.difference(a), b - a, "named != op: `{:?}` - `{:?}`", b, a,);
--                // Verify that the operations which should be symmetric are
--                // actually symmetric.
--                assert_eq!(a.union(b), b.union(a), "asymmetry: `{:?}` | `{:?}`", a, b,);
--                assert_eq!(
--                    a.intersection(b),
--                    b.intersection(a),
--                    "asymmetry: `{:?}` & `{:?}`",
--                    a,
--                    b,
--                );
--                assert_eq!(
--                    a.symmetric_difference(b),
--                    b.symmetric_difference(a),
--                    "asymmetry: `{:?}` ^ `{:?}`",
--                    a,
--                    b,
--                );
--            }
--        }
--    }
--
-     #[test]
-     fn test_set() {
-         let mut e1 = Flags::A | Flags::C;
-@@ -1392,6 +1168,8 @@ mod tests {
-         assert_eq!(m1, e1);
-     }
- 
-+
-+    #[cfg(bitflags_const_fn)]
-     #[test]
-     fn test_const_fn() {
-         const _M1: Flags = Flags::empty();
-@@ -1481,11 +1259,6 @@ mod tests {
-         assert_eq!(hash(&x), hash(&y));
-     }
- 
--    #[test]
--    fn test_default() {
--        assert_eq!(Flags::empty(), Flags::default());
--    }
--
-     #[test]
-     fn test_debug() {
-         assert_eq!(format!("{:?}", Flags::A | Flags::B), "A | B");
-@@ -1494,13 +1267,7 @@ mod tests {
-         let extra = unsafe { Flags::from_bits_unchecked(0xb8) };
-         assert_eq!(format!("{:?}", extra), "0xb8");
-         assert_eq!(format!("{:?}", Flags::A | extra), "A | 0xb8");
--
--        assert_eq!(
--            format!("{:?}", Flags::ABC | extra),
--            "A | B | C | ABC | 0xb8"
--        );
--
--        assert_eq!(format!("{:?}", EmptyFlags::empty()), "(empty)");
-+        assert_eq!(format!("{:?}", Flags::ABC | extra), "A | B | C | ABC | 0xb8");
-     }
- 
-     #[test]
-@@ -1544,7 +1311,8 @@ mod tests {
-             pub struct PublicFlags: i8 {
-                 const X = 0;
-             }
--
-+        }
-+        bitflags! {
-             struct PrivateFlags: i8 {
-                 const Y = 0;
-             }
-@@ -1659,71 +1427,4 @@ mod tests {
-         assert_eq!(format!("{:?}", Flags::empty()), "NONE");
-         assert_eq!(format!("{:?}", Flags::SOME), "SOME");
-     }
--
--    #[test]
--    fn test_empty_bitflags() {
--        bitflags! {}
--    }
--
--    #[test]
--    fn test_u128_bitflags() {
--        bitflags! {
--            struct Flags128: u128 {
--                const A = 0x0000_0000_0000_0000_0000_0000_0000_0001;
--                const B = 0x0000_0000_0000_1000_0000_0000_0000_0000;
--                const C = 0x8000_0000_0000_0000_0000_0000_0000_0000;
--                const ABC = Self::A.bits | Self::B.bits | Self::C.bits;
--            }
--        }
--
--        assert_eq!(Flags128::ABC, Flags128::A | Flags128::B | Flags128::C);
--        assert_eq!(Flags128::A.bits, 0x0000_0000_0000_0000_0000_0000_0000_0001);
--        assert_eq!(Flags128::B.bits, 0x0000_0000_0000_1000_0000_0000_0000_0000);
--        assert_eq!(Flags128::C.bits, 0x8000_0000_0000_0000_0000_0000_0000_0000);
--        assert_eq!(
--            Flags128::ABC.bits,
--            0x8000_0000_0000_1000_0000_0000_0000_0001
--        );
--        assert_eq!(format!("{:?}", Flags128::A), "A");
--        assert_eq!(format!("{:?}", Flags128::B), "B");
--        assert_eq!(format!("{:?}", Flags128::C), "C");
--        assert_eq!(format!("{:?}", Flags128::ABC), "A | B | C | ABC");
--    }
--
--    #[test]
--    fn test_serde_bitflags_serialize() {
--        let flags = SerdeFlags::A | SerdeFlags::B;
--
--        let serialized = serde_json::to_string(&flags).unwrap();
--
--        assert_eq!(serialized, r#"{"bits":3}"#);
--    }
--
--    #[test]
--    fn test_serde_bitflags_deserialize() {
--        let deserialized: SerdeFlags = serde_json::from_str(r#"{"bits":12}"#).unwrap();
--
--        let expected = SerdeFlags::C | SerdeFlags::D;
--
--        assert_eq!(deserialized.bits, expected.bits);
--    }
--
--    #[test]
--    fn test_serde_bitflags_roundtrip() {
--        let flags = SerdeFlags::A | SerdeFlags::B;
--
--        let deserialized: SerdeFlags = serde_json::from_str(&serde_json::to_string(&flags).unwrap()).unwrap();
--
--        assert_eq!(deserialized.bits, flags.bits);
--    }
--
--    bitflags! {
--        #[derive(serde::Serialize, serde::Deserialize)]
--        struct SerdeFlags: u32 {
--            const A = 1;
--            const B = 2;
--            const C = 4;
--            const D = 8;
--        }
--    }
- }
-diff --git a/third_party/rust/bitflags/tests/basic.rs b/third_party/rust/bitflags/tests/basic.rs
-deleted file mode 100644
-index 73a52bec50b60..0000000000000
---- a/third_party/rust/bitflags/tests/basic.rs
-+++ /dev/null
-@@ -1,20 +0,0 @@
--#![no_std]
--
--use bitflags::bitflags;
--
--bitflags! {
--    /// baz
--    struct Flags: u32 {
--        const A = 0b00000001;
--        #[doc = "bar"]
--        const B = 0b00000010;
--        const C = 0b00000100;
--        #[doc = "foo"]
--        const ABC = Flags::A.bits | Flags::B.bits | Flags::C.bits;
--    }
--}
--
--#[test]
--fn basic() {
--    assert_eq!(Flags::ABC, Flags::A | Flags::B | Flags::C);
--}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs b/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
-deleted file mode 100644
-index 38f4822f5a5f2..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/impls/copy.rs
-+++ /dev/null
-@@ -1,10 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    #[derive(Clone, Copy)]
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
-deleted file mode 100644
-index 0c13aa5024197..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/impls/copy.stderr.beta
-+++ /dev/null
-@@ -1,27 +0,0 @@
--error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `Flags`
-- --> $DIR/copy.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(Clone, Copy)]
--  | |              ----- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
--
--error[E0119]: conflicting implementations of trait `std::marker::Copy` for type `Flags`
-- --> $DIR/copy.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(Clone, Copy)]
--  | |                     ---- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs b/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
-deleted file mode 100644
-index 4abbd630c6e12..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/impls/eq.rs
-+++ /dev/null
-@@ -1,10 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    #[derive(PartialEq, Eq)]
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
-deleted file mode 100644
-index 8a1a3b410a0e0..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/impls/eq.stderr.beta
-+++ /dev/null
-@@ -1,55 +0,0 @@
--error[E0119]: conflicting implementations of trait `std::cmp::PartialEq` for type `Flags`
-- --> $DIR/eq.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(PartialEq, Eq)]
--  | |              --------- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
--
--error[E0119]: conflicting implementations of trait `std::cmp::Eq` for type `Flags`
-- --> $DIR/eq.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(PartialEq, Eq)]
--  | |                         -- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
--
--error[E0119]: conflicting implementations of trait `std::marker::StructuralPartialEq` for type `Flags`
-- --> $DIR/eq.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(PartialEq, Eq)]
--  | |              --------- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
--
--error[E0119]: conflicting implementations of trait `std::marker::StructuralEq` for type `Flags`
-- --> $DIR/eq.rs:3:1
--  |
--3 | / bitflags! {
--4 | |     #[derive(PartialEq, Eq)]
--  | |                         -- first implementation here
--5 | |     struct Flags: u32 {
--6 | |         const A = 0b00000001;
--7 | |     }
--8 | | }
--  | |_^ conflicting implementation for `Flags`
--  |
--  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)
-diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
-deleted file mode 100644
-index c2856b10830d3..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.rs
-+++ /dev/null
-@@ -1,123 +0,0 @@
--use std::{
--    fmt::{
--        self,
--        Debug,
--        Display,
--        LowerHex,
--        UpperHex,
--        Octal,
--        Binary,
--    },
--    ops::{
--        BitAnd,
--        BitOr,
--        BitXor,
--        BitAndAssign,
--        BitOrAssign,
--        BitXorAssign,
--        Not,
--    },
--};
--
--use bitflags::bitflags;
--
--// Ideally we'd actually want this to work, but currently need something like `num`'s `Zero`
--// With some design work it could be made possible
--#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
--struct MyInt(u8);
--
--impl BitAnd for MyInt {
--    type Output = Self;
--
--    fn bitand(self, other: Self) -> Self {
--        MyInt(self.0 & other.0)
--    }
--}
--
--impl BitOr for MyInt {
--    type Output = Self;
--
--    fn bitor(self, other: Self) -> Self {
--        MyInt(self.0 | other.0)
--    }
--}
--
--impl BitXor for MyInt {
--    type Output = Self;
--
--    fn bitxor(self, other: Self) -> Self {
--        MyInt(self.0 ^ other.0)
--    }
--}
--
--impl BitAndAssign for MyInt {
--    fn bitand_assign(&mut self, other: Self) {
--        self.0 &= other.0
--    }
--}
--
--impl BitOrAssign for MyInt {
--    fn bitor_assign(&mut self, other: Self) {
--        self.0 |= other.0
--    }
--}
--
--impl BitXorAssign for MyInt {
--    fn bitxor_assign(&mut self, other: Self) {
--        self.0 ^= other.0
--    }
--}
--
--impl Debug for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        Debug::fmt(&self.0, f)
--    }
--}
--
--impl Display for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        Display::fmt(&self.0, f)
--    }
--}
--
--impl LowerHex for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        LowerHex::fmt(&self.0, f)
--    }
--}
--
--impl UpperHex for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        UpperHex::fmt(&self.0, f)
--    }
--}
--
--impl Octal for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        Octal::fmt(&self.0, f)
--    }
--}
--
--impl Binary for MyInt {
--    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
--        Binary::fmt(&self.0, f)
--    }
--}
--
--impl Not for MyInt {
--    type Output = MyInt;
--
--    fn not(self) -> Self {
--        MyInt(!self.0)
--    }
--}
--
--bitflags! {
--    struct Flags128: MyInt {
--        const A = MyInt(0b0000_0001u8);
--        const B = MyInt(0b0000_0010u8);
--        const C = MyInt(0b0000_0100u8);
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
-deleted file mode 100644
-index 1f0fb5cf7ad0b..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_defined.stderr.beta
-+++ /dev/null
-@@ -1,27 +0,0 @@
--error[E0308]: mismatched types
--   --> $DIR/all_defined.rs:115:1
--    |
--115 | / bitflags! {
--116 | |     struct Flags128: MyInt {
--117 | |         const A = MyInt(0b0000_0001u8);
--118 | |         const B = MyInt(0b0000_0010u8);
--119 | |         const C = MyInt(0b0000_0100u8);
--120 | |     }
--121 | | }
--    | |_^ expected struct `MyInt`, found integer
--    |
--    = note: this error originates in the macro `__impl_all_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
--
--error[E0308]: mismatched types
--   --> $DIR/all_defined.rs:115:1
--    |
--115 | / bitflags! {
--116 | |     struct Flags128: MyInt {
--117 | |         const A = MyInt(0b0000_0001u8);
--118 | |         const B = MyInt(0b0000_0010u8);
--119 | |         const C = MyInt(0b0000_0100u8);
--120 | |     }
--121 | | }
--    | |_^ expected struct `MyInt`, found integer
--    |
--    = note: this error originates in the macro `__impl_bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
-diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
-deleted file mode 100644
-index fff6b2cc13062..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.rs
-+++ /dev/null
-@@ -1,13 +0,0 @@
--use bitflags::bitflags;
--
--struct MyInt(u8);
--
--bitflags! {
--    struct Flags128: MyInt {
--        const A = MyInt(0b0000_0001);
--        const B = MyInt(0b0000_0010);
--        const C = MyInt(0b0000_0100);
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
-deleted file mode 100644
-index ee95f8365e33e..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/non_integer_base/all_missing.stderr.beta
-+++ /dev/null
-@@ -1,13 +0,0 @@
--error[E0204]: the trait `Copy` may not be implemented for this type
--  --> $DIR/all_missing.rs:5:1
--   |
--5  | / bitflags! {
--6  | |     struct Flags128: MyInt {
--7  | |         const A = MyInt(0b0000_0001);
--8  | |         const B = MyInt(0b0000_0010);
--9  | |         const C = MyInt(0b0000_0100);
--10 | |     }
--11 | | }
--   | |_^ this field does not implement `Copy`
--   |
--   = note: this error originates in the derive macro `Copy` (in Nightly builds, run with -Z macro-backtrace for more info)
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
-deleted file mode 100644
-index a6a3912aea30a..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.rs
-+++ /dev/null
-@@ -1,13 +0,0 @@
--mod example {
--    use bitflags::bitflags;
--
--    bitflags! {
--        pub struct Flags1: u32 {
--            const FLAG_A = 0b00000001;
--        }
--    }
--}
--
--fn main() {
--    let flag1 = example::Flags1::FLAG_A.bits;
--}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
-deleted file mode 100644
-index 58a04660166a8..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_field.stderr.beta
-+++ /dev/null
-@@ -1,10 +0,0 @@
--error[E0616]: field `bits` of struct `Flags1` is private
--  --> $DIR/private_field.rs:12:41
--   |
--12 |     let flag1 = example::Flags1::FLAG_A.bits;
--   |                                         ^^^^ private field
--   |
--help: a method `bits` also exists, call it with parentheses
--   |
--12 |     let flag1 = example::Flags1::FLAG_A.bits();
--   |                                             ^^
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
-deleted file mode 100644
-index 85a5b1863dd43..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.rs
-+++ /dev/null
-@@ -1,18 +0,0 @@
--mod example {
--    use bitflags::bitflags;
--
--    bitflags! {
--        pub struct Flags1: u32 {
--            const FLAG_A = 0b00000001;
--        }
--
--        struct Flags2: u32 {
--            const FLAG_B = 0b00000010;
--        }
--    }
--}
--
--fn main() {
--    let flag1 = example::Flags1::FLAG_A;
--    let flag2 = example::Flags2::FLAG_B;
--}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
-deleted file mode 100644
-index d23f83209ba90..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/private_flags.stderr.beta
-+++ /dev/null
-@@ -1,18 +0,0 @@
--error[E0603]: struct `Flags2` is private
--  --> $DIR/private_flags.rs:17:26
--   |
--17 |     let flag2 = example::Flags2::FLAG_B;
--   |                          ^^^^^^ private struct
--   |
--note: the struct `Flags2` is defined here
--  --> $DIR/private_flags.rs:4:5
--   |
--4  | /     bitflags! {
--5  | |         pub struct Flags1: u32 {
--6  | |             const FLAG_A = 0b00000001;
--7  | |         }
--...  |
--11 | |         }
--12 | |     }
--   | |_____^
--   = note: this error originates in the macro `bitflags` (in Nightly builds, run with -Z macro-backtrace for more info)
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs b/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
-deleted file mode 100644
-index b90f0ce92d1e6..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.rs
-+++ /dev/null
-@@ -1,9 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    pub struct Flags1: u32 {
--        pub const FLAG_A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta b/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
-deleted file mode 100644
-index b01122c7ad879..0000000000000
---- a/third_party/rust/bitflags/tests/compile-fail/visibility/pub_const.stderr.beta
-+++ /dev/null
-@@ -1,5 +0,0 @@
--error: no rules expected the token `pub`
-- --> $DIR/pub_const.rs:5:9
--  |
--5 |         pub const FLAG_A = 0b00000001;
--  |         ^^^ no rules expected this token in macro call
-diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs b/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
-deleted file mode 100644
-index 1f02982a8fa24..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/impls/convert.rs
-+++ /dev/null
-@@ -1,17 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--impl From<u32> for Flags {
--    fn from(v: u32) -> Flags {
--        Flags::from_bits_truncate(v)
--    }
--}
--
--fn main() {
--
--}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/default.rs b/third_party/rust/bitflags/tests/compile-pass/impls/default.rs
-deleted file mode 100644
-index a97b6536f2b58..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/impls/default.rs
-+++ /dev/null
-@@ -1,10 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    #[derive(Default)]
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs b/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
-deleted file mode 100644
-index 3052c460ec33a..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/impls/inherent_methods.rs
-+++ /dev/null
-@@ -1,15 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--impl Flags {
--    pub fn new() -> Flags {
--        Flags::A
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs b/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
-deleted file mode 100644
-index 47549215948d1..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/redefinition/core.rs
-+++ /dev/null
-@@ -1,14 +0,0 @@
--use bitflags::bitflags;
--
--// Checks for possible errors caused by overriding names used by `bitflags!` internally.
--
--mod core {}
--mod _core {}
--
--bitflags! {
--    struct Test: u8 {
--        const A = 1;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs b/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
-deleted file mode 100644
-index b04f2f6a49332..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/redefinition/stringify.rs
-+++ /dev/null
-@@ -1,19 +0,0 @@
--use bitflags::bitflags;
--
--// Checks for possible errors caused by overriding names used by `bitflags!` internally.
--
--#[allow(unused_macros)]
--macro_rules! stringify {
--    ($($t:tt)*) => { "..." };
--}
--
--bitflags! {
--    struct Test: u8 {
--        const A = 1;
--    }
--}
--
--fn main() {
--    // Just make sure we don't call the redefined `stringify` macro
--    assert_eq!(format!("{:?}", Test::A), "A");
--}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/repr/c.rs b/third_party/rust/bitflags/tests/compile-pass/repr/c.rs
-deleted file mode 100644
-index 6feba36ed82c1..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/repr/c.rs
-+++ /dev/null
-@@ -1,10 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    #[repr(C)]
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs b/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
-deleted file mode 100644
-index e38db4dd11b99..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/repr/transparent.rs
-+++ /dev/null
-@@ -1,10 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    #[repr(transparent)]
--    struct Flags: u32 {
--        const A = 0b00000001;
--    }
--}
--
--fn main() {}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs b/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
-deleted file mode 100644
-index 33a7967e629ef..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/visibility/bits_field.rs
-+++ /dev/null
-@@ -1,11 +0,0 @@
--use bitflags::bitflags;
--
--bitflags! {
--    pub struct Flags1: u32 {
--        const FLAG_A = 0b00000001;
--    }
--}
--
--fn main() {
--    assert_eq!(0b00000001, Flags1::FLAG_A.bits);
--}
-diff --git a/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs b/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
-deleted file mode 100644
-index c11050e3baf0c..0000000000000
---- a/third_party/rust/bitflags/tests/compile-pass/visibility/pub_in.rs
-+++ /dev/null
-@@ -1,19 +0,0 @@
--mod a {
--    mod b {
--        use bitflags::bitflags;
--
--        bitflags! {
--            pub(in crate::a) struct Flags: u32 {
--                const FLAG_A = 0b00000001;
--            }
--        }
--    }
--
--    pub fn flags() -> u32 {
--        b::Flags::FLAG_A.bits()
--    }
--}
--
--fn main() {
--    assert_eq!(0b00000001, a::flags());
--}
-diff --git a/third_party/rust/bitflags/tests/compile.rs b/third_party/rust/bitflags/tests/compile.rs
-deleted file mode 100644
-index ed02d01e9ca1b..0000000000000
---- a/third_party/rust/bitflags/tests/compile.rs
-+++ /dev/null
-@@ -1,63 +0,0 @@
--use std::{
--    fs,
--    ffi::OsStr,
--    io,
--    path::Path,
--};
--
--use walkdir::WalkDir;
--
--#[test]
--fn fail() {
--    prepare_stderr_files("tests/compile-fail").unwrap();
--
--    let t = trybuild::TestCases::new();
--    t.compile_fail("tests/compile-fail/**/*.rs");
--}
--
--#[test]
--fn pass() {
--    let t = trybuild::TestCases::new();
--    t.pass("tests/compile-pass/**/*.rs");
--}
--
--// Compiler messages may change between versions
--// We don't want to have to track these too closely for `bitflags`, but
--// having some message to check makes sure user-facing errors are sensical.
--// 
--// The approach we use is to run the test on all compilers, but only check stderr
--// output on beta (which is the next stable release). We do this by default ignoring
--// any `.stderr` files in the `compile-fail` directory, and copying `.stderr.beta` files
--// when we happen to be running on a beta compiler.
--fn prepare_stderr_files(path: impl AsRef<Path>) -> io::Result<()> {
--    for entry in WalkDir::new(path) {
--        let entry = entry?;
--
--        if entry.path().extension().and_then(OsStr::to_str) == Some("beta") {
--            let renamed = entry.path().with_extension("");
--
--            // Unconditionally remove a corresponding `.stderr` file for a `.stderr.beta`
--            // file if it exists. On `beta` compilers, we'll recreate it. On other compilers,
--            // we don't want to end up checking it anyways.
--            if renamed.exists() {
--                fs::remove_file(&renamed)?;
--            }
--
--            rename_beta_stderr(entry.path(), renamed)?;
--        }
--    }
--
--    Ok(())
--}
--
--#[rustversion::beta]
--fn rename_beta_stderr(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
--    fs::copy(from, to)?;
--
--    Ok(())
--}
--
--#[rustversion::not(beta)]
--fn rename_beta_stderr(_: impl AsRef<Path>, _: impl AsRef<Path>) -> io::Result<()> {
--    Ok(())
--}
-diff --git a/third_party/rust/midir/.cargo-checksum.json b/third_party/rust/midir/.cargo-checksum.json
-index 390b25b1e0118..34b17c2c5c548 100644
---- a/third_party/rust/midir/.cargo-checksum.json
-+++ b/third_party/rust/midir/.cargo-checksum.json
-@@ -1 +1 @@
--{"files":{"CHANGELOG.md":"10db6f8dbb1c5566e75f2eeda6b2ee8bb44fe4a76f57e0bfb98c62f7f8c04f89","Cargo.toml":"41aa086ea813af75458515ff515917bb48d20eaef42a74352ea12ff8d5d16bce","LICENSE":"6fe6f623b1fa80e90679aee2f917d8978a184988ebb995ebc254cc9633903cac","README.md":"4131b953217e77a4463fde307ba3262b4df11732c1ff209668df12dff3c73ffc","azure-pipelines-template.yml":"c787791a94e654226a299aaa875fcc48f6eedf4dae631855cb5a7067891dbe3a","azure-pipelines.yml":"1b4fab0afacc66732a385cb6e5b213c170fc9717219a03ccda9c5db78cd461dd","examples/test_forward.rs":"6cb060aba7e8c39eaf53ea95a72d4c7939ffb4bebc82c291135fdc35495078ce","examples/test_list_ports.rs":"41ba21ab1e56d76206abc8b291d27050cb1a788372f00f6761c78f03fb5981ff","examples/test_play.rs":"22630e46af9628d8193ad8e19ff095ad02542b7ab697be4e513da78210ad5c0c","examples/test_read_input.rs":"4901f18435c3f8021750ccd4687abe92194ab38f1e7721896a6a31f6650d524c","examples/test_reuse.rs":"fdb3b430aec42c7c648fbecf22e6c726ef8a20638936a1a70fb373dff94c0632","examples/
 test_sysex.rs":"ea06427a644c3639f1c49271be5d16c9d3890d3741eb6ebf2ff64d2f7fd36e96","src/backend/alsa/mod.rs":"6bc784435247c3302bf12c3f558b6027abfbec997a280baa113c7344e5b0479f","src/backend/coremidi/mod.rs":"f827cbc5db7086ea58c5927213a2c3e0246244d5939c2ba0ff787caae7089511","src/backend/jack/mod.rs":"8f2eace3e9046ec6de8c7fc37d3502d2b971a73fe2a96e5c2a423d51445f1505","src/backend/jack/wrappers.rs":"f18718f234e41c91bb5463546fbbe61be64e9581a4fae6ef2de20cafae487298","src/backend/mod.rs":"1a8106889ecd053af27b3a72515bfb286da1b08bb90909fa6d4e7b816b50c447","src/backend/webmidi/mod.rs":"4af5b288833ee99f047a638b368eca293f89356f1e82147c9a9c1633d950955d","src/backend/winmm/handler.rs":"45b36067fd280a38943f385d3d7f6885d7448153f53e9c8f66b58b484535ad1c","src/backend/winmm/mod.rs":"94d8c57fd2d327993d01ef06d8c68190c528fe52dd39e6b97c88d9f1f0afa753","src/backend/winrt/mod.rs":"ca7ac4ac310e7f6a6c28dd6374bfe97b38ed8656c7ca343494264cce45f93ae6","src/common.rs":"2cab2e987428522ca601544b516b64b858859730fbd1be0
 e53c828e82025319d","src/errors.rs":"495ba80f9dcfeefd343b460b74549b12cb1825c3e1b315848f859d0b4d66ddbe","src/lib.rs":"ecde030ca02a90a99577cd71446857a2c00aee8ff1bc7890c54a5d0d22d2be2c","src/os/mod.rs":"507dfa95e57805c489a883dcf9efddcb718d5178267f296294f72b3c397c12c7","src/os/unix.rs":"a1977659d270fcf31111d4446b949d2760d76e2077639e6008d634800861b77b","tests/virtual.rs":"b47501eeb313f3e255d2d1888c333ff994d958865272929fe7bf116be45b6805"},"package":null}
-\ No newline at end of file
-+{"files":{"CHANGELOG.md":"10db6f8dbb1c5566e75f2eeda6b2ee8bb44fe4a76f57e0bfb98c62f7f8c04f89","Cargo.toml":"792c11a1ab6ce0443cb040994b02f1e80e07d19e6bf59f683a7fb227539bc028","LICENSE":"6fe6f623b1fa80e90679aee2f917d8978a184988ebb995ebc254cc9633903cac","README.md":"4131b953217e77a4463fde307ba3262b4df11732c1ff209668df12dff3c73ffc","azure-pipelines-template.yml":"c787791a94e654226a299aaa875fcc48f6eedf4dae631855cb5a7067891dbe3a","azure-pipelines.yml":"1b4fab0afacc66732a385cb6e5b213c170fc9717219a03ccda9c5db78cd461dd","examples/test_forward.rs":"6cb060aba7e8c39eaf53ea95a72d4c7939ffb4bebc82c291135fdc35495078ce","examples/test_list_ports.rs":"41ba21ab1e56d76206abc8b291d27050cb1a788372f00f6761c78f03fb5981ff","examples/test_play.rs":"22630e46af9628d8193ad8e19ff095ad02542b7ab697be4e513da78210ad5c0c","examples/test_read_input.rs":"4901f18435c3f8021750ccd4687abe92194ab38f1e7721896a6a31f6650d524c","examples/test_reuse.rs":"fdb3b430aec42c7c648fbecf22e6c726ef8a20638936a1a70fb373dff94c0632","examples/
 test_sysex.rs":"ea06427a644c3639f1c49271be5d16c9d3890d3741eb6ebf2ff64d2f7fd36e96","src/backend/alsa/mod.rs":"6bc784435247c3302bf12c3f558b6027abfbec997a280baa113c7344e5b0479f","src/backend/coremidi/mod.rs":"f827cbc5db7086ea58c5927213a2c3e0246244d5939c2ba0ff787caae7089511","src/backend/jack/mod.rs":"8f2eace3e9046ec6de8c7fc37d3502d2b971a73fe2a96e5c2a423d51445f1505","src/backend/jack/wrappers.rs":"f18718f234e41c91bb5463546fbbe61be64e9581a4fae6ef2de20cafae487298","src/backend/mod.rs":"1a8106889ecd053af27b3a72515bfb286da1b08bb90909fa6d4e7b816b50c447","src/backend/webmidi/mod.rs":"4af5b288833ee99f047a638b368eca293f89356f1e82147c9a9c1633d950955d","src/backend/winmm/handler.rs":"45b36067fd280a38943f385d3d7f6885d7448153f53e9c8f66b58b484535ad1c","src/backend/winmm/mod.rs":"94d8c57fd2d327993d01ef06d8c68190c528fe52dd39e6b97c88d9f1f0afa753","src/backend/winrt/mod.rs":"ca7ac4ac310e7f6a6c28dd6374bfe97b38ed8656c7ca343494264cce45f93ae6","src/common.rs":"2cab2e987428522ca601544b516b64b858859730fbd1be0
 e53c828e82025319d","src/errors.rs":"495ba80f9dcfeefd343b460b74549b12cb1825c3e1b315848f859d0b4d66ddbe","src/lib.rs":"ecde030ca02a90a99577cd71446857a2c00aee8ff1bc7890c54a5d0d22d2be2c","src/os/mod.rs":"507dfa95e57805c489a883dcf9efddcb718d5178267f296294f72b3c397c12c7","src/os/unix.rs":"a1977659d270fcf31111d4446b949d2760d76e2077639e6008d634800861b77b","tests/virtual.rs":"b47501eeb313f3e255d2d1888c333ff994d958865272929fe7bf116be45b6805"},"package":null}
-\ No newline at end of file
-diff --git a/third_party/rust/midir/Cargo.toml b/third_party/rust/midir/Cargo.toml
-index 49089e0ffe86e..ac48aab304db9 100644
---- a/third_party/rust/midir/Cargo.toml
-+++ b/third_party/rust/midir/Cargo.toml
-@@ -28,8 +28,8 @@ libc = { version = "0.2.21", optional = true }
- winrt = { version = "0.7.0", optional = true}
- 
- [target.'cfg(target_os = "linux")'.dependencies]
--alsa = "0.4.3"
--nix = "0.15"
-+alsa = "0.5.0"
-+nix = "0.20"
- libc = "0.2.21"
- 
- [target.'cfg(target_os = "macos")'.dependencies]
-diff --git a/third_party/rust/nix-0.15.0/.cargo-checksum.json b/third_party/rust/nix-0.15.0/.cargo-checksum.json
-new file mode 100644
-index 0000000000000..e5f2bc789185a
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/.cargo-checksum.json
-@@ -0,0 +1 @@
-+{"files":{"CHANGELOG.md":"91af9fd5f2d9cdb9c8bb750e24b625742e95a6c74bcff419f3de70eb26578281","CONTRIBUTING.md":"a9101e3d1487170d691d5f062ff49a433c167582ac8984dd41a744be92652f74","CONVENTIONS.md":"e150ce43c1d188c392c1a3bf7f2e08e3cf84906705c7bef43f319037d29ea385","Cargo.toml":"af0cc0ae7ff4bf6c2e5b35fe062f54fe2d619f70ba67795f4f43a981420b5de0","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"80d71b9eaac7bf7f0d307372592ed1467f994291e6fad816a44f3c70e2887d0f","build.rs":"14c9c678c33f5894509da47f77d6a326b14aecb4190ce87a24cce98687ca63b2","src/dir.rs":"21e330cbe6594274335b94d9e9b6059f1fa8e53d2e5b5c697058c52ec6b3c5ff","src/errno.rs":"a009ccf18b45c0a4c9319c65b0dc5bc322d9ad43cfe462ec4661559f44162451","src/errno_dragonfly.c":"a857e47b114acb85fddcb252a610ab5734d225c26b7bedd7c35d7789d46c8526","src/fcntl.rs":"6ae2f7f01dd2568b82a4e57f86e02b1d63eec6c26111c5adb2ca5d78a2a99fe7","src/features.rs":"22ff626ff8287a07dd55bcfc63c9f518c19c56144e15f9b6f9e3bbdcda51c2a8","
 src/ifaddrs.rs":"9a93de176edcca4613e668b8ccc2c3e3b6b711aa2d8d94ccb0ba08694d1ef35f","src/kmod.rs":"4d8a695d3d761f351a39d654303a1bd168e74295b7d142b918737e355b24f34d","src/lib.rs":"fdd8049a79ffb92384c72f0a6b0bab717001ddfa9b01f2b33413c83f424f2ac8","src/macros.rs":"aec27fa0fd98900913fada926c9a4581cd28f2640e3a7b5480707f923c9200f8","src/mount.rs":"cdf5db8409017483132db9d7493b5d6cc96df5560d0fa5ad8f385aff72db10ca","src/mqueue.rs":"82af42b31381af73e7966f845d1ed93957f0b9976bf2da524b178fad15b2b08d","src/net/if_.rs":"f7e02076fcf3cadf3fdf141884c9bd2c468a7047ba60bc490f0057df802b53ce","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"7305e250066cd1a7318cd239ed3db787937ee98426fe9289cf00fa874d76b6c7","src/pty.rs":"6b965b586579933af47d4efef4c82c391b927037eaa08d8c83fc974ef17fc7c8","src/sched.rs":"f9b214fa60006b5450ffb3589a55ec59c3694bd49597c65c38ac813fcd96c7dd","src/sys/aio.rs":"a1ba629258b3ce1268e5fe8e5b41dce3581f77d415dc5e2455c1f82f26dd3085","src/sys/e
 poll.rs":"f0b539e0645569657f2142db91a38c94ebe1925f44852d64c61c818758dbbf0b","src/sys/event.rs":"ef8bc02a08d9ce7924c87f8f891fa051587b195a36913712fe85237a2fe0685b","src/sys/eventfd.rs":"08008cf3dc64c2216847c02c0dd8d7189cf08edbaafe35ba2c57c053fde09ef4","src/sys/inotify.rs":"687c8417d737939aa93f805d6003afc4f84f50828b1bd9429ef5d00bef0e0955","src/sys/ioctl/bsd.rs":"56ca6ecf5f7cfb566f4f3ba589fcc778f747a517dd45e13780981922e6215344","src/sys/ioctl/linux.rs":"6cfbdff4dbfa1a3782acdedebe89ffa9f000fdfc4ab68cb46f52890ebc1c6f2d","src/sys/ioctl/mod.rs":"20bc3cf1fcbbc7c31e4d507baa4e576a793ea42fb33618d2e7afeda730c4324f","src/sys/memfd.rs":"11cd93c867fdbdbc9588cecb94268691de42b2ef2a38fe33525be7c7f60c85d5","src/sys/mman.rs":"f77d28611a7ff3bf62784a3c4f26d7d79969395b1d9bbc6ff15e734f52dc404f","src/sys/mod.rs":"f39a08c72e37638c7cecfb9c087e0a41e2b69409aa545b0ef7bbd59c0a063ee2","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"8a7eacfc172b55763ae
 32109bf9b252669ba68b72cd5122f7504eb35c0c08345","src/sys/ptrace/linux.rs":"f09b45148004f4b28d8503c397a8d112d31046c98e68335bf4e89425d5b33f07","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"7eb8e797466b506f6ed882f18eda92c4639cf43d9384a19bc39cd1bf982989c9","src/sys/reboot.rs":"fde9da27c2928f7026231430fa14fec2058df4e49a0aeda2a237a60524f11241","src/sys/select.rs":"57d6c4403d1bf788bd52ab6f03cfc16a189d31b6bfb338b135cb775fe369121f","src/sys/sendfile.rs":"ea386e83baf9b5b23488aca26635aacdc92f2bfe238e4399a7380bd0331e0ef7","src/sys/signal.rs":"9216cdd609b4dfb9c2e559c411be6b7c722f7ddd8024682c0895a32126b488aa","src/sys/signalfd.rs":"bfcfce619bf199e50f9cc80a3eb778d48474a015cfdafc64a0c3517373a225a9","src/sys/socket/addr.rs":"8b297ce13cd8ad200b3e764888c26ceb582ee505385d1e172440de94ade99644","src/sys/socket/mod.rs":"e0353f04f3d098a8bf5e2aae431645897b96e0889fb76537dc0330159c6f233d","src/sys/socket/sockopt.rs":"c663505d6a7a7ae9d76e03fbc17e5
 3d308ea6b1eae92212812e1d76b2bf2916f","src/sys/stat.rs":"c4807048f86be67026756737cf81f448ec23c2a4745776cb40f40b533a88e0c8","src/sys/statfs.rs":"d2b72069f20aa7782ce5de4ec2d00c76a82a92376c2066bbb270cdac2167719e","src/sys/statvfs.rs":"2d328cf525ba04ab1e1351128624a7df7d0c55ea91fda6c8d620d13710d61606","src/sys/sysinfo.rs":"0c05244655aa9e6dff5138392c5c1ae97630d35bae0e5510d7f51a75c31fd425","src/sys/termios.rs":"a2e99afdfc3526641a2cb82b57bfd0a25a362fb9be5ad37ff9f11acaeb0b9439","src/sys/time.rs":"8a1224b9262026086af698630aedbed21b45d661fbd045fc6c6af41a16a23374","src/sys/uio.rs":"60a974275ff8c485ea183bdd6f7e25894e6f2360a5bfb25442391a825a3b9b8c","src/sys/utsname.rs":"c977a1aec6e051c72b27506395e942abab9cbd9523e6d345ea66dc10875ee87d","src/sys/wait.rs":"30b14a8f518d031805cae6c6ff644116f162d8c8a75fddcfce4479d8d55fd1c0","src/ucontext.rs":"075560ec08a362881534211f8c6b78844886d6b767c2f7067174600e38ed3f63","src/unistd.rs":"82308ec31b6293b55f86fafd04e976a41127fedebb8f158abd1399c7399af947","test/sys/mod.
 rs":"e0821cbc289ad952f17229609c7de4282cca1e44cd13e1a7494a6378ecbc12f8","test/sys/test_aio.rs":"b2544bfb321ca7fbed276ee637c769fb438156d14666cdc1e1d547b3514a44e3","test/sys/test_aio_drop.rs":"30dd1d238269d00381fa50f6d3cb2b13794b7cceb9f6455f3878fcbffa9aa62d","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"eea690ed386da0a666df5eb23a417421fddb99dc8e39556f63b30969bb6cf779","test/sys/test_lio_listio_resubmit.rs":"203a583313542593148f375b087ae30620222a745680173fa98fc448d1e5ae7f","test/sys/test_pthread.rs":"3890e5ecbf2082e0d05d102cc9cec6e76ede3c15f250d104e3483b1c1c3400b1","test/sys/test_ptrace.rs":"4e8d5dff5fe6bc56e4ae53bdfd10f5e8ea567d8099576d1c690cf7a6b2bc955f","test/sys/test_select.rs":"bdb20211fc6ec1e3f186337eac51e08757acb6901d307d67c71bf9011f0d54bd","test/sys/test_signal.rs":"84ae63c2baa49eebeabe5bbd347b9c5417e14ba97f342719d7
 53dc1c1c768d60","test/sys/test_signalfd.rs":"71b5d6d782283f6db64ca90f7fb06617faec71091d59d2587e41bbc9d8c43d5c","test/sys/test_socket.rs":"09a7ef0322e07b4579893e0307a7c4f81fbbc653d005b827a519c33a33e185ce","test/sys/test_sockopt.rs":"b3d386c8279f86bf9439c772317bafcdba5630fa806c8319e87ddac0ccfa3a03","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"fa4be3ade859b527bf33408f85a6f57b127917cf5f2afb662d09f6019d07913a","test/sys/test_uio.rs":"9da234e3bd5003fd200cc37c4a5be147ecda1a7670feb1d505f23d646d3e1c57","test/sys/test_wait.rs":"e6c5147e213daa93892cd828f53214995d2e019ff2372cc48d85ce9b93d26ec9","test/test.rs":"e6307f82a39426a949b8e925a2df4a62e31c0e43081d7a33d23759bdfeeece1f","test/test_dir.rs":"5d137a62f11d1a4993b4bb35dccc38a4c4416b7da374887f2335a9895b4fdee4","test/test_fcntl.rs":"730e64e99dc867ba5af7cc4ca83a4489c8b96b1a52f8937bcc666d673af27002","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c903
 33ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"f4754f028402a8ba788c87686288424cd3784e77c7eb5d96682ef491b1dd5262","test/test_mount.rs":"78ddc657f5098360c764fffa3a7d844503e4b6b65b44bfd42d9aa9045b415cb6","test/test_mq.rs":"5806f8825e91edc79dd0e2bc81d8be3ba094c2de6c0b2ac0268221ae2ad22701","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"46c71ee988fe1b85561ea0530d099750be8c1b8f95ab6e845c8a9f46f16f060c","test/test_pty.rs":"be04f99904fa47b60400c2bd156a388b73df4b9aec2eebf13df7dcdfc9aacf45","test/test_ptymaster_drop.rs":"5cfbbb79551c205ab510c2d4ef497bf937ceac9151fbe2f2e543d6515e406990","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"1dc420d3119bf4d863a7ae0ba63efa7f1416f6e46e4
 100ea161003fe1c3f66ba","test/test_unistd.rs":"0325c998acca1e826e9e2b3d351d55ab9723a6cb2ca2072245978e7f5a9acee8"},"package":"3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"}
-\ No newline at end of file
-diff --git a/third_party/rust/nix-0.15.0/CHANGELOG.md b/third_party/rust/nix-0.15.0/CHANGELOG.md
-new file mode 100644
-index 0000000000000..d93a5ce6bbfc9
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/CHANGELOG.md
-@@ -0,0 +1,742 @@
-+# Change Log
-+
-+All notable changes to this project will be documented in this file.
-+This project adheres to [Semantic Versioning](http://semver.org/).
-+
-+## [Unreleased] - ReleaseDate
-+### Added
-+### Changed
-+### Fixed
-+### Removed
-+
-+## [0.15.0] - 10 August 2019
-+### Added
-+- Added `MSG_WAITALL` to `MsgFlags` in `sys::socket`.
-+  ([#1079](https://github.com/nix-rust/nix/pull/1079))
-+- Implemented `Clone`, `Copy`, `Debug`, `Eq`, `Hash`, and `PartialEq` for most
-+  types that support them. ([#1035](https://github.com/nix-rust/nix/pull/1035))
-+- Added `copy_file_range` wrapper
-+  ([#1069](https://github.com/nix-rust/nix/pull/1069))
-+- Add `mkdirat`.
-+  ([#1084](https://github.com/nix-rust/nix/pull/1084))
-+- Add `posix_fadvise`.
-+  ([#1089](https://github.com/nix-rust/nix/pull/1089))
-+- Added `AF_VSOCK` to `AddressFamily`.
-+  ([#1091](https://github.com/nix-rust/nix/pull/1091))
-+- Add `unlinkat`
-+  ([#1058](https://github.com/nix-rust/nix/pull/1058))
-+- Add `renameat`.
-+  ([#1097](https://github.com/nix-rust/nix/pull/1097))
-+
-+### Changed
-+- Support for `ifaddrs` now present when building for Android.
-+  ([#1077](https://github.com/nix-rust/nix/pull/1077))
-+- Minimum supported Rust version is now 1.31.0
-+  ([#1035](https://github.com/nix-rust/nix/pull/1035))
-+  ([#1095](https://github.com/nix-rust/nix/pull/1095))
-+- Now functions `statfs()` and `fstatfs()` return result with `Statfs` wrapper
-+  ([#928](https://github.com/nix-rust/nix/pull/928))
-+
-+### Fixed
-+- Enabled `sched_yield` for all nix hosts.
-+  ([#1090](https://github.com/nix-rust/nix/pull/1090))
-+
-+### Removed
-+
-+## [0.14.1] - 2019-06-06
-+### Added
-+- Macros exported by `nix` may now be imported via `use` on the Rust 2018
-+  edition without importing helper macros on Linux targets.
-+  ([#1066](https://github.com/nix-rust/nix/pull/1066))
-+
-+  For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
-+  without importing the `convert_ioctl_res!` macro.
-+
-+  ```rust
-+  use nix::ioctl_read_bad;
-+
-+  ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-+  ```
-+
-+### Changed
-+- Changed some public types from reexports of libc types like `uint32_t` to the
-+  native equivalents like `u32.`
-+  ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
-+
-+### Fixed
-+- Fix the build on Android and Linux/mips with recent versions of libc.
-+  ([#1072](https://github.com/nix-rust/nix/pull/1072/commits))
-+
-+### Removed
-+
-+## [0.14.0] - 2019-05-21
-+### Added
-+- Add IP_RECVIF & IP_RECVDSTADDR. Enable IP_PKTINFO and IP6_PKTINFO on netbsd/openbsd.
-+  ([#1002](https://github.com/nix-rust/nix/pull/1002))
-+- Added `inotify_init1`, `inotify_add_watch` and `inotify_rm_watch` wrappers for
-+  Android and Linux. ([#1016](https://github.com/nix-rust/nix/pull/1016))
-+- Add `ALG_SET_IV`, `ALG_SET_OP` and `ALG_SET_AEAD_ASSOCLEN` control messages and `AF_ALG`
-+  socket types on Linux and Android ([#1031](https://github.com/nix-rust/nix/pull/1031))
-+- Add killpg
-+  ([#1034](https://github.com/nix-rust/nix/pull/1034))
-+- Added ENOTSUP errno support for Linux and Android.
-+  ([#969](https://github.com/nix-rust/nix/pull/969))
-+- Add several errno constants from OpenBSD 6.2
-+  ([#1036](https://github.com/nix-rust/nix/pull/1036))
-+- Added `from_std` and `to_std` methods for `sys::socket::IpAddr`
-+  ([#1043](https://github.com/nix-rust/nix/pull/1043))
-+- Added `nix::unistd:seteuid` and `nix::unistd::setegid` for those platforms that do
-+  not support `setresuid` nor `setresgid` respectively.
-+  ([#1044](https://github.com/nix-rust/nix/pull/1044))
-+- Added a `access` wrapper
-+  ([#1045](https://github.com/nix-rust/nix/pull/1045))
-+- Add `forkpty`
-+  ([#1042](https://github.com/nix-rust/nix/pull/1042))
-+- Add `sched_yield`
-+  ([#1050](https://github.com/nix-rust/nix/pull/1050))
-+
-+### Changed
-+- `PollFd` event flags renamed to `PollFlags` ([#1024](https://github.com/nix-rust/nix/pull/1024/))
-+- `recvmsg` now returns an Iterator over `ControlMessageOwned` objects rather
-+  than `ControlMessage` objects.  This is sadly not backwards-compatible.  Fix
-+  code like this:
-+  ```rust
-+  if let ControlMessage::ScmRights(&fds) = cmsg {
-+  ```
-+
-+  By replacing it with code like this:
-+  ```rust
-+  if let ControlMessageOwned::ScmRights(fds) = cmsg {
-+  ```
-+  ([#1020](https://github.com/nix-rust/nix/pull/1020))
-+- Replaced `CmsgSpace` with the `cmsg_space` macro.
-+  ([#1020](https://github.com/nix-rust/nix/pull/1020))
-+
-+### Fixed
-+- Fixed multiple bugs when using `sendmsg` and `recvmsg` with ancillary control messages
-+  ([#1020](https://github.com/nix-rust/nix/pull/1020))
-+- Macros exported by `nix` may now be imported via `use` on the Rust 2018
-+  edition without importing helper macros for BSD targets.
-+  ([#1041](https://github.com/nix-rust/nix/pull/1041))
-+
-+  For example, in Rust 2018, the `ioctl_read_bad!` macro can now be imported
-+  without importing the `convert_ioctl_res!` macro.
-+
-+  ```rust
-+  use nix::ioctl_read_bad;
-+
-+  ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-+  ```
-+
-+### Removed
-+- `Daemon`, `NOTE_REAP`, and `NOTE_EXIT_REPARENTED` are now deprecated on OSX
-+  and iOS.
-+  ([#1033](https://github.com/nix-rust/nix/pull/1033))
-+- `PTRACE_GETREGS`, `PTRACE_SETREGS`, `PTRACE_GETFPREGS`, and
-+  `PTRACE_SETFPREGS` have been removed from some platforms where they never
-+  should've been defined in the first place.
-+  ([#1055](https://github.com/nix-rust/nix/pull/1055))
-+
-+## [0.13.0] - 2019-01-15
-+### Added
-+- Added PKTINFO(V4) & V6PKTINFO cmsg support - Android/FreeBSD/iOS/Linux/MacOS.
-+  ([#990](https://github.com/nix-rust/nix/pull/990))
-+- Added support of CString type in `setsockopt`.
-+  ([#972](https://github.com/nix-rust/nix/pull/972))
-+- Added option `TCP_CONGESTION` in `setsockopt`.
-+  ([#972](https://github.com/nix-rust/nix/pull/972))
-+- Added `symlinkat` wrapper.
-+  ([#997](https://github.com/nix-rust/nix/pull/997))
-+- Added `ptrace::{getregs, setregs}`.
-+  ([#1010](https://github.com/nix-rust/nix/pull/1010))
-+- Added `nix::sys::signal::signal`.
-+  ([#817](https://github.com/nix-rust/nix/pull/817))
-+- Added an `mprotect` wrapper.
-+  ([#991](https://github.com/nix-rust/nix/pull/991))
-+
-+### Changed
-+### Fixed
-+- `lutimes` never worked on OpenBSD as it is not implemented on OpenBSD. It has
-+  been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
-+- `fexecve` never worked on NetBSD or on OpenBSD as it is not implemented on
-+  either OS. It has been removed. ([#1000](https://github.com/nix-rust/nix/pull/1000))
-+
-+### Removed
-+
-+## [0.12.0] 2018-11-28
-+
-+### Added
-+- Added `FromStr` and `Display` impls for `nix::sys::Signal`
-+  ([#884](https://github.com/nix-rust/nix/pull/884))
-+- Added a `sync` wrapper.
-+  ([#961](https://github.com/nix-rust/nix/pull/961))
-+- Added a `sysinfo` wrapper.
-+  ([#922](https://github.com/nix-rust/nix/pull/922))
-+- Support the `SO_PEERCRED` socket option and the `UnixCredentials` type on all Linux and Android targets.
-+  ([#921](https://github.com/nix-rust/nix/pull/921))
-+- Added support for `SCM_CREDENTIALS`, allowing to send process credentials over Unix sockets.
-+  ([#923](https://github.com/nix-rust/nix/pull/923))
-+- Added a `dir` module for reading directories (wraps `fdopendir`, `readdir`, and `rewinddir`).
-+  ([#916](https://github.com/nix-rust/nix/pull/916))
-+- Added `kmod` module that allows loading and unloading kernel modules on Linux.
-+  ([#930](https://github.com/nix-rust/nix/pull/930))
-+- Added `futimens` and `utimesat` wrappers ([#944](https://github.com/nix-rust/nix/pull/944)),
-+  an `lutimes` wrapper ([#967](https://github.com/nix-rust/nix/pull/967)),
-+  and a `utimes` wrapper ([#946](https://github.com/nix-rust/nix/pull/946)).
-+- Added `AF_UNSPEC` wrapper to `AddressFamily` ([#948](https://github.com/nix-rust/nix/pull/948))
-+- Added the `mode_t` public alias within `sys::stat`.
-+  ([#954](https://github.com/nix-rust/nix/pull/954))
-+- Added a `truncate` wrapper.
-+  ([#956](https://github.com/nix-rust/nix/pull/956))
-+- Added a `fchownat` wrapper.
-+  ([#955](https://github.com/nix-rust/nix/pull/955))
-+- Added support for `ptrace` on BSD operating systems ([#949](https://github.com/nix-rust/nix/pull/949))
-+- Added `ptrace` functions for reads and writes to tracee memory and ptrace kill
-+  ([#949](https://github.com/nix-rust/nix/pull/949)) ([#958](https://github.com/nix-rust/nix/pull/958))
-+- Added a `acct` wrapper module for enabling and disabling process accounting
-+  ([#952](https://github.com/nix-rust/nix/pull/952))
-+- Added the `time_t` and `suseconds_t` public aliases within `sys::time`.
-+  ([#968](https://github.com/nix-rust/nix/pull/968))
-+- Added `unistd::execvpe` for Haiku, Linux and OpenBSD
-+  ([#975](https://github.com/nix-rust/nix/pull/975))
-+- Added `Error::as_errno`.
-+  ([#977](https://github.com/nix-rust/nix/pull/977))
-+
-+### Changed
-+- Increased required Rust version to 1.24.1
-+  ([#900](https://github.com/nix-rust/nix/pull/900))
-+  ([#966](https://github.com/nix-rust/nix/pull/966))
-+
-+### Fixed
-+- Made `preadv` take immutable slice of IoVec.
-+  ([#914](https://github.com/nix-rust/nix/pull/914))
-+- Fixed passing multiple file descriptors over Unix Sockets.
-+  ([#918](https://github.com/nix-rust/nix/pull/918))
-+
-+### Removed
-+
-+## [0.11.0] 2018-06-01
-+
-+### Added
-+- Added `sendfile` on FreeBSD and Darwin.
-+  ([#901](https://github.com/nix-rust/nix/pull/901))
-+- Added `pselect`
-+  ([#894](https://github.com/nix-rust/nix/pull/894))
-+- Exposed `preadv` and `pwritev` on the BSDs.
-+  ([#883](https://github.com/nix-rust/nix/pull/883))
-+- Added `mlockall` and `munlockall`
-+  ([#876](https://github.com/nix-rust/nix/pull/876))
-+- Added `SO_MARK` on Linux.
-+  ([#873](https://github.com/nix-rust/nix/pull/873))
-+- Added safe support for nearly any buffer type in the `sys::aio` module.
-+  ([#872](https://github.com/nix-rust/nix/pull/872))
-+- Added `sys::aio::LioCb` as a wrapper for `libc::lio_listio`.
-+  ([#872](https://github.com/nix-rust/nix/pull/872))
-+- Added `unistd::getsid`
-+  ([#850](https://github.com/nix-rust/nix/pull/850))
-+- Added `alarm`. ([#830](https://github.com/nix-rust/nix/pull/830))
-+- Added interface flags `IFF_NO_PI, IFF_TUN, IFF_TAP` on linux-like systems.
-+  ([#853](https://github.com/nix-rust/nix/pull/853))
-+- Added `statvfs` module to all MacOS and Linux architectures.
-+  ([#832](https://github.com/nix-rust/nix/pull/832))
-+- Added `EVFILT_EMPTY`, `EVFILT_PROCDESC`, and `EVFILT_SENDFILE` on FreeBSD.
-+  ([#825](https://github.com/nix-rust/nix/pull/825))
-+- Exposed `termios::cfmakesane` on FreeBSD.
-+  ([#825](https://github.com/nix-rust/nix/pull/825))
-+- Exposed `MSG_CMSG_CLOEXEC` on *BSD.
-+  ([#825](https://github.com/nix-rust/nix/pull/825))
-+- Added `fchmod`, `fchmodat`.
-+  ([#857](https://github.com/nix-rust/nix/pull/857))
-+- Added `request_code_write_int!` on FreeBSD/DragonFlyBSD
-+  ([#833](https://github.com/nix-rust/nix/pull/833))
-+
-+### Changed
-+- `Display` and `Debug` for `SysControlAddr` now includes all fields.
-+  ([#837](https://github.com/nix-rust/nix/pull/837))
-+- `ioctl!` has been replaced with a family of `ioctl_*!` macros.
-+  ([#833](https://github.com/nix-rust/nix/pull/833))
-+- `io!`, `ior!`, `iow!`, and `iorw!` has been renamed to `request_code_none!`, `request_code_read!`,
-+  `request_code_write!`, and `request_code_readwrite!` respectively. These have also now been exposed
-+  in the documentation.
-+  ([#833](https://github.com/nix-rust/nix/pull/833))
-+- Enabled more `ptrace::Request` definitions for uncommon Linux platforms
-+  ([#892](https://github.com/nix-rust/nix/pull/892))
-+- Emulation of `FD_CLOEXEC` and `O_NONBLOCK` was removed from `socket()`, `accept4()`, and
-+  `socketpair()`.
-+  ([#907](https://github.com/nix-rust/nix/pull/907))
-+
-+### Fixed
-+- Fixed possible panics when using `SigAction::flags` on Linux
-+  ([#869](https://github.com/nix-rust/nix/pull/869))
-+- Properly exposed 460800 and 921600 baud rates on NetBSD
-+  ([#837](https://github.com/nix-rust/nix/pull/837))
-+- Fixed `ioctl_write_int!` on FreeBSD/DragonFlyBSD
-+  ([#833](https://github.com/nix-rust/nix/pull/833))
-+- `ioctl_write_int!` now properly supports passing a `c_ulong` as the parameter on Linux non-musl targets
-+  ([#833](https://github.com/nix-rust/nix/pull/833))
-+
-+### Removed
-+- Removed explicit support for the `bytes` crate from the `sys::aio` module.
-+  See `sys::aio::AioCb::from_boxed_slice` examples for alternatives.
-+  ([#872](https://github.com/nix-rust/nix/pull/872))
-+- Removed `sys::aio::lio_listio`.  Use `sys::aio::LioCb::listio` instead.
-+  ([#872](https://github.com/nix-rust/nix/pull/872))
-+- Removed emulated `accept4()` from macos, ios, and netbsd targets
-+  ([#907](https://github.com/nix-rust/nix/pull/907))
-+- Removed `IFF_NOTRAILERS` on OpenBSD, as it has been removed in OpenBSD 6.3
-+  ([#893](https://github.com/nix-rust/nix/pull/893))
-+
-+## [0.10.0] 2018-01-26
-+
-+### Added
-+- Added specialized wrapper: `sys::ptrace::step`
-+  ([#852](https://github.com/nix-rust/nix/pull/852))
-+- Added `AioCb::from_ptr` and `AioCb::from_mut_ptr`
-+  ([#820](https://github.com/nix-rust/nix/pull/820))
-+- Added specialized wrappers: `sys::ptrace::{traceme, syscall, cont, attach}`. Using the matching routines
-+  with `sys::ptrace::ptrace` is now deprecated.
-+- Added `nix::poll` module for all platforms
-+  ([#672](https://github.com/nix-rust/nix/pull/672))
-+- Added `nix::ppoll` function for FreeBSD and DragonFly
-+  ([#672](https://github.com/nix-rust/nix/pull/672))
-+- Added protocol families in `AddressFamily` enum.
-+  ([#647](https://github.com/nix-rust/nix/pull/647))
-+- Added the `pid()` method to `WaitStatus` for extracting the PID.
-+  ([#722](https://github.com/nix-rust/nix/pull/722))
-+- Added `nix::unistd:fexecve`.
-+  ([#727](https://github.com/nix-rust/nix/pull/727))
-+- Expose `uname()` on all platforms.
-+  ([#739](https://github.com/nix-rust/nix/pull/739))
-+- Expose `signalfd` module on Android as well.
-+  ([#739](https://github.com/nix-rust/nix/pull/739))
-+- Added `nix::sys::ptrace::detach`.
-+  ([#749](https://github.com/nix-rust/nix/pull/749))
-+- Added timestamp socket control message variant:
-+  `nix::sys::socket::ControlMessage::ScmTimestamp`
-+  ([#663](https://github.com/nix-rust/nix/pull/663))
-+- Added socket option variant that enables the timestamp socket
-+  control message: `nix::sys::socket::sockopt::ReceiveTimestamp`
-+  ([#663](https://github.com/nix-rust/nix/pull/663))
-+- Added more accessor methods for `AioCb`
-+  ([#773](https://github.com/nix-rust/nix/pull/773))
-+- Add `nix::sys::fallocate`
-+  ([#768](https:://github.com/nix-rust/nix/pull/768))
-+- Added `nix::unistd::mkfifo`.
-+  ([#602](https://github.com/nix-rust/nix/pull/774))
-+- Added `ptrace::Options::PTRACE_O_EXITKILL` on Linux and Android.
-+  ([#771](https://github.com/nix-rust/nix/pull/771))
-+- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}` on Linux
-+  ([#568](https://github.com/nix-rust/nix/pull/568))
-+- Added `nix::unistd::{getgroups, setgroups, getgrouplist, initgroups}`. ([#733](https://github.com/nix-rust/nix/pull/733))
-+- Added `nix::sys::socket::UnixAddr::as_abstract` on Linux and Android.
-+  ([#785](https://github.com/nix-rust/nix/pull/785))
-+- Added `nix::unistd::execveat` on Linux and Android.
-+  ([#800](https://github.com/nix-rust/nix/pull/800))
-+- Added the `from_raw()` method to `WaitStatus` for converting raw status values
-+  to `WaitStatus` independent of syscalls.
-+  ([#741](https://github.com/nix-rust/nix/pull/741))
-+- Added more standard trait implementations for various types.
-+  ([#814](https://github.com/nix-rust/nix/pull/814))
-+- Added `sigprocmask` to the signal module.
-+  ([#826](https://github.com/nix-rust/nix/pull/826))
-+- Added `nix::sys::socket::LinkAddr` on Linux and all bsdlike system.
-+  ([#813](https://github.com/nix-rust/nix/pull/813))
-+- Add socket options for `IP_TRANSPARENT` / `BIND_ANY`.
-+  ([#835](https://github.com/nix-rust/nix/pull/835))
-+
-+### Changed
-+- Exposed the `mqueue` module for all supported operating systems.
-+  ([#834](https://github.com/nix-rust/nix/pull/834))
-+- Use native `pipe2` on all BSD targets.  Users should notice no difference.
-+  ([#777](https://github.com/nix-rust/nix/pull/777))
-+- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
-+- Marked `sys::ptrace::ptrace` as `unsafe`.
-+- Changed function signature of `socket()` and `socketpair()`. The `protocol` argument
-+  has changed type from `c_int` to `SockProtocol`.
-+  It accepts a `None` value for default protocol that was specified with zero using `c_int`.
-+  ([#647](https://github.com/nix-rust/nix/pull/647))
-+- Made `select` easier to use, adding the ability to automatically calculate the `nfds` parameter using the new
-+  `FdSet::highest` ([#701](https://github.com/nix-rust/nix/pull/701))
-+- Exposed `unistd::setresuid` and `unistd::setresgid` on FreeBSD and OpenBSD
-+  ([#721](https://github.com/nix-rust/nix/pull/721))
-+- Refactored the `statvfs` module removing extraneous API functions and the
-+  `statvfs::vfs` module. Additionally  `(f)statvfs()` now return the struct
-+  directly. And the returned `Statvfs` struct now exposes its data through
-+  accessor methods. ([#729](https://github.com/nix-rust/nix/pull/729))
-+- The `addr` argument to `madvise` and `msync` is now `*mut` to better match the
-+  libc API. ([#731](https://github.com/nix-rust/nix/pull/731))
-+- `shm_open` and `shm_unlink` are no longer exposed on Android targets, where
-+  they are not officially supported. ([#731](https://github.com/nix-rust/nix/pull/731))
-+- `MapFlags`, `MmapAdvise`, and `MsFlags` expose some more variants and only
-+  officially-supported variants are provided for each target.
-+  ([#731](https://github.com/nix-rust/nix/pull/731))
-+- Marked `pty::ptsname` function as `unsafe`
-+  ([#744](https://github.com/nix-rust/nix/pull/744))
-+- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly.
-+  ([#749](https://github.com/nix-rust/nix/pull/749))
-+- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#715](https://github.com/nix-rust/nix/pull/715))
-+- Restricted `nix::sys::socket::UnixAddr::new_abstract` to Linux and Android only.
-+  ([#785](https://github.com/nix-rust/nix/pull/785))
-+- The `ucred` struct has been removed in favor of a `UserCredentials` struct that
-+  contains only getters for its fields.
-+  ([#814](https://github.com/nix-rust/nix/pull/814))
-+- Both `ip_mreq` and `ipv6_mreq` have been replaced with `IpMembershipRequest` and
-+  `Ipv6MembershipRequest`.
-+  ([#814](https://github.com/nix-rust/nix/pull/814))
-+- Removed return type from `pause`.
-+  ([#829](https://github.com/nix-rust/nix/pull/829))
-+- Changed the termios APIs to allow for using a `u32` instead of the `BaudRate`
-+  enum on BSD platforms to support arbitrary baud rates. See the module docs for
-+  `nix::sys::termios` for more details.
-+  ([#843](https://github.com/nix-rust/nix/pull/843))
-+
-+### Fixed
-+- Fix compilation and tests for OpenBSD targets
-+  ([#688](https://github.com/nix-rust/nix/pull/688))
-+- Fixed error handling in `AioCb::fsync`, `AioCb::read`, and `AioCb::write`.
-+  It is no longer an error to drop an `AioCb` that failed to enqueue in the OS.
-+  ([#715](https://github.com/nix-rust/nix/pull/715))
-+- Fix potential memory corruption on non-Linux platforms when using
-+  `sendmsg`/`recvmsg`, caused by mismatched `msghdr` definition.
-+  ([#648](https://github.com/nix-rust/nix/pull/648))
-+
-+### Removed
-+- `AioCb::from_boxed_slice` has been removed.  It was never actually safe.  Use
-+  `from_bytes` or `from_bytes_mut` instead.
-+  ([#820](https://github.com/nix-rust/nix/pull/820))
-+- The syscall module has been removed. This only exposed enough functionality for
-+  `memfd_create()` and `pivot_root()`, which are still exposed as separate functions.
-+  ([#747](https://github.com/nix-rust/nix/pull/747))
-+- The `Errno` variants are no longer reexported from the `errno` module. `Errno` itself is no longer reexported from the
-+  crate root and instead must be accessed using the `errno` module. ([#696](https://github.com/nix-rust/nix/pull/696))
-+- Removed `MS_VERBOSE`, `MS_NOSEC`, and `MS_BORN` from `MsFlags`. These
-+  are internal kernel flags and should never have been exposed.
-+  ([#814](https://github.com/nix-rust/nix/pull/814))
-+
-+
-+## [0.9.0] 2017-07-23
-+
-+### Added
-+- Added `sysconf`, `pathconf`, and `fpathconf`
-+  ([#630](https://github.com/nix-rust/nix/pull/630)
-+- Added `sys::signal::SigAction::{ flags, mask, handler}`
-+  ([#611](https://github.com/nix-rust/nix/pull/609)
-+- Added `nix::sys::pthread::pthread_self`
-+  ([#591](https://github.com/nix-rust/nix/pull/591)
-+- Added `AioCb::from_boxed_slice`
-+  ([#582](https://github.com/nix-rust/nix/pull/582)
-+- Added `nix::unistd::{openat, fstatat, readlink, readlinkat}`
-+  ([#551](https://github.com/nix-rust/nix/pull/551))
-+- Added `nix::pty::{grantpt, posix_openpt, ptsname/ptsname_r, unlockpt}`
-+  ([#556](https://github.com/nix-rust/nix/pull/556)
-+- Added `nix::ptr::openpty`
-+  ([#456](https://github.com/nix-rust/nix/pull/456))
-+- Added `nix::ptrace::{ptrace_get_data, ptrace_getsiginfo, ptrace_setsiginfo
-+  and nix::Error::UnsupportedOperation}`
-+  ([#614](https://github.com/nix-rust/nix/pull/614))
-+- Added `cfmakeraw`, `cfsetspeed`, and `tcgetsid`. ([#527](https://github.com/nix-rust/nix/pull/527))
-+- Added "bad none", "bad write_ptr", "bad write_int", and "bad readwrite" variants to the `ioctl!`
-+  macro. ([#670](https://github.com/nix-rust/nix/pull/670))
-+- On Linux and Android, added support for receiving `PTRACE_O_TRACESYSGOOD`
-+  events from `wait` and `waitpid` using `WaitStatus::PtraceSyscall`
-+  ([#566](https://github.com/nix-rust/nix/pull/566)).
-+
-+### Changed
-+- The `ioctl!` macro and its variants now allow the generated functions to have
-+  doccomments. ([#661](https://github.com/nix-rust/nix/pull/661))
-+- Changed `ioctl!(write ...)` into `ioctl!(write_ptr ...)` and `ioctl!(write_int ..)` variants
-+  to more clearly separate those use cases. ([#670](https://github.com/nix-rust/nix/pull/670))
-+- Marked `sys::mman::{ mmap, munmap, madvise, munlock, msync }` as unsafe.
-+  ([#559](https://github.com/nix-rust/nix/pull/559))
-+- Minimum supported Rust version is now 1.13.
-+- Removed `revents` argument from `PollFd::new()` as it's an output argument and
-+  will be overwritten regardless of value.
-+  ([#542](https://github.com/nix-rust/nix/pull/542))
-+- Changed type signature of `sys::select::FdSet::contains` to make `self`
-+  immutable ([#564](https://github.com/nix-rust/nix/pull/564))
-+- Introduced wrapper types for `gid_t`, `pid_t`, and `uid_t` as `Gid`, `Pid`, and `Uid`
-+  respectively. Various functions have been changed to use these new types as
-+  arguments. ([#629](https://github.com/nix-rust/nix/pull/629))
-+- Fixed compilation on all Android and iOS targets ([#527](https://github.com/nix-rust/nix/pull/527))
-+  and promoted them to Tier 2 support.
-+- `nix::sys::statfs::{statfs,fstatfs}` uses statfs definition from `libc::statfs` instead of own linux specific type `nix::sys::Statfs`.
-+  Also file system type constants like `nix::sys::statfs::ADFS_SUPER_MAGIC` were removed in favor of the libc equivalent.
-+  ([#561](https://github.com/nix-rust/nix/pull/561))
-+- Revised the termios API including additional tests and documentation and exposed it on iOS. ([#527](https://github.com/nix-rust/nix/pull/527))
-+- `eventfd`, `signalfd`, and `pwritev`/`preadv` functionality is now included by default for all
-+  supported platforms. ([#681](https://github.com/nix-rust/nix/pull/561))
-+- The `ioctl!` macro's plain variants has been replaced with "bad read" to be consistent with
-+  other variants. The generated functions also have more strict types for their arguments. The
-+  "*_buf" variants also now calculate total array size and take slice references for improved type
-+  safety. The documentation has also been dramatically improved.
-+  ([#670](https://github.com/nix-rust/nix/pull/670))
-+
-+### Removed
-+- Removed `io::Error` from `nix::Error` and the conversion from `nix::Error` to `Errno`
-+  ([#614](https://github.com/nix-rust/nix/pull/614))
-+- All feature flags have been removed in favor of conditional compilation on supported platforms.
-+  `execvpe` is no longer supported, but this was already broken and will be added back in the next
-+  release. ([#681](https://github.com/nix-rust/nix/pull/561))
-+- Removed `ioc_*` functions and many helper constants and macros within the `ioctl` module. These
-+  should always have been private and only the `ioctl!` should be used in public code.
-+  ([#670](https://github.com/nix-rust/nix/pull/670))
-+
-+### Fixed
-+- Fixed multiple issues compiling under different archetectures and OSes.
-+  Now compiles on Linux/MIPS ([#538](https://github.com/nix-rust/nix/pull/538)),
-+  `Linux/PPC` ([#553](https://github.com/nix-rust/nix/pull/553)),
-+  `MacOS/x86_64,i686` ([#553](https://github.com/nix-rust/nix/pull/553)),
-+  `NetBSD/x64_64` ([#538](https://github.com/nix-rust/nix/pull/538)),
-+  `FreeBSD/x86_64,i686` ([#536](https://github.com/nix-rust/nix/pull/536)), and
-+  `Android` ([#631](https://github.com/nix-rust/nix/pull/631)).
-+- `bind` and `errno_location` now work correctly on `Android`
-+  ([#631](https://github.com/nix-rust/nix/pull/631))
-+- Added `nix::ptrace` on all Linux-kernel-based platforms
-+  [#624](https://github.com/nix-rust/nix/pull/624). Previously it was
-+  only available on x86, x86-64, and ARM, and also not on Android.
-+- Fixed `sys::socket::sendmsg` with zero entry `cmsgs` parameter.
-+  ([#623](https://github.com/nix-rust/nix/pull/623))
-+- Multiple constants related to the termios API have now been properly defined for
-+  all supported platforms. ([#527](https://github.com/nix-rust/nix/pull/527))
-+- `ioctl!` macro now supports working with non-int datatypes and properly supports all platforms.
-+  ([#670](https://github.com/nix-rust/nix/pull/670))
-+
-+## [0.8.1] 2017-04-16
-+
-+### Fixed
-+- Fixed build on FreeBSD. (Cherry-picked
-+  [a859ee3c](https://github.com/nix-rust/nix/commit/a859ee3c9396dfdb118fcc2c8ecc697e2d303467))
-+
-+## [0.8.0] 2017-03-02
-+
-+### Added
-+- Added `::nix::sys::termios::BaudRate` enum to provide portable baudrate
-+  values. ([#518](https://github.com/nix-rust/nix/pull/518))
-+- Added a new `WaitStatus::PtraceEvent` to support ptrace events on Linux
-+  and Android ([#438](https://github.com/nix-rust/nix/pull/438))
-+- Added support for POSIX AIO
-+  ([#483](https://github.com/nix-rust/nix/pull/483))
-+  ([#506](https://github.com/nix-rust/nix/pull/506))
-+- Added support for XNU system control sockets
-+  ([#478](https://github.com/nix-rust/nix/pull/478))
-+- Added support for `ioctl` calls on BSD platforms
-+  ([#478](https://github.com/nix-rust/nix/pull/478))
-+- Added struct `TimeSpec`
-+  ([#475](https://github.com/nix-rust/nix/pull/475))
-+  ([#483](https://github.com/nix-rust/nix/pull/483))
-+- Added complete definitions for all kqueue-related constants on all supported
-+  OSes
-+  ([#415](https://github.com/nix-rust/nix/pull/415))
-+- Added function `epoll_create1` and bitflags `EpollCreateFlags` in
-+  `::nix::sys::epoll` in order to support `::libc::epoll_create1`.
-+  ([#410](https://github.com/nix-rust/nix/pull/410))
-+- Added `setresuid` and `setresgid` for Linux in `::nix::unistd`
-+  ([#448](https://github.com/nix-rust/nix/pull/448))
-+- Added `getpgid` in `::nix::unistd`
-+  ([#433](https://github.com/nix-rust/nix/pull/433))
-+- Added `tcgetpgrp` and `tcsetpgrp` in `::nix::unistd`
-+  ([#451](https://github.com/nix-rust/nix/pull/451))
-+- Added `CLONE_NEWCGROUP` in `::nix::sched`
-+  ([#457](https://github.com/nix-rust/nix/pull/457))
-+- Added `getpgrp` in `::nix::unistd`
-+  ([#491](https://github.com/nix-rust/nix/pull/491))
-+- Added `fchdir` in `::nix::unistd`
-+  ([#497](https://github.com/nix-rust/nix/pull/497))
-+- Added `major` and `minor` in `::nix::sys::stat` for decomposing `dev_t`
-+  ([#508](https://github.com/nix-rust/nix/pull/508))
-+- Fixed the style of many bitflags and use `libc` in more places.
-+  ([#503](https://github.com/nix-rust/nix/pull/503))
-+- Added `ppoll` in `::nix::poll`
-+  ([#520](https://github.com/nix-rust/nix/pull/520))
-+- Added support for getting and setting pipe size with fcntl(2) on Linux
-+  ([#540](https://github.com/nix-rust/nix/pull/540))
-+
-+### Changed
-+- `::nix::sys::termios::{cfgetispeed, cfsetispeed, cfgetospeed, cfsetospeed}`
-+  switched  to use `BaudRate` enum from `speed_t`.
-+  ([#518](https://github.com/nix-rust/nix/pull/518))
-+- `epoll_ctl` now could accept None as argument `event`
-+  when op is `EpollOp::EpollCtlDel`.
-+  ([#480](https://github.com/nix-rust/nix/pull/480))
-+- Removed the `bad` keyword from the `ioctl!` macro
-+  ([#478](https://github.com/nix-rust/nix/pull/478))
-+- Changed `TimeVal` into an opaque Newtype
-+  ([#475](https://github.com/nix-rust/nix/pull/475))
-+- `kill`'s signature, defined in `::nix::sys::signal`, changed, so that the
-+  signal parameter has type `T: Into<Option<Signal>>`. `None` as an argument
-+  for that parameter will result in a 0 passed to libc's `kill`, while a
-+  `Some`-argument will result in the previous behavior for the contained
-+  `Signal`.
-+  ([#445](https://github.com/nix-rust/nix/pull/445))
-+- The minimum supported version of rustc is now 1.7.0.
-+  ([#444](https://github.com/nix-rust/nix/pull/444))
-+- Changed `KEvent` to an opaque structure that may only be modified by its
-+  constructor and the `ev_set` method.
-+  ([#415](https://github.com/nix-rust/nix/pull/415))
-+  ([#442](https://github.com/nix-rust/nix/pull/442))
-+  ([#463](https://github.com/nix-rust/nix/pull/463))
-+- `pipe2` now calls `libc::pipe2` where available. Previously it was emulated
-+  using `pipe`, which meant that setting `O_CLOEXEC` was not atomic.
-+  ([#427](https://github.com/nix-rust/nix/pull/427))
-+- Renamed `EpollEventKind` to `EpollFlags` in `::nix::sys::epoll` in order for
-+  it to conform with our conventions.
-+  ([#410](https://github.com/nix-rust/nix/pull/410))
-+- `EpollEvent` in `::nix::sys::epoll` is now an opaque proxy for
-+  `::libc::epoll_event`. The formerly public field `events` is now be read-only
-+  accessible with the new method `events()` of `EpollEvent`. Instances of
-+  `EpollEvent` can be constructed using the new method `new()` of EpollEvent.
-+  ([#410](https://github.com/nix-rust/nix/pull/410))
-+- `SigFlags` in `::nix::sys::signal` has be renamed to `SigmaskHow` and its type
-+  has changed from `bitflags` to `enum` in order to conform to our conventions.
-+  ([#460](https://github.com/nix-rust/nix/pull/460))
-+- `sethostname` now takes a `&str` instead of a `&[u8]` as this provides an API
-+  that makes more sense in normal, correct usage of the API.
-+- `gethostname` previously did not expose the actual length of the hostname
-+  written from the underlying system call at all.  This has been updated to
-+  return a `&CStr` within the provided buffer that is always properly
-+  NUL-terminated (this is not guaranteed by the call with all platforms/libc
-+  implementations).
-+- Exposed all fcntl(2) operations at the module level, so they can be
-+  imported direclty instead of via `FcntlArg` enum.
-+  ([#541](https://github.com/nix-rust/nix/pull/541))
-+
-+### Fixed
-+- Fixed multiple issues with Unix domain sockets on non-Linux OSes
-+  ([#474](https://github.com/nix-rust/nix/pull/415))
-+- Fixed using kqueue with `EVFILT_USER` on FreeBSD
-+  ([#415](https://github.com/nix-rust/nix/pull/415))
-+- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
-+  functions on that same OS.
-+  ([#397](https://github.com/nix-rust/nix/pull/397))
-+- Fixed an off-by-one bug in `UnixAddr::new_abstract` in `::nix::sys::socket`.
-+  ([#429](https://github.com/nix-rust/nix/pull/429))
-+- Fixed clone passing a potentially unaligned stack.
-+  ([#490](https://github.com/nix-rust/nix/pull/490))
-+- Fixed mkdev not creating a `dev_t` the same way as libc.
-+  ([#508](https://github.com/nix-rust/nix/pull/508))
-+
-+## [0.7.0] 2016-09-09
-+
-+### Added
-+- Added `lseek` and `lseek64` in `::nix::unistd`
-+  ([#377](https://github.com/nix-rust/nix/pull/377))
-+- Added `mkdir` and `getcwd` in `::nix::unistd`
-+  ([#416](https://github.com/nix-rust/nix/pull/416))
-+- Added accessors `sigmask_mut` and `sigmask` to `UContext` in
-+  `::nix::ucontext`.
-+  ([#370](https://github.com/nix-rust/nix/pull/370))
-+- Added `WUNTRACED` to `WaitPidFlag` in `::nix::sys::wait` for non-_linux_
-+  targets.
-+  ([#379](https://github.com/nix-rust/nix/pull/379))
-+- Added new module `::nix::sys::reboot` with enumeration `RebootMode` and
-+  functions `reboot` and `set_cad_enabled`. Currently for _linux_ only.
-+  ([#386](https://github.com/nix-rust/nix/pull/386))
-+- `FdSet` in `::nix::sys::select` now also implements `Clone`.
-+  ([#405](https://github.com/nix-rust/nix/pull/405))
-+- Added `F_FULLFSYNC` to `FcntlArg` in `::nix::fcntl` for _apple_ targets.
-+  ([#407](https://github.com/nix-rust/nix/pull/407))
-+- Added `CpuSet::unset` in `::nix::sched`.
-+  ([#402](https://github.com/nix-rust/nix/pull/402))
-+- Added constructor method `new()` to `PollFd` in `::nix::poll`, in order to
-+  allow creation of objects, after removing public access to members.
-+  ([#399](https://github.com/nix-rust/nix/pull/399))
-+- Added method `revents()` to `PollFd` in `::nix::poll`, in order to provide
-+  read access to formerly public member `revents`.
-+  ([#399](https://github.com/nix-rust/nix/pull/399))
-+- Added `MSG_CMSG_CLOEXEC` to `MsgFlags` in `::nix::sys::socket` for _linux_ only.
-+  ([#422](https://github.com/nix-rust/nix/pull/422))
-+
-+### Changed
-+- Replaced the reexported integer constants for signals by the enumeration
-+  `Signal` in `::nix::sys::signal`.
-+  ([#362](https://github.com/nix-rust/nix/pull/362))
-+- Renamed `EventFdFlag` to `EfdFlags` in `::nix::sys::eventfd`.
-+  ([#383](https://github.com/nix-rust/nix/pull/383))
-+- Changed the result types of `CpuSet::is_set` and `CpuSet::set` in
-+  `::nix::sched` to `Result<bool>` and `Result<()>`, respectively. They now
-+  return `EINVAL`, if an invalid argument for the `field` parameter is passed.
-+  ([#402](https://github.com/nix-rust/nix/pull/402))
-+- `MqAttr` in `::nix::mqueue` is now an opaque proxy for `::libc::mq_attr`,
-+  which has the same structure as the old `MqAttr`. The field `mq_flags` of
-+  `::libc::mq_attr` is readable using the new method `flags()` of `MqAttr`.
-+  `MqAttr` also no longer implements `Debug`.
-+  ([#392](https://github.com/nix-rust/nix/pull/392))
-+- The parameter `msq_prio` of `mq_receive` with type `u32` in `::nix::mqueue`
-+  was replaced by a parameter named `msg_prio` with type `&mut u32`, so that
-+  the message priority can be obtained by the caller.
-+  ([#392](https://github.com/nix-rust/nix/pull/392))
-+- The type alias `MQd` in `::nix::queue` was replaced by the type alias
-+  `libc::mqd_t`, both of which are aliases for the same type.
-+  ([#392](https://github.com/nix-rust/nix/pull/392))
-+
-+### Removed
-+- Type alias `SigNum` from `::nix::sys::signal`.
-+  ([#362](https://github.com/nix-rust/nix/pull/362))
-+- Type alias `CpuMask` from `::nix::shed`.
-+  ([#402](https://github.com/nix-rust/nix/pull/402))
-+- Removed public fields from `PollFd` in `::nix::poll`. (See also added method
-+  `revents()`.
-+  ([#399](https://github.com/nix-rust/nix/pull/399))
-+
-+### Fixed
-+- Fixed the build problem for NetBSD (Note, that we currently do not support
-+  it, so it might already be broken again).
-+  ([#389](https://github.com/nix-rust/nix/pull/389))
-+- Fixed the build on FreeBSD, and fixed the getsockopt, sendmsg, and recvmsg
-+  functions on that same OS.
-+  ([#397](https://github.com/nix-rust/nix/pull/397))
-+
-+## [0.6.0] 2016-06-10
-+
-+### Added
-+- Added `gettid` in `::nix::unistd` for _linux_ and _android_.
-+  ([#293](https://github.com/nix-rust/nix/pull/293))
-+- Some _mips_ support in `::nix::sched` and `::nix::sys::syscall`.
-+  ([#301](https://github.com/nix-rust/nix/pull/301))
-+- Added `SIGNALFD_SIGINFO_SIZE` in `::nix::sys::signalfd`.
-+  ([#309](https://github.com/nix-rust/nix/pull/309))
-+- Added new module `::nix::ucontext` with struct `UContext`. Currently for
-+  _linux_ only.
-+  ([#311](https://github.com/nix-rust/nix/pull/311))
-+- Added `EPOLLEXCLUSIVE` to `EpollEventKind` in `::nix::sys::epoll`.
-+  ([#330](https://github.com/nix-rust/nix/pull/330))
-+- Added `pause` to `::nix::unistd`.
-+  ([#336](https://github.com/nix-rust/nix/pull/336))
-+- Added `sleep` to `::nix::unistd`.
-+  ([#351](https://github.com/nix-rust/nix/pull/351))
-+- Added `S_IFDIR`, `S_IFLNK`, `S_IFMT` to `SFlag` in `::nix::sys::stat`.
-+  ([#359](https://github.com/nix-rust/nix/pull/359))
-+- Added `clear` and `extend` functions to `SigSet`'s implementation in
-+  `::nix::sys::signal`.
-+  ([#347](https://github.com/nix-rust/nix/pull/347))
-+- `sockaddr_storage_to_addr` in `::nix::sys::socket` now supports `sockaddr_nl`
-+  on _linux_ and _android_.
-+  ([#366](https://github.com/nix-rust/nix/pull/366))
-+- Added support for `SO_ORIGINAL_DST` in `::nix::sys::socket` on _linux_.
-+  ([#367](https://github.com/nix-rust/nix/pull/367))
-+- Added `SIGINFO` in `::nix::sys::signal` for the _macos_ target as well as
-+  `SIGPWR` and `SIGSTKFLT` in `::nix::sys::signal` for non-_macos_ targets.
-+  ([#361](https://github.com/nix-rust/nix/pull/361))
-+
-+### Changed
-+- Changed the structure `IoVec` in `::nix::sys::uio`.
-+  ([#304](https://github.com/nix-rust/nix/pull/304))
-+- Replaced `CREATE_NEW_FD` by `SIGNALFD_NEW` in `::nix::sys::signalfd`.
-+  ([#309](https://github.com/nix-rust/nix/pull/309))
-+- Renamed `SaFlag` to `SaFlags` and `SigFlag` to `SigFlags` in
-+  `::nix::sys::signal`.
-+  ([#314](https://github.com/nix-rust/nix/pull/314))
-+- Renamed `Fork` to `ForkResult` and changed its fields in `::nix::unistd`.
-+  ([#332](https://github.com/nix-rust/nix/pull/332))
-+- Added the `signal` parameter to `clone`'s signature in `::nix::sched`.
-+  ([#344](https://github.com/nix-rust/nix/pull/344))
-+- `execv`, `execve`, and `execvp` now return `Result<Void>` instead of
-+  `Result<()>` in `::nix::unistd`.
-+  ([#357](https://github.com/nix-rust/nix/pull/357))
-+
-+### Fixed
-+- Improved the conversion from `std::net::SocketAddr` to `InetAddr` in
-+  `::nix::sys::socket::addr`.
-+  ([#335](https://github.com/nix-rust/nix/pull/335))
-+
-+## [0.5.0] 2016-03-01
-diff --git a/third_party/rust/nix-0.15.0/CONTRIBUTING.md b/third_party/rust/nix-0.15.0/CONTRIBUTING.md
-new file mode 100644
-index 0000000000000..03a1f630dbb06
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/CONTRIBUTING.md
-@@ -0,0 +1,114 @@
-+# Contributing to nix
-+
-+We're really glad you're interested in contributing to nix! This
-+document has a few pointers and guidelines to help get you started.
-+
-+To have a welcoming and inclusive project, nix uses the Rust project's
-+[Code of Conduct][conduct]. All contributors are expected to follow it.
-+
-+[conduct]: https://www.rust-lang.org/conduct.html
-+
-+
-+# Issues
-+
-+We use GitHub's [issue tracker][issues].
-+
-+[issues]: https://github.com/nix-rust/nix/issues
-+
-+
-+## Bug reports
-+
-+Before submitting a new bug report, please [search existing
-+issues][issue-search] to see if there's something related. If not, just
-+[open a new issue][new-issue]!
-+
-+As a reminder, the more information you can give in your issue, the
-+easier it is to figure out how to fix it. For nix, this will likely
-+include the OS and version, and the architecture.
-+
-+[issue-search]: https://github.com/nix-rust/nix/search?utf8=%E2%9C%93&q=is%3Aissue&type=Issues
-+[new-issue]: https://github.com/nix-rust/nix/issues/new
-+
-+
-+## Feature / API requests
-+
-+If you'd like a new API or feature added, please [open a new
-+issue][new-issue] requesting it. As with reporting a bug, the more
-+information you can provide, the better.
-+
-+
-+## Labels
-+
-+We use labels to help manage issues. The structure is modeled after
-+[Rust's issue labeling scheme][rust-labels]:
-+- **A-**prefixed labels state which area of the project the issue
-+  relates to
-+- **E-**prefixed labels explain the level of experience necessary to fix the
-+  issue
-+- **O-**prefixed labels specify the OS for issues that are OS-specific
-+- **R-**prefixed labels specify the architecture for issues that are
-+  architecture-specific
-+
-+[rust-labels]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#issue-triage
-+
-+
-+# Pull requests
-+
-+GitHub pull requests are the primary mechanism we use to change nix. GitHub itself has
-+some [great documentation][pr-docs] on using the Pull Request feature. We use the 'fork and
-+pull' model described there.
-+
-+Please make pull requests against the `master` branch.
-+
-+If you change the API by way of adding, removing or changing something or if
-+you fix a bug, please add an appropriate note to the [change log][cl]. We
-+follow the conventions of [Keep A CHANGELOG][kacl].
-+
-+[cl]: https://github.com/nix-rust/nix/blob/master/CHANGELOG.md
-+[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
-+[pr-docs]: https://help.github.com/articles/using-pull-requests/
-+
-+## Testing
-+
-+nix has a test suite that you can run with `cargo test`. Ideally, we'd like pull
-+requests to include tests where they make sense. For example, when fixing a bug,
-+add a test that would have failed without the fix.
-+
-+After you've made your change, make sure the tests pass in your development
-+environment. We also have [continuous integration set up on
-+Travis-CI][travis-ci], which might find some issues on other platforms. The CI
-+will run once you open a pull request.
-+
-+There is also infrastructure for running tests for other targets
-+locally.  More information is available in the [CI Readme][ci-readme].
-+
-+[travis-ci]: https://travis-ci.org/nix-rust/nix
-+[ci-readme]: ci/README.md
-+
-+### Disabling a test in the CI environment
-+
-+Sometimes there are features that cannot be tested in the CI environment.
-+To stop a test from running under CI, add `#[cfg_attr(travis, ignore)]`
-+to it. Please include a comment describing the reason it shouldn't run
-+under CI, and a link to an upstream issue if possible!
-+
-+## bors, the bot who merges all the PRs
-+
-+All pull requests are merged via [bors], an integration bot. After the
-+pull request has been reviewed, the reviewer will leave a comment like
-+
-+> bors r+
-+
-+to let bors know that it was approved. Then bors will check that it passes
-+tests when merged with the latest changes in the `master` branch, and
-+merge if the tests succeed.
-+
-+[bors]: https://bors-ng.github.io/
-+
-+
-+## API conventions
-+
-+If you're adding a new API, we have a [document with
-+conventions][conventions] to use throughout the nix project.
-+
-+[conventions]: https://github.com/nix-rust/nix/blob/master/CONVENTIONS.md
-diff --git a/third_party/rust/nix-0.15.0/CONVENTIONS.md b/third_party/rust/nix-0.15.0/CONVENTIONS.md
-new file mode 100644
-index 0000000000000..48daa937345d2
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/CONVENTIONS.md
-@@ -0,0 +1,87 @@
-+# Conventions
-+
-+In order to achieve our goal of wrapping [libc][libc] code in idiomatic rust
-+constructs with minimal performance overhead, we follow the following
-+conventions.
-+
-+Note that, thus far, not all the code follows these conventions and not all
-+conventions we try to follow have been documented here. If you find an instance
-+of either, feel free to remedy the flaw by opening a pull request with
-+appropriate changes or additions.
-+
-+## Change Log
-+
-+We follow the conventions laid out in [Keep A CHANGELOG][kacl].
-+
-+[kacl]: https://github.com/olivierlacan/keep-a-changelog/tree/18adb5f5be7a898d046f6a4acb93e39dcf40c4ad
-+
-+## libc constants, functions and structs
-+
-+We do not define integer constants ourselves, but use or reexport them from the
-+[libc crate][libc].
-+
-+We use the functions exported from [libc][libc] instead of writing our own
-+`extern` declarations.
-+
-+We use the `struct` definitions from [libc][libc] internally instead of writing
-+our own. If we want to add methods to a libc type, we use the newtype pattern.
-+For example,
-+
-+```rust
-+pub struct SigSet(libc::sigset_t);
-+
-+impl SigSet {
-+    ...
-+}
-+```
-+
-+When creating newtypes, we use Rust's `CamelCase` type naming convention.
-+
-+## Bitflags
-+
-+Many C functions have flags parameters that are combined from constants using
-+bitwise operations. We represent the types of these parameters by types defined
-+using our `libc_bitflags!` macro, which is a convenience wrapper around the
-+`bitflags!` macro from the [bitflags crate][bitflags] that brings in the
-+constant value from `libc`.
-+
-+We name the type for a set of constants whose element's names start with `FOO_`
-+`FooFlags`.
-+
-+For example,
-+
-+```rust
-+libc_bitflags!{
-+    pub struct ProtFlags: libc::c_int {
-+        PROT_NONE;
-+        PROT_READ;
-+        PROT_WRITE;
-+        PROT_EXEC;
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        PROT_GROWSDOWN;
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        PROT_GROWSUP;
-+    }
-+}
-+```
-+
-+
-+## Enumerations
-+
-+We represent sets of constants that are intended as mutually exclusive arguments
-+to parameters of functions by [enumerations][enum].
-+
-+
-+## Structures Initialized by libc Functions
-+
-+Whenever we need to use a [libc][libc] function to properly initialize a
-+variable and said function allows us to use uninitialized memory, we use
-+[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized])
-+when defining the variable. This allows us to avoid the overhead incurred by
-+zeroing or otherwise initializing the variable.
-+
-+[bitflags]: https://crates.io/crates/bitflags/
-+[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html
-+[enum]: https://doc.rust-lang.org/reference.html#enumerations
-+[libc]: https://crates.io/crates/libc/
-+[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
-diff --git a/third_party/rust/nix-0.15.0/Cargo.toml b/third_party/rust/nix-0.15.0/Cargo.toml
-new file mode 100644
-index 0000000000000..555b99020d68f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/Cargo.toml
-@@ -0,0 +1,71 @@
-+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-+#
-+# When uploading crates to the registry Cargo will automatically
-+# "normalize" Cargo.toml files for maximal compatibility
-+# with all versions of Cargo and also rewrite `path` dependencies
-+# to registry (e.g., crates.io) dependencies
-+#
-+# If you believe there's an error in this file please file an
-+# issue against the rust-lang/cargo repository. If you're
-+# editing this file be aware that the upstream Cargo.toml
-+# will likely look very different (and much more reasonable)
-+
-+[package]
-+name = "nix"
-+version = "0.15.0"
-+authors = ["The nix-rust Project Developers"]
-+exclude = ["/.gitignore", "/.travis.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
-+description = "Rust friendly bindings to *nix APIs"
-+categories = ["os::unix-apis"]
-+license = "MIT"
-+repository = "https://github.com/nix-rust/nix"
-+
-+[[test]]
-+name = "test"
-+path = "test/test.rs"
-+
-+[[test]]
-+name = "test-aio-drop"
-+path = "test/sys/test_aio_drop.rs"
-+
-+[[test]]
-+name = "test-lio-listio-resubmit"
-+path = "test/sys/test_lio_listio_resubmit.rs"
-+
-+[[test]]
-+name = "test-mount"
-+path = "test/test_mount.rs"
-+harness = false
-+
-+[[test]]
-+name = "test-ptymaster-drop"
-+path = "test/test_ptymaster_drop.rs"
-+[dependencies.bitflags]
-+version = "1.0"
-+
-+[dependencies.cfg-if]
-+version = "0.1.2"
-+
-+[dependencies.libc]
-+version = "0.2.60"
-+features = ["extra_traits"]
-+
-+[dependencies.void]
-+version = "1.0.2"
-+[dev-dependencies.bytes]
-+version = "0.4.8"
-+
-+[dev-dependencies.lazy_static]
-+version = "1.2"
-+
-+[dev-dependencies.rand]
-+version = ">= 0.6, < 0.7"
-+
-+[dev-dependencies.tempfile]
-+version = ">= 3.0.5, < 3.0.9"
-+[target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
-+version = "0.3.1"
-+[target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
-+version = "1"
-+[target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
-+version = "0.1"
-diff --git a/third_party/rust/nix-0.15.0/LICENSE b/third_party/rust/nix-0.15.0/LICENSE
-new file mode 100644
-index 0000000000000..aff9096fdf11d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/LICENSE
-@@ -0,0 +1,21 @@
-+The MIT License (MIT)
-+
-+Copyright (c) 2015 Carl Lerche + nix-rust Authors
-+
-+Permission is hereby granted, free of charge, to any person obtaining a copy
-+of this software and associated documentation files (the "Software"), to deal
-+in the Software without restriction, including without limitation the rights
-+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-+copies of the Software, and to permit persons to whom the Software is
-+furnished to do so, subject to the following conditions:
-+
-+The above copyright notice and this permission notice shall be included in
-+all copies or substantial portions of the Software.
-+
-+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-+THE SOFTWARE.
-diff --git a/third_party/rust/nix-0.15.0/README.md b/third_party/rust/nix-0.15.0/README.md
-new file mode 100644
-index 0000000000000..0e540ba5b968e
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/README.md
-@@ -0,0 +1,111 @@
-+# Rust bindings to *nix APIs
-+
-+[![Build Status](https://travis-ci.org/nix-rust/nix.svg?branch=master)](https://travis-ci.org/nix-rust/nix)
-+[![crates.io](http://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
-+
-+[Documentation (Releases)](https://docs.rs/nix/)
-+
-+Nix seeks to provide friendly bindings to various *nix platform APIs (Linux, Darwin,
-+...). The goal is to not provide a 100% unified interface, but to unify
-+what can be while still providing platform specific APIs.
-+
-+For many system APIs, Nix provides a safe alternative to the unsafe APIs
-+exposed by the [libc crate](https://github.com/rust-lang/libc).  This is done by
-+wrapping the libc functionality with types/abstractions that enforce legal/safe
-+usage.
-+
-+
-+As an example of what Nix provides, examine the differences between what is
-+exposed by libc and nix for the
-+[gethostname](http://man7.org/linux/man-pages/man2/gethostname.2.html) system
-+call:
-+
-+```rust,ignore
-+// libc api (unsafe, requires handling return code/errno)
-+pub unsafe extern fn gethostname(name: *mut c_char, len: size_t) -> c_int;
-+
-+// nix api (returns a nix::Result<CStr>)
-+pub fn gethostname<'a>(buffer: &'a mut [u8]) -> Result<&'a CStr>;
-+```
-+
-+## Supported Platforms
-+
-+nix target support consists of two tiers. While nix attempts to support all
-+platforms supported by [libc](https://github.com/rust-lang/libc), only some
-+platforms are actively supported due to either technical or manpower
-+limitations. Support for platforms is split into three tiers:
-+
-+  * Tier 1 - Builds and tests for this target are run in CI. Failures of either
-+             block the inclusion of new code.
-+  * Tier 2 - Builds for this target are run in CI. Failures during the build
-+             blocks the inclusion of new code. Tests may be run, but failures
-+             in tests don't block the inclusion of new code.
-+  * Tier 3 - Builds for this target are run in CI. Failures during the build
-+             *do not* block the inclusion of new code. Testing may be run, but
-+             failures in tests don't block the inclusion of new code.
-+
-+The following targets are supported by `nix`:
-+
-+Tier 1:
-+  * aarch64-unknown-linux-gnu
-+  * arm-unknown-linux-gnueabi
-+  * armv7-unknown-linux-gnueabihf
-+  * i686-apple-darwin
-+  * i686-unknown-freebsd
-+  * i686-unknown-linux-gnu
-+  * i686-unknown-linux-musl
-+  * mips-unknown-linux-gnu
-+  * mips64-unknown-linux-gnuabi64
-+  * mips64el-unknown-linux-gnuabi64
-+  * mipsel-unknown-linux-gnu
-+  * powerpc64-unknown-linux-gnu
-+  * powerpc64le-unknown-linux-gnu
-+  * x86_64-apple-darwin
-+  * x86_64-unknown-freebsd
-+  * x86_64-unknown-linux-gnu
-+  * x86_64-unknown-linux-musl
-+
-+Tier 2:
-+  * aarch64-apple-ios
-+  * aarch64-linux-android
-+  * arm-linux-androideabi
-+  * arm-unknown-linux-musleabi
-+  * armv7-apple-ios
-+  * armv7-linux-androideabi
-+  * armv7s-apple-ios
-+  * i386-apple-ios
-+  * i686-linux-android
-+  * powerpc-unknown-linux-gnu
-+  * s390x-unknown-linux-gnu
-+  * x86_64-apple-ios
-+  * x86_64-linux-android
-+  * x86_64-unknown-netbsd
-+
-+## Usage
-+
-+`nix` requires Rust 1.31.0 or newer.
-+
-+To use `nix`, first add this to your `Cargo.toml`:
-+
-+```toml
-+[dependencies]
-+nix = "0.15.0"
-+```
-+
-+Then, add this to your crate root:
-+
-+```rust,ignore
-+extern crate nix;
-+```
-+
-+## Contributing
-+
-+Contributions are very welcome.  Please See [CONTRIBUTING](CONTRIBUTING.md) for
-+additional details.
-+
-+Feel free to join us in [the nix-rust/nix](https://gitter.im/nix-rust/nix) channel on Gitter to
-+discuss `nix` development.
-+
-+## License
-+
-+Nix is licensed under the MIT license.  See [LICENSE](LICENSE) for more details.
-diff --git a/third_party/rust/nix/build.rs b/third_party/rust/nix-0.15.0/build.rs
-similarity index 100%
-rename from third_party/rust/nix/build.rs
-rename to third_party/rust/nix-0.15.0/build.rs
-diff --git a/third_party/rust/nix-0.15.0/src/dir.rs b/third_party/rust/nix-0.15.0/src/dir.rs
-new file mode 100644
-index 0000000000000..1820b5330ff60
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/dir.rs
-@@ -0,0 +1,193 @@
-+use {Error, NixPath, Result};
-+use errno::Errno;
-+use fcntl::{self, OFlag};
-+use libc;
-+use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
-+use std::{ffi, ptr};
-+use sys;
-+
-+#[cfg(target_os = "linux")]
-+use libc::{dirent64 as dirent, readdir64_r as readdir_r};
-+
-+#[cfg(not(target_os = "linux"))]
-+use libc::{dirent, readdir_r};
-+
-+/// An open directory.
-+///
-+/// This is a lower-level interface than `std::fs::ReadDir`. Notable differences:
-+///    * can be opened from a file descriptor (as returned by `openat`, perhaps before knowing
-+///      if the path represents a file or directory).
-+///    * implements `AsRawFd`, so it can be passed to `fstat`, `openat`, etc.
-+///      The file descriptor continues to be owned by the `Dir`, so callers must not keep a `RawFd`
-+///      after the `Dir` is dropped.
-+///    * can be iterated through multiple times without closing and reopening the file
-+///      descriptor. Each iteration rewinds when finished.
-+///    * returns entries for `.` (current directory) and `..` (parent directory).
-+///    * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
-+///      does).
-+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct Dir(
-+    ptr::NonNull<libc::DIR>
-+);
-+
-+impl Dir {
-+    /// Opens the given path as with `fcntl::open`.
-+    pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag,
-+                                     mode: sys::stat::Mode) -> Result<Self> {
-+        let fd = fcntl::open(path, oflag, mode)?;
-+        Dir::from_fd(fd)
-+    }
-+
-+    /// Opens the given path as with `fcntl::openat`.
-+    pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag,
-+                                       mode: sys::stat::Mode) -> Result<Self> {
-+        let fd = fcntl::openat(dirfd, path, oflag, mode)?;
-+        Dir::from_fd(fd)
-+    }
-+
-+    /// Converts from a descriptor-based object, closing the descriptor on success or failure.
-+    #[inline]
-+    pub fn from<F: IntoRawFd>(fd: F) -> Result<Self> {
-+        Dir::from_fd(fd.into_raw_fd())
-+    }
-+
-+    /// 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 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()))
-+    }
-+
-+    /// Returns an iterator of `Result<Entry>` which rewinds when finished.
-+    pub fn iter(&mut self) -> Iter {
-+        Iter(self)
-+    }
-+}
-+
-+// `Dir` is not `Sync`. With the current implementation, it could be, but according to
-+// https://www.gnu.org/software/libc/manual/html_node/Reading_002fClosing-Directory.html,
-+// future versions of POSIX are likely to obsolete `readdir_r` and specify that it's unsafe to
-+// call `readdir` simultaneously from multiple threads.
-+//
-+// `Dir` is safe to pass from one thread to another, as it's not reference-counted.
-+unsafe impl Send for Dir {}
-+
-+impl AsRawFd for Dir {
-+    fn as_raw_fd(&self) -> RawFd {
-+        unsafe { libc::dirfd(self.0.as_ptr()) }
-+    }
-+}
-+
-+impl Drop for Dir {
-+    fn drop(&mut self) {
-+        unsafe { libc::closedir(self.0.as_ptr()) };
-+    }
-+}
-+
-+#[derive(Debug, Eq, Hash, PartialEq)]
-+pub struct Iter<'d>(&'d mut Dir);
-+
-+impl<'d> Iterator for Iter<'d> {
-+    type Item = Result<Entry>;
-+
-+    fn next(&mut self) -> Option<Self::Item> {
-+        unsafe {
-+            // Note: POSIX specifies that portable applications should dynamically allocate a
-+            // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
-+            // for the NUL byte. It doesn't look like the std library does this; it just uses
-+            // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
-+            // Probably fine here too then.
-+            let mut ent: Entry = Entry(::std::mem::uninitialized());
-+            let mut result = ptr::null_mut();
-+            if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) {
-+                return Some(Err(e));
-+            }
-+            if result == ptr::null_mut() {
-+                return None;
-+            }
-+            assert_eq!(result, &mut ent.0 as *mut dirent);
-+            return Some(Ok(ent));
-+        }
-+    }
-+}
-+
-+impl<'d> Drop for Iter<'d> {
-+    fn drop(&mut self) {
-+        unsafe { libc::rewinddir((self.0).0.as_ptr()) }
-+    }
-+}
-+
-+/// A directory entry, similar to `std::fs::DirEntry`.
-+///
-+/// Note that unlike the std version, this may represent the `.` or `..` entries.
-+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct Entry(dirent);
-+
-+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+pub enum Type {
-+    Fifo,
-+    CharacterDevice,
-+    Directory,
-+    BlockDevice,
-+    File,
-+    Symlink,
-+    Socket,
-+}
-+
-+impl Entry {
-+    /// Returns the inode number (`d_ino`) of the underlying `dirent`.
-+    #[cfg(any(target_os = "android",
-+              target_os = "emscripten",
-+              target_os = "fuchsia",
-+              target_os = "haiku",
-+              target_os = "ios",
-+              target_os = "l4re",
-+              target_os = "linux",
-+              target_os = "macos",
-+              target_os = "solaris"))]
-+    pub fn ino(&self) -> u64 {
-+        self.0.d_ino as u64
-+    }
-+
-+    /// Returns the inode number (`d_fileno`) of the underlying `dirent`.
-+    #[cfg(not(any(target_os = "android",
-+                  target_os = "emscripten",
-+                  target_os = "fuchsia",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "l4re",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "solaris")))]
-+    pub fn ino(&self) -> u64 {
-+        self.0.d_fileno as u64
-+    }
-+
-+    /// Returns the bare file name of this directory entry without any other leading path component.
-+    pub fn file_name(&self) -> &ffi::CStr {
-+        unsafe { ::std::ffi::CStr::from_ptr(self.0.d_name.as_ptr()) }
-+    }
-+
-+    /// Returns the type of this directory entry, if known.
-+    ///
-+    /// See platform `readdir(3)` or `dirent(5)` manpage for when the file type is known;
-+    /// 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> {
-+        match self.0.d_type {
-+            libc::DT_FIFO => Some(Type::Fifo),
-+            libc::DT_CHR => Some(Type::CharacterDevice),
-+            libc::DT_DIR => Some(Type::Directory),
-+            libc::DT_BLK => Some(Type::BlockDevice),
-+            libc::DT_REG => Some(Type::File),
-+            libc::DT_LNK => Some(Type::Symlink),
-+            libc::DT_SOCK => Some(Type::Socket),
-+            /* libc::DT_UNKNOWN | */ _ => None,
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/errno.rs b/third_party/rust/nix-0.15.0/src/errno.rs
-new file mode 100644
-index 0000000000000..6a2447bc52675
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/errno.rs
-@@ -0,0 +1,1963 @@
-+#[cfg(not(target_os = "dragonfly"))]
-+use libc;
-+use libc::{c_int, c_void};
-+use std::{fmt, io, error};
-+use {Error, Result};
-+
-+pub use self::consts::*;
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "freebsd",
-+                 target_os = "ios",
-+                 target_os = "macos"))] {
-+        unsafe fn errno_location() -> *mut c_int {
-+            libc::__error()
-+        }
-+    } else if #[cfg(target_os = "dragonfly")] {
-+        // DragonFly uses a thread-local errno variable, but #[thread_local] is
-+        // feature-gated and not available in stable Rust as of this writing
-+        // (Rust 1.21.0). We have to use a C extension to access it
-+        // (src/errno_dragonfly.c).
-+        //
-+        // Tracking issue for `thread_local` stabilization:
-+        //
-+        //     https://github.com/rust-lang/rust/issues/29594
-+        //
-+        // Once this becomes stable, we can remove build.rs,
-+        // src/errno_dragonfly.c, and use:
-+        //
-+        //     extern { #[thread_local] static errno: c_int; }
-+        //
-+        #[link(name="errno_dragonfly", kind="static")]
-+        extern {
-+            pub fn errno_location() -> *mut c_int;
-+        }
-+    } else if #[cfg(any(target_os = "android",
-+                        target_os = "netbsd",
-+                        target_os = "openbsd"))] {
-+        unsafe fn errno_location() -> *mut c_int {
-+            libc::__errno()
-+        }
-+    } else if #[cfg(target_os = "linux")] {
-+        unsafe fn errno_location() -> *mut c_int {
-+            libc::__errno_location()
-+        }
-+    }
-+}
-+
-+/// Sets the platform-specific errno to no-error
-+unsafe fn clear() -> () {
-+    *errno_location() = 0;
-+}
-+
-+/// Returns the platform-specific value of errno
-+pub fn errno() -> i32 {
-+    unsafe {
-+        (*errno_location()) as i32
-+    }
-+}
-+
-+impl Errno {
-+    pub fn last() -> Self {
-+        last()
-+    }
-+
-+    pub fn desc(self) -> &'static str {
-+        desc(self)
-+    }
-+
-+    pub fn from_i32(err: i32) -> Errno {
-+        from_i32(err)
-+    }
-+
-+    pub unsafe fn clear() -> () {
-+        clear()
-+    }
-+
-+    /// Returns `Ok(value)` if it does not contain the sentinel value. This
-+    /// should not be used when `-1` is not the errno sentinel value.
-+    pub fn result<S: ErrnoSentinel + PartialEq<S>>(value: S) -> Result<S> {
-+        if value == S::sentinel() {
-+            Err(Error::Sys(Self::last()))
-+        } else {
-+            Ok(value)
-+        }
-+    }
-+}
-+
-+/// The sentinel value indicates that a function failed and more detailed
-+/// information about the error can be found in `errno`
-+pub trait ErrnoSentinel: Sized {
-+    fn sentinel() -> Self;
-+}
-+
-+impl ErrnoSentinel for isize {
-+    fn sentinel() -> Self { -1 }
-+}
-+
-+impl ErrnoSentinel for i32 {
-+    fn sentinel() -> Self { -1 }
-+}
-+
-+impl ErrnoSentinel for i64 {
-+    fn sentinel() -> Self { -1 }
-+}
-+
-+impl ErrnoSentinel for *mut c_void {
-+    fn sentinel() -> Self { (-1 as isize) as *mut c_void }
-+}
-+
-+impl ErrnoSentinel for libc::sighandler_t {
-+    fn sentinel() -> Self { libc::SIG_ERR }
-+}
-+
-+impl error::Error for Errno {
-+    fn description(&self) -> &str {
-+        self.desc()
-+    }
-+}
-+
-+impl fmt::Display for Errno {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        write!(f, "{:?}: {}", self, self.desc())
-+    }
-+}
-+
-+impl From<Errno> for io::Error {
-+    fn from(err: Errno) -> Self {
-+        io::Error::from_raw_os_error(err as i32)
-+    }
-+}
-+
-+fn last() -> Errno {
-+    Errno::from_i32(errno())
-+}
-+
-+fn desc(errno: Errno) -> &'static str {
-+    use self::Errno::*;
-+    match errno {
-+        UnknownErrno    => "Unknown errno",
-+        EPERM           => "Operation not permitted",
-+        ENOENT          => "No such file or directory",
-+        ESRCH           => "No such process",
-+        EINTR           => "Interrupted system call",
-+        EIO             => "I/O error",
-+        ENXIO           => "No such device or address",
-+        E2BIG           => "Argument list too long",
-+        ENOEXEC         => "Exec format error",
-+        EBADF           => "Bad file number",
-+        ECHILD          => "No child processes",
-+        EAGAIN          => "Try again",
-+        ENOMEM          => "Out of memory",
-+        EACCES          => "Permission denied",
-+        EFAULT          => "Bad address",
-+        ENOTBLK         => "Block device required",
-+        EBUSY           => "Device or resource busy",
-+        EEXIST          => "File exists",
-+        EXDEV           => "Cross-device link",
-+        ENODEV          => "No such device",
-+        ENOTDIR         => "Not a directory",
-+        EISDIR          => "Is a directory",
-+        EINVAL          => "Invalid argument",
-+        ENFILE          => "File table overflow",
-+        EMFILE          => "Too many open files",
-+        ENOTTY          => "Not a typewriter",
-+        ETXTBSY         => "Text file busy",
-+        EFBIG           => "File too large",
-+        ENOSPC          => "No space left on device",
-+        ESPIPE          => "Illegal seek",
-+        EROFS           => "Read-only file system",
-+        EMLINK          => "Too many links",
-+        EPIPE           => "Broken pipe",
-+        EDOM            => "Math argument out of domain of func",
-+        ERANGE          => "Math result not representable",
-+        EDEADLK         => "Resource deadlock would occur",
-+        ENAMETOOLONG    => "File name too long",
-+        ENOLCK          => "No record locks available",
-+        ENOSYS          => "Function not implemented",
-+        ENOTEMPTY       => "Directory not empty",
-+        ELOOP           => "Too many symbolic links encountered",
-+        ENOMSG          => "No message of desired type",
-+        EIDRM           => "Identifier removed",
-+        EINPROGRESS     => "Operation now in progress",
-+        EALREADY        => "Operation already in progress",
-+        ENOTSOCK        => "Socket operation on non-socket",
-+        EDESTADDRREQ    => "Destination address required",
-+        EMSGSIZE        => "Message too long",
-+        EPROTOTYPE      => "Protocol wrong type for socket",
-+        ENOPROTOOPT     => "Protocol not available",
-+        EPROTONOSUPPORT => "Protocol not supported",
-+        ESOCKTNOSUPPORT => "Socket type not supported",
-+        EPFNOSUPPORT    => "Protocol family not supported",
-+        EAFNOSUPPORT    => "Address family not supported by protocol",
-+        EADDRINUSE      => "Address already in use",
-+        EADDRNOTAVAIL   => "Cannot assign requested address",
-+        ENETDOWN        => "Network is down",
-+        ENETUNREACH     => "Network is unreachable",
-+        ENETRESET       => "Network dropped connection because of reset",
-+        ECONNABORTED    => "Software caused connection abort",
-+        ECONNRESET      => "Connection reset by peer",
-+        ENOBUFS         => "No buffer space available",
-+        EISCONN         => "Transport endpoint is already connected",
-+        ENOTCONN        => "Transport endpoint is not connected",
-+        ESHUTDOWN       => "Cannot send after transport endpoint shutdown",
-+        ETOOMANYREFS    => "Too many references: cannot splice",
-+        ETIMEDOUT       => "Connection timed out",
-+        ECONNREFUSED    => "Connection refused",
-+        EHOSTDOWN       => "Host is down",
-+        EHOSTUNREACH    => "No route to host",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ECHRNG          => "Channel number out of range",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EL2NSYNC        => "Level 2 not synchronized",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EL3HLT          => "Level 3 halted",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EL3RST          => "Level 3 reset",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELNRNG          => "Link number out of range",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EUNATCH         => "Protocol driver not attached",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOCSI          => "No CSI structure available",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EL2HLT          => "Level 2 halted",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADE           => "Invalid exchange",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADR           => "Invalid request descriptor",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EXFULL          => "Exchange full",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOANO          => "No anode",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADRQC         => "Invalid request code",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADSLT         => "Invalid slot",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBFONT          => "Bad font file format",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOSTR          => "Device not a stream",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENODATA         => "No data available",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ETIME           => "Timer expired",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOSR           => "Out of streams resources",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENONET          => "Machine is not on the network",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOPKG          => "Package not installed",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EREMOTE         => "Object is remote",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOLINK         => "Link has been severed",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EADV            => "Advertise error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ESRMNT          => "Srmount error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ECOMM           => "Communication error on send",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EPROTO          => "Protocol error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EMULTIHOP       => "Multihop attempted",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EDOTDOT         => "RFS specific error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADMSG         => "Not a data message",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EOVERFLOW       => "Value too large for defined data type",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOTUNIQ        => "Name not unique on network",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EBADFD          => "File descriptor in bad state",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EREMCHG         => "Remote address changed",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELIBACC         => "Can not access a needed shared library",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELIBBAD         => "Accessing a corrupted shared library",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELIBSCN         => ".lib section in a.out corrupted",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELIBMAX         => "Attempting to link in too many shared libraries",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ELIBEXEC        => "Cannot exec a shared library directly",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
-+        EILSEQ          => "Illegal byte sequence",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ERESTART        => "Interrupted system call should be restarted",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ESTRPIPE        => "Streams pipe error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EUSERS          => "Too many users",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
-+        EOPNOTSUPP      => "Operation not supported on transport endpoint",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ESTALE          => "Stale file handle",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EUCLEAN         => "Structure needs cleaning",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOTNAM         => "Not a XENIX named type file",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENAVAIL         => "No XENIX semaphores available",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EISNAM          => "Is a named type file",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EREMOTEIO       => "Remote I/O error",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EDQUOT          => "Quota exceeded",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "openbsd", target_os = "dragonfly"))]
-+        ENOMEDIUM       => "No medium found",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
-+        EMEDIUMTYPE     => "Wrong medium type",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ECANCELED       => "Operation canceled",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOKEY          => "Required key not available",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EKEYEXPIRED     => "Key has expired",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EKEYREVOKED     => "Key has been revoked",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EKEYREJECTED    => "Key was rejected by service",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        EOWNERDEAD      => "Owner died",
-+
-+        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        ENOTRECOVERABLE => "State not recoverable",
-+
-+        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
-+        ERFKILL         => "Operation not possible due to RF-kill",
-+
-+        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
-+        EHWPOISON       => "Memory page has hardware error",
-+
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        EDOOFUS         => "Programming error",
-+
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        EMULTIHOP       => "Multihop attempted",
-+
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        ENOLINK         => "Link has been severed",
-+
-+        #[cfg(target_os = "freebsd")]
-+        ENOTCAPABLE     => "Capabilities insufficient",
-+
-+        #[cfg(target_os = "freebsd")]
-+        ECAPMODE        => "Not permitted in capability mode",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ENEEDAUTH       => "Need authenticator",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EOVERFLOW       => "Value too large to be stored in data type",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "netbsd"))]
-+        EILSEQ          => "Illegal byte sequence",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ENOATTR         => "Attribute not found",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EBADMSG         => "Bad message",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EPROTO          => "Protocol error",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "ios", target_os = "openbsd", ))]
-+        ENOTRECOVERABLE => "State not recoverable",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "ios", target_os = "openbsd"))]
-+        EOWNERDEAD      => "Previous owner died",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ENOTSUP         => "Operation not supported",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EPROCLIM        => "Too many processes",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EUSERS          => "Too many users",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EDQUOT          => "Disc quota exceeded",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ESTALE          => "Stale NFS file handle",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EREMOTE         => "Too many levels of remote in path",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EBADRPC         => "RPC struct is bad",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ERPCMISMATCH    => "RPC version wrong",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EPROGUNAVAIL    => "RPC prog. not avail",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EPROGMISMATCH   => "Program version wrong",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EPROCUNAVAIL    => "Bad procedure for program",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EFTYPE          => "Inappropriate file type or format",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        EAUTH           => "Authentication error",
-+
-+        #[cfg(any(target_os = "macos", target_os = "freebsd",
-+                  target_os = "dragonfly", target_os = "ios",
-+                  target_os = "openbsd", target_os = "netbsd"))]
-+        ECANCELED       => "Operation canceled",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EPWROFF         => "Device power is off",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EDEVERR         => "Device error, e.g. paper out",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EBADEXEC        => "Bad executable",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EBADARCH        => "Bad CPU type in executable",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        ESHLIBVERS      => "Shared library version mismatch",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EBADMACHO       => "Malformed Macho file",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        EMULTIHOP       => "Reserved",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        ENODATA         => "No message available on STREAM",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        ENOLINK         => "Reserved",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        ENOSR           => "No STREAM resources",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        ENOSTR          => "Not a STREAM",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        ETIME           => "STREAM ioctl timeout",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EOPNOTSUPP      => "Operation not supported on socket",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        ENOPOLICY       => "No such policy registered",
-+
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EQFULL          => "Interface output queue is full",
-+
-+        #[cfg(target_os = "openbsd")]
-+        EOPNOTSUPP      => "Operation not supported",
-+
-+        #[cfg(target_os = "openbsd")]
-+        EIPSEC          => "IPsec processing failure",
-+
-+        #[cfg(target_os = "dragonfly")]
-+        EASYNC          => "Async",
-+    }
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        ELOOP           = libc::ELOOP,
-+        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,
-+        EBADE           = libc::EBADE,
-+        EBADR           = libc::EBADR,
-+        EXFULL          = libc::EXFULL,
-+        ENOANO          = libc::ENOANO,
-+        EBADRQC         = libc::EBADRQC,
-+        EBADSLT         = libc::EBADSLT,
-+        EBFONT          = libc::EBFONT,
-+        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,
-+        EMULTIHOP       = libc::EMULTIHOP,
-+        EDOTDOT         = libc::EDOTDOT,
-+        EBADMSG         = libc::EBADMSG,
-+        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,
-+        ERESTART        = libc::ERESTART,
-+        ESTRPIPE        = libc::ESTRPIPE,
-+        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,
-+        EUCLEAN         = libc::EUCLEAN,
-+        ENOTNAM         = libc::ENOTNAM,
-+        ENAVAIL         = libc::ENAVAIL,
-+        EISNAM          = libc::EISNAM,
-+        EREMOTEIO       = libc::EREMOTEIO,
-+        EDQUOT          = libc::EDQUOT,
-+        ENOMEDIUM       = libc::ENOMEDIUM,
-+        EMEDIUMTYPE     = libc::EMEDIUMTYPE,
-+        ECANCELED       = libc::ECANCELED,
-+        ENOKEY          = libc::ENOKEY,
-+        EKEYEXPIRED     = libc::EKEYEXPIRED,
-+        EKEYREVOKED     = libc::EKEYREVOKED,
-+        EKEYREJECTED    = libc::EKEYREJECTED,
-+        EOWNERDEAD      = libc::EOWNERDEAD,
-+        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
-+        #[cfg(not(any(target_os = "android", target_arch="mips")))]
-+        ERFKILL         = libc::ERFKILL,
-+        #[cfg(not(any(target_os = "android", target_arch="mips")))]
-+        EHWPOISON       = libc::EHWPOISON,
-+    }
-+
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-+    pub const ENOTSUP:     Errno = Errno::EOPNOTSUPP;
-+
-+    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::EDEADLK => EDEADLK,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::ELOOP => ELOOP,
-+            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::EBADE => EBADE,
-+            libc::EBADR => EBADR,
-+            libc::EXFULL => EXFULL,
-+            libc::ENOANO => ENOANO,
-+            libc::EBADRQC => EBADRQC,
-+            libc::EBADSLT => EBADSLT,
-+            libc::EBFONT => EBFONT,
-+            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::EMULTIHOP => EMULTIHOP,
-+            libc::EDOTDOT => EDOTDOT,
-+            libc::EBADMSG => EBADMSG,
-+            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::ERESTART => ERESTART,
-+            libc::ESTRPIPE => ESTRPIPE,
-+            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,
-+            libc::EUCLEAN => EUCLEAN,
-+            libc::ENOTNAM => ENOTNAM,
-+            libc::ENAVAIL => ENAVAIL,
-+            libc::EISNAM => EISNAM,
-+            libc::EREMOTEIO => EREMOTEIO,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ENOMEDIUM => ENOMEDIUM,
-+            libc::EMEDIUMTYPE => EMEDIUMTYPE,
-+            libc::ECANCELED => ECANCELED,
-+            libc::ENOKEY => ENOKEY,
-+            libc::EKEYEXPIRED => EKEYEXPIRED,
-+            libc::EKEYREVOKED => EKEYREVOKED,
-+            libc::EKEYREJECTED => EKEYREJECTED,
-+            libc::EOWNERDEAD => EOWNERDEAD,
-+            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
-+            #[cfg(not(any(target_os = "android", target_arch="mips")))]
-+            libc::ERFKILL => ERFKILL,
-+            #[cfg(not(any(target_os = "android", target_arch="mips")))]
-+            libc::EHWPOISON => EHWPOISON,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "macos", target_os = "ios"))]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        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,
-+        EAGAIN          = libc::EAGAIN,
-+        EINPROGRESS     = libc::EINPROGRESS,
-+        EALREADY        = libc::EALREADY,
-+        ENOTSOCK        = libc::ENOTSOCK,
-+        EDESTADDRREQ    = libc::EDESTADDRREQ,
-+        EMSGSIZE        = libc::EMSGSIZE,
-+        EPROTOTYPE      = libc::EPROTOTYPE,
-+        ENOPROTOOPT     = libc::ENOPROTOOPT,
-+        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
-+        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
-+        ENOTSUP         = libc::ENOTSUP,
-+        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,
-+        ELOOP           = libc::ELOOP,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        EHOSTDOWN       = libc::EHOSTDOWN,
-+        EHOSTUNREACH    = libc::EHOSTUNREACH,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        EPROCLIM        = libc::EPROCLIM,
-+        EUSERS          = libc::EUSERS,
-+        EDQUOT          = libc::EDQUOT,
-+        ESTALE          = libc::ESTALE,
-+        EREMOTE         = libc::EREMOTE,
-+        EBADRPC         = libc::EBADRPC,
-+        ERPCMISMATCH    = libc::ERPCMISMATCH,
-+        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
-+        EPROGMISMATCH   = libc::EPROGMISMATCH,
-+        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        EFTYPE          = libc::EFTYPE,
-+        EAUTH           = libc::EAUTH,
-+        ENEEDAUTH       = libc::ENEEDAUTH,
-+        EPWROFF         = libc::EPWROFF,
-+        EDEVERR         = libc::EDEVERR,
-+        EOVERFLOW       = libc::EOVERFLOW,
-+        EBADEXEC        = libc::EBADEXEC,
-+        EBADARCH        = libc::EBADARCH,
-+        ESHLIBVERS      = libc::ESHLIBVERS,
-+        EBADMACHO       = libc::EBADMACHO,
-+        ECANCELED       = libc::ECANCELED,
-+        EIDRM           = libc::EIDRM,
-+        ENOMSG          = libc::ENOMSG,
-+        EILSEQ          = libc::EILSEQ,
-+        ENOATTR         = libc::ENOATTR,
-+        EBADMSG         = libc::EBADMSG,
-+        EMULTIHOP       = libc::EMULTIHOP,
-+        ENODATA         = libc::ENODATA,
-+        ENOLINK         = libc::ENOLINK,
-+        ENOSR           = libc::ENOSR,
-+        ENOSTR          = libc::ENOSTR,
-+        EPROTO          = libc::EPROTO,
-+        ETIME           = libc::ETIME,
-+        EOPNOTSUPP      = libc::EOPNOTSUPP,
-+        ENOPOLICY       = libc::ENOPOLICY,
-+        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
-+        EOWNERDEAD      = libc::EOWNERDEAD,
-+        EQFULL          = libc::EQFULL,
-+    }
-+
-+    pub const ELAST: Errno       = Errno::EQFULL;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    pub 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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            libc::ENOTSOCK => ENOTSOCK,
-+            libc::EDESTADDRREQ => EDESTADDRREQ,
-+            libc::EMSGSIZE => EMSGSIZE,
-+            libc::EPROTOTYPE => EPROTOTYPE,
-+            libc::ENOPROTOOPT => ENOPROTOOPT,
-+            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
-+            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
-+            libc::ENOTSUP => ENOTSUP,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EPROCLIM => EPROCLIM,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::EBADRPC => EBADRPC,
-+            libc::ERPCMISMATCH => ERPCMISMATCH,
-+            libc::EPROGUNAVAIL => EPROGUNAVAIL,
-+            libc::EPROGMISMATCH => EPROGMISMATCH,
-+            libc::EPROCUNAVAIL => EPROCUNAVAIL,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EFTYPE => EFTYPE,
-+            libc::EAUTH => EAUTH,
-+            libc::ENEEDAUTH => ENEEDAUTH,
-+            libc::EPWROFF => EPWROFF,
-+            libc::EDEVERR => EDEVERR,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::EBADEXEC => EBADEXEC,
-+            libc::EBADARCH => EBADARCH,
-+            libc::ESHLIBVERS => ESHLIBVERS,
-+            libc::EBADMACHO => EBADMACHO,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ENOATTR => ENOATTR,
-+            libc::EBADMSG => EBADMSG,
-+            libc::EMULTIHOP => EMULTIHOP,
-+            libc::ENODATA => ENODATA,
-+            libc::ENOLINK => ENOLINK,
-+            libc::ENOSR => ENOSR,
-+            libc::ENOSTR => ENOSTR,
-+            libc::EPROTO => EPROTO,
-+            libc::ETIME => ETIME,
-+            libc::EOPNOTSUPP => EOPNOTSUPP,
-+            libc::ENOPOLICY => ENOPOLICY,
-+            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
-+            libc::EOWNERDEAD => EOWNERDEAD,
-+            libc::EQFULL => EQFULL,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        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,
-+        EAGAIN          = libc::EAGAIN,
-+        EINPROGRESS     = libc::EINPROGRESS,
-+        EALREADY        = libc::EALREADY,
-+        ENOTSOCK        = libc::ENOTSOCK,
-+        EDESTADDRREQ    = libc::EDESTADDRREQ,
-+        EMSGSIZE        = libc::EMSGSIZE,
-+        EPROTOTYPE      = libc::EPROTOTYPE,
-+        ENOPROTOOPT     = libc::ENOPROTOOPT,
-+        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
-+        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
-+        ENOTSUP         = libc::ENOTSUP,
-+        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,
-+        ELOOP           = libc::ELOOP,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        EHOSTDOWN       = libc::EHOSTDOWN,
-+        EHOSTUNREACH    = libc::EHOSTUNREACH,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        EPROCLIM        = libc::EPROCLIM,
-+        EUSERS          = libc::EUSERS,
-+        EDQUOT          = libc::EDQUOT,
-+        ESTALE          = libc::ESTALE,
-+        EREMOTE         = libc::EREMOTE,
-+        EBADRPC         = libc::EBADRPC,
-+        ERPCMISMATCH    = libc::ERPCMISMATCH,
-+        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
-+        EPROGMISMATCH   = libc::EPROGMISMATCH,
-+        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        EFTYPE          = libc::EFTYPE,
-+        EAUTH           = libc::EAUTH,
-+        ENEEDAUTH       = libc::ENEEDAUTH,
-+        EIDRM           = libc::EIDRM,
-+        ENOMSG          = libc::ENOMSG,
-+        EOVERFLOW       = libc::EOVERFLOW,
-+        ECANCELED       = libc::ECANCELED,
-+        EILSEQ          = libc::EILSEQ,
-+        ENOATTR         = libc::ENOATTR,
-+        EDOOFUS         = libc::EDOOFUS,
-+        EBADMSG         = libc::EBADMSG,
-+        EMULTIHOP       = libc::EMULTIHOP,
-+        ENOLINK         = libc::ENOLINK,
-+        EPROTO          = libc::EPROTO,
-+        ENOTCAPABLE     = libc::ENOTCAPABLE,
-+        ECAPMODE        = libc::ECAPMODE,
-+        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
-+        EOWNERDEAD      = libc::EOWNERDEAD,
-+    }
-+
-+    pub const ELAST: Errno       = Errno::EOWNERDEAD;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            libc::ENOTSOCK => ENOTSOCK,
-+            libc::EDESTADDRREQ => EDESTADDRREQ,
-+            libc::EMSGSIZE => EMSGSIZE,
-+            libc::EPROTOTYPE => EPROTOTYPE,
-+            libc::ENOPROTOOPT => ENOPROTOOPT,
-+            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
-+            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
-+            libc::ENOTSUP => ENOTSUP,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EPROCLIM => EPROCLIM,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::EBADRPC => EBADRPC,
-+            libc::ERPCMISMATCH => ERPCMISMATCH,
-+            libc::EPROGUNAVAIL => EPROGUNAVAIL,
-+            libc::EPROGMISMATCH => EPROGMISMATCH,
-+            libc::EPROCUNAVAIL => EPROCUNAVAIL,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EFTYPE => EFTYPE,
-+            libc::EAUTH => EAUTH,
-+            libc::ENEEDAUTH => ENEEDAUTH,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ENOATTR => ENOATTR,
-+            libc::EDOOFUS => EDOOFUS,
-+            libc::EBADMSG => EBADMSG,
-+            libc::EMULTIHOP => EMULTIHOP,
-+            libc::ENOLINK => ENOLINK,
-+            libc::EPROTO => EPROTO,
-+            libc::ENOTCAPABLE => ENOTCAPABLE,
-+            libc::ECAPMODE => ECAPMODE,
-+            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
-+            libc::EOWNERDEAD => EOWNERDEAD,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-+
-+
-+#[cfg(target_os = "dragonfly")]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        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,
-+        EAGAIN          = libc::EAGAIN,
-+        EINPROGRESS     = libc::EINPROGRESS,
-+        EALREADY        = libc::EALREADY,
-+        ENOTSOCK        = libc::ENOTSOCK,
-+        EDESTADDRREQ    = libc::EDESTADDRREQ,
-+        EMSGSIZE        = libc::EMSGSIZE,
-+        EPROTOTYPE      = libc::EPROTOTYPE,
-+        ENOPROTOOPT     = libc::ENOPROTOOPT,
-+        EPROTONOSUPPORT = libc::EPROTONOSUPPORT,
-+        ESOCKTNOSUPPORT = libc::ESOCKTNOSUPPORT,
-+        ENOTSUP         = libc::ENOTSUP,
-+        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,
-+        ELOOP           = libc::ELOOP,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        EHOSTDOWN       = libc::EHOSTDOWN,
-+        EHOSTUNREACH    = libc::EHOSTUNREACH,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        EPROCLIM        = libc::EPROCLIM,
-+        EUSERS          = libc::EUSERS,
-+        EDQUOT          = libc::EDQUOT,
-+        ESTALE          = libc::ESTALE,
-+        EREMOTE         = libc::EREMOTE,
-+        EBADRPC         = libc::EBADRPC,
-+        ERPCMISMATCH    = libc::ERPCMISMATCH,
-+        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
-+        EPROGMISMATCH   = libc::EPROGMISMATCH,
-+        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        EFTYPE          = libc::EFTYPE,
-+        EAUTH           = libc::EAUTH,
-+        ENEEDAUTH       = libc::ENEEDAUTH,
-+        EIDRM           = libc::EIDRM,
-+        ENOMSG          = libc::ENOMSG,
-+        EOVERFLOW       = libc::EOVERFLOW,
-+        ECANCELED       = libc::ECANCELED,
-+        EILSEQ          = libc::EILSEQ,
-+        ENOATTR         = libc::ENOATTR,
-+        EDOOFUS         = libc::EDOOFUS,
-+        EBADMSG         = libc::EBADMSG,
-+        EMULTIHOP       = libc::EMULTIHOP,
-+        ENOLINK         = libc::ENOLINK,
-+        EPROTO          = libc::EPROTO,
-+        ENOMEDIUM       = libc::ENOMEDIUM,
-+        EASYNC          = libc::EASYNC,
-+    }
-+
-+    pub const ELAST: Errno       = Errno::EASYNC;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+    pub const EDEADLOCK:   Errno = Errno::EDEADLK;
-+    pub const EOPNOTSUPP:  Errno = Errno::ENOTSUP;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    pub 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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            libc::ENOTSOCK => ENOTSOCK,
-+            libc::EDESTADDRREQ => EDESTADDRREQ,
-+            libc::EMSGSIZE => EMSGSIZE,
-+            libc::EPROTOTYPE => EPROTOTYPE,
-+            libc::ENOPROTOOPT => ENOPROTOOPT,
-+            libc::EPROTONOSUPPORT => EPROTONOSUPPORT,
-+            libc::ESOCKTNOSUPPORT => ESOCKTNOSUPPORT,
-+            libc::ENOTSUP => ENOTSUP,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EPROCLIM => EPROCLIM,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::EBADRPC => EBADRPC,
-+            libc::ERPCMISMATCH => ERPCMISMATCH,
-+            libc::EPROGUNAVAIL => EPROGUNAVAIL,
-+            libc::EPROGMISMATCH => EPROGMISMATCH,
-+            libc::EPROCUNAVAIL => EPROCUNAVAIL,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EFTYPE => EFTYPE,
-+            libc::EAUTH => EAUTH,
-+            libc::ENEEDAUTH => ENEEDAUTH,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ENOATTR => ENOATTR,
-+            libc::EDOOFUS => EDOOFUS,
-+            libc::EBADMSG => EBADMSG,
-+            libc::EMULTIHOP => EMULTIHOP,
-+            libc::ENOLINK => ENOLINK,
-+            libc::EPROTO => EPROTO,
-+            libc::ENOMEDIUM => ENOMEDIUM,
-+            libc::EASYNC => EASYNC,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-+
-+
-+#[cfg(target_os = "openbsd")]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        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,
-+        EAGAIN          = libc::EAGAIN,
-+        EINPROGRESS     = libc::EINPROGRESS,
-+        EALREADY        = libc::EALREADY,
-+        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,
-+        ELOOP           = libc::ELOOP,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        EHOSTDOWN       = libc::EHOSTDOWN,
-+        EHOSTUNREACH    = libc::EHOSTUNREACH,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        EPROCLIM        = libc::EPROCLIM,
-+        EUSERS          = libc::EUSERS,
-+        EDQUOT          = libc::EDQUOT,
-+        ESTALE          = libc::ESTALE,
-+        EREMOTE         = libc::EREMOTE,
-+        EBADRPC         = libc::EBADRPC,
-+        ERPCMISMATCH    = libc::ERPCMISMATCH,
-+        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
-+        EPROGMISMATCH   = libc::EPROGMISMATCH,
-+        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        EFTYPE          = libc::EFTYPE,
-+        EAUTH           = libc::EAUTH,
-+        ENEEDAUTH       = libc::ENEEDAUTH,
-+        EIPSEC          = libc::EIPSEC,
-+        ENOATTR         = libc::ENOATTR,
-+        EILSEQ          = libc::EILSEQ,
-+        ENOMEDIUM       = libc::ENOMEDIUM,
-+        EMEDIUMTYPE     = libc::EMEDIUMTYPE,
-+        EOVERFLOW       = libc::EOVERFLOW,
-+        ECANCELED       = libc::ECANCELED,
-+        EIDRM           = libc::EIDRM,
-+        ENOMSG          = libc::ENOMSG,
-+        ENOTSUP         = libc::ENOTSUP,
-+        EBADMSG         = libc::EBADMSG,
-+        ENOTRECOVERABLE = libc::ENOTRECOVERABLE,
-+        EOWNERDEAD      = libc::EOWNERDEAD,
-+        EPROTO          = libc::EPROTO,
-+    }
-+
-+    pub const ELAST: Errno       = Errno::ENOTSUP;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EPROCLIM => EPROCLIM,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::EBADRPC => EBADRPC,
-+            libc::ERPCMISMATCH => ERPCMISMATCH,
-+            libc::EPROGUNAVAIL => EPROGUNAVAIL,
-+            libc::EPROGMISMATCH => EPROGMISMATCH,
-+            libc::EPROCUNAVAIL => EPROCUNAVAIL,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EFTYPE => EFTYPE,
-+            libc::EAUTH => EAUTH,
-+            libc::ENEEDAUTH => ENEEDAUTH,
-+            libc::EIPSEC => EIPSEC,
-+            libc::ENOATTR => ENOATTR,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ENOMEDIUM => ENOMEDIUM,
-+            libc::EMEDIUMTYPE => EMEDIUMTYPE,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::ENOTSUP => ENOTSUP,
-+            libc::EBADMSG => EBADMSG,
-+            libc::ENOTRECOVERABLE => ENOTRECOVERABLE,
-+            libc::EOWNERDEAD => EOWNERDEAD,
-+            libc::EPROTO => EPROTO,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-+
-+#[cfg(target_os = "netbsd")]
-+mod consts {
-+    use libc;
-+
-+    #[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,
-+        EDEADLK         = libc::EDEADLK,
-+        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,
-+        EAGAIN          = libc::EAGAIN,
-+        EINPROGRESS     = libc::EINPROGRESS,
-+        EALREADY        = libc::EALREADY,
-+        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,
-+        ELOOP           = libc::ELOOP,
-+        ENAMETOOLONG    = libc::ENAMETOOLONG,
-+        EHOSTDOWN       = libc::EHOSTDOWN,
-+        EHOSTUNREACH    = libc::EHOSTUNREACH,
-+        ENOTEMPTY       = libc::ENOTEMPTY,
-+        EPROCLIM        = libc::EPROCLIM,
-+        EUSERS          = libc::EUSERS,
-+        EDQUOT          = libc::EDQUOT,
-+        ESTALE          = libc::ESTALE,
-+        EREMOTE         = libc::EREMOTE,
-+        EBADRPC         = libc::EBADRPC,
-+        ERPCMISMATCH    = libc::ERPCMISMATCH,
-+        EPROGUNAVAIL    = libc::EPROGUNAVAIL,
-+        EPROGMISMATCH   = libc::EPROGMISMATCH,
-+        EPROCUNAVAIL    = libc::EPROCUNAVAIL,
-+        ENOLCK          = libc::ENOLCK,
-+        ENOSYS          = libc::ENOSYS,
-+        EFTYPE          = libc::EFTYPE,
-+        EAUTH           = libc::EAUTH,
-+        ENEEDAUTH       = libc::ENEEDAUTH,
-+        EIDRM           = libc::EIDRM,
-+        ENOMSG          = libc::ENOMSG,
-+        EOVERFLOW       = libc::EOVERFLOW,
-+        EILSEQ          = libc::EILSEQ,
-+        ENOTSUP         = libc::ENOTSUP,
-+        ECANCELED       = libc::ECANCELED,
-+        EBADMSG         = libc::EBADMSG,
-+        ENODATA         = libc::ENODATA,
-+        ENOSR           = libc::ENOSR,
-+        ENOSTR          = libc::ENOSTR,
-+        ETIME           = libc::ETIME,
-+        ENOATTR         = libc::ENOATTR,
-+        EMULTIHOP       = libc::EMULTIHOP,
-+        ENOLINK         = libc::ENOLINK,
-+        EPROTO          = libc::EPROTO,
-+    }
-+
-+    pub const ELAST: Errno       = Errno::ENOTSUP;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EPROCLIM => EPROCLIM,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::EBADRPC => EBADRPC,
-+            libc::ERPCMISMATCH => ERPCMISMATCH,
-+            libc::EPROGUNAVAIL => EPROGUNAVAIL,
-+            libc::EPROGMISMATCH => EPROGMISMATCH,
-+            libc::EPROCUNAVAIL => EPROCUNAVAIL,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EFTYPE => EFTYPE,
-+            libc::EAUTH => EAUTH,
-+            libc::ENEEDAUTH => ENEEDAUTH,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ENOTSUP => ENOTSUP,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EBADMSG => EBADMSG,
-+            libc::ENODATA => ENODATA,
-+            libc::ENOSR => ENOSR,
-+            libc::ENOSTR => ENOSTR,
-+            libc::ETIME => ETIME,
-+            libc::ENOATTR => ENOATTR,
-+            libc::EMULTIHOP => EMULTIHOP,
-+            libc::ENOLINK => ENOLINK,
-+            libc::EPROTO => EPROTO,
-+            _   => UnknownErrno,
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix/src/errno_dragonfly.c b/third_party/rust/nix-0.15.0/src/errno_dragonfly.c
-similarity index 100%
-rename from third_party/rust/nix/src/errno_dragonfly.c
-rename to third_party/rust/nix-0.15.0/src/errno_dragonfly.c
-diff --git a/third_party/rust/nix-0.15.0/src/fcntl.rs b/third_party/rust/nix-0.15.0/src/fcntl.rs
-new file mode 100644
-index 0000000000000..be6ee0f73a8be
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/fcntl.rs
-@@ -0,0 +1,506 @@
-+use {Error, Result, NixPath};
-+use errno::Errno;
-+use libc::{self, c_int, c_uint, c_char, size_t, ssize_t};
-+use sys::stat::Mode;
-+use std::os::raw;
-+use std::os::unix::io::RawFd;
-+use std::ffi::OsStr;
-+use std::os::unix::ffi::OsStrExt;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use std::ptr; // For splice and copy_file_range
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use sys::uio::IoVec;  // For vmsplice
-+
-+#[cfg(any(target_os = "linux",
-+          target_os = "android",
-+          target_os = "emscripten",
-+          target_os = "fuchsia",
-+          any(target_os = "wasi", target_env = "wasi"),
-+          target_env = "uclibc",
-+          target_env = "freebsd"))]
-+pub use self::posix_fadvise::*;
-+
-+libc_bitflags!{
-+    pub struct AtFlags: c_int {
-+        AT_REMOVEDIR;
-+        AT_SYMLINK_NOFOLLOW;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        AT_NO_AUTOMOUNT;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        AT_EMPTY_PATH;
-+    }
-+}
-+
-+libc_bitflags!(
-+    /// Configuration options for opened files.
-+    pub struct OFlag: c_int {
-+        /// Mask for the access mode of the file.
-+        O_ACCMODE;
-+        /// Use alternate I/O semantics.
-+        #[cfg(target_os = "netbsd")]
-+        O_ALT_IO;
-+        /// Open the file in append-only mode.
-+        O_APPEND;
-+        /// Generate a signal when input or output becomes possible.
-+        O_ASYNC;
-+        /// Closes the file descriptor once an `execve` call is made.
-+        ///
-+        /// Also sets the file offset to the beginning of the file.
-+        O_CLOEXEC;
-+        /// Create the file if it does not exist.
-+        O_CREAT;
-+        /// Try to minimize cache effects of the I/O for this file.
-+        #[cfg(any(target_os = "android",
-+                  target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd"))]
-+        O_DIRECT;
-+        /// If the specified path isn't a directory, fail.
-+        O_DIRECTORY;
-+        /// Implicitly follow each `write()` with an `fdatasync()`.
-+        #[cfg(any(target_os = "android",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        O_DSYNC;
-+        /// Error out if a file was not created.
-+        O_EXCL;
-+        /// Open for execute only.
-+        #[cfg(target_os = "freebsd")]
-+        O_EXEC;
-+        /// Open with an exclusive file lock.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        O_EXLOCK;
-+        /// Same as `O_SYNC`.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  all(target_os = "linux", not(target_env = "musl")),
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        O_FSYNC;
-+        /// Allow files whose sizes can't be represented in an `off_t` to be opened.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        O_LARGEFILE;
-+        /// Do not update the file last access time during `read(2)`s.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        O_NOATIME;
-+        /// Don't attach the device as the process' controlling terminal.
-+        O_NOCTTY;
-+        /// Same as `O_NONBLOCK`.
-+        O_NDELAY;
-+        /// `open()` will fail if the given path is a symbolic link.
-+        O_NOFOLLOW;
-+        /// When possible, open the file in nonblocking mode.
-+        O_NONBLOCK;
-+        /// Don't deliver `SIGPIPE`.
-+        #[cfg(target_os = "netbsd")]
-+        O_NOSIGPIPE;
-+        /// Obtain a file descriptor for low-level access.
-+        ///
-+        /// The file itself is not opened and other file operations will fail.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        O_PATH;
-+        /// Only allow reading.
-+        ///
-+        /// This should not be combined with `O_WRONLY` or `O_RDWR`.
-+        O_RDONLY;
-+        /// Allow both reading and writing.
-+        ///
-+        /// This should not be combined with `O_WRONLY` or `O_RDONLY`.
-+        O_RDWR;
-+        /// Similar to `O_DSYNC` but applies to `read`s instead.
-+        #[cfg(any(target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
-+        O_RSYNC;
-+        /// Skip search permission checks.
-+        #[cfg(target_os = "netbsd")]
-+        O_SEARCH;
-+        /// Open with a shared file lock.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        O_SHLOCK;
-+        /// Implicitly follow each `write()` with an `fsync()`.
-+        O_SYNC;
-+        /// Create an unnamed temporary file.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        O_TMPFILE;
-+        /// Truncate an existing regular file to 0 length if it allows writing.
-+        O_TRUNC;
-+        /// Restore default TTY attributes.
-+        #[cfg(target_os = "freebsd")]
-+        O_TTY_INIT;
-+        /// Only allow writing.
-+        ///
-+        /// This should not be combined with `O_RDONLY` or `O_RDWR`.
-+        O_WRONLY;
-+    }
-+);
-+
-+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) }
-+    })?;
-+
-+    Errno::result(fd)
-+}
-+
-+pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
-+    let fd = path.with_nix_path(|cstr| {
-+        unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
-+    })?;
-+    Errno::result(fd)
-+}
-+
-+pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<RawFd>, old_path: &P1,
-+                                                            new_dirfd: Option<RawFd>, new_path: &P2)
-+                                                            -> Result<()> {
-+    let res = old_path.with_nix_path(|old_cstr| {
-+        new_path.with_nix_path(|new_cstr| unsafe {
-+            libc::renameat(at_rawfd(old_dirfd), old_cstr.as_ptr(),
-+                           at_rawfd(new_dirfd), new_cstr.as_ptr())
-+        })
-+    })??;
-+    Errno::result(res).map(drop)
-+}
-+
-+fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
-+    match Errno::result(res) {
-+        Err(err) => Err(err),
-+        Ok(len) => {
-+            if (len as usize) >= buffer.len() {
-+                Err(Error::Sys(Errno::ENAMETOOLONG))
-+            } else {
-+                Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
-+            }
-+        }
-+    }
-+}
-+
-+pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
-+    })?;
-+
-+    wrap_readlink_result(buffer, res)
-+}
-+
-+
-+pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
-+    })?;
-+
-+    wrap_readlink_result(buffer, res)
-+}
-+
-+/// Computes the raw fd consumed by a function of the form `*at`.
-+pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
-+    match fd {
-+        None => libc::AT_FDCWD,
-+        Some(fd) => fd,
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+libc_bitflags!(
-+    /// Additional flags for file sealing, which allows for limiting operations on a file.
-+    pub struct SealFlag: c_int {
-+        /// Prevents further calls to `fcntl()` with `F_ADD_SEALS`.
-+        F_SEAL_SEAL;
-+        /// The file cannot be reduced in size.
-+        F_SEAL_SHRINK;
-+        /// The size of the file cannot be increased.
-+        F_SEAL_GROW;
-+        /// The file contents cannot be modified.
-+        F_SEAL_WRITE;
-+    }
-+);
-+
-+libc_bitflags!(
-+    /// Additional configuration flags for `fcntl`'s `F_SETFD`.
-+    pub struct FdFlag: c_int {
-+        /// The file descriptor will automatically be closed during a successful `execve(2)`.
-+        FD_CLOEXEC;
-+    }
-+);
-+
-+#[derive(Debug, Eq, Hash, PartialEq)]
-+pub enum FcntlArg<'a> {
-+    F_DUPFD(RawFd),
-+    F_DUPFD_CLOEXEC(RawFd),
-+    F_GETFD,
-+    F_SETFD(FdFlag), // FD_FLAGS
-+    F_GETFL,
-+    F_SETFL(OFlag), // O_NONBLOCK
-+    F_SETLK(&'a libc::flock),
-+    F_SETLKW(&'a libc::flock),
-+    F_GETLK(&'a mut libc::flock),
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    F_OFD_SETLK(&'a libc::flock),
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    F_OFD_SETLKW(&'a libc::flock),
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    F_OFD_GETLK(&'a mut libc::flock),
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    F_ADD_SEALS(SealFlag),
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    F_GET_SEALS,
-+    #[cfg(any(target_os = "macos", target_os = "ios"))]
-+    F_FULLFSYNC,
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    F_GETPIPE_SZ,
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    F_SETPIPE_SZ(c_int),
-+
-+    // TODO: Rest of flags
-+}
-+pub use self::FcntlArg::*;
-+
-+// TODO: Figure out how to handle value fcntl returns
-+pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
-+    let res = unsafe {
-+        match arg {
-+            F_DUPFD(rawfd) => libc::fcntl(fd, libc::F_DUPFD, rawfd),
-+            F_DUPFD_CLOEXEC(rawfd) => libc::fcntl(fd, libc::F_DUPFD_CLOEXEC, rawfd),
-+            F_GETFD => libc::fcntl(fd, libc::F_GETFD),
-+            F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
-+            F_GETFL => libc::fcntl(fd, libc::F_GETFL),
-+            F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
-+            F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
-+            F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
-+            F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
-+            #[cfg(any(target_os = "macos", target_os = "ios"))]
-+            F_FULLFSYNC => libc::fcntl(fd, libc::F_FULLFSYNC),
-+            #[cfg(any(target_os = "linux", target_os = "android"))]
-+            F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
-+            #[cfg(any(target_os = "linux", target_os = "android"))]
-+            F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
-+            #[cfg(any(target_os = "linux", target_os = "android"))]
-+            _ => unimplemented!()
-+        }
-+    };
-+
-+    Errno::result(res)
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum FlockArg {
-+    LockShared,
-+    LockExclusive,
-+    Unlock,
-+    LockSharedNonblock,
-+    LockExclusiveNonblock,
-+    UnlockNonblock,
-+}
-+
-+pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
-+    use self::FlockArg::*;
-+
-+    let res = unsafe {
-+        match arg {
-+            LockShared => libc::flock(fd, libc::LOCK_SH),
-+            LockExclusive => libc::flock(fd, libc::LOCK_EX),
-+            Unlock => libc::flock(fd, libc::LOCK_UN),
-+            LockSharedNonblock => libc::flock(fd, libc::LOCK_SH | libc::LOCK_NB),
-+            LockExclusiveNonblock => libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB),
-+            UnlockNonblock => libc::flock(fd, libc::LOCK_UN | libc::LOCK_NB),
-+        }
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+libc_bitflags! {
-+    /// Additional flags to `splice` and friends.
-+    pub struct SpliceFFlags: c_uint {
-+        /// Request that pages be moved instead of copied.
-+        ///
-+        /// Not applicable to `vmsplice`.
-+        SPLICE_F_MOVE;
-+        /// Do not block on I/O.
-+        SPLICE_F_NONBLOCK;
-+        /// Hint that more data will be coming in a subsequent splice.
-+        ///
-+        /// Not applicable to `vmsplice`.
-+        SPLICE_F_MORE;
-+        /// Gift the user pages to the kernel.
-+        ///
-+        /// Not applicable to `splice`.
-+        SPLICE_F_GIFT;
-+    }
-+}
-+
-+/// Copy a range of data from one file to another
-+///
-+/// The `copy_file_range` system call performs an in-kernel copy between
-+/// file descriptors `fd_in` and `fd_out` without the additional cost of
-+/// transferring data from the kernel to user space and then back into the
-+/// kernel. It copies up to `len` bytes of data from file descriptor `fd_in` to
-+/// file descriptor `fd_out`, overwriting any data that exists within the
-+/// requested range of the target file.
-+///
-+/// If the `off_in` and/or `off_out` arguments are used, the values
-+/// will be mutated to reflect the new position within the file after
-+/// copying. If they are not used, the relevant filedescriptors will be seeked
-+/// to the new position.
-+///
-+/// On successful completion the number of bytes actually copied will be
-+/// returned.
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub fn copy_file_range(
-+    fd_in: RawFd,
-+    off_in: Option<&mut libc::loff_t>,
-+    fd_out: RawFd,
-+    off_out: Option<&mut libc::loff_t>,
-+    len: usize,
-+) -> Result<usize> {
-+    let off_in = off_in
-+        .map(|offset| offset as *mut libc::loff_t)
-+        .unwrap_or(ptr::null_mut());
-+    let off_out = off_out
-+        .map(|offset| offset as *mut libc::loff_t)
-+        .unwrap_or(ptr::null_mut());
-+
-+    let ret = unsafe {
-+        libc::syscall(
-+            libc::SYS_copy_file_range,
-+            fd_in,
-+            off_in,
-+            fd_out,
-+            off_out,
-+            len,
-+            0,
-+        )
-+    };
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn splice(
-+    fd_in: RawFd,
-+    off_in: Option<&mut libc::loff_t>,
-+    fd_out: RawFd,
-+    off_out: Option<&mut libc::loff_t>,
-+    len: usize,
-+    flags: SpliceFFlags,
-+) -> Result<usize> {
-+    let off_in = off_in
-+        .map(|offset| offset as *mut libc::loff_t)
-+        .unwrap_or(ptr::null_mut());
-+    let off_out = off_out
-+        .map(|offset| offset as *mut libc::loff_t)
-+        .unwrap_or(ptr::null_mut());
-+
-+    let ret = unsafe {
-+        libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
-+    };
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Result<usize> {
-+    let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<usize> {
-+    let ret = unsafe {
-+        libc::vmsplice(fd, iov.as_ptr() as *const libc::iovec, iov.len(), flags.bits())
-+    };
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+#[cfg(any(target_os = "linux"))]
-+libc_bitflags!(
-+    /// Mode argument flags for fallocate determining operation performed on a given range.
-+    pub struct FallocateFlags: c_int {
-+        /// File size is not changed.
-+        ///
-+        /// offset + len can be greater than file size.
-+        FALLOC_FL_KEEP_SIZE;
-+        /// Deallocates space by creating a hole.
-+        ///
-+        /// Must be ORed with FALLOC_FL_KEEP_SIZE. Byte range starts at offset and continues for len bytes.
-+        FALLOC_FL_PUNCH_HOLE;
-+        /// Removes byte range from a file without leaving a hole.
-+        ///
-+        /// Byte range to collapse starts at offset and continues for len bytes.
-+        FALLOC_FL_COLLAPSE_RANGE;
-+        /// Zeroes space in specified byte range.
-+        ///
-+        /// Byte range starts at offset and continues for len bytes.
-+        FALLOC_FL_ZERO_RANGE;
-+        /// Increases file space by inserting a hole within the file size.
-+        ///
-+        /// Does not overwrite existing data. Hole starts at offset and continues for len bytes.
-+        FALLOC_FL_INSERT_RANGE;
-+        /// Shared file data extants are made private to the file.
-+        ///
-+        /// Gaurantees that a subsequent write will not fail due to lack of space.
-+        FALLOC_FL_UNSHARE_RANGE;
-+    }
-+);
-+
-+/// Manipulates file space.
-+///
-+/// Allows the caller to directly manipulate the allocated disk space for the
-+/// file referred to by fd.
-+#[cfg(any(target_os = "linux"))]
-+pub fn fallocate(fd: RawFd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t) -> Result<c_int> {
-+    let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
-+    Errno::result(res)
-+}
-+
-+#[cfg(any(target_os = "linux",
-+          target_os = "android",
-+          target_os = "emscripten",
-+          target_os = "fuchsia",
-+          any(target_os = "wasi", target_env = "wasi"),
-+          target_env = "uclibc",
-+          target_env = "freebsd"))]
-+mod posix_fadvise {
-+    use Result;
-+    use libc;
-+    use errno::Errno;
-+    use std::os::unix::io::RawFd;
-+
-+    libc_enum! {
-+        #[repr(i32)]
-+        pub enum PosixFadviseAdvice {
-+            POSIX_FADV_NORMAL,
-+            POSIX_FADV_SEQUENTIAL,
-+            POSIX_FADV_RANDOM,
-+            POSIX_FADV_NOREUSE,
-+            POSIX_FADV_WILLNEED,
-+            POSIX_FADV_DONTNEED,
-+        }
-+    }
-+
-+    pub fn posix_fadvise(fd: RawFd,
-+                         offset: libc::off_t,
-+                         len: libc::off_t,
-+                         advice: PosixFadviseAdvice) -> Result<libc::c_int> {
-+        let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
-+        Errno::result(res)
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/features.rs b/third_party/rust/nix-0.15.0/src/features.rs
-new file mode 100644
-index 0000000000000..76cdfd3a1a6f1
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/features.rs
-@@ -0,0 +1,103 @@
-+//! Feature tests for OS functionality
-+pub use self::os::*;
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+mod os {
-+    use sys::utsname::uname;
-+
-+    // Features:
-+    // * atomic cloexec on socket: 2.6.27
-+    // * pipe2: 2.6.27
-+    // * accept4: 2.6.28
-+
-+    static VERS_UNKNOWN: usize = 1;
-+    static VERS_2_6_18:  usize = 2;
-+    static VERS_2_6_27:  usize = 3;
-+    static VERS_2_6_28:  usize = 4;
-+    static VERS_3:       usize = 5;
-+
-+    #[inline]
-+    fn digit(dst: &mut usize, b: u8) {
-+        *dst *= 10;
-+        *dst += (b - b'0') as usize;
-+    }
-+
-+    fn parse_kernel_version() -> usize {
-+        let u = uname();
-+
-+        let mut curr:  usize = 0;
-+        let mut major: usize = 0;
-+        let mut minor: usize = 0;
-+        let mut patch: usize = 0;
-+
-+        for b in u.release().bytes() {
-+            if curr >= 3 {
-+                break;
-+            }
-+
-+            match b {
-+                b'.' | b'-' => {
-+                    curr += 1;
-+                }
-+                b'0'..=b'9' => {
-+                    match curr {
-+                        0 => digit(&mut major, b),
-+                        1 => digit(&mut minor, b),
-+                        _ => digit(&mut patch, b),
-+                    }
-+                }
-+                _ => break,
-+            }
-+        }
-+
-+        if major >= 3 {
-+            VERS_3
-+        } else if major >= 2 {
-+            if minor >= 7 {
-+                VERS_UNKNOWN
-+            } else if minor >= 6 {
-+                if patch >= 28 {
-+                    VERS_2_6_28
-+                } else if patch >= 27 {
-+                    VERS_2_6_27
-+                } else {
-+                    VERS_2_6_18
-+                }
-+            } else {
-+                VERS_UNKNOWN
-+            }
-+        } else {
-+            VERS_UNKNOWN
-+        }
-+    }
-+
-+    fn kernel_version() -> usize {
-+        static mut KERNEL_VERS: usize = 0;
-+
-+        unsafe {
-+            if KERNEL_VERS == 0 {
-+                KERNEL_VERS = parse_kernel_version();
-+            }
-+
-+            KERNEL_VERS
-+        }
-+    }
-+
-+    /// Check if the OS supports atomic close-on-exec for sockets
-+    pub fn socket_atomic_cloexec() -> bool {
-+        kernel_version() >= VERS_2_6_27
-+    }
-+
-+    #[test]
-+    pub fn test_parsing_kernel_version() {
-+        assert!(kernel_version() > 0);
-+    }
-+}
-+
-+#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))]
-+mod os {
-+    /// Check if the OS supports atomic close-on-exec for sockets
-+    pub fn socket_atomic_cloexec() -> bool {
-+        false
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/ifaddrs.rs b/third_party/rust/nix-0.15.0/src/ifaddrs.rs
-new file mode 100644
-index 0000000000000..12b59bcc92bef
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/ifaddrs.rs
-@@ -0,0 +1,146 @@
-+//! Query network interface addresses
-+//!
-+//! Uses the Linux and/or BSD specific function `getifaddrs` to query the list
-+//! of interfaces and their associated addresses.
-+
-+use std::ffi;
-+use std::iter::Iterator;
-+use std::mem;
-+use std::option::Option;
-+
-+use libc;
-+
-+use {Result, Errno};
-+use sys::socket::SockAddr;
-+use net::if_::*;
-+
-+/// Describes a single address for an interface as returned by `getifaddrs`.
-+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct InterfaceAddress {
-+    /// Name of the network interface
-+    pub interface_name: String,
-+    /// Flags as from `SIOCGIFFLAGS` ioctl
-+    pub flags: InterfaceFlags,
-+    /// Network address of this interface
-+    pub address: Option<SockAddr>,
-+    /// Netmask of this interface
-+    pub netmask: Option<SockAddr>,
-+    /// Broadcast address of this interface, if applicable
-+    pub broadcast: Option<SockAddr>,
-+    /// Point-to-point destination address
-+    pub destination: Option<SockAddr>,
-+}
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "fuchsia", target_os = "linux"))] {
-+        fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
-+            info.ifa_ifu
-+        }
-+    } else {
-+        fn get_ifu_from_sockaddr(info: &libc::ifaddrs) -> *const libc::sockaddr {
-+            info.ifa_dstaddr
-+        }
-+    }
-+}
-+
-+impl InterfaceAddress {
-+    /// Create an `InterfaceAddress` from the libc struct.
-+    fn from_libc_ifaddrs(info: &libc::ifaddrs) -> InterfaceAddress {
-+        let ifname = unsafe { ffi::CStr::from_ptr(info.ifa_name) };
-+        let address = unsafe { SockAddr::from_libc_sockaddr(info.ifa_addr) };
-+        let netmask = unsafe { SockAddr::from_libc_sockaddr(info.ifa_netmask) };
-+        let mut addr = InterfaceAddress {
-+            interface_name: ifname.to_string_lossy().to_string(),
-+            flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
-+            address: address,
-+            netmask: netmask,
-+            broadcast: None,
-+            destination: None,
-+        };
-+
-+        let ifu = get_ifu_from_sockaddr(info);
-+        if addr.flags.contains(InterfaceFlags::IFF_POINTOPOINT) {
-+            addr.destination = unsafe { SockAddr::from_libc_sockaddr(ifu) };
-+        } else if addr.flags.contains(InterfaceFlags::IFF_BROADCAST) {
-+            addr.broadcast = unsafe { SockAddr::from_libc_sockaddr(ifu) };
-+        }
-+
-+        addr
-+    }
-+}
-+
-+/// Holds the results of `getifaddrs`.
-+///
-+/// Use the function `getifaddrs` to create this Iterator. Note that the
-+/// actual list of interfaces can be iterated once and will be freed as
-+/// soon as the Iterator goes out of scope.
-+#[derive(Debug, Eq, Hash, PartialEq)]
-+pub struct InterfaceAddressIterator {
-+    base: *mut libc::ifaddrs,
-+    next: *mut libc::ifaddrs,
-+}
-+
-+impl Drop for InterfaceAddressIterator {
-+    fn drop(&mut self) {
-+        unsafe { libc::freeifaddrs(self.base) };
-+    }
-+}
-+
-+impl Iterator for InterfaceAddressIterator {
-+    type Item = InterfaceAddress;
-+    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
-+        match unsafe { self.next.as_ref() } {
-+            Some(ifaddr) => {
-+                self.next = ifaddr.ifa_next;
-+                Some(InterfaceAddress::from_libc_ifaddrs(ifaddr))
-+            }
-+            None => None,
-+        }
-+    }
-+}
-+
-+/// Get interface addresses using libc's `getifaddrs`
-+///
-+/// Note that the underlying implementation differs between OSes. Only the
-+/// most common address families are supported by the nix crate (due to
-+/// lack of time and complexity of testing). The address family is encoded
-+/// in the specific variant of `SockAddr` returned for the fields `address`,
-+/// `netmask`, `broadcast`, and `destination`. For any entry not supported,
-+/// the returned list will contain a `None` entry.
-+///
-+/// # Example
-+/// ```
-+/// let addrs = nix::ifaddrs::getifaddrs().unwrap();
-+/// for ifaddr in addrs {
-+///   match ifaddr.address {
-+///     Some(address) => {
-+///       println!("interface {} address {}",
-+///                ifaddr.interface_name, address);
-+///     },
-+///     None => {
-+///       println!("interface {} with unsupported address family",
-+///                ifaddr.interface_name);
-+///     }
-+///   }
-+/// }
-+/// ```
-+pub fn getifaddrs() -> Result<InterfaceAddressIterator> {
-+    let mut addrs: *mut libc::ifaddrs = unsafe { mem::uninitialized() };
-+    Errno::result(unsafe { libc::getifaddrs(&mut addrs) }).map(|_| {
-+        InterfaceAddressIterator {
-+            base: addrs,
-+            next: addrs,
-+        }
-+    })
-+}
-+
-+#[cfg(test)]
-+mod tests {
-+    use super::*;
-+
-+    // Only checks if `getifaddrs` can be invoked without panicking.
-+    #[test]
-+    fn test_getifaddrs() {
-+        let _ = getifaddrs();
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/kmod.rs b/third_party/rust/nix-0.15.0/src/kmod.rs
-new file mode 100644
-index 0000000000000..e853261b14f9d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/kmod.rs
-@@ -0,0 +1,123 @@
-+//! Load and unload kernel modules.
-+//!
-+//! For more details see
-+
-+use libc;
-+use std::ffi::CStr;
-+use std::os::unix::io::AsRawFd;
-+
-+use errno::Errno;
-+use Result;
-+
-+/// Loads a kernel module from a buffer.
-+///
-+/// It loads an ELF image into kernel space,
-+/// performs any necessary symbol relocations,
-+/// initializes module parameters to values provided by the caller,
-+/// and then runs the module's init function.
-+///
-+/// This function requires `CAP_SYS_MODULE` privilege.
-+///
-+/// The `module_image` argument points to a buffer containing the binary image
-+/// to be loaded. The buffer should contain a valid ELF image
-+/// built for the running kernel.
-+///
-+/// The `param_values` argument is a string containing space-delimited specifications
-+/// of the values for module parameters.
-+/// Each of the parameter specifications has the form:
-+///
-+/// `name[=value[,value...]]`
-+///
-+/// # Example
-+///
-+/// ```no_run
-+/// use std::fs::File;
-+/// use std::io::Read;
-+/// use std::ffi::CString;
-+/// use nix::kmod::init_module;
-+///
-+/// let mut f = File::open("mykernel.ko").unwrap();
-+/// let mut contents: Vec<u8> = Vec::new();
-+/// f.read_to_end(&mut contents).unwrap();
-+/// 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.
-+pub fn init_module(module_image: &[u8], param_values: &CStr) -> Result<()> {
-+    let res = unsafe {
-+        libc::syscall(
-+            libc::SYS_init_module,
-+            module_image.as_ptr(),
-+            module_image.len(),
-+            param_values.as_ptr(),
-+        )
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+libc_bitflags!(
-+    /// Flags used by the `finit_module` function.
-+    pub struct ModuleInitFlags: libc::c_uint {
-+        /// Ignore symbol version hashes.
-+        MODULE_INIT_IGNORE_MODVERSIONS;
-+        /// Ignore kernel version magic.
-+        MODULE_INIT_IGNORE_VERMAGIC;
-+    }
-+);
-+
-+/// Loads a kernel module from a given file descriptor.
-+///
-+/// # Example
-+///
-+/// ```no_run
-+/// use std::fs::File;
-+/// use std::ffi::CString;
-+/// use nix::kmod::{finit_module, ModuleInitFlags};
-+///
-+/// let f = File::open("mymod.ko").unwrap();
-+/// 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.
-+pub fn finit_module<T: AsRawFd>(fd: &T, param_values: &CStr, flags: ModuleInitFlags) -> Result<()> {
-+    let res = unsafe {
-+        libc::syscall(
-+            libc::SYS_finit_module,
-+            fd.as_raw_fd(),
-+            param_values.as_ptr(),
-+            flags.bits(),
-+        )
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+libc_bitflags!(
-+    /// Flags used by `delete_module`.
-+    ///
-+    /// See [`man delete_module(2)`](http://man7.org/linux/man-pages/man2/delete_module.2.html)
-+    /// for a detailed description how these flags work.
-+    pub struct DeleteModuleFlags: libc::c_int {
-+        O_NONBLOCK;
-+        O_TRUNC;
-+    }
-+);
-+
-+/// Unloads the kernel module with the given name.
-+///
-+/// # Example
-+///
-+/// ```no_run
-+/// use std::ffi::CString;
-+/// use nix::kmod::{delete_module, DeleteModuleFlags};
-+///
-+/// 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.
-+pub fn delete_module(name: &CStr, flags: DeleteModuleFlags) -> Result<()> {
-+    let res = unsafe { libc::syscall(libc::SYS_delete_module, name.as_ptr(), flags.bits()) };
-+
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/lib.rs b/third_party/rust/nix-0.15.0/src/lib.rs
-new file mode 100644
-index 0000000000000..71485d2af1824
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/lib.rs
-@@ -0,0 +1,284 @@
-+//! Rust friendly bindings to the various *nix system functions.
-+//!
-+//! Modules are structured according to the C header file that they would be
-+//! defined in.
-+#![crate_name = "nix"]
-+#![cfg(unix)]
-+#![allow(non_camel_case_types)]
-+// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
-+// warnings even though the macro expands into something with allow(dead_code)
-+#![allow(dead_code)]
-+#![cfg_attr(test, deny(warnings))]
-+#![recursion_limit = "500"]
-+#![deny(unused)]
-+#![deny(unstable_features)]
-+#![deny(missing_copy_implementations)]
-+#![deny(missing_debug_implementations)]
-+// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
-+#![allow(deprecated)]
-+
-+// External crates
-+#[macro_use]
-+extern crate bitflags;
-+#[macro_use]
-+extern crate cfg_if;
-+extern crate void;
-+
-+// Re-exported external crates
-+pub extern crate libc;
-+
-+// Private internal modules
-+#[macro_use] mod macros;
-+
-+// Public crates
-+pub mod dir;
-+pub mod errno;
-+#[deny(missing_docs)]
-+pub mod features;
-+pub mod fcntl;
-+#[deny(missing_docs)]
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub mod ifaddrs;
-+#[cfg(any(target_os = "android",
-+          target_os = "linux"))]
-+pub mod kmod;
-+#[cfg(any(target_os = "android",
-+          target_os = "linux"))]
-+pub mod mount;
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "fushsia",
-+          target_os = "linux",
-+          target_os = "netbsd"))]
-+pub mod mqueue;
-+#[deny(missing_docs)]
-+pub mod net;
-+#[deny(missing_docs)]
-+pub mod poll;
-+#[deny(missing_docs)]
-+pub mod pty;
-+pub mod sched;
-+pub mod sys;
-+// This can be implemented for other platforms as soon as libc
-+// provides bindings for them.
-+#[cfg(all(target_os = "linux",
-+          any(target_arch = "x86", target_arch = "x86_64")))]
-+pub mod ucontext;
-+pub mod unistd;
-+
-+/*
-+ *
-+ * ===== Result / Error =====
-+ *
-+ */
-+
-+use libc::{c_char, PATH_MAX};
-+
-+use std::{error, fmt, ptr, result};
-+use std::ffi::{CStr, OsStr};
-+use std::os::unix::ffi::OsStrExt;
-+use std::path::{Path, PathBuf};
-+
-+use errno::Errno;
-+
-+/// Nix Result Type
-+pub type Result<T> = result::Result<T, Error>;
-+
-+/// Nix Error Type
-+///
-+/// The nix error type provides a common way of dealing with
-+/// various system system/libc calls that might fail.  Each
-+/// error has a corresponding errno (usually the one from the
-+/// underlying OS) to which it can be mapped in addition to
-+/// implementing other common traits.
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub enum Error {
-+    Sys(Errno),
-+    InvalidPath,
-+    /// The operation involved a conversion to Rust's native String type, which failed because the
-+    /// string did not contain all valid UTF-8.
-+    InvalidUtf8,
-+    /// The operation is not supported by Nix, in this instance either use the libc bindings or
-+    /// consult the module documentation to see if there is a more appropriate interface available.
-+    UnsupportedOperation,
-+}
-+
-+impl Error {
-+    /// Convert this `Error` to an [`Errno`](enum.Errno.html).
-+    ///
-+    /// # Example
-+    ///
-+    /// ```
-+    /// # use nix::Error;
-+    /// # use nix::errno::Errno;
-+    /// let e = Error::from(Errno::EPERM);
-+    /// assert_eq!(Some(Errno::EPERM), e.as_errno());
-+    /// ```
-+    pub fn as_errno(&self) -> Option<Errno> {
-+        if let &Error::Sys(ref e) = self {
-+            Some(*e)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Create a nix Error from a given errno
-+    pub fn from_errno(errno: Errno) -> Error {
-+        Error::Sys(errno)
-+    }
-+
-+    /// Get the current errno and convert it to a nix Error
-+    pub fn last() -> Error {
-+        Error::Sys(Errno::last())
-+    }
-+
-+    /// Create a new invalid argument error (`EINVAL`)
-+    pub fn invalid_argument() -> Error {
-+        Error::Sys(Errno::EINVAL)
-+    }
-+
-+}
-+
-+impl From<Errno> for Error {
-+    fn from(errno: Errno) -> Error { Error::from_errno(errno) }
-+}
-+
-+impl From<std::string::FromUtf8Error> for Error {
-+    fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
-+}
-+
-+impl error::Error for Error {
-+    fn description(&self) -> &str {
-+        match *self {
-+            Error::InvalidPath => "Invalid path",
-+            Error::InvalidUtf8 => "Invalid UTF-8 string",
-+            Error::UnsupportedOperation => "Unsupported Operation",
-+            Error::Sys(ref errno) => errno.desc(),
-+        }
-+    }
-+}
-+
-+impl fmt::Display for Error {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        match *self {
-+            Error::InvalidPath => write!(f, "Invalid path"),
-+            Error::InvalidUtf8 => write!(f, "Invalid UTF-8 string"),
-+            Error::UnsupportedOperation => write!(f, "Unsupported Operation"),
-+            Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
-+        }
-+    }
-+}
-+
-+pub trait NixPath {
-+    fn len(&self) -> usize;
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-+        where F: FnOnce(&CStr) -> T;
-+}
-+
-+impl NixPath for str {
-+    fn len(&self) -> usize {
-+        NixPath::len(OsStr::new(self))
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-+        where F: FnOnce(&CStr) -> T {
-+            OsStr::new(self).with_nix_path(f)
-+        }
-+}
-+
-+impl NixPath for OsStr {
-+    fn len(&self) -> usize {
-+        self.as_bytes().len()
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-+        where F: FnOnce(&CStr) -> T {
-+            self.as_bytes().with_nix_path(f)
-+        }
-+}
-+
-+impl NixPath for CStr {
-+    fn len(&self) -> usize {
-+        self.to_bytes().len()
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-+            where F: FnOnce(&CStr) -> T {
-+        // Equivalence with the [u8] impl.
-+        if self.len() >= PATH_MAX as usize {
-+            return Err(Error::InvalidPath);
-+        }
-+
-+        Ok(f(self))
-+    }
-+}
-+
-+impl NixPath for [u8] {
-+    fn len(&self) -> usize {
-+        self.len()
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-+            where F: FnOnce(&CStr) -> T {
-+        let mut buf = [0u8; PATH_MAX as usize];
-+
-+        if self.len() >= PATH_MAX as usize {
-+            return Err(Error::InvalidPath);
-+        }
-+
-+        match self.iter().position(|b| *b == 0) {
-+            Some(_) => Err(Error::InvalidPath),
-+            None => {
-+                unsafe {
-+                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
-+                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
-+                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
-+                }
-+
-+            }
-+        }
-+    }
-+}
-+
-+impl NixPath for Path {
-+    fn len(&self) -> usize {
-+        NixPath::len(self.as_os_str())
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
-+        self.as_os_str().with_nix_path(f)
-+    }
-+}
-+
-+impl NixPath for PathBuf {
-+    fn len(&self) -> usize {
-+        NixPath::len(self.as_os_str())
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
-+        self.as_os_str().with_nix_path(f)
-+    }
-+}
-+
-+/// Treats `None` as an empty string.
-+impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
-+    fn len(&self) -> usize {
-+        self.map_or(0, NixPath::len)
-+    }
-+
-+    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
-+        if let Some(nix_path) = *self {
-+            nix_path.with_nix_path(f)
-+        } else {
-+            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/macros.rs b/third_party/rust/nix-0.15.0/src/macros.rs
-new file mode 100644
-index 0000000000000..3d1b0e4b7699c
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/macros.rs
-@@ -0,0 +1,264 @@
-+/// The `libc_bitflags!` macro helps with a common use case of defining a public bitflags type
-+/// with values from the libc crate. It is used the same way as the `bitflags!` macro, except
-+/// that only the name of the flag value has to be given.
-+///
-+/// The `libc` crate must be in scope with the name `libc`.
-+///
-+/// # Example
-+/// ```
-+/// libc_bitflags!{
-+///     pub struct ProtFlags: libc::c_int {
-+///         PROT_NONE;
-+///         PROT_READ;
-+///         /// PROT_WRITE enables write protect
-+///         PROT_WRITE;
-+///         PROT_EXEC;
-+///         #[cfg(any(target_os = "linux", target_os = "android"))]
-+///         PROT_GROWSDOWN;
-+///         #[cfg(any(target_os = "linux", target_os = "android"))]
-+///         PROT_GROWSUP;
-+///     }
-+/// }
-+/// ```
-+///
-+/// Example with casting, due to a mistake in libc. In this example, the
-+/// various flags have different types, so we cast the broken ones to the right
-+/// type.
-+///
-+/// ```
-+/// libc_bitflags!{
-+///     pub struct SaFlags: libc::c_ulong {
-+///         SA_NOCLDSTOP as libc::c_ulong;
-+///         SA_NOCLDWAIT;
-+///         SA_NODEFER as libc::c_ulong;
-+///         SA_ONSTACK;
-+///         SA_RESETHAND as libc::c_ulong;
-+///         SA_RESTART as libc::c_ulong;
-+///         SA_SIGINFO;
-+///     }
-+/// }
-+/// ```
-+macro_rules! libc_bitflags {
-+    (
-+        $(#[$outer:meta])*
-+        pub struct $BitFlags:ident: $T:ty {
-+            $(
-+                $(#[$inner:ident $($args:tt)*])*
-+                $Flag:ident $(as $cast:ty)*;
-+            )+
-+        }
-+    ) => {
-+        bitflags! {
-+            $(#[$outer])*
-+            pub struct $BitFlags: $T {
-+                $(
-+                    $(#[$inner $($args)*])*
-+                    const $Flag = libc::$Flag $(as $cast)*;
-+                )+
-+            }
-+        }
-+    };
-+}
-+
-+/// The `libc_enum!` macro helps with a common use case of defining an enum exclusively using
-+/// values from the `libc` crate. This macro supports both `pub` and private `enum`s.
-+///
-+/// The `libc` crate must be in scope with the name `libc`.
-+///
-+/// # Example
-+/// ```
-+/// libc_enum!{
-+///     pub enum ProtFlags {
-+///         PROT_NONE,
-+///         PROT_READ,
-+///         PROT_WRITE,
-+///         PROT_EXEC,
-+///         #[cfg(any(target_os = "linux", target_os = "android"))]
-+///         PROT_GROWSDOWN,
-+///         #[cfg(any(target_os = "linux", target_os = "android"))]
-+///         PROT_GROWSUP,
-+///     }
-+/// }
-+/// ```
-+macro_rules! libc_enum {
-+    // (non-pub) Exit rule.
-+    (@make_enum
-+        {
-+            name: $BitFlags:ident,
-+            attrs: [$($attrs:tt)*],
-+            entries: [$($entries:tt)*],
-+        }
-+    ) => {
-+        $($attrs)*
-+        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-+        enum $BitFlags {
-+            $($entries)*
-+        }
-+    };
-+
-+    // (pub) Exit rule.
-+    (@make_enum
-+        {
-+            pub,
-+            name: $BitFlags:ident,
-+            attrs: [$($attrs:tt)*],
-+            entries: [$($entries:tt)*],
-+        }
-+    ) => {
-+        $($attrs)*
-+        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
-+        pub enum $BitFlags {
-+            $($entries)*
-+        }
-+    };
-+
-+    // (non-pub) Done accumulating.
-+    (@accumulate_entries
-+        {
-+            name: $BitFlags:ident,
-+            attrs: $attrs:tt,
-+        },
-+        $entries:tt;
-+    ) => {
-+        libc_enum! {
-+            @make_enum
-+            {
-+                name: $BitFlags,
-+                attrs: $attrs,
-+                entries: $entries,
-+            }
-+        }
-+    };
-+
-+    // (pub) Done accumulating.
-+    (@accumulate_entries
-+        {
-+            pub,
-+            name: $BitFlags:ident,
-+            attrs: $attrs:tt,
-+        },
-+        $entries:tt;
-+    ) => {
-+        libc_enum! {
-+            @make_enum
-+            {
-+                pub,
-+                name: $BitFlags,
-+                attrs: $attrs,
-+                entries: $entries,
-+            }
-+        }
-+    };
-+
-+    // Munch an attr.
-+    (@accumulate_entries
-+        $prefix:tt,
-+        [$($entries:tt)*];
-+        #[$attr:meta] $($tail:tt)*
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            $prefix,
-+            [
-+                $($entries)*
-+                #[$attr]
-+            ];
-+            $($tail)*
-+        }
-+    };
-+
-+    // Munch last ident if not followed by a comma.
-+    (@accumulate_entries
-+        $prefix:tt,
-+        [$($entries:tt)*];
-+        $entry:ident
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            $prefix,
-+            [
-+                $($entries)*
-+                $entry = libc::$entry,
-+            ];
-+        }
-+    };
-+
-+    // Munch an ident; covers terminating comma case.
-+    (@accumulate_entries
-+        $prefix:tt,
-+        [$($entries:tt)*];
-+        $entry:ident, $($tail:tt)*
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            $prefix,
-+            [
-+                $($entries)*
-+                $entry = libc::$entry,
-+            ];
-+            $($tail)*
-+        }
-+    };
-+
-+    // Munch an ident and cast it to the given type; covers terminating comma.
-+    (@accumulate_entries
-+        $prefix:tt,
-+        [$($entries:tt)*];
-+        $entry:ident as $ty:ty, $($tail:tt)*
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            $prefix,
-+            [
-+                $($entries)*
-+                $entry = libc::$entry as $ty,
-+            ];
-+            $($tail)*
-+        }
-+    };
-+
-+    // (non-pub) Entry rule.
-+    (
-+        $(#[$attr:meta])*
-+        enum $BitFlags:ident {
-+            $($vals:tt)*
-+        }
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            {
-+                name: $BitFlags,
-+                attrs: [$(#[$attr])*],
-+            },
-+            [];
-+            $($vals)*
-+        }
-+    };
-+
-+    // (pub) Entry rule.
-+    (
-+        $(#[$attr:meta])*
-+        pub enum $BitFlags:ident {
-+            $($vals:tt)*
-+        }
-+    ) => {
-+        libc_enum! {
-+            @accumulate_entries
-+            {
-+                pub,
-+                name: $BitFlags,
-+                attrs: [$(#[$attr])*],
-+            },
-+            [];
-+            $($vals)*
-+        }
-+    };
-+}
-+
-+/// A Rust version of the familiar C `offset_of` macro.  It returns the byte
-+/// offset of `field` within struct `ty`
-+macro_rules! offset_of {
-+    ($ty:ty, $field:ident) => {
-+        &(*(0 as *const $ty)).$field as *const _ as usize
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/mount.rs b/third_party/rust/nix-0.15.0/src/mount.rs
-new file mode 100644
-index 0000000000000..a9902b170ace8
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/mount.rs
-@@ -0,0 +1,98 @@
-+use libc::{self, c_ulong, c_int};
-+use {Result, NixPath};
-+use errno::Errno;
-+
-+libc_bitflags!(
-+    pub struct MsFlags: c_ulong {
-+        /// Mount read-only
-+        MS_RDONLY;
-+        /// Ignore suid and sgid bits
-+        MS_NOSUID;
-+        /// Disallow access to device special files
-+        MS_NODEV;
-+        /// Disallow program execution
-+        MS_NOEXEC;
-+        /// Writes are synced at once
-+        MS_SYNCHRONOUS;
-+        /// Alter flags of a mounted FS
-+        MS_REMOUNT;
-+        /// Allow mandatory locks on a FS
-+        MS_MANDLOCK;
-+        /// Directory modifications are synchronous
-+        MS_DIRSYNC;
-+        /// Do not update access times
-+        MS_NOATIME;
-+        /// Do not update directory access times
-+        MS_NODIRATIME;
-+        /// Linux 2.4.0 - Bind directory at different place
-+        MS_BIND;
-+        MS_MOVE;
-+        MS_REC;
-+        MS_SILENT;
-+        MS_POSIXACL;
-+        MS_UNBINDABLE;
-+        MS_PRIVATE;
-+        MS_SLAVE;
-+        MS_SHARED;
-+        MS_RELATIME;
-+        MS_KERNMOUNT;
-+        MS_I_VERSION;
-+        MS_STRICTATIME;
-+        MS_ACTIVE;
-+        MS_NOUSER;
-+        MS_RMT_MASK;
-+        MS_MGC_VAL;
-+        MS_MGC_MSK;
-+    }
-+);
-+
-+libc_bitflags!(
-+    pub struct MntFlags: c_int {
-+        MNT_FORCE;
-+        MNT_DETACH;
-+        MNT_EXPIRE;
-+    }
-+);
-+
-+pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P4: ?Sized + NixPath>(
-+        source: Option<&P1>,
-+        target: &P2,
-+        fstype: Option<&P3>,
-+        flags: MsFlags,
-+        data: Option<&P4>) -> Result<()> {
-+
-+    let res =
-+        source.with_nix_path(|source| {
-+            target.with_nix_path(|target| {
-+                fstype.with_nix_path(|fstype| {
-+                    data.with_nix_path(|data| {
-+                        unsafe {
-+                            libc::mount(source.as_ptr(),
-+                                       target.as_ptr(),
-+                                       fstype.as_ptr(),
-+                                       flags.bits,
-+                                       data.as_ptr() as *const libc::c_void)
-+                        }
-+                    })
-+                })
-+            })
-+        })????;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+pub fn umount<P: ?Sized + NixPath>(target: &P) -> Result<()> {
-+    let res = target.with_nix_path(|cstr| {
-+        unsafe { libc::umount(cstr.as_ptr()) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+pub fn umount2<P: ?Sized + NixPath>(target: &P, flags: MntFlags) -> Result<()> {
-+    let res = target.with_nix_path(|cstr| {
-+        unsafe { libc::umount2(cstr.as_ptr(), flags.bits) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/mqueue.rs b/third_party/rust/nix-0.15.0/src/mqueue.rs
-new file mode 100644
-index 0000000000000..b958b71cddb46
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/mqueue.rs
-@@ -0,0 +1,162 @@
-+//! Posix Message Queue functions
-+//!
-+//! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
-+
-+use Result;
-+use errno::Errno;
-+
-+use libc::{self, c_char, c_long, mqd_t, size_t};
-+use std::ffi::CString;
-+use sys::stat::Mode;
-+use std::mem;
-+
-+libc_bitflags!{
-+    pub struct MQ_OFlag: libc::c_int {
-+        O_RDONLY;
-+        O_WRONLY;
-+        O_RDWR;
-+        O_CREAT;
-+        O_EXCL;
-+        O_NONBLOCK;
-+        O_CLOEXEC;
-+    }
-+}
-+
-+libc_bitflags!{
-+    pub struct FdFlag: libc::c_int {
-+        FD_CLOEXEC;
-+    }
-+}
-+
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct MqAttr {
-+    mq_attr: libc::mq_attr,
-+}
-+
-+impl MqAttr {
-+    pub fn new(mq_flags: c_long,
-+               mq_maxmsg: c_long,
-+               mq_msgsize: c_long,
-+               mq_curmsgs: c_long)
-+               -> MqAttr {
-+        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
-+        attr.mq_flags = mq_flags;
-+        attr.mq_maxmsg = mq_maxmsg;
-+        attr.mq_msgsize = mq_msgsize;
-+        attr.mq_curmsgs = mq_curmsgs;
-+        MqAttr { mq_attr: attr }
-+    }
-+
-+    pub fn flags(&self) -> c_long {
-+        self.mq_attr.mq_flags
-+    }
-+}
-+
-+
-+/// Open a message queue
-+///
-+/// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
-+pub fn mq_open(name: &CString,
-+               oflag: MQ_OFlag,
-+               mode: Mode,
-+               attr: Option<&MqAttr>)
-+               -> Result<mqd_t> {
-+    let res = match attr {
-+        Some(mq_attr) => unsafe {
-+            libc::mq_open(name.as_ptr(),
-+                          oflag.bits(),
-+                          mode.bits() as libc::c_int,
-+                          &mq_attr.mq_attr as *const libc::mq_attr)
-+        },
-+        None => unsafe { libc::mq_open(name.as_ptr(), oflag.bits()) },
-+    };
-+    Errno::result(res)
-+}
-+
-+/// Remove a message queue
-+///
-+/// See also [`mq_unlink(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_unlink.html)
-+pub fn mq_unlink(name: &CString) -> Result<()> {
-+    let res = unsafe { libc::mq_unlink(name.as_ptr()) };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Close a message queue
-+///
-+/// See also [`mq_close(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_close.html)
-+pub fn mq_close(mqdes: mqd_t) -> Result<()> {
-+    let res = unsafe { libc::mq_close(mqdes) };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Receive a message from a message queue
-+///
-+/// See also [`mq_receive(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_receive.html)
-+pub fn mq_receive(mqdes: mqd_t, message: &mut [u8], msg_prio: &mut u32) -> Result<usize> {
-+    let len = message.len() as size_t;
-+    let res = unsafe {
-+        libc::mq_receive(mqdes,
-+                         message.as_mut_ptr() as *mut c_char,
-+                         len,
-+                         msg_prio as *mut u32)
-+    };
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Send a message to a message queue
-+///
-+/// See also [`mq_send(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_send.html)
-+pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
-+    let res = unsafe {
-+        libc::mq_send(mqdes,
-+                      message.as_ptr() as *const c_char,
-+                      message.len(),
-+                      msq_prio)
-+    };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Get message queue attributes
-+///
-+/// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
-+pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
-+    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
-+    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
-+    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
-+}
-+
-+/// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
-+/// 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)
-+pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
-+    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
-+    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
-+    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
-+}
-+
-+/// Convenience function.
-+/// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
-+/// Returns the old attributes
-+pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
-+    let oldattr = mq_getattr(mqd)?;
-+    let newattr = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long,
-+                              oldattr.mq_attr.mq_maxmsg,
-+                              oldattr.mq_attr.mq_msgsize,
-+                              oldattr.mq_attr.mq_curmsgs);
-+    mq_setattr(mqd, &newattr)
-+}
-+
-+/// Convenience function.
-+/// Removes `O_NONBLOCK` attribute for a given message queue descriptor
-+/// Returns the old attributes
-+pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
-+    let oldattr = mq_getattr(mqd)?;
-+    let newattr = MqAttr::new(0,
-+                              oldattr.mq_attr.mq_maxmsg,
-+                              oldattr.mq_attr.mq_msgsize,
-+                              oldattr.mq_attr.mq_curmsgs);
-+    mq_setattr(mqd, &newattr)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/net/if_.rs b/third_party/rust/nix-0.15.0/src/net/if_.rs
-new file mode 100644
-index 0000000000000..58d677ae343d1
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/net/if_.rs
-@@ -0,0 +1,268 @@
-+//! Network interface name resolution.
-+//!
-+//! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
-+//! or "socan1" into device numbers.
-+
-+use libc;
-+use libc::c_uint;
-+use {Result, Error, NixPath};
-+
-+/// Resolve an interface into a interface number.
-+pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
-+    let if_index = name.with_nix_path(|name| unsafe { libc::if_nametoindex(name.as_ptr()) })?;
-+
-+    if if_index == 0 {
-+        Err(Error::last())
-+    } else {
-+        Ok(if_index)
-+    }
-+}
-+
-+libc_bitflags!(
-+    /// 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))
-+        IFF_UP;
-+        /// Valid broadcast address set. (see
-+        /// [`netdevice(7)`](http://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))
-+        IFF_DEBUG;
-+        /// Interface is a loopback interface. (see
-+        /// [`netdevice(7)`](http://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))
-+        IFF_POINTOPOINT;
-+        /// Avoid use of trailers. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        #[cfg(any(target_os = "android",
-+                  target_os = "fuchsia",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "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))
-+        #[cfg(any(target_os = "android",
-+                  target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "fuchsia",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  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))
-+        IFF_NOARP;
-+        /// Interface is in promiscuous mode. (see
-+        /// [`netdevice(7)`](http://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))
-+        IFF_ALLMULTI;
-+        /// Master of a load balancing bundle. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_MASTER;
-+        /// transmission in progress, tx hardware queue is full
-+        #[cfg(any(target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  target_os = "ios"))]
-+        IFF_OACTIVE;
-+        /// Protocol code on board.
-+        #[cfg(target_os = "solaris")]
-+        IFF_INTELLIGENT;
-+        /// Slave of a load balancing bundle. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_SLAVE;
-+        /// Can't hear own transmissions.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  target_os = "osx"))]
-+        IFF_SIMPLEX;
-+        /// Supports multicast. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        IFF_MULTICAST;
-+        /// Per link layer defined bit.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  target_os = "ios"))]
-+        IFF_LINK0;
-+        /// Multicast using broadcast.
-+        #[cfg(any(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))
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_PORTSEL;
-+        /// Per link layer defined bit.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  target_os = "ios"))]
-+        IFF_LINK1;
-+        /// Non-unique address.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_UNNUMBERED;
-+        /// Auto media selection active. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_AUTOMEDIA;
-+        /// Per link layer defined bit.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd",
-+                  target_os = "ios"))]
-+        IFF_LINK2;
-+        /// Use alternate physical connection.
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "ios"))]
-+        IFF_ALTPHYS;
-+        /// DHCP controlls interface.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_DHCPRUNNING;
-+        /// The addresses are lost when the interface goes down. (see
-+        /// [`netdevice(7)`](http://man7.org/linux/man-pages/man7/netdevice.7.html))
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_DYNAMIC;
-+        /// Do not advertise.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_PRIVATE;
-+        /// Driver signals L1 up. Volatile.
-+        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
-+        IFF_LOWER_UP;
-+        /// Interface is in polling mode.
-+        #[cfg(any(target_os = "dragonfly"))]
-+        IFF_POLLING_COMPAT;
-+        /// Unconfigurable using ioctl(2).
-+        #[cfg(any(target_os = "freebsd"))]
-+        IFF_CANTCONFIG;
-+        /// Do not transmit packets.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_NOXMIT;
-+        /// Driver signals dormant. Volatile.
-+        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
-+        IFF_DORMANT;
-+        /// User-requested promisc mode.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        IFF_PPROMISC;
-+        /// Just on-link subnet.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_NOLOCAL;
-+        /// Echo sent packets. Volatile.
-+        #[cfg(any(target_os = "fuchsia", target_os = "linux"))]
-+        IFF_ECHO;
-+        /// User-requested monitor mode.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        IFF_MONITOR;
-+        /// Address is deprecated.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_DEPRECATED;
-+        /// Static ARP.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        IFF_STATICARP;
-+        /// Address from stateless addrconf.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_ADDRCONF;
-+        /// Interface is in polling mode.
-+        #[cfg(any(target_os = "dragonfly"))]
-+        IFF_NPOLLING;
-+        /// Router on interface.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_ROUTER;
-+        /// Interface is in polling mode.
-+        #[cfg(any(target_os = "dragonfly"))]
-+        IFF_IDIRECT;
-+        /// Interface is winding down
-+        #[cfg(any(target_os = "freebsd"))]
-+        IFF_DYING;
-+        /// No NUD on interface.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_NONUD;
-+        /// Interface is being renamed
-+        #[cfg(any(target_os = "freebsd"))]
-+        IFF_RENAMING;
-+        /// Anycast address.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_ANYCAST;
-+        /// Don't exchange routing info.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_NORTEXCH;
-+        /// Do not provide packet information
-+        #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
-+        IFF_NO_PI as libc::c_int;
-+        /// TUN device (no Ethernet headers) 
-+        #[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"))]
-+        IFF_IPV4;
-+        /// IPv6 interface.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_IPV6;
-+        /// in.mpathd test address
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_NOFAILOVER;
-+        /// Interface has failed
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_FAILED;
-+        /// Interface is a hot-spare
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_STANDBY;
-+        /// Functioning but not used
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_INACTIVE;
-+        /// Interface is offline
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_OFFLINE;
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_COS_ENABLED;
-+        /// Prefer as source addr.
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_PREFERRED;
-+        /// RFC3041
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_TEMPORARY;
-+        /// MTU set with SIOCSLIFMTU
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_FIXEDMTU;
-+        /// Cannot send / receive packets
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_VIRTUAL;
-+        /// Local address in use
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_DUPLICATE;
-+        /// IPMP IP interface
-+        #[cfg(any(target_os = "solaris"))]
-+        IFF_IPMP;
-+    }
-+);
-diff --git a/third_party/rust/nix-0.15.0/src/net/mod.rs b/third_party/rust/nix-0.15.0/src/net/mod.rs
-new file mode 100644
-index 0000000000000..079fcfde6fd44
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/net/mod.rs
-@@ -0,0 +1,4 @@
-+//! Functionality involving network interfaces
-+// To avoid clashing with the keyword "if", we use "if_" as the module name.
-+// The original header is called "net/if.h".
-+pub mod if_;
-diff --git a/third_party/rust/nix-0.15.0/src/poll.rs b/third_party/rust/nix-0.15.0/src/poll.rs
-new file mode 100644
-index 0000000000000..c603611e3176f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/poll.rs
-@@ -0,0 +1,143 @@
-+//! Wait for events to trigger on specific file descriptors
-+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-+use sys::time::TimeSpec;
-+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-+use sys::signal::SigSet;
-+use std::os::unix::io::RawFd;
-+
-+use libc;
-+use Result;
-+use errno::Errno;
-+
-+/// This is a wrapper around `libc::pollfd`.
-+///
-+/// It's meant to be used as an argument to the [`poll`](fn.poll.html) and
-+/// [`ppoll`](fn.ppoll.html) functions to specify the events of interest
-+/// for a specific file descriptor.
-+///
-+/// After a call to `poll` or `ppoll`, the events that occured can be
-+/// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct PollFd {
-+    pollfd: libc::pollfd,
-+}
-+
-+impl PollFd {
-+    /// Creates a new `PollFd` specifying the events of interest
-+    /// for a given file descriptor.
-+    pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
-+        PollFd {
-+            pollfd: libc::pollfd {
-+                fd: fd,
-+                events: events.bits(),
-+                revents: PollFlags::empty().bits(),
-+            },
-+        }
-+    }
-+
-+    /// Returns the events that occured in the last call to `poll` or `ppoll`.
-+    pub fn revents(&self) -> Option<PollFlags> {
-+        PollFlags::from_bits(self.pollfd.revents)
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// These flags define the different events that can be monitored by `poll` and `ppoll`
-+    pub struct PollFlags: libc::c_short {
-+        /// There is data to read.
-+        POLLIN;
-+        /// There is some exceptional condition on the file descriptor.
-+        ///
-+        /// 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)).
-+        /// *  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)).
-+        /// *  A cgroup.events file has been modified (see
-+        ///    [cgroups(7)](http://man7.org/linux/man-pages/man7/cgroups.7.html)).
-+        POLLPRI;
-+        /// Writing is now possible, though a write larger that the
-+        /// available space in a socket or pipe will still block (unless
-+        /// `O_NONBLOCK` is set).
-+        POLLOUT;
-+        /// Equivalent to [`POLLIN`](constant.POLLIN.html)
-+        POLLRDNORM;
-+        /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
-+        POLLWRNORM;
-+        /// Priority band data can be read (generally unused on Linux).
-+        POLLRDBAND;
-+        /// Priority data may be written.
-+        POLLWRBAND;
-+        /// Error condition (only returned in
-+        /// [`PollFd::revents`](struct.PollFd.html#method.revents);
-+        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
-+        /// This bit is also set for a file descriptor referring to the
-+        /// write end of a pipe when the read end has been closed.
-+        POLLERR;
-+        /// Hang up (only returned in [`PollFd::revents`](struct.PollFd.html#method.revents);
-+        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
-+        /// Note that when reading from a channel such as a pipe or a stream
-+        /// socket, this event merely indicates that the peer closed its
-+        /// end of the channel.  Subsequent reads from the channel will
-+        /// return 0 (end of file) only after all outstanding data in the
-+        /// channel has been consumed.
-+        POLLHUP;
-+        /// Invalid request: `fd` not open (only returned in
-+        /// [`PollFd::revents`](struct.PollFd.html#method.revents);
-+        /// ignored in [`PollFd::new`](struct.PollFd.html#method.new)).
-+        POLLNVAL;
-+    }
-+}
-+
-+/// `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))
-+///
-+/// `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.
-+///
-+/// The `timeout` argument specifies the number of milliseconds that `poll()`
-+/// should block waiting for a file descriptor to become ready.  The call
-+/// will block until either:
-+///
-+/// *  a file descriptor becomes ready;
-+/// *  the call is interrupted by a signal handler; or
-+/// *  the timeout expires.
-+///
-+/// Note that the timeout interval will be rounded up to the system clock
-+/// granularity, and kernel scheduling delays mean that the blocking
-+/// interval may overrun by a small amount.  Specifying a negative value
-+/// in timeout means an infinite timeout.  Specifying a timeout of zero
-+/// causes `poll()` to return immediately, even if no file descriptors are
-+/// ready.
-+pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
-+    let res = unsafe {
-+        libc::poll(fds.as_mut_ptr() as *mut libc::pollfd,
-+                   fds.len() as libc::nfds_t,
-+                   timeout)
-+    };
-+
-+    Errno::result(res)
-+}
-+
-+/// `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))
-+///
-+/// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
-+/// with the `sigmask` argument.
-+///
-+#[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-+pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> {
-+
-+
-+    let res = unsafe {
-+        libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
-+                    fds.len() as libc::nfds_t,
-+                    timeout.as_ref(),
-+                    sigmask.as_ref())
-+    };
-+    Errno::result(res)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/pty.rs b/third_party/rust/nix-0.15.0/src/pty.rs
-new file mode 100644
-index 0000000000000..db012d8158c53
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/pty.rs
-@@ -0,0 +1,326 @@
-+//! Create master and slave virtual pseudo-terminals (PTYs)
-+
-+use libc;
-+
-+pub use libc::pid_t as SessionId;
-+pub use libc::winsize as Winsize;
-+
-+use std::ffi::CStr;
-+use std::mem;
-+use std::os::unix::prelude::*;
-+
-+use sys::termios::Termios;
-+use unistd::ForkResult;
-+use {Result, Error, fcntl};
-+use errno::Errno;
-+
-+/// Representation of a master/slave pty pair
-+///
-+/// This is returned by `openpty`.  Note that this type does *not* implement `Drop`, so the user
-+/// must manually close the file descriptors.
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct OpenptyResult {
-+    /// The master port in a virtual pty pair
-+    pub master: RawFd,
-+    /// The slave port in a virtual pty pair
-+    pub slave: RawFd,
-+}
-+
-+/// Representation of a master with a forked pty
-+///
-+/// This is returned by `forkpty`. Note that this type does *not* implement `Drop`, so the user
-+/// must manually close the file descriptors.
-+#[derive(Clone, Copy, Debug)]
-+pub struct ForkptyResult {
-+    /// The master port in a virtual pty pair
-+    pub master: RawFd,
-+    /// Metadata about forked process
-+    pub fork_result: ForkResult,
-+}
-+
-+
-+/// Representation of the Master device in a master/slave pty pair
-+///
-+/// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
-+/// functions are given the correct file descriptor. Additionally this type implements `Drop`,
-+/// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
-+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct PtyMaster(RawFd);
-+
-+impl AsRawFd for PtyMaster {
-+    fn as_raw_fd(&self) -> RawFd {
-+        self.0
-+    }
-+}
-+
-+impl IntoRawFd for PtyMaster {
-+    fn into_raw_fd(self) -> RawFd {
-+        let fd = self.0;
-+        mem::forget(self);
-+        fd
-+    }
-+}
-+
-+impl Drop for PtyMaster {
-+    fn drop(&mut self) {
-+        // On drop, we ignore errors like EINTR and EIO because there's no clear
-+        // way to handle them, we can't return anything, and (on FreeBSD at
-+        // least) the file descriptor is deallocated in these cases.  However,
-+        // we must panic on EBADF, because it is always an error to close an
-+        // invalid file descriptor.  That frequently indicates a double-close
-+        // condition, which can cause confusing errors for future I/O
-+        // operations.
-+        let e = ::unistd::close(self.0);
-+        if e == Err(Error::Sys(Errno::EBADF)) {
-+            panic!("Closing an invalid file descriptor!");
-+        };
-+    }
-+}
-+
-+/// Grant access to a slave pseudoterminal (see
-+/// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
-+///
-+/// `grantpt()` changes the mode and owner of the slave pseudoterminal device corresponding to the
-+/// master pseudoterminal referred to by `fd`. This is a necessary step towards opening the slave.
-+#[inline]
-+pub fn grantpt(fd: &PtyMaster) -> Result<()> {
-+    if unsafe { libc::grantpt(fd.as_raw_fd()) } < 0 {
-+        return Err(Error::last());
-+    }
-+
-+    Ok(())
-+}
-+
-+/// Open a pseudoterminal device (see
-+/// [`posix_openpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_openpt.html))
-+///
-+/// `posix_openpt()` returns a file descriptor to an existing unused pseuterminal master device.
-+///
-+/// # Examples
-+///
-+/// A common use case with this function is to open both a master and slave PTY pair. This can be
-+/// done as follows:
-+///
-+/// ```
-+/// use std::path::Path;
-+/// use nix::fcntl::{OFlag, open};
-+/// use nix::pty::{grantpt, posix_openpt, ptsname, unlockpt};
-+/// use nix::sys::stat::Mode;
-+///
-+/// # #[allow(dead_code)]
-+/// # fn run() -> nix::Result<()> {
-+/// // Open a new PTY master
-+/// let master_fd = posix_openpt(OFlag::O_RDWR)?;
-+///
-+/// // Allow a slave to be generated for it
-+/// grantpt(&master_fd)?;
-+/// unlockpt(&master_fd)?;
-+///
-+/// // Get the name of the slave
-+/// let slave_name = unsafe { ptsname(&master_fd) }?;
-+///
-+/// // Try to open the slave
-+/// let _slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, Mode::empty())?;
-+/// # Ok(())
-+/// # }
-+/// ```
-+#[inline]
-+pub fn posix_openpt(flags: fcntl::OFlag) -> Result<PtyMaster> {
-+    let fd = unsafe {
-+        libc::posix_openpt(flags.bits())
-+    };
-+
-+    if fd < 0 {
-+        return Err(Error::last());
-+    }
-+
-+    Ok(PtyMaster(fd))
-+}
-+
-+/// Get the name of the slave pseudoterminal (see
-+/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
-+///
-+/// `ptsname()` returns the name of the slave pseudoterminal device corresponding to the master
-+/// referred to by `fd`.
-+///
-+/// This value is useful for opening the slave pty once the master has already been opened with
-+/// `posix_openpt()`.
-+///
-+/// # Safety
-+///
-+/// `ptsname()` mutates global variables and is *not* threadsafe.
-+/// Mutating global variables is always considered `unsafe` by Rust and this
-+/// function is marked as `unsafe` to reflect that.
-+///
-+/// For a threadsafe and non-`unsafe` alternative on Linux, see `ptsname_r()`.
-+#[inline]
-+pub unsafe fn ptsname(fd: &PtyMaster) -> Result<String> {
-+    let name_ptr = libc::ptsname(fd.as_raw_fd());
-+    if name_ptr.is_null() {
-+        return Err(Error::last());
-+    }
-+
-+    let name = CStr::from_ptr(name_ptr);
-+    Ok(name.to_string_lossy().into_owned())
-+}
-+
-+/// Get the name of the slave pseudoterminal (see
-+/// [`ptsname(3)`](http://man7.org/linux/man-pages/man3/ptsname.3.html))
-+///
-+/// `ptsname_r()` returns the name of the slave pseudoterminal device corresponding to the master
-+/// referred to by `fd`. This is the threadsafe version of `ptsname()`, but it is not part of the
-+/// POSIX standard and is instead a Linux-specific extension.
-+///
-+/// This value is useful for opening the slave ptty once the master has already been opened with
-+/// `posix_openpt()`.
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[inline]
-+pub fn ptsname_r(fd: &PtyMaster) -> Result<String> {
-+    let mut name_buf = vec![0u8; 64];
-+    let name_buf_ptr = name_buf.as_mut_ptr() as *mut libc::c_char;
-+    if unsafe { libc::ptsname_r(fd.as_raw_fd(), name_buf_ptr, name_buf.capacity()) } != 0 {
-+        return Err(Error::last());
-+    }
-+
-+    // Find the first null-character terminating this string. This is guaranteed to succeed if the
-+    // return value of `libc::ptsname_r` is 0.
-+    let null_index = name_buf.iter().position(|c| *c == b'\0').unwrap();
-+    name_buf.truncate(null_index);
-+
-+    let name = String::from_utf8(name_buf)?;
-+    Ok(name)
-+}
-+
-+/// Unlock a pseudoterminal master/slave pseudoterminal pair (see
-+/// [`unlockpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlockpt.html))
-+///
-+/// `unlockpt()` unlocks the slave pseudoterminal device corresponding to the master pseudoterminal
-+/// referred to by `fd`. This must be called before trying to open the slave side of a
-+/// pseuoterminal.
-+#[inline]
-+pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
-+    if unsafe { libc::unlockpt(fd.as_raw_fd()) } < 0 {
-+        return Err(Error::last());
-+    }
-+
-+    Ok(())
-+}
-+
-+
-+/// 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)).
-+///
-+/// 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`.
-+#[inline]
-+pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
-+    use std::ptr;
-+
-+    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
-+    let mut master: libc::c_int = unsafe { mem::uninitialized() };
-+    let ret = {
-+        match (termios.into(), winsize.into()) {
-+            (Some(termios), Some(winsize)) => {
-+                let inner_termios = termios.get_libc_termios();
-+                unsafe {
-+                    libc::openpty(
-+                        &mut master,
-+                        &mut slave,
-+                        ptr::null_mut(),
-+                        &*inner_termios as *const libc::termios as *mut _,
-+                        winsize as *const Winsize as *mut _,
-+                    )
-+                }
-+            }
-+            (None, Some(winsize)) => {
-+                unsafe {
-+                    libc::openpty(
-+                        &mut master,
-+                        &mut slave,
-+                        ptr::null_mut(),
-+                        ptr::null_mut(),
-+                        winsize as *const Winsize as *mut _,
-+                    )
-+                }
-+            }
-+            (Some(termios), None) => {
-+                let inner_termios = termios.get_libc_termios();
-+                unsafe {
-+                    libc::openpty(
-+                        &mut master,
-+                        &mut slave,
-+                        ptr::null_mut(),
-+                        &*inner_termios as *const libc::termios as *mut _,
-+                        ptr::null_mut(),
-+                    )
-+                }
-+            }
-+            (None, None) => {
-+                unsafe {
-+                    libc::openpty(
-+                        &mut master,
-+                        &mut slave,
-+                        ptr::null_mut(),
-+                        ptr::null_mut(),
-+                        ptr::null_mut(),
-+                    )
-+                }
-+            }
-+        }
-+    };
-+
-+    Errno::result(ret)?;
-+
-+    Ok(OpenptyResult {
-+        master: master,
-+        slave: slave,
-+    })
-+}
-+
-+/// 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)).
-+///
-+/// 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>>>(
-+    winsize: T,
-+    termios: U,
-+) -> Result<ForkptyResult> {
-+    use std::ptr;
-+    use unistd::Pid;
-+    use unistd::ForkResult::*;
-+
-+    let mut master: libc::c_int = unsafe { mem::uninitialized() };
-+
-+    let term = match termios.into() {
-+        Some(termios) => {
-+            let inner_termios = termios.get_libc_termios();
-+            &*inner_termios as *const libc::termios as *mut _
-+        },
-+        None => ptr::null_mut(),
-+    };
-+
-+    let win = winsize
-+        .into()
-+        .map(|ws| ws as *const Winsize as *mut _)
-+        .unwrap_or(ptr::null_mut());
-+
-+    let res = unsafe {
-+        libc::forkpty(&mut master, ptr::null_mut(), term, win)
-+    };
-+
-+    let fork_result = Errno::result(res).map(|res| match res {
-+        0 => Child,
-+        res => Parent { child: Pid::from_raw(res) },
-+    })?;
-+
-+    Ok(ForkptyResult {
-+        master: master,
-+        fork_result: fork_result,
-+    })
-+}
-+
-diff --git a/third_party/rust/nix-0.15.0/src/sched.rs b/third_party/rust/nix-0.15.0/src/sched.rs
-new file mode 100644
-index 0000000000000..67188c57eef7d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sched.rs
-@@ -0,0 +1,147 @@
-+use libc;
-+use {Errno, Result};
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use self::sched_linux_like::*;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod sched_linux_like {
-+    use errno::Errno;
-+    use libc::{self, c_int, c_void};
-+    use std::mem;
-+    use std::option::Option;
-+    use std::os::unix::io::RawFd;
-+    use unistd::Pid;
-+    use {Error, Result};
-+
-+    // For some functions taking with a parameter of type CloneFlags,
-+    // only a subset of these flags have an effect.
-+    libc_bitflags! {
-+        pub struct CloneFlags: c_int {
-+            CLONE_VM;
-+            CLONE_FS;
-+            CLONE_FILES;
-+            CLONE_SIGHAND;
-+            CLONE_PTRACE;
-+            CLONE_VFORK;
-+            CLONE_PARENT;
-+            CLONE_THREAD;
-+            CLONE_NEWNS;
-+            CLONE_SYSVSEM;
-+            CLONE_SETTLS;
-+            CLONE_PARENT_SETTID;
-+            CLONE_CHILD_CLEARTID;
-+            CLONE_DETACHED;
-+            CLONE_UNTRACED;
-+            CLONE_CHILD_SETTID;
-+            CLONE_NEWCGROUP;
-+            CLONE_NEWUTS;
-+            CLONE_NEWIPC;
-+            CLONE_NEWUSER;
-+            CLONE_NEWPID;
-+            CLONE_NEWNET;
-+            CLONE_IO;
-+        }
-+    }
-+
-+    pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
-+
-+    #[repr(C)]
-+    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+    pub struct CpuSet {
-+        cpu_set: libc::cpu_set_t,
-+    }
-+
-+    impl CpuSet {
-+        pub fn new() -> CpuSet {
-+            CpuSet {
-+                cpu_set: unsafe { mem::zeroed() },
-+            }
-+        }
-+
-+        pub fn is_set(&self, field: usize) -> Result<bool> {
-+            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+                Err(Error::Sys(Errno::EINVAL))
-+            } else {
-+                Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
-+            }
-+        }
-+
-+        pub fn set(&mut self, field: usize) -> Result<()> {
-+            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+                Err(Error::Sys(Errno::EINVAL))
-+            } else {
-+                Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
-+            }
-+        }
-+
-+        pub fn unset(&mut self, field: usize) -> Result<()> {
-+            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+                Err(Error::Sys(Errno::EINVAL))
-+            } else {
-+                Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
-+            }
-+        }
-+    }
-+
-+    pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
-+        let res = unsafe {
-+            libc::sched_setaffinity(
-+                pid.into(),
-+                mem::size_of::<CpuSet>() as libc::size_t,
-+                &cpuset.cpu_set,
-+            )
-+        };
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    pub fn clone(
-+        mut cb: CloneCb,
-+        stack: &mut [u8],
-+        flags: CloneFlags,
-+        signal: Option<c_int>,
-+    ) -> Result<Pid> {
-+        extern "C" fn callback(data: *mut CloneCb) -> c_int {
-+            let cb: &mut CloneCb = unsafe { &mut *data };
-+            (*cb)() as c_int
-+        }
-+
-+        let res = unsafe {
-+            let combined = flags.bits() | signal.unwrap_or(0);
-+            let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
-+            let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
-+            libc::clone(
-+                mem::transmute(
-+                    callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
-+                ),
-+                ptr_aligned as *mut c_void,
-+                combined,
-+                &mut cb as *mut _ as *mut c_void,
-+            )
-+        };
-+
-+        Errno::result(res).map(Pid::from_raw)
-+    }
-+
-+    pub fn unshare(flags: CloneFlags) -> Result<()> {
-+        let res = unsafe { libc::unshare(flags.bits()) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    pub fn setns(fd: RawFd, nstype: CloneFlags) -> Result<()> {
-+        let res = unsafe { libc::setns(fd, nstype.bits()) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+/// Explicitly yield the processor to other threads.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_yield.html)
-+pub fn sched_yield() -> Result<()> {
-+    let res = unsafe { libc::sched_yield() };
-+
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/aio.rs b/third_party/rust/nix-0.15.0/src/sys/aio.rs
-new file mode 100644
-index 0000000000000..9258a0657cc8a
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/aio.rs
-@@ -0,0 +1,1280 @@
-+// vim: tw=80
-+//! POSIX Asynchronous I/O
-+//!
-+//! The POSIX AIO interface is used for asynchronous I/O on files and disk-like
-+//! devices.  It supports [`read`](struct.AioCb.html#method.read),
-+//! [`write`](struct.AioCb.html#method.write), and
-+//! [`fsync`](struct.AioCb.html#method.fsync) operations.  Completion
-+//! notifications can optionally be delivered via
-+//! [signals](../signal/enum.SigevNotify.html#variant.SigevSignal), via the
-+//! [`aio_suspend`](fn.aio_suspend.html) function, or via polling.  Some
-+//! platforms support other completion
-+//! notifications, such as
-+//! [kevent](../signal/enum.SigevNotify.html#variant.SigevKevent).
-+//!
-+//! Multiple operations may be submitted in a batch with
-+//! [`lio_listio`](fn.lio_listio.html), though the standard does not guarantee
-+//! that they will be executed atomically.
-+//!
-+//! Outstanding operations may be cancelled with
-+//! [`cancel`](struct.AioCb.html#method.cancel) or
-+//! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
-+//! not support this for all filesystems and devices.
-+
-+use {Error, Result};
-+use errno::Errno;
-+use std::os::unix::io::RawFd;
-+use libc::{c_void, off_t, size_t};
-+use libc;
-+use std::borrow::{Borrow, BorrowMut};
-+use std::fmt;
-+use std::fmt::Debug;
-+use std::marker::PhantomData;
-+use std::mem;
-+use std::ptr::{null, null_mut};
-+use sys::signal::*;
-+use std::thread;
-+use sys::time::TimeSpec;
-+
-+libc_enum! {
-+    /// Mode for `AioCb::fsync`.  Controls whether only data or both data and
-+    /// metadata are synced.
-+    #[repr(i32)]
-+    pub enum AioFsyncMode {
-+        /// do it like `fsync`
-+        O_SYNC,
-+        /// on supported operating systems only, do it like `fdatasync`
-+        #[cfg(any(target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        O_DSYNC
-+    }
-+}
-+
-+libc_enum! {
-+    /// When used with [`lio_listio`](fn.lio_listio.html), determines whether a
-+    /// given `aiocb` should be used for a read operation, a write operation, or
-+    /// ignored.  Has no effect for any other aio functions.
-+    #[repr(i32)]
-+    pub enum LioOpcode {
-+        LIO_NOP,
-+        LIO_WRITE,
-+        LIO_READ,
-+    }
-+}
-+
-+libc_enum! {
-+    /// Mode for [`lio_listio`](fn.lio_listio.html)
-+    #[repr(i32)]
-+    pub enum LioMode {
-+        /// Requests that [`lio_listio`](fn.lio_listio.html) block until all
-+        /// requested operations have been completed
-+        LIO_WAIT,
-+        /// Requests that [`lio_listio`](fn.lio_listio.html) return immediately
-+        LIO_NOWAIT,
-+    }
-+}
-+
-+/// Return values for [`AioCb::cancel`](struct.AioCb.html#method.cancel) and
-+/// [`aio_cancel_all`](fn.aio_cancel_all.html)
-+#[repr(i32)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum AioCancelStat {
-+    /// All outstanding requests were canceled
-+    AioCanceled = libc::AIO_CANCELED,
-+    /// Some requests were not canceled.  Their status should be checked with
-+    /// `AioCb::error`
-+    AioNotCanceled = libc::AIO_NOTCANCELED,
-+    /// All of the requests have already finished
-+    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]>>),
-+}
-+
-+impl<'a> Debug for Buffer<'a> {
-+    // Note: someday it may be possible to Derive Debug for a trait object, but
-+    // not today.
-+    // https://github.com/rust-lang/rust/issues/1563
-+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-+        match *self {
-+            Buffer::None => write!(fmt, "None"),
-+            Buffer::Phantom(p) => p.fmt(fmt),
-+            Buffer::BoxedSlice(ref bs) => {
-+                let borrowed : &dyn Borrow<[u8]> = bs.borrow();
-+                write!(fmt, "BoxedSlice({:?})",
-+                    borrowed as *const dyn Borrow<[u8]>)
-+            },
-+            Buffer::BoxedMutSlice(ref bms) => {
-+                let borrowed : &dyn BorrowMut<[u8]> = bms.borrow();
-+                write!(fmt, "BoxedMutSlice({:?})",
-+                    borrowed as *const dyn BorrowMut<[u8]>)
-+            }
-+        }
-+    }
-+}
-+
-+/// AIO Control Block.
-+///
-+/// The basic structure used by all aio functions.  Each `AioCb` represents one
-+/// I/O request.
-+pub struct AioCb<'a> {
-+    aiocb: libc::aiocb,
-+    /// Tracks whether the buffer pointed to by `libc::aiocb.aio_buf` is mutable
-+    mutable: bool,
-+    /// Could this `AioCb` potentially have any in-kernel state?
-+    in_progress: bool,
-+    /// Optionally keeps a reference to the data.
-+    ///
-+    /// Used to keep buffers from `Drop`'ing, and may be returned once the
-+    /// `AioCb` is completed by [`buffer`](#method.buffer).
-+    buffer: Buffer<'a>
-+}
-+
-+impl<'a> AioCb<'a> {
-+    /// Remove the inner `Buffer` and return it
-+    ///
-+    /// It is an error to call this method while the `AioCb` is still in
-+    /// progress.
-+    pub fn buffer(&mut self) -> Buffer<'a> {
-+        assert!(!self.in_progress);
-+        let mut x = Buffer::None;
-+        mem::swap(&mut self.buffer, &mut x);
-+        x
-+    }
-+
-+    /// Remove the inner boxed slice, if any, and return it.
-+    ///
-+    /// The returned value will be the argument that was passed to
-+    /// `from_boxed_slice` when this `AioCb` was created.
-+    ///
-+    /// It is an error to call this method while the `AioCb` is still in
-+    /// progress.
-+    pub fn boxed_slice(&mut self) -> Option<Box<dyn Borrow<[u8]>>> {
-+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
-+        if let Buffer::BoxedSlice(_) = self.buffer {
-+            let mut oldbuffer = Buffer::None;
-+            mem::swap(&mut self.buffer, &mut oldbuffer);
-+            if let Buffer::BoxedSlice(inner) = oldbuffer {
-+                Some(inner)
-+            } else {
-+                unreachable!();
-+            }
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Remove the inner boxed mutable slice, if any, and return it.
-+    ///
-+    /// The returned value will be the argument that was passed to
-+    /// `from_boxed_mut_slice` when this `AioCb` was created.
-+    ///
-+    /// It is an error to call this method while the `AioCb` is still in
-+    /// progress.
-+    pub fn boxed_mut_slice(&mut self) -> Option<Box<dyn BorrowMut<[u8]>>> {
-+        assert!(!self.in_progress, "Can't remove the buffer from an AioCb that's still in-progress.  Did you forget to call aio_return?");
-+        if let Buffer::BoxedMutSlice(_) = self.buffer {
-+            let mut oldbuffer = Buffer::None;
-+            mem::swap(&mut self.buffer, &mut oldbuffer);
-+            if let Buffer::BoxedMutSlice(inner) = oldbuffer {
-+                Some(inner)
-+            } else {
-+                unreachable!();
-+            }
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Returns the underlying file descriptor associated with the `AioCb`
-+    pub fn fd(&self) -> RawFd {
-+        self.aiocb.aio_fildes
-+    }
-+
-+    /// Constructs a new `AioCb` with no associated buffer.
-+    ///
-+    /// The resulting `AioCb` structure is suitable for use with `AioCb::fsync`.
-+    ///
-+    /// # Parameters
-+    ///
-+    /// * `fd`:           File descriptor.  Required for all aio functions.
-+    /// * `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.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Create an `AioCb` from a raw file descriptor and use it for an
-+    /// [`fsync`](#method.fsync) operation.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::errno::Errno;
-+    /// # use nix::Error;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify::SigevNone;
-+    /// # use std::{thread, time};
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// let f = tempfile().unwrap();
-+    /// let mut aiocb = AioCb::from_fd( f.as_raw_fd(), 0, SigevNone);
-+    /// aiocb.fsync(AioFsyncMode::O_SYNC).expect("aio_fsync failed early");
-+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
-+    ///     thread::sleep(time::Duration::from_millis(10));
-+    /// }
-+    /// aiocb.aio_return().expect("aio_fsync failed late");
-+    /// # }
-+    /// ```
-+    pub fn from_fd(fd: RawFd, prio: libc::c_int,
-+                    sigev_notify: SigevNotify) -> 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();
-+
-+        AioCb {
-+            aiocb: a,
-+            mutable: false,
-+            in_progress: false,
-+            buffer: Buffer::None
-+        }
-+    }
-+
-+    /// Constructs a new `AioCb` from a mutable slice.
-+    ///
-+    /// 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.
-+    ///
-+    /// # Parameters
-+    ///
-+    /// * `fd`:           File descriptor.  Required for all aio functions.
-+    /// * `offs`:         File offset
-+    /// * `buf`:          A memory buffer
-+    /// * `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 mutable slice and read into it.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # 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 mut rbuf = vec![0; LEN];
-+    /// let mut f = tempfile().unwrap();
-+    /// f.write_all(INITIAL).unwrap();
-+    /// {
-+    ///     let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
-+    ///         2,   //offset
-+    ///         &mut 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);
-+    /// }
-+    /// assert_eq!(rbuf, b"cdef");
-+    /// # }
-+    /// ```
-+    pub fn from_mut_slice(fd: RawFd, offs: off_t, buf: &'a mut [u8],
-+                          prio: libc::c_int, sigev_notify: SigevNotify,
-+                          opcode: LioOpcode) -> 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;
-+
-+        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
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # 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
-+    ///
-+    /// ```
-+    /// # extern crate bytes;
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # 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.
-+    ///
-+    /// ```
-+    /// # extern crate bytes;
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # 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
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::errno::Errno;
-+    /// # use nix::Error;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify;
-+    /// # use std::{thread, time};
-+    /// # use std::io::Write;
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// const INITIAL: &[u8] = b"abcdef123456";
-+    /// const LEN: usize = 4;
-+    /// let rbuf = Box::new(vec![0; LEN]);
-+    /// let mut f = tempfile().unwrap();
-+    /// f.write_all(INITIAL).unwrap();
-+    /// let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
-+    ///     2,   //offset
-+    ///     rbuf,
-+    ///     0,   //priority
-+    ///     SigevNotify::SigevNone,
-+    ///     LioOpcode::LIO_NOP);
-+    /// aiocb.read().unwrap();
-+    /// while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
-+    ///     thread::sleep(time::Duration::from_millis(10));
-+    /// }
-+    /// assert_eq!(aiocb.aio_return().unwrap() as usize, LEN);
-+    /// let mut buffer = aiocb.boxed_mut_slice().unwrap();
-+    /// const EXPECT: &[u8] = b"cdef";
-+    /// assert_eq!(buffer.borrow_mut(), EXPECT);
-+    /// # }
-+    /// ```
-+    ///
-+    /// [`from_boxed_slice`]: #method.from_boxed_slice
-+    /// [`from_mut_slice`]: #method.from_mut_slice
-+    pub fn from_boxed_mut_slice(fd: RawFd, offs: off_t,
-+                                mut buf: Box<dyn BorrowMut<[u8]>>,
-+                                prio: libc::c_int, sigev_notify: SigevNotify,
-+                                opcode: LioOpcode) -> AioCb<'a> {
-+        let mut a = AioCb::common_init(fd, prio, sigev_notify);
-+        {
-+            let borrowed : &mut dyn BorrowMut<[u8]> = buf.borrow_mut();
-+            let slice : &mut [u8] = borrowed.borrow_mut();
-+            a.aio_nbytes = slice.len() as size_t;
-+            a.aio_buf = slice.as_mut_ptr() as *mut c_void;
-+        }
-+        a.aio_offset = offs;
-+        a.aio_lio_opcode = opcode as libc::c_int;
-+
-+        AioCb {
-+            aiocb: a,
-+            mutable: true,
-+            in_progress: false,
-+            buffer: Buffer::BoxedMutSlice(buf),
-+        }
-+    }
-+
-+    /// Constructs a new `AioCb` from a mutable raw pointer
-+    ///
-+    /// 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]>`
-+    ///
-+    /// # Parameters
-+    ///
-+    /// * `fd`:           File descriptor.  Required for all aio functions.
-+    /// * `offs`:         File offset
-+    /// * `buf`:          Pointer to the memory buffer
-+    /// * `len`:          Length of the buffer pointed to by `buf`
-+    /// * `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
-+    ///
-+    /// # Safety
-+    ///
-+    /// The caller must ensure that the storage pointed to by `buf` outlives the
-+    /// `AioCb`.  The lifetime checker can't help here.
-+    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> {
-+        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;
-+
-+        AioCb {
-+            aiocb: a,
-+            mutable: true,
-+            in_progress: false,
-+            buffer: Buffer::None
-+        }
-+    }
-+
-+    /// Constructs a new `AioCb` from a raw pointer.
-+    ///
-+    /// Unlike `from_slice`, this method returns a structure suitable for
-+    /// placement on the heap.  Due to its unsafety, this method is not
-+    /// recommended.  It is most useful when heap allocation is required but for
-+    /// some reason the data cannot be wrapped in a `struct` that implements
-+    /// `Borrow<[u8]>`
-+    ///
-+    /// # Parameters
-+    ///
-+    /// * `fd`:           File descriptor.  Required for all aio functions.
-+    /// * `offs`:         File offset
-+    /// * `buf`:          Pointer to the memory buffer
-+    /// * `len`:          Length of the buffer pointed to by `buf`
-+    /// * `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
-+    ///
-+    /// # Safety
-+    ///
-+    /// The caller must ensure that the storage pointed to by `buf` outlives the
-+    /// `AioCb`.  The lifetime checker can't help here.
-+    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> {
-+        let mut a = AioCb::common_init(fd, prio, sigev_notify);
-+        a.aio_offset = offs;
-+        a.aio_nbytes = len;
-+        // casting a const ptr to a mutable ptr here is ok, because we set the
-+        // AioCb's mutable field to false
-+        a.aio_buf = buf as *mut c_void;
-+        a.aio_lio_opcode = opcode as libc::c_int;
-+
-+        AioCb {
-+            aiocb: a,
-+            mutable: false,
-+            in_progress: false,
-+            buffer: Buffer::None
-+        }
-+    }
-+
-+    /// 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
-+    /// `LioOpcode` cannot be set to `LIO_READ`.  This method is useful when
-+    /// writing a const buffer with `AioCb::write`, since `from_mut_slice` can't
-+    /// work with const buffers.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Construct an `AioCb` from a slice and use it for writing.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::errno::Errno;
-+    /// # use nix::Error;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify;
-+    /// # use std::{thread, time};
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// const WBUF: &[u8] = b"abcdef123456";
-+    /// let mut f = tempfile().unwrap();
-+    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+    ///     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, WBUF.len());
-+    /// # }
-+    /// ```
-+    // Note: another solution to the problem of writing const buffers would be
-+    // to genericize AioCb for both &mut [u8] and &[u8] buffers.  AioCb::read
-+    // could take the former and AioCb::write could take the latter.  However,
-+    // then lio_listio wouldn't work, because that function needs a slice of
-+    // 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,
-+        }
-+    }
-+
-+    fn common_init(fd: RawFd, prio: libc::c_int,
-+                   sigev_notify: SigevNotify) -> libc::aiocb {
-+        // Use mem::zeroed instead of explicitly zeroing each field, because the
-+        // number and name of reserved fields is OS-dependent.  On some OSes,
-+        // some reserved fields are used the kernel for state, and must be
-+        // explicitly zeroed when allocated.
-+        let mut a = unsafe { mem::zeroed::<libc::aiocb>()};
-+        a.aio_fildes = fd;
-+        a.aio_reqprio = prio;
-+        a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
-+        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();
-+    }
-+
-+    /// Cancels an outstanding AIO request.
-+    ///
-+    /// The operating system is not required to implement cancellation for all
-+    /// file and device types.  Even if it does, there is no guarantee that the
-+    /// operation has not already completed.  So the caller must check the
-+    /// result and handle operations that were not canceled or that have already
-+    /// completed.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Cancel an outstanding aio operation.  Note that we must still call
-+    /// `aio_return` to free resources, even though we don't care about the
-+    /// result.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # 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 = b"CDEF";
-+    /// let mut f = tempfile().unwrap();
-+    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+    ///     2,   //offset
-+    ///     &wbuf[..],
-+    ///     0,   //priority
-+    ///     SigevNotify::SigevNone,
-+    ///     LioOpcode::LIO_NOP);
-+    /// aiocb.write().unwrap();
-+    /// let cs = aiocb.cancel().unwrap();
-+    /// if cs == AioCancelStat::AioNotCanceled {
-+    ///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
-+    ///         thread::sleep(time::Duration::from_millis(10));
-+    ///     }
-+    /// }
-+    /// // Must call `aio_return`, but ignore the result
-+    /// let _ = aiocb.aio_return();
-+    /// # }
-+    /// ```
-+    ///
-+    /// # References
-+    ///
-+    /// [aio_cancel](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
-+    pub fn cancel(&mut self) -> Result<AioCancelStat> {
-+        match unsafe { libc::aio_cancel(self.aiocb.aio_fildes, &mut self.aiocb) } {
-+            libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
-+            libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
-+            libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
-+            -1 => Err(Error::last()),
-+            _ => panic!("unknown aio_cancel return value")
-+        }
-+    }
-+
-+    /// Retrieve error status of an asynchronous operation.
-+    ///
-+    /// If the request has not yet completed, returns `EINPROGRESS`.  Otherwise,
-+    /// returns `Ok` or any other error.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Issue an aio operation and use `error` to poll for completion.  Polling
-+    /// is an alternative to `aio_suspend`, used by most of the other examples.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::errno::Errno;
-+    /// # use nix::Error;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify;
-+    /// # use std::{thread, time};
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// const WBUF: &[u8] = b"abcdef123456";
-+    /// let mut f = tempfile().unwrap();
-+    /// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+    ///     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, WBUF.len());
-+    /// # }
-+    /// ```
-+    ///
-+    /// # 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)
-+        }
-+    }
-+
-+    /// 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 {
-+                libc::aio_fsync(mode as libc::c_int, p)
-+        }).map(|_| {
-+            self.in_progress = true;
-+        })
-+    }
-+
-+    /// Returns the `aiocb`'s `LioOpcode` field
-+    ///
-+    /// 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 {
-+            libc::LIO_READ => Some(LioOpcode::LIO_READ),
-+            libc::LIO_WRITE => Some(LioOpcode::LIO_WRITE),
-+            libc::LIO_NOP => Some(LioOpcode::LIO_NOP),
-+            _ => None
-+        }
-+    }
-+
-+    /// Returns the requested length of the aio operation in bytes
-+    ///
-+    /// This method returns the *requested* length of the operation.  To get the
-+    /// number of bytes actually read or written by a completed operation, use
-+    /// `aio_return` instead.
-+    pub fn nbytes(&self) -> usize {
-+        self.aiocb.aio_nbytes
-+    }
-+
-+    /// Returns the file offset stored in the `AioCb`
-+    pub fn offset(&self) -> off_t {
-+        self.aiocb.aio_offset
-+    }
-+
-+    /// Returns the priority of the `AioCb`
-+    pub fn priority(&self) -> libc::c_int {
-+        self.aiocb.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<()> {
-+        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)
-+        }).map(|_| {
-+            self.in_progress = true;
-+        })
-+    }
-+
-+    /// Returns the `SigEvent` stored in the `AioCb`
-+    pub fn sigevent(&self) -> SigEvent {
-+        SigEvent::from(&self.aiocb.aio_sigevent)
-+    }
-+
-+    /// Retrieve return status of an asynchronous operation.
-+    ///
-+    /// Should only be called once for each `AioCb`, after `AioCb::error`
-+    /// indicates that it has completed.  The result is the same as for the
-+    /// synchronous `read(2)`, `write(2)`, of `fsync(2)` functions.
-+    ///
-+    /// # References
-+    ///
-+    /// [aio_return](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_return.html)
-+    // Note: this should be just `return`, but that's a reserved word
-+    pub fn aio_return(&mut self) -> Result<isize> {
-+        let p: *mut libc::aiocb = &mut self.aiocb;
-+        self.in_progress = false;
-+        Errno::result(unsafe { libc::aio_return(p) })
-+    }
-+
-+    /// Asynchronously writes from a buffer to a file descriptor
-+    ///
-+    /// # References
-+    ///
-+    /// [aio_write](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_write.html)
-+    pub fn write(&mut self) -> Result<()> {
-+        let p: *mut libc::aiocb = &mut self.aiocb;
-+        Errno::result(unsafe {
-+            libc::aio_write(p)
-+        }).map(|_| {
-+            self.in_progress = true;
-+        })
-+    }
-+
-+}
-+
-+/// Cancels outstanding AIO requests for a given file descriptor.
-+///
-+/// # Examples
-+///
-+/// Issue an aio operation, then cancel all outstanding operations on that file
-+/// descriptor.
-+///
-+/// ```
-+/// # extern crate tempfile;
-+/// # extern crate nix;
-+/// # 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 = b"CDEF";
-+/// let mut f = tempfile().unwrap();
-+/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+///     2,   //offset
-+///     &wbuf[..],
-+///     0,   //priority
-+///     SigevNotify::SigevNone,
-+///     LioOpcode::LIO_NOP);
-+/// aiocb.write().unwrap();
-+/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
-+/// if cs == AioCancelStat::AioNotCanceled {
-+///     while (aiocb.error() == Err(Error::from(Errno::EINPROGRESS))) {
-+///         thread::sleep(time::Duration::from_millis(10));
-+///     }
-+/// }
-+/// // Must call `aio_return`, but ignore the result
-+/// let _ = aiocb.aio_return();
-+/// # }
-+/// ```
-+///
-+/// # References
-+///
-+/// [`aio_cancel`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
-+pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
-+    match unsafe { libc::aio_cancel(fd, null_mut()) } {
-+        libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
-+        libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
-+        libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
-+        -1 => Err(Error::last()),
-+        _ => panic!("unknown aio_cancel return value")
-+    }
-+}
-+
-+/// Suspends the calling process until at least one of the specified `AioCb`s
-+/// has completed, a signal is delivered, or the timeout has passed.
-+///
-+/// If `timeout` is `None`, `aio_suspend` will block indefinitely.
-+///
-+/// # Examples
-+///
-+/// Use `aio_suspend` to block until an aio operation completes.
-+///
-+// Disable doctest due to a known bug in FreeBSD's 32-bit emulation.  The fix
-+// will be included in release 11.2.
-+// FIXME reenable the doc test when the CI machine gets upgraded to that release.
-+// https://svnweb.freebsd.org/base?view=revision&revision=325018
-+/// ```no_run
-+/// # extern crate tempfile;
-+/// # extern crate nix;
-+/// # use nix::sys::aio::*;
-+/// # use nix::sys::signal::SigevNotify;
-+/// # use std::os::unix::io::AsRawFd;
-+/// # use tempfile::tempfile;
-+/// # fn main() {
-+/// const WBUF: &[u8] = b"abcdef123456";
-+/// let mut f = tempfile().unwrap();
-+/// let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+///     2,   //offset
-+///     WBUF,
-+///     0,   //priority
-+///     SigevNotify::SigevNone,
-+///     LioOpcode::LIO_NOP);
-+/// aiocb.write().unwrap();
-+/// aio_suspend(&[&aiocb], 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];
-+    let p = plist as *const *const libc::aiocb;
-+    let timep = match timeout {
-+        None    => null::<libc::timespec>(),
-+        Some(x) => x.as_ref() as *const libc::timespec
-+    };
-+    Errno::result(unsafe {
-+        libc::aio_suspend(p, list.len() as i32, timep)
-+    }).map(drop)
-+}
-+
-+impl<'a> Debug for AioCb<'a> {
-+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-+        fmt.debug_struct("AioCb")
-+            .field("aiocb", &self.aiocb)
-+            .field("mutable", &self.mutable)
-+            .field("in_progress", &self.in_progress)
-+            .finish()
-+    }
-+}
-+
-+impl<'a> Drop for AioCb<'a> {
-+    /// If the `AioCb` has no remaining state in the kernel, just drop it.
-+    /// Otherwise, dropping constitutes a resource leak, which is an error
-+    fn drop(&mut self) {
-+        assert!(thread::panicking() || !self.in_progress,
-+                "Dropped an in-progress AioCb");
-+    }
-+}
-+
-+/// LIO Control Block.
-+///
-+/// The basic structure used to issue multiple AIO operations simultaneously.
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+pub struct LioCb<'a> {
-+    /// A collection of [`AioCb`]s.  All of these will be issued simultaneously
-+    /// by the [`listio`] method.
-+    ///
-+    /// [`AioCb`]: struct.AioCb.html
-+    /// [`listio`]: #method.listio
-+    pub aiocbs: Vec<AioCb<'a>>,
-+
-+    /// The actual list passed to `libc::lio_listio`.
-+    ///
-+    /// It must live for as long as any of the operations are still being
-+    /// processesed, because the aio subsystem uses its address as a unique
-+    /// identifier.
-+    list: Vec<*mut libc::aiocb>,
-+
-+    /// A partial set of results.  This field will get populated by
-+    /// `listio_resubmit` when an `LioCb` is resubmitted after an error
-+    results: Vec<Option<Result<isize>>>
-+}
-+
-+#[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)
-+        }
-+    }
-+
-+    /// Submits multiple asynchronous I/O requests with a single system call.
-+    ///
-+    /// They are not guaranteed to complete atomically, and the order in which
-+    /// the requests are carried out is not specified.  Reads, writes, and
-+    /// fsyncs may be freely mixed.
-+    ///
-+    /// This function is useful for reducing the context-switch overhead of
-+    /// submitting many AIO operations.  It can also be used with
-+    /// `LioMode::LIO_WAIT` to block on the result of several independent
-+    /// operations.  Used that way, it is often useful in programs that
-+    /// otherwise make little use of AIO.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Use `listio` to submit an aio operation and wait for its completion.  In
-+    /// this case, there is no need to use [`aio_suspend`] to wait or
-+    /// [`AioCb::error`] to poll.
-+    ///
-+    /// ```
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify;
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// const WBUF: &[u8] = b"abcdef123456";
-+    /// let mut f = tempfile().unwrap();
-+    /// let mut liocb = LioCb::with_capacity(1);
-+    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
-+    ///     2,   //offset
-+    ///     WBUF,
-+    ///     0,   //priority
-+    ///     SigevNotify::SigevNone,
-+    ///     LioOpcode::LIO_WRITE));
-+    /// liocb.listio(LioMode::LIO_WAIT,
-+    ///              SigevNotify::SigevNone).unwrap();
-+    /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
-+    /// # }
-+    /// ```
-+    ///
-+    /// # References
-+    ///
-+    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
-+    ///
-+    /// [`aio_suspend`]: fn.aio_suspend.html
-+    /// [`AioCb::error`]: struct.AioCb.html#method.error
-+    pub fn listio(&mut self, mode: LioMode,
-+                  sigev_notify: SigevNotify) -> Result<()> {
-+        let sigev = SigEvent::new(sigev_notify);
-+        let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
-+        self.list.clear();
-+        for a in &mut self.aiocbs {
-+            a.in_progress = true;
-+            self.list.push(a as *mut AioCb<'a>
-+                             as *mut libc::aiocb);
-+        }
-+        let p = self.list.as_ptr();
-+        Errno::result(unsafe {
-+            libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
-+        }).map(drop)
-+    }
-+
-+    /// Resubmits any incomplete operations with [`lio_listio`].
-+    ///
-+    /// Sometimes, due to system resource limitations, an `lio_listio` call will
-+    /// return `EIO`, or `EAGAIN`.  Or, if a signal is received, it may return
-+    /// `EINTR`.  In any of these cases, only a subset of its constituent
-+    /// operations will actually have been initiated.  `listio_resubmit` will
-+    /// resubmit any operations that are still uninitiated.
-+    ///
-+    /// After calling `listio_resubmit`, results should be collected by
-+    /// [`LioCb::aio_return`].
-+    ///
-+    /// # Examples
-+    /// ```no_run
-+    /// # extern crate tempfile;
-+    /// # extern crate nix;
-+    /// # use nix::Error;
-+    /// # use nix::errno::Errno;
-+    /// # use nix::sys::aio::*;
-+    /// # use nix::sys::signal::SigevNotify;
-+    /// # use std::os::unix::io::AsRawFd;
-+    /// # use std::{thread, time};
-+    /// # use tempfile::tempfile;
-+    /// # fn main() {
-+    /// const WBUF: &[u8] = b"abcdef123456";
-+    /// let mut f = tempfile().unwrap();
-+    /// let mut liocb = LioCb::with_capacity(1);
-+    /// liocb.aiocbs.push(AioCb::from_slice( f.as_raw_fd(),
-+    ///     2,   //offset
-+    ///     WBUF,
-+    ///     0,   //priority
-+    ///     SigevNotify::SigevNone,
-+    ///     LioOpcode::LIO_WRITE));
-+    /// let mut err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
-+    /// while err == Err(Error::Sys(Errno::EIO)) ||
-+    ///       err == Err(Error::Sys(Errno::EAGAIN)) {
-+    ///     thread::sleep(time::Duration::from_millis(10));
-+    ///     err = liocb.listio_resubmit(LioMode::LIO_WAIT, SigevNotify::SigevNone);
-+    /// }
-+    /// assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
-+    /// # }
-+    /// ```
-+    ///
-+    /// # References
-+    ///
-+    /// [`lio_listio`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html)
-+    ///
-+    /// [`lio_listio`]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
-+    /// [`LioCb::aio_return`]: struct.LioCb.html#method.aio_return
-+    // Note: the addresses of any EINPROGRESS or EOK aiocbs _must_ not be
-+    // changed by this method, because the kernel relies on their addresses
-+    // being stable.
-+    // Note: aiocbs that are Ok(()) must be finalized by aio_return, or else the
-+    // sigev_notify will immediately refire.
-+    pub fn listio_resubmit(&mut self, mode:LioMode,
-+                           sigev_notify: SigevNotify) -> Result<()> {
-+        let sigev = SigEvent::new(sigev_notify);
-+        let sigevp = &mut sigev.sigevent() as *mut libc::sigevent;
-+        self.list.clear();
-+
-+        while self.results.len() < self.aiocbs.len() {
-+            self.results.push(None);
-+        }
-+
-+        for (i, a) in self.aiocbs.iter_mut().enumerate() {
-+            if self.results[i].is_some() {
-+                // Already collected final status for this operation
-+                continue;
-+            }
-+            match a.error() {
-+                Ok(()) => {
-+                    // aiocb is complete; collect its status and don't resubmit
-+                    self.results[i] = Some(a.aio_return());
-+                },
-+                Err(Error::Sys(Errno::EAGAIN)) => {
-+                    self.list.push(a as *mut AioCb<'a> as *mut libc::aiocb);
-+                },
-+                Err(Error::Sys(Errno::EINPROGRESS)) => {
-+                    // aiocb is was successfully queued; no need to do anything
-+                    ()
-+                },
-+                Err(Error::Sys(Errno::EINVAL)) => panic!(
-+                    "AioCb was never submitted, or already finalized"),
-+                _ => unreachable!()
-+            }
-+        }
-+        let p = self.list.as_ptr();
-+        Errno::result(unsafe {
-+            libc::lio_listio(mode as i32, p, self.list.len() as i32, sigevp)
-+        }).map(drop)
-+    }
-+
-+    /// Collect final status for an individual `AioCb` submitted as part of an
-+    /// `LioCb`.
-+    ///
-+    /// This is just like [`AioCb::aio_return`], except it takes into account
-+    /// operations that were restarted by [`LioCb::listio_resubmit`]
-+    ///
-+    /// [`AioCb::aio_return`]: struct.AioCb.html#method.aio_return
-+    /// [`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()
-+        } else {
-+            self.results[i].unwrap()
-+        }
-+    }
-+
-+    /// Retrieve error status of an individual `AioCb` submitted as part of an
-+    /// `LioCb`.
-+    ///
-+    /// This is just like [`AioCb::error`], except it takes into account
-+    /// operations that were restarted by [`LioCb::listio_resubmit`]
-+    ///
-+    /// [`AioCb::error`]: struct.AioCb.html#method.error
-+    /// [`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()
-+        } else {
-+            Ok(())
-+        }
-+    }
-+}
-+
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+impl<'a> Debug for LioCb<'a> {
-+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-+        fmt.debug_struct("LioCb")
-+            .field("aiocbs", &self.aiocbs)
-+            .finish()
-+    }
-+}
-+
-+#[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,
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/epoll.rs b/third_party/rust/nix-0.15.0/src/sys/epoll.rs
-new file mode 100644
-index 0000000000000..fef6f4e3ec92c
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/epoll.rs
-@@ -0,0 +1,109 @@
-+use Result;
-+use errno::Errno;
-+use libc::{self, c_int};
-+use std::os::unix::io::RawFd;
-+use std::ptr;
-+use std::mem;
-+use ::Error;
-+
-+libc_bitflags!(
-+    pub struct EpollFlags: c_int {
-+        EPOLLIN;
-+        EPOLLPRI;
-+        EPOLLOUT;
-+        EPOLLRDNORM;
-+        EPOLLRDBAND;
-+        EPOLLWRNORM;
-+        EPOLLWRBAND;
-+        EPOLLMSG;
-+        EPOLLERR;
-+        EPOLLHUP;
-+        EPOLLRDHUP;
-+        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
-+        EPOLLEXCLUSIVE;
-+        #[cfg(not(target_arch = "mips"))]
-+        EPOLLWAKEUP;
-+        EPOLLONESHOT;
-+        EPOLLET;
-+    }
-+);
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+#[repr(i32)]
-+pub enum EpollOp {
-+    EpollCtlAdd = libc::EPOLL_CTL_ADD,
-+    EpollCtlDel = libc::EPOLL_CTL_DEL,
-+    EpollCtlMod = libc::EPOLL_CTL_MOD,
-+}
-+
-+libc_bitflags!{
-+    pub struct EpollCreateFlags: c_int {
-+        EPOLL_CLOEXEC;
-+    }
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+#[repr(C)]
-+pub struct EpollEvent {
-+    event: libc::epoll_event,
-+}
-+
-+impl EpollEvent {
-+    pub fn new(events: EpollFlags, data: u64) -> Self {
-+        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
-+    }
-+
-+    pub fn empty() -> Self {
-+        unsafe { mem::zeroed::<EpollEvent>() }
-+    }
-+
-+    pub fn events(&self) -> EpollFlags {
-+        EpollFlags::from_bits(self.event.events as c_int).unwrap()
-+    }
-+
-+    pub fn data(&self) -> u64 {
-+        self.event.u64
-+    }
-+}
-+
-+#[inline]
-+pub fn epoll_create() -> Result<RawFd> {
-+    let res = unsafe { libc::epoll_create(1024) };
-+
-+    Errno::result(res)
-+}
-+
-+#[inline]
-+pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
-+    let res = unsafe { libc::epoll_create1(flags.bits()) };
-+
-+    Errno::result(res)
-+}
-+
-+#[inline]
-+pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
-+    where T: Into<Option<&'a mut EpollEvent>>
-+{
-+    let mut event: Option<&mut EpollEvent> = event.into();
-+    if event.is_none() && op != EpollOp::EpollCtlDel {
-+        Err(Error::Sys(Errno::EINVAL))
-+    } else {
-+        let res = unsafe {
-+            if let Some(ref mut event) = event {
-+                libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event)
-+            } else {
-+                libc::epoll_ctl(epfd, op as c_int, fd, ptr::null_mut())
-+            }
-+        };
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+#[inline]
-+pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
-+    let res = unsafe {
-+        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/event.rs b/third_party/rust/nix-0.15.0/src/sys/event.rs
-new file mode 100644
-index 0000000000000..8cd7372f88188
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/event.rs
-@@ -0,0 +1,351 @@
-+/* TOOD: Implement for other kqueue based systems
-+ */
-+
-+use {Errno, Result};
-+#[cfg(not(target_os = "netbsd"))]
-+use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
-+#[cfg(target_os = "netbsd")]
-+use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
-+use libc;
-+use std::os::unix::io::RawFd;
-+use std::ptr;
-+use std::mem;
-+
-+// Redefine kevent in terms of programmer-friendly enums and bitfields.
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct KEvent {
-+    kevent: libc::kevent,
-+}
-+
-+#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-+          target_os = "ios", target_os = "macos",
-+          target_os = "openbsd"))]
-+type type_of_udata = *mut libc::c_void;
-+#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-+          target_os = "ios", target_os = "macos"))]
-+type type_of_data = intptr_t;
-+#[cfg(any(target_os = "netbsd"))]
-+type type_of_udata = intptr_t;
-+#[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
-+type type_of_data = libc::int64_t;
-+
-+#[cfg(target_os = "netbsd")]
-+type type_of_event_filter = u32;
-+#[cfg(not(target_os = "netbsd"))]
-+type type_of_event_filter = i16;
-+libc_enum! {
-+    #[cfg_attr(target_os = "netbsd", repr(u32))]
-+    #[cfg_attr(not(target_os = "netbsd"), repr(i16))]
-+    pub enum EventFilter {
-+        EVFILT_AIO,
-+        /// Returns whenever there is no remaining data in the write buffer
-+        #[cfg(target_os = "freebsd")]
-+        EVFILT_EMPTY,
-+        #[cfg(target_os = "dragonfly")]
-+        EVFILT_EXCEPT,
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  target_os = "macos"))]
-+        EVFILT_FS,
-+        #[cfg(target_os = "freebsd")]
-+        EVFILT_LIO,
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        EVFILT_MACHPORT,
-+        EVFILT_PROC,
-+        /// Returns events associated with the process referenced by a given
-+        /// process descriptor, created by `pdfork()`. The events to monitor are:
-+        ///
-+        /// - NOTE_EXIT: the process has exited. The exit status will be stored in data.
-+        #[cfg(target_os = "freebsd")]
-+        EVFILT_PROCDESC,
-+        EVFILT_READ,
-+        /// Returns whenever an asynchronous `sendfile()` call completes.
-+        #[cfg(target_os = "freebsd")]
-+        EVFILT_SENDFILE,
-+        EVFILT_SIGNAL,
-+        EVFILT_TIMER,
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  target_os = "macos"))]
-+        EVFILT_USER,
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        EVFILT_VM,
-+        EVFILT_VNODE,
-+        EVFILT_WRITE,
-+    }
-+}
-+
-+#[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-+          target_os = "ios", target_os = "macos",
-+          target_os = "openbsd"))]
-+pub type type_of_event_flag = u16;
-+#[cfg(any(target_os = "netbsd"))]
-+pub type type_of_event_flag = u32;
-+libc_bitflags!{
-+    pub struct EventFlag: type_of_event_flag {
-+        EV_ADD;
-+        EV_CLEAR;
-+        EV_DELETE;
-+        EV_DISABLE;
-+        // No released version of OpenBSD supports EV_DISPATCH or EV_RECEIPT.
-+        // These have been commited to the -current branch though and are
-+        // expected to be part of the OpenBSD 6.2 release in Nov 2017.
-+        // See: https://marc.info/?l=openbsd-tech&m=149621427511219&w=2
-+        // https://github.com/rust-lang/libc/pull/613
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-+                  target_os = "ios", target_os = "macos",
-+                  target_os = "netbsd"))]
-+        EV_DISPATCH;
-+        #[cfg(target_os = "freebsd")]
-+        EV_DROP;
-+        EV_ENABLE;
-+        EV_EOF;
-+        EV_ERROR;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EV_FLAG0;
-+        EV_FLAG1;
-+        #[cfg(target_os = "dragonfly")]
-+        EV_NODATA;
-+        EV_ONESHOT;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EV_OOBAND;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        EV_POLL;
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-+                  target_os = "ios", target_os = "macos",
-+                  target_os = "netbsd"))]
-+        EV_RECEIPT;
-+        EV_SYSFLAGS;
-+    }
-+}
-+
-+libc_bitflags!(
-+    pub struct FilterFlag: u32 {
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_ABSOLUTE;
-+        NOTE_ATTRIB;
-+        NOTE_CHILD;
-+        NOTE_DELETE;
-+        #[cfg(target_os = "openbsd")]
-+        NOTE_EOF;
-+        NOTE_EXEC;
-+        NOTE_EXIT;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
-+        #[allow(deprecated)]
-+        NOTE_EXIT_REPARENTED;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_EXITSTATUS;
-+        NOTE_EXTEND;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFAND;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFCOPY;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFCTRLMASK;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFLAGSMASK;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFNOP;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_FFOR;
-+        NOTE_FORK;
-+        NOTE_LINK;
-+        NOTE_LOWAT;
-+        #[cfg(target_os = "freebsd")]
-+        NOTE_MSECONDS;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_NONE;
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
-+        NOTE_NSECONDS;
-+        #[cfg(target_os = "dragonfly")]
-+        NOTE_OOB;
-+        NOTE_PCTRLMASK;
-+        NOTE_PDATAMASK;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
-+        #[allow(deprecated)]
-+        NOTE_REAP;
-+        NOTE_RENAME;
-+        NOTE_REVOKE;
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
-+        NOTE_SECONDS;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_SIGNAL;
-+        NOTE_TRACK;
-+        NOTE_TRACKERR;
-+        #[cfg(any(target_os = "macos",
-+                  target_os = "ios",
-+                  target_os = "freebsd",
-+                  target_os = "dragonfly"))]
-+        NOTE_TRIGGER;
-+        #[cfg(target_os = "openbsd")]
-+        NOTE_TRUNCATE;
-+        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
-+        NOTE_USECONDS;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_VM_ERROR;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_VM_PRESSURE;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_VM_PRESSURE_SUDDEN_TERMINATE;
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        NOTE_VM_PRESSURE_TERMINATE;
-+        NOTE_WRITE;
-+    }
-+);
-+
-+pub fn kqueue() -> Result<RawFd> {
-+    let res = unsafe { libc::kqueue() };
-+
-+    Errno::result(res)
-+}
-+
-+
-+// KEvent can't derive Send because on some operating systems, udata is defined
-+// as a void*.  However, KEvent's public API always treats udata as an intptr_t,
-+// which is safe to Send.
-+unsafe impl Send for KEvent {
-+}
-+
-+impl KEvent {
-+    pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
-+               fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
-+        KEvent { kevent: libc::kevent {
-+            ident: ident,
-+            filter: filter as type_of_event_filter,
-+            flags: flags.bits(),
-+            fflags: fflags.bits(),
-+            data: data as type_of_data,
-+            udata: udata as type_of_udata
-+        } }
-+    }
-+
-+    pub fn ident(&self) -> uintptr_t {
-+        self.kevent.ident
-+    }
-+
-+    pub fn filter(&self) -> EventFilter {
-+        unsafe { mem::transmute(self.kevent.filter as type_of_event_filter) }
-+    }
-+
-+    pub fn flags(&self) -> EventFlag {
-+        EventFlag::from_bits(self.kevent.flags).unwrap()
-+    }
-+
-+    pub fn fflags(&self) -> FilterFlag {
-+        FilterFlag::from_bits(self.kevent.fflags).unwrap()
-+    }
-+
-+    pub fn data(&self) -> intptr_t {
-+        self.kevent.data as intptr_t
-+    }
-+
-+    pub fn udata(&self) -> intptr_t {
-+        self.kevent.udata as intptr_t
-+    }
-+}
-+
-+pub fn kevent(kq: RawFd,
-+              changelist: &[KEvent],
-+              eventlist: &mut [KEvent],
-+              timeout_ms: usize) -> Result<usize> {
-+
-+    // Convert ms to timespec
-+    let timeout = timespec {
-+        tv_sec: (timeout_ms / 1000) as time_t,
-+        tv_nsec: ((timeout_ms % 1000) * 1_000_000) as c_long
-+    };
-+
-+    kevent_ts(kq, changelist, eventlist, Some(timeout))
-+}
-+
-+#[cfg(any(target_os = "macos",
-+          target_os = "ios",
-+          target_os = "freebsd",
-+          target_os = "dragonfly",
-+          target_os = "openbsd"))]
-+type type_of_nchanges = c_int;
-+#[cfg(target_os = "netbsd")]
-+type type_of_nchanges = size_t;
-+
-+pub fn kevent_ts(kq: RawFd,
-+              changelist: &[KEvent],
-+              eventlist: &mut [KEvent],
-+              timeout_opt: Option<timespec>) -> Result<usize> {
-+
-+    let res = unsafe {
-+        libc::kevent(
-+            kq,
-+            changelist.as_ptr() as *const libc::kevent,
-+            changelist.len() as type_of_nchanges,
-+            eventlist.as_mut_ptr() as *mut libc::kevent,
-+            eventlist.len() as type_of_nchanges,
-+            if let Some(ref timeout) = timeout_opt {timeout as *const timespec} else {ptr::null()})
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+#[inline]
-+pub fn ev_set(ev: &mut KEvent,
-+              ident: usize,
-+              filter: EventFilter,
-+              flags: EventFlag,
-+              fflags: FilterFlag,
-+              udata: intptr_t) {
-+
-+    ev.kevent.ident  = ident as uintptr_t;
-+    ev.kevent.filter = filter as type_of_event_filter;
-+    ev.kevent.flags  = flags.bits();
-+    ev.kevent.fflags = fflags.bits();
-+    ev.kevent.data   = 0;
-+    ev.kevent.udata  = udata as type_of_udata;
-+}
-+
-+#[test]
-+fn test_struct_kevent() {
-+    let udata : intptr_t = 12345;
-+
-+    let expected = libc::kevent{ident: 0xdead_beef,
-+                                filter: libc::EVFILT_READ,
-+                                flags: libc::EV_ONESHOT | libc::EV_ADD,
-+                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
-+                                data: 0x1337,
-+                                udata: udata as type_of_udata};
-+    let actual = KEvent::new(0xdead_beef,
-+                             EventFilter::EVFILT_READ,
-+                             EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
-+                             FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
-+                             0x1337,
-+                             udata);
-+    assert!(expected.ident == actual.ident());
-+    assert!(expected.filter == actual.filter() as type_of_event_filter);
-+    assert!(expected.flags == actual.flags().bits());
-+    assert!(expected.fflags == actual.fflags().bits());
-+    assert!(expected.data == actual.data() as type_of_data);
-+    assert!(expected.udata == actual.udata() as type_of_udata);
-+    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/eventfd.rs b/third_party/rust/nix-0.15.0/src/sys/eventfd.rs
-new file mode 100644
-index 0000000000000..c5a54e46a1735
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/eventfd.rs
-@@ -0,0 +1,18 @@
-+use libc;
-+use std::os::unix::io::RawFd;
-+use Result;
-+use errno::Errno;
-+
-+libc_bitflags! {
-+    pub struct EfdFlags: libc::c_int {
-+        EFD_CLOEXEC; // Since Linux 2.6.27
-+        EFD_NONBLOCK; // Since Linux 2.6.27
-+        EFD_SEMAPHORE; // Since Linux 2.6.30
-+    }
-+}
-+
-+pub fn eventfd(initval: libc::c_uint, flags: EfdFlags) -> Result<RawFd> {
-+    let res = unsafe { libc::eventfd(initval, flags.bits()) };
-+
-+    Errno::result(res).map(|r| r as RawFd)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/inotify.rs b/third_party/rust/nix-0.15.0/src/sys/inotify.rs
-new file mode 100644
-index 0000000000000..e6c2cf64d29dc
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/inotify.rs
-@@ -0,0 +1,230 @@
-+//! Monitoring API for filesystem events.
-+//!
-+//! 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).
-+//! 
-+//! # Examples
-+//!
-+//! Monitor all events happening in directory "test":
-+//! ```no_run
-+//! # use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
-+//! #
-+//! // We create a new inotify instance.
-+//! let instance = Inotify::init(InitFlags::empty()).unwrap();
-+//!
-+//! // We add a new watch on directory "test" for all events.
-+//! let wd = instance.add_watch("test", AddWatchFlags::IN_ALL_EVENTS).unwrap();
-+//!
-+//! loop {
-+//!     // We read from our inotify instance for events.
-+//!     let events = instance.read_events().unwrap();
-+//!     println!("Events: {:?}", events);
-+//! }
-+//! ```
-+
-+use libc;
-+use libc::{
-+    c_char,
-+    c_int,
-+};
-+use std::ffi::{OsString,OsStr,CStr};
-+use std::os::unix::ffi::OsStrExt;
-+use std::mem::size_of;
-+use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
-+use unistd::read;
-+use Result;
-+use NixPath;
-+use errno::Errno;
-+
-+libc_bitflags! {
-+    /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
-+    pub struct AddWatchFlags: u32 {
-+        IN_ACCESS;
-+        IN_MODIFY;
-+        IN_ATTRIB;
-+        IN_CLOSE_WRITE;
-+        IN_CLOSE_NOWRITE;
-+        IN_OPEN;
-+        IN_MOVED_FROM;
-+        IN_MOVED_TO;
-+        IN_CREATE;
-+        IN_DELETE;
-+        IN_DELETE_SELF;
-+        IN_MOVE_SELF;
-+
-+        IN_UNMOUNT;
-+        IN_Q_OVERFLOW;
-+        IN_IGNORED;
-+
-+        IN_CLOSE;
-+        IN_MOVE;
-+
-+        IN_ONLYDIR;
-+        IN_DONT_FOLLOW;
-+
-+        IN_ISDIR;
-+        IN_ONESHOT;
-+        IN_ALL_EVENTS;
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Configuration options for [`inotify_init1`](fn.inotify_init1.html).
-+    pub struct InitFlags: c_int {
-+        IN_CLOEXEC;
-+        IN_NONBLOCK;
-+    }
-+}
-+
-+/// An inotify instance. This is also a file descriptor, you can feed it to
-+/// other interfaces consuming file descriptors, epoll for example.
-+#[derive(Debug, Clone, Copy)]
-+pub struct Inotify {
-+    fd: RawFd
-+}
-+
-+/// 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. 
-+#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
-+pub struct WatchDescriptor {
-+    wd: i32
-+}
-+
-+/// A single inotify event.
-+///
-+/// For more documentation see, [inotify(7)](http://man7.org/linux/man-pages/man7/inotify.7.html).
-+#[derive(Debug)]
-+pub struct InotifyEvent {
-+    /// Watch descriptor. This field corresponds to the watch descriptor you
-+    /// were issued when calling add_watch. It allows you to know which watch
-+    /// this event comes from. 
-+    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. 
-+    pub cookie: u32,
-+    /// Filename. This field exists only if the event was triggered for a file
-+    /// inside the watched directory.
-+    pub name: Option<OsString>
-+}
-+
-+impl Inotify {
-+    /// Initialize a new inotify instance.
-+    ///
-+    /// 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).
-+    pub fn init(flags: InitFlags) -> Result<Inotify> {
-+        let res = Errno::result(unsafe {
-+            libc::inotify_init1(flags.bits())
-+        });
-+
-+        res.map(|fd| Inotify { fd })
-+    }
-+
-+    /// Adds a new watch on the target file or directory. 
-+    ///
-+    /// 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).
-+    pub fn add_watch<P: ?Sized + NixPath>(&self,
-+                                          path: &P,
-+                                          mask: AddWatchFlags) 
-+                                            -> Result<WatchDescriptor>
-+    {
-+        let res = path.with_nix_path(|cstr| {
-+            unsafe {
-+                libc::inotify_add_watch(self.fd, cstr.as_ptr(), mask.bits())
-+            }
-+        })?;
-+
-+        Errno::result(res).map(|wd| WatchDescriptor { wd })
-+    }
-+
-+    /// Removes an existing watch using the watch descriptor returned by
-+    /// inotify_add_watch.
-+    ///
-+    /// 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).
-+    #[cfg(target_os = "linux")]
-+    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
-+        let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    #[cfg(target_os = "android")]
-+    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
-+        let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    /// 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. 
-+    /// 
-+    /// 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>> {
-+        let header_size = size_of::<libc::inotify_event>();
-+        let mut buffer = [0u8; 4096];
-+        let mut events = Vec::new();
-+        let mut offset = 0;
-+
-+        let nread = read(self.fd, &mut buffer)?;
-+
-+        while (nread - offset) >= header_size {
-+            let event = unsafe {
-+                &*(
-+                    buffer
-+                        .as_ptr()
-+                        .offset(offset as isize) as *const libc::inotify_event
-+                )
-+            };
-+
-+            let name = match event.len {
-+                0 => None,
-+                _ => {
-+                    let ptr = unsafe { 
-+                        buffer
-+                            .as_ptr()
-+                            .offset(offset as isize + header_size as isize)
-+                            as *const c_char
-+                    };
-+                    let cstr = unsafe { CStr::from_ptr(ptr) };
-+                
-+                    Some(OsStr::from_bytes(cstr.to_bytes()).to_owned())
-+                }
-+            };
-+
-+            events.push(InotifyEvent {
-+                wd: WatchDescriptor { wd: event.wd },
-+                mask: AddWatchFlags::from_bits_truncate(event.mask),
-+                cookie: event.cookie,
-+                name
-+            });
-+
-+            offset += header_size + event.len as usize;
-+        }
-+
-+        Ok(events)
-+    }
-+}
-+
-+impl AsRawFd for Inotify {
-+    fn as_raw_fd(&self) -> RawFd {
-+        self.fd
-+    }
-+}
-+
-+impl FromRawFd for Inotify {
-+    unsafe fn from_raw_fd(fd: RawFd) -> Self {
-+        Inotify { fd }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
-new file mode 100644
-index 0000000000000..9b8b0ff1a155f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/bsd.rs
-@@ -0,0 +1,102 @@
-+/// The datatype used for the ioctl number
-+#[doc(hidden)]
-+pub type ioctl_num_type = ::libc::c_ulong;
-+/// The datatype used for the 3rd argument
-+#[doc(hidden)]
-+pub type ioctl_param_type = ::libc::c_int;
-+
-+mod consts {
-+    use ::sys::ioctl::ioctl_num_type;
-+    #[doc(hidden)]
-+    pub const VOID: ioctl_num_type = 0x2000_0000;
-+    #[doc(hidden)]
-+    pub const OUT: ioctl_num_type = 0x4000_0000;
-+    #[doc(hidden)]
-+    pub const IN: ioctl_num_type = 0x8000_0000;
-+    #[doc(hidden)]
-+    pub const INOUT: ioctl_num_type = (IN|OUT);
-+    #[doc(hidden)]
-+    pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
-+}
-+
-+pub use self::consts::*;
-+
-+#[macro_export]
-+#[doc(hidden)]
-+macro_rules! ioc {
-+    ($inout:expr, $group:expr, $num:expr, $len:expr) => (
-+        $inout | (($len as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::IOCPARM_MASK) << 16) | (($group as $crate::sys::ioctl::ioctl_num_type) << 8) | ($num as $crate::sys::ioctl::ioctl_num_type)
-+    )
-+}
-+
-+/// Generate an ioctl request code for a command that passes no data.
-+///
-+/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_none!()` directly.
-+///
-+/// # Example
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// const KVMIO: u8 = 0xAE;
-+/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_none {
-+    ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, 0))
-+}
-+
-+/// Generate an ioctl request code for a command that passes an integer
-+///
-+/// This is equivalent to the `_IOWINT()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_write_int!()` directly.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_write_int {
-+    ($g:expr, $n:expr) => (ioc!($crate::sys::ioctl::VOID, $g, $n, ::std::mem::size_of::<$crate::libc::c_int>()))
-+}
-+
-+/// Generate an ioctl request code for a command that reads.
-+///
-+/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_read!()` directly.
-+///
-+/// The read/write direction is relative to userland, so this
-+/// command would be userland is reading and the kernel is
-+/// writing.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_read {
-+    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::OUT, $g, $n, $len))
-+}
-+
-+/// Generate an ioctl request code for a command that writes.
-+///
-+/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_write!()` directly.
-+///
-+/// The read/write direction is relative to userland, so this
-+/// command would be userland is writing and the kernel is
-+/// reading.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_write {
-+    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::IN, $g, $n, $len))
-+}
-+
-+/// Generate an ioctl request code for a command that reads and writes.
-+///
-+/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_readwrite {
-+    ($g:expr, $n:expr, $len:expr) => (ioc!($crate::sys::ioctl::INOUT, $g, $n, $len))
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
-new file mode 100644
-index 0000000000000..9cdac72a4b80b
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/linux.rs
-@@ -0,0 +1,140 @@
-+/// The datatype used for the ioctl number
-+#[cfg(any(target_os = "android", target_env = "musl"))]
-+#[doc(hidden)]
-+pub type ioctl_num_type = ::libc::c_int;
-+#[cfg(not(any(target_os = "android", target_env = "musl")))]
-+#[doc(hidden)]
-+pub type ioctl_num_type = ::libc::c_ulong;
-+/// The datatype used for the 3rd argument
-+#[doc(hidden)]
-+pub type ioctl_param_type = ::libc::c_ulong;
-+
-+#[doc(hidden)]
-+pub const NRBITS: ioctl_num_type = 8;
-+#[doc(hidden)]
-+pub const TYPEBITS: ioctl_num_type = 8;
-+
-+#[cfg(any(target_arch = "mips", target_arch = "mips64", target_arch = "powerpc", target_arch = "powerpc64", target_arch = "sparc64"))]
-+mod consts {
-+    #[doc(hidden)]
-+    pub const NONE: u8 = 1;
-+    #[doc(hidden)]
-+    pub const READ: u8 = 2;
-+    #[doc(hidden)]
-+    pub const WRITE: u8 = 4;
-+    #[doc(hidden)]
-+    pub const SIZEBITS: u8 = 13;
-+    #[doc(hidden)]
-+    pub const DIRBITS: u8 = 3;
-+}
-+
-+// "Generic" ioctl protocol
-+#[cfg(any(target_arch = "x86",
-+          target_arch = "arm",
-+          target_arch = "s390x",
-+          target_arch = "x86_64",
-+          target_arch = "aarch64"))]
-+mod consts {
-+    #[doc(hidden)]
-+    pub const NONE: u8 = 0;
-+    #[doc(hidden)]
-+    pub const READ: u8 = 2;
-+    #[doc(hidden)]
-+    pub const WRITE: u8 = 1;
-+    #[doc(hidden)]
-+    pub const SIZEBITS: u8 = 14;
-+    #[doc(hidden)]
-+    pub const DIRBITS: u8 = 2;
-+}
-+
-+pub use self::consts::*;
-+
-+#[doc(hidden)]
-+pub const NRSHIFT: ioctl_num_type = 0;
-+#[doc(hidden)]
-+pub const TYPESHIFT: ioctl_num_type = NRSHIFT + NRBITS as ioctl_num_type;
-+#[doc(hidden)]
-+pub const SIZESHIFT: ioctl_num_type = TYPESHIFT + TYPEBITS as ioctl_num_type;
-+#[doc(hidden)]
-+pub const DIRSHIFT: ioctl_num_type = SIZESHIFT + SIZEBITS as ioctl_num_type;
-+
-+#[doc(hidden)]
-+pub const NRMASK: ioctl_num_type = (1 << NRBITS) - 1;
-+#[doc(hidden)]
-+pub const TYPEMASK: ioctl_num_type = (1 << TYPEBITS) - 1;
-+#[doc(hidden)]
-+pub const SIZEMASK: ioctl_num_type = (1 << SIZEBITS) - 1;
-+#[doc(hidden)]
-+pub const DIRMASK: ioctl_num_type = (1 << DIRBITS) - 1;
-+
-+/// Encode an ioctl command.
-+#[macro_export]
-+#[doc(hidden)]
-+macro_rules! ioc {
-+    ($dir:expr, $ty:expr, $nr:expr, $sz:expr) => (
-+        (($dir as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::DIRMASK) << $crate::sys::ioctl::DIRSHIFT) |
-+        (($ty as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::TYPEMASK) << $crate::sys::ioctl::TYPESHIFT) |
-+        (($nr as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::NRMASK) << $crate::sys::ioctl::NRSHIFT) |
-+        (($sz as $crate::sys::ioctl::ioctl_num_type & $crate::sys::ioctl::SIZEMASK) << $crate::sys::ioctl::SIZESHIFT))
-+}
-+
-+/// Generate an ioctl request code for a command that passes no data.
-+///
-+/// This is equivalent to the `_IO()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_none!()` directly.
-+///
-+/// # Example
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// const KVMIO: u8 = 0xAE;
-+/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_none {
-+    ($ty:expr, $nr:expr) => (ioc!($crate::sys::ioctl::NONE, $ty, $nr, 0))
-+}
-+
-+/// Generate an ioctl request code for a command that reads.
-+///
-+/// This is equivalent to the `_IOR()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_read!()` directly.
-+///
-+/// The read/write direction is relative to userland, so this
-+/// command would be userland is reading and the kernel is
-+/// writing.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_read {
-+    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ, $ty, $nr, $sz))
-+}
-+
-+/// Generate an ioctl request code for a command that writes.
-+///
-+/// This is equivalent to the `_IOW()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_write!()` directly.
-+///
-+/// The read/write direction is relative to userland, so this
-+/// command would be userland is writing and the kernel is
-+/// reading.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_write {
-+    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::WRITE, $ty, $nr, $sz))
-+}
-+
-+/// Generate an ioctl request code for a command that reads and writes.
-+///
-+/// This is equivalent to the `_IOWR()` macro exposed by the C ioctl API.
-+///
-+/// You should only use this macro directly if the `ioctl` you're working
-+/// with is "bad" and you cannot use `ioctl_readwrite!()` directly.
-+#[macro_export(local_inner_macros)]
-+macro_rules! request_code_readwrite {
-+    ($ty:expr, $nr:expr, $sz:expr) => (ioc!($crate::sys::ioctl::READ | $crate::sys::ioctl::WRITE, $ty, $nr, $sz))
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs b/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
-new file mode 100644
-index 0000000000000..4513bf877434a
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ioctl/mod.rs
-@@ -0,0 +1,778 @@
-+//! Provide helpers for making ioctl system calls.
-+//!
-+//! This library is pretty low-level and messy. `ioctl` is not fun.
-+//!
-+//! What is an `ioctl`?
-+//! ===================
-+//!
-+//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
-+//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
-+//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
-+//! descriptor.
-+//!
-+//! It is common to see `ioctl`s used for the following purposes:
-+//!
-+//!   * Provide read/write access to out-of-band data related to a device such as configuration
-+//!     (for instance, setting serial port options)
-+//!   * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
-+//!     devices).
-+//!   * Provide access to control functions on a device (for example, on Linux you can send
-+//!     commands like pause, resume, and eject to the CDROM device.
-+//!   * Do whatever else the device driver creator thought made most sense.
-+//!
-+//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
-+//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
-+//! Additionally they may read or write data and therefore need to pass along a data pointer.
-+//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
-+//! be difficult.
-+//!
-+//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
-+//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
-+//! subcomponents (For linux this is documented in
-+//! [`Documentation/ioctl/ioctl-number.txt`](http://elixir.free-electrons.com/linux/latest/source/Documentation/ioctl/ioctl-number.txt)):
-+//!
-+//!   * Number: The actual ioctl ID
-+//!   * Type: A grouping of ioctls for a common purpose or driver
-+//!   * Size: The size in bytes of the data that will be transferred
-+//!   * Direction: Whether there is any data and if it's read, write, or both
-+//!
-+//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
-+//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
-+//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
-+//! commonly referred to as "bad" in `ioctl` documentation.
-+//!
-+//! Defining `ioctl`s
-+//! =================
-+//!
-+//! This library provides several `ioctl_*!` macros for binding `ioctl`s. These generate public
-+//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
-+//! ways it can be used depending on the specific ioctl you're working with.
-+//!
-+//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
-+//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
-+//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
-+//! macro, we know it's a `read` ioctl and can use the `ioctl_read!` macro as follows:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-+//! const SPI_IOC_TYPE_MODE: u8 = 1;
-+//! ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-+//! # fn main() {}
-+//! ```
-+//!
-+//! This generates the function:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! # use std::mem;
-+//! # use nix::{libc, Result};
-+//! # use nix::errno::Errno;
-+//! # use nix::libc::c_int as c_int;
-+//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-+//! # const SPI_IOC_TYPE_MODE: u8 = 1;
-+//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
-+//!     let res = libc::ioctl(fd, request_code_read!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
-+//!     Errno::result(res)
-+//! }
-+//! # fn main() {}
-+//! ```
-+//!
-+//! The return value for the wrapper functions generated by the `ioctl_*!` macros are `nix::Error`s.
-+//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
-+//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
-+//! of the range of "good" values (-Inf..-2, 0..Inf) into a smaller range in a helper function.
-+//!
-+//! Writing `ioctl`s generally use pointers as their data source and these should use the
-+//! `ioctl_write_ptr!`. But in some cases an `int` is passed directly. For these `ioctl`s use the
-+//! `ioctl_write_int!` macro. This variant does not take a type as the last argument:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! const HCI_IOC_MAGIC: u8 = b'k';
-+//! const HCI_IOC_HCIDEVUP: u8 = 1;
-+//! ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
-+//! # fn main() {}
-+//! ```
-+//!
-+//! Some `ioctl`s don't transfer any data, and those should use `ioctl_none!`. This macro
-+//! doesn't take a type and so it is declared similar to the `write_int` variant shown above.
-+//!
-+//! The mode for a given `ioctl` should be clear from the documentation if it has good
-+//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
-+//! number where `_IO`, `_IOR`, `_IOW`, and `_IOWR` map to "none", "read", "write_*", and "readwrite"
-+//! 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
-+//! large number of `ioctl`s and describes their argument data type.
-+//!
-+//! Using "bad" `ioctl`s
-+//! --------------------
-+//!
-+//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
-+//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the
-+//! `ioctl_*_bad!` macros. This naming comes from the Linux kernel which refers to these
-+//! `ioctl`s as "bad". These are a different variant as they bypass calling the macro that generates
-+//! the ioctl number and instead use the defined value directly.
-+//!
-+//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
-+//! It's defined as `0x5401` in `ioctls.h` on Linux and can be implemented as:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-+//! # use nix::libc::TCGETS as TCGETS;
-+//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-+//! # use nix::libc::termios as termios;
-+//! # #[cfg(any(target_os = "android", target_os = "linux"))]
-+//! ioctl_read_bad!(tcgets, TCGETS, termios);
-+//! # fn main() {}
-+//! ```
-+//!
-+//! The generated function has the same form as that generated by `ioctl_read!`:
-+//!
-+//! ```text
-+//! pub unsafe fn tcgets(fd: c_int, data: *mut termios) -> Result<c_int>;
-+//! ```
-+//!
-+//! Working with Arrays
-+//! -------------------
-+//!
-+//! Some `ioctl`s work with entire arrays of elements. These are supported by the `ioctl_*_buf`
-+//! family of macros: `ioctl_read_buf`, `ioctl_write_buf`, and `ioctl_readwrite_buf`. Note that
-+//! there are no "bad" versions for working with buffers. The generated functions include a `len`
-+//! argument to specify the number of elements (where the type of each element is specified in the
-+//! macro).
-+//!
-+//! Again looking to the SPI `ioctl`s on Linux for an example, there is a `SPI_IOC_MESSAGE` `ioctl`
-+//! that queues up multiple SPI messages by writing an entire array of `spi_ioc_transfer` structs.
-+//! `linux/spi/spidev.h` defines a macro to calculate the `ioctl` number like:
-+//!
-+//! ```C
-+//! #define SPI_IOC_MAGIC 'k'
-+//! #define SPI_MSGSIZE(N) ...
-+//! #define SPI_IOC_MESSAGE(N) _IOW(SPI_IOC_MAGIC, 0, char[SPI_MSGSIZE(N)])
-+//! ```
-+//!
-+//! The `SPI_MSGSIZE(N)` calculation is already handled by the `ioctl_*!` macros, so all that's
-+//! needed to define this `ioctl` is:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-+//! const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-+//! # pub struct spi_ioc_transfer(u64);
-+//! ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-+//! # fn main() {}
-+//! ```
-+//!
-+//! This generates a function like:
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! # use std::mem;
-+//! # use nix::{libc, Result};
-+//! # use nix::errno::Errno;
-+//! # use nix::libc::c_int as c_int;
-+//! # const SPI_IOC_MAGIC: u8 = b'k';
-+//! # const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-+//! # pub struct spi_ioc_transfer(u64);
-+//! pub unsafe fn spi_message(fd: c_int, data: &mut [spi_ioc_transfer]) -> Result<c_int> {
-+//!     let res = libc::ioctl(fd,
-+//!                           request_code_write!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, data.len() * mem::size_of::<spi_ioc_transfer>()),
-+//!                           data);
-+//!     Errno::result(res)
-+//! }
-+//! # fn main() {}
-+//! ```
-+//!
-+//! Finding `ioctl` Documentation
-+//! -----------------------------
-+//!
-+//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
-+//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IOWR`. Some `ioctl`s are
-+//! documented directly in the headers defining their constants, but others have more extensive
-+//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
-+//!
-+//! Documenting the Generated Functions
-+//! ===================================
-+//!
-+//! In many cases, users will wish for the functions generated by the `ioctl`
-+//! macro to be public and documented. For this reason, the generated functions
-+//! are public by default. If you wish to hide the ioctl, you will need to put
-+//! them in a private module.
-+//!
-+//! For documentation, it is possible to use doc comments inside the `ioctl_*!` macros. Here is an
-+//! example :
-+//!
-+//! ```
-+//! # #[macro_use] extern crate nix;
-+//! # use nix::libc::c_int;
-+//! ioctl_read! {
-+//!     /// Make the given terminal the controlling terminal of the calling process. The calling
-+//!     /// process must be a session leader and not have a controlling terminal already. If the
-+//!     /// terminal is already the controlling terminal of a different session group then the
-+//!     /// ioctl will fail with **EPERM**, unless the caller is root (more precisely: has the
-+//!     /// **CAP_SYS_ADMIN** capability) and arg equals 1, in which case the terminal is stolen
-+//!     /// and all processes that had it as controlling terminal lose it.
-+//!     tiocsctty, b't', 19, c_int
-+//! }
-+//!
-+//! # fn main() {}
-+//! ```
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[macro_use]
-+mod linux;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use self::linux::*;
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+#[macro_use]
-+mod bsd;
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub use self::bsd::*;
-+
-+/// Convert raw ioctl return value to a Nix result
-+#[macro_export]
-+#[doc(hidden)]
-+macro_rules! convert_ioctl_res {
-+    ($w:expr) => (
-+        {
-+            $crate::errno::Errno::result($w)
-+        }
-+    );
-+}
-+
-+/// Generates a wrapper function for an ioctl that passes no data to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// The `videodev2` driver on Linux defines the `log_status` `ioctl` as:
-+///
-+/// ```C
-+/// #define VIDIOC_LOG_STATUS         _IO('V', 70)
-+/// ```
-+///
-+/// This can be implemented in Rust like:
-+///
-+/// ```no_run
-+/// # #[macro_use] extern crate nix;
-+/// ioctl_none!(log_status, b'V', 70);
-+/// fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_none {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_none!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for a "bad" ioctl that passes no data to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl request code
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```no_run
-+/// # #[macro_use] extern crate nix;
-+/// # extern crate libc;
-+/// # use libc::TIOCNXCL;
-+/// # use std::fs::File;
-+/// # use std::os::unix::io::AsRawFd;
-+/// ioctl_none_bad!(tiocnxcl, TIOCNXCL);
-+/// fn main() {
-+///     let file = File::open("/dev/ttyUSB0").unwrap();
-+///     unsafe { tiocnxcl(file.as_raw_fd()) }.unwrap();
-+/// }
-+/// ```
-+// TODO: add an example using request_code_*!()
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_none_bad {
-+    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that reads data from the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-+/// const SPI_IOC_TYPE_MODE: u8 = 1;
-+/// ioctl_read!(spi_read_mode, SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, u8);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_read {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *mut $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for a "bad" ioctl that reads data from the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl request code
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```
-+/// # extern crate libc;
-+/// # #[macro_use] extern crate nix;
-+/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-+/// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_read_bad {
-+    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *mut $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that writes data through a pointer to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// # pub struct v4l2_audio {}
-+/// ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_write_ptr {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *const $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for a "bad" ioctl that writes data through a pointer to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl request code
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *const DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```
-+/// # extern crate libc;
-+/// # #[macro_use] extern crate nix;
-+/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-+/// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_write_ptr_bad {
-+    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *const $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+cfg_if!{
-+    if #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))] {
-+        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
-+        ///
-+        /// The arguments to this macro are:
-+        ///
-+        /// * The function name
-+        /// * The ioctl identifier
-+        /// * The ioctl sequence number
-+        ///
-+        /// The generated function has the following signature:
-+        ///
-+        /// ```rust,ignore
-+        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
-+        /// ```
-+        ///
-+        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
-+        /// *   BSD - `libc::c_int`
-+        /// *   Linux - `libc::c_ulong`
-+        ///
-+        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+        ///
-+        /// # Example
-+        ///
-+        /// ```
-+        /// # #[macro_use] extern crate nix;
-+        /// ioctl_write_int!(vt_activate, b'v', 4);
-+        /// # fn main() {}
-+        /// ```
-+        #[macro_export(local_inner_macros)]
-+        macro_rules! ioctl_write_int {
-+            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
-+                $(#[$attr])*
-+                pub unsafe fn $name(fd: $crate::libc::c_int,
-+                                    data: $crate::sys::ioctl::ioctl_param_type)
-+                                    -> $crate::Result<$crate::libc::c_int> {
-+                    convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write_int!($ioty, $nr) as $crate::sys::ioctl::ioctl_num_type, data))
-+                }
-+            )
-+        }
-+    } else {
-+        /// Generates a wrapper function for a ioctl that writes an integer to the kernel.
-+        ///
-+        /// The arguments to this macro are:
-+        ///
-+        /// * The function name
-+        /// * The ioctl identifier
-+        /// * The ioctl sequence number
-+        ///
-+        /// The generated function has the following signature:
-+        ///
-+        /// ```rust,ignore
-+        /// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: nix::sys::ioctl::ioctl_param_type) -> Result<libc::c_int>
-+        /// ```
-+        ///
-+        /// `nix::sys::ioctl::ioctl_param_type` depends on the OS:
-+        /// *   BSD - `libc::c_int`
-+        /// *   Linux - `libc::c_ulong`
-+        ///
-+        /// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+        ///
-+        /// # Example
-+        ///
-+        /// ```
-+        /// # #[macro_use] extern crate nix;
-+        /// const HCI_IOC_MAGIC: u8 = b'k';
-+        /// const HCI_IOC_HCIDEVUP: u8 = 1;
-+        /// ioctl_write_int!(hci_dev_up, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
-+        /// # fn main() {}
-+        /// ```
-+        #[macro_export(local_inner_macros)]
-+        macro_rules! ioctl_write_int {
-+            ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr) => (
-+                $(#[$attr])*
-+                pub unsafe fn $name(fd: $crate::libc::c_int,
-+                                    data: $crate::sys::ioctl::ioctl_param_type)
-+                                    -> $crate::Result<$crate::libc::c_int> {
-+                    convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, ::std::mem::size_of::<$crate::libc::c_int>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+                }
-+            )
-+        }
-+    }
-+}
-+
-+/// Generates a wrapper function for a "bad" ioctl that writes an integer to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl request code
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: libc::c_int) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Examples
-+///
-+/// ```
-+/// # extern crate libc;
-+/// # #[macro_use] extern crate nix;
-+/// # #[cfg(any(target_os = "android", target_os = "linux"))]
-+/// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
-+/// # fn main() {}
-+/// ```
-+///
-+/// ```rust
-+/// # #[macro_use] extern crate nix;
-+/// const KVMIO: u8 = 0xAE;
-+/// ioctl_write_int_bad!(kvm_create_vm, request_code_none!(KVMIO, 0x03));
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_write_int_bad {
-+    ($(#[$attr:meta])* $name:ident, $nr:expr) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: $crate::libc::c_int)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that reads and writes data to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Example
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// # pub struct v4l2_audio {}
-+/// ioctl_readwrite!(enum_audio, b'V', 65, v4l2_audio);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_readwrite {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *mut $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for a "bad" ioctl that reads and writes data to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl request code
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: *mut DATA_TYPE) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+// TODO: Find an example for ioctl_readwrite_bad
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_readwrite_bad {
-+    ($(#[$attr:meta])* $name:ident, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: *mut $ty)
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that reads an array of elements from the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+// TODO: Find an example for ioctl_read_buf
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_read_buf {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: &mut [$ty])
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_read!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that writes an array of elements to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &[DATA_TYPE]) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+///
-+/// # Examples
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
-+/// const SPI_IOC_TYPE_MESSAGE: u8 = 0;
-+/// # pub struct spi_ioc_transfer(u64);
-+/// ioctl_write_buf!(spi_transfer, SPI_IOC_MAGIC, SPI_IOC_TYPE_MESSAGE, spi_ioc_transfer);
-+/// # fn main() {}
-+/// ```
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_write_buf {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: &[$ty])
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_write!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-+
-+/// Generates a wrapper function for an ioctl that reads and writes an array of elements to the kernel.
-+///
-+/// The arguments to this macro are:
-+///
-+/// * The function name
-+/// * The ioctl identifier
-+/// * The ioctl sequence number
-+/// * The data type passed by this ioctl
-+///
-+/// The generated function has the following signature:
-+///
-+/// ```rust,ignore
-+/// pub unsafe fn FUNCTION_NAME(fd: libc::c_int, data: &mut [DATA_TYPE]) -> Result<libc::c_int>
-+/// ```
-+///
-+/// For a more in-depth explanation of ioctls, see [`::sys::ioctl`](sys/ioctl/index.html).
-+// TODO: Find an example for readwrite_buf
-+#[macro_export(local_inner_macros)]
-+macro_rules! ioctl_readwrite_buf {
-+    ($(#[$attr:meta])* $name:ident, $ioty:expr, $nr:expr, $ty:ty) => (
-+        $(#[$attr])*
-+        pub unsafe fn $name(fd: $crate::libc::c_int,
-+                            data: &mut [$ty])
-+                            -> $crate::Result<$crate::libc::c_int> {
-+            convert_ioctl_res!($crate::libc::ioctl(fd, request_code_readwrite!($ioty, $nr, data.len() * ::std::mem::size_of::<$ty>()) as $crate::sys::ioctl::ioctl_num_type, data))
-+        }
-+    )
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/memfd.rs b/third_party/rust/nix-0.15.0/src/sys/memfd.rs
-new file mode 100644
-index 0000000000000..9672429b31e7f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/memfd.rs
-@@ -0,0 +1,20 @@
-+use libc;
-+use std::os::unix::io::RawFd;
-+use Result;
-+use errno::Errno;
-+use std::ffi::CStr;
-+
-+libc_bitflags!(
-+    pub struct MemFdCreateFlag: libc::c_uint {
-+        MFD_CLOEXEC;
-+        MFD_ALLOW_SEALING;
-+    }
-+);
-+
-+pub fn memfd_create(name: &CStr, flags: MemFdCreateFlag) -> Result<RawFd> {
-+    let res = unsafe {
-+        libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags.bits())
-+    };
-+
-+    Errno::result(res).map(|r| r as RawFd)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/mman.rs b/third_party/rust/nix-0.15.0/src/sys/mman.rs
-new file mode 100644
-index 0000000000000..4e250501dd0f0
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/mman.rs
-@@ -0,0 +1,325 @@
-+use {Error, Result};
-+#[cfg(not(target_os = "android"))]
-+use NixPath;
-+use errno::Errno;
-+#[cfg(not(target_os = "android"))]
-+use fcntl::OFlag;
-+use libc::{self, c_int, c_void, size_t, off_t};
-+#[cfg(not(target_os = "android"))]
-+use sys::stat::Mode;
-+use std::os::unix::io::RawFd;
-+
-+libc_bitflags!{
-+    /// Desired memory protection of a memory mapping.
-+    pub struct ProtFlags: c_int {
-+        /// Pages cannot be accessed.
-+        PROT_NONE;
-+        /// Pages can be read.
-+        PROT_READ;
-+        /// Pages can be written.
-+        PROT_WRITE;
-+        /// Pages can be executed
-+        PROT_EXEC;
-+        /// Apply protection up to the end of a mapping that grows upwards.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        PROT_GROWSDOWN;
-+        /// Apply protection down to the beginning of a mapping that grows downwards.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        PROT_GROWSUP;
-+    }
-+}
-+
-+libc_bitflags!{
-+    /// Additional parameters for `mmap()`.
-+    pub struct MapFlags: c_int {
-+        /// Compatibility flag. Ignored.
-+        MAP_FILE;
-+        /// Share this mapping. Mutually exclusive with `MAP_PRIVATE`.
-+        MAP_SHARED;
-+        /// Create a private copy-on-write mapping. Mutually exclusive with `MAP_SHARED`.
-+        MAP_PRIVATE;
-+        /// Place the mapping at exactly the address specified in `addr`.
-+        MAP_FIXED;
-+        /// Synonym for `MAP_ANONYMOUS`.
-+        MAP_ANON;
-+        /// The mapping is not backed by any file.
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))]
-+        MAP_ANONYMOUS;
-+        /// Put the mapping into the first 2GB of the process address space.
-+        #[cfg(any(all(any(target_os = "android", target_os = "linux"),
-+                      any(target_arch = "x86", target_arch = "x86_64")),
-+                  all(target_os = "linux", target_env = "musl", any(target_arch = "x86", target_arch = "x86_64")),
-+                  all(target_os = "freebsd", target_pointer_width = "64")))]
-+        MAP_32BIT;
-+        /// Used for stacks; indicates to the kernel that the mapping should extend downward in memory.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_GROWSDOWN;
-+        /// Compatibility flag. Ignored.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_DENYWRITE;
-+        /// Compatibility flag. Ignored.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_EXECUTABLE;
-+        /// Mark the mmaped region to be locked in the same way as `mlock(2)`.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_LOCKED;
-+        /// Do not reserve swap space for this mapping.
-+        ///
-+        /// This was removed in FreeBSD 11.
-+        #[cfg(not(target_os = "freebsd"))]
-+        MAP_NORESERVE;
-+        /// Populate page tables for a mapping.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_POPULATE;
-+        /// Only meaningful when used with `MAP_POPULATE`. Don't perform read-ahead.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_NONBLOCK;
-+        /// Allocate the mapping using "huge pages."
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MAP_HUGETLB;
-+        /// Lock the mapped region into memory as with `mlock(2)`.
-+        #[cfg(target_os = "netbsd")]
-+        MAP_WIRED;
-+        /// Causes dirtied data in the specified range to be flushed to disk only when necessary.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        MAP_NOSYNC;
-+        /// Rename private pages to a file.
-+        ///
-+        /// This was removed in FreeBSD 11.
-+        #[cfg(any(target_os = "dragonfly", target_os = "netbsd", target_os = "openbsd"))]
-+        MAP_RENAME;
-+        /// Region may contain semaphores.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))]
-+        MAP_HASSEMAPHORE;
-+        /// Region grows down, like a stack.
-+        #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-+        MAP_STACK;
-+        /// Pages in this mapping are not retained in the kernel's memory cache.
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MAP_NOCACHE;
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MAP_JIT;
-+    }
-+}
-+
-+libc_enum!{
-+    /// Usage information for a range of memory to allow for performance optimizations by the kernel.
-+    ///
-+    /// Used by [`madvise`](./fn.madvise.html).
-+    #[repr(i32)]
-+    pub enum MmapAdvise {
-+        /// No further special treatment. This is the default.
-+        MADV_NORMAL,
-+        /// Expect random page references.
-+        MADV_RANDOM,
-+        /// Expect sequential page references.
-+        MADV_SEQUENTIAL,
-+        /// Expect access in the near future.
-+        MADV_WILLNEED,
-+        /// Do not expect access in the near future.
-+        MADV_DONTNEED,
-+        /// Free up a given range of pages and its associated backing store.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_REMOVE,
-+        /// Do not make pages in this range available to the child after a `fork(2)`.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_DONTFORK,
-+        /// Undo the effect of `MADV_DONTFORK`.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_DOFORK,
-+        /// Poison the given pages.
-+        ///
-+        /// Subsequent references to those pages are treated like hardware memory corruption.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_HWPOISON,
-+        /// Enable Kernel Samepage Merging (KSM) for the given pages.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_MERGEABLE,
-+        /// Undo the effect of `MADV_MERGEABLE`
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_UNMERGEABLE,
-+        /// Preserve the memory of each page but offline the original page.
-+        #[cfg(any(target_os = "android",
-+            all(target_os = "linux", any(
-+                target_arch = "aarch64",
-+                target_arch = "arm",
-+                target_arch = "ppc",
-+                target_arch = "s390x",
-+                target_arch = "x86",
-+                target_arch = "x86_64",
-+                target_arch = "sparc64"))))]
-+        MADV_SOFT_OFFLINE,
-+        /// Enable Transparent Huge Pages (THP) for pages in the given range.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_HUGEPAGE,
-+        /// Undo the effect of `MADV_HUGEPAGE`.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_NOHUGEPAGE,
-+        /// Exclude the given range from a core dump.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_DONTDUMP,
-+        /// Undo the effect of an earlier `MADV_DONTDUMP`.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MADV_DODUMP,
-+        /// Specify that the application no longer needs the pages in the given range.
-+        MADV_FREE,
-+        /// Request that the system not flush the current range to disk unless it needs to.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        MADV_NOSYNC,
-+        /// Undoes the effects of `MADV_NOSYNC` for any future pages dirtied within the given range.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        MADV_AUTOSYNC,
-+        /// Region is not included in a core file.
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        MADV_NOCORE,
-+        /// Include region in a core file
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        MADV_CORE,
-+        #[cfg(any(target_os = "freebsd"))]
-+        MADV_PROTECT,
-+        /// Invalidate the hardware page table for the given region.
-+        #[cfg(target_os = "dragonfly")]
-+        MADV_INVAL,
-+        /// Set the offset of the page directory page to `value` for the virtual page table.
-+        #[cfg(target_os = "dragonfly")]
-+        MADV_SETMAP,
-+        /// Indicates that the application will not need the data in the given range.
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MADV_ZERO_WIRED_PAGES,
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MADV_FREE_REUSABLE,
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MADV_FREE_REUSE,
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MADV_CAN_REUSE,
-+    }
-+}
-+
-+libc_bitflags!{
-+    /// Configuration flags for `msync`.
-+    pub struct MsFlags: c_int {
-+        /// Schedule an update but return immediately.
-+        MS_ASYNC;
-+        /// Invalidate all cached data.
-+        MS_INVALIDATE;
-+        /// Invalidate pages, but leave them mapped.
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MS_KILLPAGES;
-+        /// Deactivate pages, but leave them mapped.
-+        #[cfg(any(target_os = "ios", target_os = "macos"))]
-+        MS_DEACTIVATE;
-+        /// Perform an update and wait for it to complete.
-+        MS_SYNC;
-+    }
-+}
-+
-+libc_bitflags!{
-+    /// Flags for `mlockall`.
-+    pub struct MlockAllFlags: c_int {
-+        /// Lock pages that are currently mapped into the address space of the process.
-+        MCL_CURRENT;
-+        /// Lock pages which will become mapped into the address space of the process in the future.
-+        MCL_FUTURE;
-+    }
-+}
-+
-+/// Locks all memory pages that contain part of the address range with `length` bytes starting at
-+/// `addr`. Locked pages never move to the swap area.
-+pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
-+    Errno::result(libc::mlock(addr, length)).map(drop)
-+}
-+
-+/// Unlocks all memory pages that contain part of the address range with `length` bytes starting at
-+/// `addr`.
-+pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
-+    Errno::result(libc::munlock(addr, length)).map(drop)
-+}
-+
-+/// Locks all memory pages mapped into this process' address space. Locked pages never move to the
-+/// swap area.
-+pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
-+    unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
-+}
-+
-+/// Unlocks all memory pages mapped into this process' address space.
-+pub fn munlockall() -> Result<()> {
-+    unsafe { Errno::result(libc::munlockall()) }.map(drop)
-+}
-+
-+/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
-+/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
-+pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
-+    let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
-+
-+    if ret == libc::MAP_FAILED {
-+        Err(Error::Sys(Errno::last()))
-+    } else {
-+        Ok(ret)
-+    }
-+}
-+
-+pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
-+    Errno::result(libc::munmap(addr, len)).map(drop)
-+}
-+
-+pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
-+    Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
-+}
-+
-+/// Set protection of memory mapping.
-+///
-+/// See [`mprotect(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mprotect.html) for
-+/// details.
-+///
-+/// # Safety
-+///
-+/// Calls to `mprotect` are inherently unsafe, as changes to memory protections can lead to
-+/// SIGSEGVs.
-+///
-+/// ```
-+/// # use nix::libc::size_t;
-+/// # use nix::sys::mman::{mmap, mprotect, MapFlags, ProtFlags};
-+/// # use std::ptr;
-+/// const ONE_K: size_t = 1024;
-+/// let mut slice: &mut [u8] = unsafe {
-+///     let mem = mmap(ptr::null_mut(), ONE_K, ProtFlags::PROT_NONE,
-+///                    MapFlags::MAP_ANON | MapFlags::MAP_PRIVATE, -1, 0).unwrap();
-+///     mprotect(mem, ONE_K, ProtFlags::PROT_READ | ProtFlags::PROT_WRITE).unwrap();
-+///     std::slice::from_raw_parts_mut(mem as *mut u8, ONE_K)
-+/// };
-+/// assert_eq!(slice[0], 0x00);
-+/// slice[0] = 0xFF;
-+/// assert_eq!(slice[0], 0xFF);
-+/// ```
-+pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Result<()> {
-+    Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
-+}
-+
-+pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
-+    Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
-+}
-+
-+#[cfg(not(target_os = "android"))]
-+pub fn shm_open<P: ?Sized + NixPath>(name: &P, flag: OFlag, mode: Mode) -> Result<RawFd> {
-+    let ret = name.with_nix_path(|cstr| {
-+        #[cfg(any(target_os = "macos", target_os = "ios"))]
-+        unsafe {
-+            libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::c_uint)
-+        }
-+        #[cfg(not(any(target_os = "macos", target_os = "ios")))]
-+        unsafe {
-+            libc::shm_open(cstr.as_ptr(), flag.bits(), mode.bits() as libc::mode_t)
-+        }
-+    })?;
-+
-+    Errno::result(ret)
-+}
-+
-+#[cfg(not(target_os = "android"))]
-+pub fn shm_unlink<P: ?Sized + NixPath>(name: &P) -> Result<()> {
-+    let ret = name.with_nix_path(|cstr| {
-+        unsafe { libc::shm_unlink(cstr.as_ptr()) }
-+    })?;
-+
-+    Errno::result(ret).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/mod.rs b/third_party/rust/nix-0.15.0/src/sys/mod.rs
-new file mode 100644
-index 0000000000000..d3c2f92bbaaea
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/mod.rs
-@@ -0,0 +1,100 @@
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd"))]
-+pub mod aio;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod epoll;
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub mod event;
-+
-+#[cfg(target_os = "linux")]
-+pub mod eventfd;
-+
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+#[macro_use]
-+pub mod ioctl;
-+
-+#[cfg(target_os = "linux")]
-+pub mod memfd;
-+
-+pub mod mman;
-+
-+pub mod pthread;
-+
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub mod ptrace;
-+
-+#[cfg(target_os = "linux")]
-+pub mod quota;
-+
-+#[cfg(any(target_os = "linux"))]
-+pub mod reboot;
-+
-+pub mod select;
-+
-+#[cfg(any(target_os = "android",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos"))]
-+pub mod sendfile;
-+
-+pub mod signal;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod signalfd;
-+
-+pub mod socket;
-+
-+pub mod stat;
-+
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "openbsd"
-+))]
-+pub mod statfs;
-+
-+pub mod statvfs;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod sysinfo;
-+
-+pub mod termios;
-+
-+pub mod time;
-+
-+pub mod uio;
-+
-+pub mod utsname;
-+
-+pub mod wait;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod inotify;
-diff --git a/third_party/rust/nix-0.15.0/src/sys/pthread.rs b/third_party/rust/nix-0.15.0/src/sys/pthread.rs
-new file mode 100644
-index 0000000000000..a4d98250f2b8b
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/pthread.rs
-@@ -0,0 +1,13 @@
-+use libc::{self, pthread_t};
-+
-+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)
-+///
-+/// The thread ID returned by `pthread_self()` is not the same thing as
-+/// the kernel thread ID returned by a call to `gettid(2)`.
-+#[inline]
-+pub fn pthread_self() -> Pthread {
-+    unsafe { libc::pthread_self() }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
-new file mode 100644
-index 0000000000000..7797d10647ef4
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/bsd.rs
-@@ -0,0 +1,170 @@
-+use errno::Errno;
-+use libc::{self, c_int};
-+use std::ptr;
-+use sys::signal::Signal;
-+use unistd::Pid;
-+use Result;
-+
-+pub type RequestType = c_int;
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "dragonfly", 
-+                 target_os = "freebsd", 
-+                 target_os = "macos",
-+                 target_os = "openbsd"))] {
-+        #[doc(hidden)]
-+        pub type AddressType = *mut ::libc::c_char;
-+    } else {
-+        #[doc(hidden)]
-+        pub type AddressType = *mut ::libc::c_void;
-+    }
-+}
-+
-+libc_enum! {
-+    #[repr(i32)]
-+    /// Ptrace Request enum defining the action to be taken.
-+    pub enum Request {
-+        PT_TRACE_ME,
-+        PT_READ_I,
-+        PT_READ_D,
-+        #[cfg(target_os = "macos")]
-+        PT_READ_U,
-+        PT_WRITE_I,
-+        PT_WRITE_D,
-+        #[cfg(target_os = "macos")]
-+        PT_WRITE_U,
-+        PT_CONTINUE,
-+        PT_KILL,
-+        #[cfg(any(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos"),
-+                  all(target_os = "openbsd", target_arch = "x86_64"),
-+                  all(target_os = "netbsd", any(target_arch = "x86_64",
-+                                                target_arch = "powerpc"))))]
-+        PT_STEP,
-+        PT_ATTACH,
-+        PT_DETACH,
-+        #[cfg(target_os = "macos")]
-+        PT_SIGEXC,
-+        #[cfg(target_os = "macos")]
-+        PT_THUPDATE,
-+        #[cfg(target_os = "macos")]
-+        PT_ATTACHEXC
-+    }
-+}
-+
-+unsafe fn ptrace_other(
-+    request: Request,
-+    pid: Pid,
-+    addr: AddressType,
-+    data: c_int,
-+) -> Result<c_int> {
-+    Errno::result(libc::ptrace(
-+        request as RequestType,
-+        libc::pid_t::from(pid),
-+        addr,
-+        data,
-+    )).map(|_| 0)
-+}
-+
-+/// Sets the process as traceable, as with `ptrace(PT_TRACEME, ...)`
-+///
-+/// Indicates that this process is to be traced by its parent.
-+/// This is the only ptrace request to be issued by the tracee.
-+pub fn traceme() -> Result<()> {
-+    unsafe { ptrace_other(Request::PT_TRACE_ME, Pid::from_raw(0), ptr::null_mut(), 0).map(drop) }
-+}
-+
-+/// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
-+///
-+/// Attaches to the process specified in pid, making it a tracee of the calling process.
-+pub fn attach(pid: Pid) -> Result<()> {
-+    unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
-+}
-+
-+/// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
-+///
-+/// Detaches from the process specified in pid allowing it to run freely
-+pub fn detach(pid: Pid) -> Result<()> {
-+    unsafe { ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), 0).map(drop) }
-+}
-+
-+/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-+///
-+/// Continues the execution of the process with PID `pid`, optionally
-+/// delivering a signal specified by `sig`.
-+pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as c_int,
-+        None => 0,
-+    };
-+    unsafe {
-+        // Ignore the useless return value
-+        ptrace_other(Request::PT_CONTINUE, pid, 1 as AddressType, data).map(drop)
-+    }
-+}
-+
-+/// Issues a kill request as with `ptrace(PT_KILL, ...)`
-+///
-+/// This request is equivalent to `ptrace(PT_CONTINUE, ..., SIGKILL);` 
-+pub fn kill(pid: Pid) -> Result<()> {
-+    unsafe {
-+        ptrace_other(Request::PT_KILL, pid, 0 as AddressType, 0).map(drop)
-+    }
-+}
-+
-+/// Move the stopped tracee process forward by a single step as with
-+/// `ptrace(PT_STEP, ...)`
-+///
-+/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-+/// signal specified by `sig`.
-+///
-+/// # Example
-+/// ```rust
-+/// extern crate nix;
-+/// use nix::sys::ptrace::step;
-+/// 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);
-+///         }
-+///         _ => {},
-+///     }
-+/// }
-+/// ```
-+#[cfg(
-+    any(
-+        any(target_os = "dragonfly", target_os = "freebsd", target_os = "macos"),
-+        all(target_os = "openbsd", target_arch = "x86_64"),
-+        all(target_os = "netbsd",
-+            any(target_arch = "x86_64", target_arch = "powerpc")
-+        )
-+    )
-+)]
-+pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as c_int,
-+        None => 0,
-+    };
-+    unsafe { ptrace_other(Request::PT_STEP, pid, ptr::null_mut(), data).map(drop) }
-+}
-+
-+/// Reads a word from a processes memory at the given address
-+pub fn read(pid: Pid, addr: AddressType) -> Result<c_int> {
-+    unsafe {
-+        // Traditionally there was a difference between reading data or
-+        // instruction memory but not in modern systems.
-+        ptrace_other(Request::PT_READ_D, pid, addr, 0)
-+    }
-+}
-+
-+/// Writes a word into the processes memory at the given address
-+pub fn write(pid: Pid, addr: AddressType, data: c_int) -> Result<()> {
-+    unsafe { ptrace_other(Request::PT_WRITE_D, pid, addr, data).map(drop) }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
-new file mode 100644
-index 0000000000000..df15e66527562
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/linux.rs
-@@ -0,0 +1,402 @@
-+//! For detailed description of the ptrace requests, consult `man ptrace`.
-+
-+use std::{mem, ptr};
-+use {Error, Result};
-+use errno::Errno;
-+use libc::{self, c_void, c_long, siginfo_t};
-+use ::unistd::Pid;
-+use sys::signal::Signal;
-+
-+pub type AddressType = *mut ::libc::c_void;
-+
-+#[cfg(all(target_os = "linux",
-+          any(target_arch = "x86_64",
-+              target_arch = "x86"),
-+          target_env = "gnu"))]
-+use libc::user_regs_struct;
-+
-+cfg_if! {
-+    if #[cfg(any(all(target_os = "linux", target_arch = "s390x"),
-+                 all(target_os = "linux", target_env = "gnu")))] {
-+        #[doc(hidden)]
-+        pub type RequestType = ::libc::c_uint;
-+    } else {
-+        #[doc(hidden)]
-+        pub type RequestType = ::libc::c_int;
-+    }
-+}
-+
-+libc_enum!{
-+    #[cfg_attr(not(any(target_env = "musl", target_os = "android")), repr(u32))]
-+    #[cfg_attr(any(target_env = "musl", target_os = "android"), repr(i32))]
-+    /// Ptrace Request enum defining the action to be taken.
-+    pub enum Request {
-+        PTRACE_TRACEME,
-+        PTRACE_PEEKTEXT,
-+        PTRACE_PEEKDATA,
-+        PTRACE_PEEKUSER,
-+        PTRACE_POKETEXT,
-+        PTRACE_POKEDATA,
-+        PTRACE_POKEUSER,
-+        PTRACE_CONT,
-+        PTRACE_KILL,
-+        PTRACE_SINGLESTEP,
-+        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
-+                  all(target_os = "linux", any(target_env = "musl",
-+                                               target_arch = "mips",
-+                                               target_arch = "mips64",
-+                                               target_arch = "x86_64",
-+                                               target_pointer_width = "32"))))]
-+        PTRACE_GETREGS,
-+        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
-+                  all(target_os = "linux", any(target_env = "musl",
-+                                               target_arch = "mips",
-+                                               target_arch = "mips64",
-+                                               target_arch = "x86_64",
-+                                               target_pointer_width = "32"))))]
-+        PTRACE_SETREGS,
-+        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
-+                  all(target_os = "linux", any(target_env = "musl",
-+                                               target_arch = "mips",
-+                                               target_arch = "mips64",
-+                                               target_arch = "x86_64",
-+                                               target_pointer_width = "32"))))]
-+        PTRACE_GETFPREGS,
-+        #[cfg(any(all(target_os = "android", target_pointer_width = "32"),
-+                  all(target_os = "linux", any(target_env = "musl",
-+                                               target_arch = "mips",
-+                                               target_arch = "mips64",
-+                                               target_arch = "x86_64",
-+                                               target_pointer_width = "32"))))]
-+        PTRACE_SETFPREGS,
-+        PTRACE_ATTACH,
-+        PTRACE_DETACH,
-+        #[cfg(all(target_os = "linux", any(target_env = "musl",
-+                                           target_arch = "mips",
-+                                           target_arch = "mips64",
-+                                           target_arch = "x86",
-+                                           target_arch = "x86_64")))]
-+        PTRACE_GETFPXREGS,
-+        #[cfg(all(target_os = "linux", any(target_env = "musl",
-+                                           target_arch = "mips",
-+                                           target_arch = "mips64",
-+                                           target_arch = "x86",
-+                                           target_arch = "x86_64")))]
-+        PTRACE_SETFPXREGS,
-+        PTRACE_SYSCALL,
-+        PTRACE_SETOPTIONS,
-+        PTRACE_GETEVENTMSG,
-+        PTRACE_GETSIGINFO,
-+        PTRACE_SETSIGINFO,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_GETREGSET,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_SETREGSET,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_SEIZE,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_INTERRUPT,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_LISTEN,
-+        #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-+                                               target_arch = "mips64"))))]
-+        PTRACE_PEEKSIGINFO,
-+    }
-+}
-+
-+libc_enum!{
-+    #[repr(i32)]
-+    /// Using the ptrace options the tracer can configure the tracee to stop
-+    /// at certain events. This enum is used to define those events as defined
-+    /// in `man ptrace`.
-+    pub enum Event {
-+        /// Event that stops before a return from fork or clone.
-+        PTRACE_EVENT_FORK,
-+        /// Event that stops before a return from vfork or clone.
-+        PTRACE_EVENT_VFORK,
-+        /// Event that stops before a return from clone.
-+        PTRACE_EVENT_CLONE,
-+        /// Event that stops before a return from execve.
-+        PTRACE_EVENT_EXEC,
-+        /// Event for a return from vfork.
-+        PTRACE_EVENT_VFORK_DONE,
-+        /// Event for a stop before an exit. Unlike the waitpid Exit status program.
-+        /// registers can still be examined
-+        PTRACE_EVENT_EXIT,
-+        /// STop triggered by a seccomp rule on a tracee.
-+        PTRACE_EVENT_SECCOMP,
-+        // PTRACE_EVENT_STOP not provided by libc because it's defined in glibc 2.26
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
-+    /// See `man ptrace` for more details.
-+    pub struct Options: libc::c_int {
-+        /// When delivering system call traps set a bit to allow tracer to
-+        /// distinguish between normal stops or syscall stops. May not work on
-+        /// all systems.
-+        PTRACE_O_TRACESYSGOOD;
-+        /// Stop tracee at next fork and start tracing the forked process.
-+        PTRACE_O_TRACEFORK;
-+        /// Stop tracee at next vfork call and trace the vforked process.
-+        PTRACE_O_TRACEVFORK;
-+        /// Stop tracee at next clone call and trace the cloned process.
-+        PTRACE_O_TRACECLONE;
-+        /// Stop tracee at next execve call.
-+        PTRACE_O_TRACEEXEC;
-+        /// Stop tracee at vfork completion.
-+        PTRACE_O_TRACEVFORKDONE;
-+        /// Stop tracee at next exit call. Stops before exit commences allowing
-+        /// tracer to see location of exit and register states.
-+        PTRACE_O_TRACEEXIT;
-+        /// Stop tracee when a SECCOMP_RET_TRACE rule is triggered. See `man seccomp` for more
-+        /// details.
-+        PTRACE_O_TRACESECCOMP;
-+        /// Send a SIGKILL to the tracee if the tracer exits.  This is useful
-+        /// for ptrace jailers to prevent tracees from escaping their control.
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        PTRACE_O_EXITKILL;
-+    }
-+}
-+
-+/// Performs a ptrace request. If the request in question is provided by a specialised function
-+/// this function will return an unsupported operation error.
-+#[deprecated(
-+    since="0.10.0",
-+    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
-+)]
-+pub unsafe fn ptrace(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
-+    use self::Request::*;
-+    match request {
-+        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_GETSIGINFO | 
-+            PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS | 
-+            PTRACE_POKETEXT | PTRACE_POKEDATA | PTRACE_KILL => Err(Error::UnsupportedOperation),
-+        _ => ptrace_other(request, pid, addr, data)
-+    }
-+}
-+
-+fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
-+    let ret = unsafe {
-+        Errno::clear();
-+        libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)
-+    };
-+    match Errno::result(ret) {
-+        Ok(..) | Err(Error::Sys(Errno::UnknownErrno)) => Ok(ret),
-+        err @ Err(..) => err,
-+    }
-+}
-+
-+/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
-+#[cfg(all(target_os = "linux",
-+          any(target_arch = "x86_64",
-+              target_arch = "x86"),
-+          target_env = "gnu"))]
-+pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
-+    ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
-+}
-+
-+/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
-+#[cfg(all(target_os = "linux",
-+          any(target_arch = "x86_64",
-+              target_arch = "x86"),
-+          target_env = "gnu"))]
-+pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
-+    let res = unsafe {
-+        libc::ptrace(Request::PTRACE_SETREGS as RequestType,
-+                     libc::pid_t::from(pid),
-+                     ptr::null_mut::<c_void>(),
-+                     &regs as *const _ as *const c_void)
-+    };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Function for ptrace requests that return values from the data field.
-+/// Some ptrace get requests populate structs or larger elements than `c_long`
-+/// and therefore use the data field to return values. This function handles these
-+/// requests.
-+fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
-+    // Creates an uninitialized pointer to store result in
-+    let data: T = unsafe { mem::uninitialized() };
-+    let res = unsafe {
-+        libc::ptrace(request as RequestType,
-+                     libc::pid_t::from(pid),
-+                     ptr::null_mut::<T>(),
-+                     &data as *const _ as *const c_void)
-+    };
-+    Errno::result(res)?;
-+    Ok(data)
-+}
-+
-+unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
-+    Errno::result(libc::ptrace(request as RequestType, libc::pid_t::from(pid), addr, data)).map(|_| 0)
-+}
-+
-+/// Set options, as with `ptrace(PTRACE_SETOPTIONS,...)`.
-+pub fn setoptions(pid: Pid, options: Options) -> Result<()> {
-+    let res = unsafe {
-+        libc::ptrace(Request::PTRACE_SETOPTIONS as RequestType,
-+                     libc::pid_t::from(pid),
-+                     ptr::null_mut::<c_void>(),
-+                     options.bits() as *mut c_void)
-+    };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Gets a ptrace event as described by `ptrace(PTRACE_GETEVENTMSG,...)`
-+pub fn getevent(pid: Pid) -> Result<c_long> {
-+    ptrace_get_data::<c_long>(Request::PTRACE_GETEVENTMSG, pid)
-+}
-+
-+/// Get siginfo as with `ptrace(PTRACE_GETSIGINFO,...)`
-+pub fn getsiginfo(pid: Pid) -> Result<siginfo_t> {
-+    ptrace_get_data::<siginfo_t>(Request::PTRACE_GETSIGINFO, pid)
-+}
-+
-+/// Set siginfo as with `ptrace(PTRACE_SETSIGINFO,...)`
-+pub fn setsiginfo(pid: Pid, sig: &siginfo_t) -> Result<()> {
-+    let ret = unsafe{
-+        Errno::clear();
-+        libc::ptrace(Request::PTRACE_SETSIGINFO as RequestType,
-+                     libc::pid_t::from(pid),
-+                     ptr::null_mut::<c_void>(),
-+                     sig as *const _ as *const c_void)
-+    };
-+    match Errno::result(ret) {
-+        Ok(_) => Ok(()),
-+        Err(e) => Err(e),
-+    }
-+}
-+
-+/// Sets the process as traceable, as with `ptrace(PTRACE_TRACEME, ...)`
-+///
-+/// Indicates that this process is to be traced by its parent.
-+/// This is the only ptrace request to be issued by the tracee.
-+pub fn traceme() -> Result<()> {
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_TRACEME,
-+            Pid::from_raw(0),
-+            ptr::null_mut(),
-+            ptr::null_mut(),
-+        ).map(drop) // ignore the useless return value
-+    }
-+}
-+
-+/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
-+///
-+/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
-+pub fn syscall(pid: Pid) -> Result<()> {
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_SYSCALL,
-+            pid,
-+            ptr::null_mut(),
-+            ptr::null_mut(),
-+        ).map(drop) // ignore the useless return value
-+    }
-+}
-+
-+/// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
-+///
-+/// Attaches to the process specified in pid, making it a tracee of the calling process.
-+pub fn attach(pid: Pid) -> Result<()> {
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_ATTACH,
-+            pid,
-+            ptr::null_mut(),
-+            ptr::null_mut(),
-+        ).map(drop) // ignore the useless return value
-+    }
-+}
-+
-+/// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
-+///
-+/// Detaches from the process specified in pid allowing it to run freely
-+pub fn detach(pid: Pid) -> Result<()> {
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_DETACH,
-+            pid,
-+            ptr::null_mut(),
-+            ptr::null_mut()
-+        ).map(drop)
-+    }
-+}
-+
-+/// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-+///
-+/// Continues the execution of the process with PID `pid`, optionally
-+/// delivering a signal specified by `sig`.
-+pub fn cont<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-+    unsafe {
-+        ptrace_other(Request::PTRACE_CONT, pid, ptr::null_mut(), data).map(drop) // ignore the useless return value
-+    }
-+}
-+
-+/// Issues a kill request as with `ptrace(PTRACE_KILL, ...)`
-+///
-+/// This request is equivalent to `ptrace(PTRACE_CONT, ..., SIGKILL);`
-+pub fn kill(pid: Pid) -> Result<()> {
-+    unsafe {
-+        ptrace_other(Request::PTRACE_KILL, pid, ptr::null_mut(), ptr::null_mut()).map(drop)
-+    }
-+}
-+
-+/// Move the stopped tracee process forward by a single step as with 
-+/// `ptrace(PTRACE_SINGLESTEP, ...)`
-+///
-+/// Advances the execution of the process with PID `pid` by a single step optionally delivering a
-+/// signal specified by `sig`.
-+///
-+/// # Example
-+/// ```rust
-+/// extern crate nix;
-+/// use nix::sys::ptrace::step;
-+/// 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);
-+///         }
-+///         _ => {},
-+///     }
-+/// }
-+/// ```
-+pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-+    unsafe {
-+        ptrace_other(Request::PTRACE_SINGLESTEP, pid, ptr::null_mut(), data).map(drop)
-+    }
-+}
-+
-+
-+/// Reads a word from a processes memory at the given address
-+pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
-+    ptrace_peek(Request::PTRACE_PEEKDATA, pid, addr, ptr::null_mut())
-+}
-+
-+/// Writes a word into the processes memory at the given address
-+pub fn write(pid: Pid, addr: AddressType, data: *mut c_void) -> Result<()> {
-+    unsafe {
-+        ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs b/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
-new file mode 100644
-index 0000000000000..782c30409bc12
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/ptrace/mod.rs
-@@ -0,0 +1,22 @@
-+///! Provides helpers for making ptrace system calls 
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod linux;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use self::linux::*;
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+mod bsd;
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"
-+          ))]
-+pub use self::bsd::*;
-diff --git a/third_party/rust/nix-0.15.0/src/sys/quota.rs b/third_party/rust/nix-0.15.0/src/sys/quota.rs
-new file mode 100644
-index 0000000000000..8946fca2213c8
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/quota.rs
-@@ -0,0 +1,273 @@
-+//! Set and configure disk quotas for users, groups, or projects.
-+//!
-+//! # Examples
-+//!
-+//! Enabling and setting a quota:
-+//!
-+//! ```rust,no_run
-+//! # use nix::sys::quota::{Dqblk, quotactl_on, quotactl_set, QuotaFmt, QuotaType, QuotaValidFlags};
-+//! quotactl_on(QuotaType::USRQUOTA, "/dev/sda1", QuotaFmt::QFMT_VFS_V1, "aquota.user");
-+//! let mut dqblk: Dqblk = Default::default();
-+//! dqblk.set_blocks_hard_limit(10000);
-+//! dqblk.set_blocks_soft_limit(8000);
-+//! quotactl_set(QuotaType::USRQUOTA, "/dev/sda1", 50, &dqblk, QuotaValidFlags::QIF_BLIMITS);
-+//! ```
-+use std::default::Default;
-+use std::{mem, ptr};
-+use libc::{self, c_int, c_char};
-+use {Result, NixPath};
-+use errno::Errno;
-+
-+struct QuotaCmd(QuotaSubCmd, QuotaType);
-+
-+impl QuotaCmd {
-+    fn as_int(&self) -> c_int {
-+        unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
-+    }
-+}
-+
-+// linux quota version >= 2
-+libc_enum!{
-+    #[repr(i32)]
-+    enum QuotaSubCmd {
-+        Q_SYNC,
-+        Q_QUOTAON,
-+        Q_QUOTAOFF,
-+        Q_GETQUOTA,
-+        Q_SETQUOTA,
-+    }
-+}
-+
-+libc_enum!{
-+    /// The scope of the quota.
-+    #[repr(i32)]
-+    pub enum QuotaType {
-+        /// Specify a user quota
-+        USRQUOTA,
-+        /// Specify a group quota
-+        GRPQUOTA,
-+    }
-+}
-+
-+libc_enum!{
-+    /// The type of quota format to use.
-+    #[repr(i32)]
-+    pub enum QuotaFmt {
-+        /// Use the original quota format.
-+        QFMT_VFS_OLD,
-+        /// Use the standard VFS v0 quota format.
-+        ///
-+        /// Handles 32-bit UIDs/GIDs and quota limits up to 2<sup>32</sup> bytes/2<sup>32</sup> inodes.
-+        QFMT_VFS_V0,
-+        /// Use the VFS v1 quota format.
-+        ///
-+        /// Handles 32-bit UIDs/GIDs and quota limits of 2<sup>64</sup> bytes/2<sup>64</sup> inodes.
-+        QFMT_VFS_V1,
-+    }
-+}
-+
-+libc_bitflags!(
-+    /// Indicates the quota fields that are valid to read from.
-+    #[derive(Default)]
-+    pub struct QuotaValidFlags: u32 {
-+        /// The block hard & soft limit fields.
-+        QIF_BLIMITS;
-+        /// The current space field.
-+        QIF_SPACE;
-+        /// The inode hard & soft limit fields.
-+        QIF_ILIMITS;
-+        /// The current inodes field.
-+        QIF_INODES;
-+        /// The disk use time limit field.
-+        QIF_BTIME;
-+        /// The file quote time limit field.
-+        QIF_ITIME;
-+        /// All block & inode limits.
-+        QIF_LIMITS;
-+        /// The space & inodes usage fields.
-+        QIF_USAGE;
-+        /// The time limit fields.
-+        QIF_TIMES;
-+        /// All fields.
-+        QIF_ALL;
-+    }
-+);
-+
-+/// Wrapper type for `if_dqblk`
-+// FIXME: Change to repr(transparent)
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct Dqblk(libc::dqblk);
-+
-+impl Default for Dqblk {
-+    fn default() -> Dqblk {
-+        Dqblk(libc::dqblk {
-+            dqb_bhardlimit: 0,
-+            dqb_bsoftlimit: 0,
-+            dqb_curspace: 0,
-+            dqb_ihardlimit: 0,
-+            dqb_isoftlimit: 0,
-+            dqb_curinodes: 0,
-+            dqb_btime: 0,
-+            dqb_itime: 0,
-+            dqb_valid: 0,
-+        })
-+    }
-+}
-+
-+impl Dqblk {
-+    /// The absolute limit on disk quota blocks allocated.
-+    pub fn blocks_hard_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
-+            Some(self.0.dqb_bhardlimit)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the absolute limit on disk quota blocks allocated.
-+    pub fn set_blocks_hard_limit(&mut self, limit: u64) {
-+        self.0.dqb_bhardlimit = limit;
-+    }
-+
-+    /// Preferred limit on disk quota blocks
-+    pub fn blocks_soft_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_BLIMITS) {
-+            Some(self.0.dqb_bsoftlimit)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the preferred limit on disk quota blocks allocated.
-+    pub fn set_blocks_soft_limit(&mut self, limit: u64) {
-+        self.0.dqb_bsoftlimit = limit;
-+    }
-+
-+    /// Current occupied space (bytes).
-+    pub fn occupied_space(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_SPACE) {
-+            Some(self.0.dqb_curspace)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Maximum number of allocated inodes.
-+    pub fn inodes_hard_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
-+            Some(self.0.dqb_ihardlimit)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the maximum number of allocated inodes.
-+    pub fn set_inodes_hard_limit(&mut self, limit: u64) {
-+        self.0.dqb_ihardlimit = limit;
-+    }
-+
-+    /// Preferred inode limit
-+    pub fn inodes_soft_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_ILIMITS) {
-+            Some(self.0.dqb_isoftlimit)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the preferred limit of allocated inodes.
-+    pub fn set_inodes_soft_limit(&mut self, limit: u64) {
-+        self.0.dqb_isoftlimit = limit;
-+    }
-+
-+    /// Current number of allocated inodes.
-+    pub fn allocated_inodes(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_INODES) {
-+            Some(self.0.dqb_curinodes)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Time limit for excessive disk use.
-+    pub fn block_time_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_BTIME) {
-+            Some(self.0.dqb_btime)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the time limit for excessive disk use.
-+    pub fn set_block_time_limit(&mut self, limit: u64) {
-+        self.0.dqb_btime = limit;
-+    }
-+
-+    /// Time limit for excessive files.
-+    pub fn inode_time_limit(&self) -> Option<u64> {
-+        let valid_fields = QuotaValidFlags::from_bits_truncate(self.0.dqb_valid);
-+        if valid_fields.contains(QuotaValidFlags::QIF_ITIME) {
-+            Some(self.0.dqb_itime)
-+        } else {
-+            None
-+        }
-+    }
-+
-+    /// Set the time limit for excessive files.
-+    pub fn set_inode_time_limit(&mut self, limit: u64) {
-+        self.0.dqb_itime = limit;
-+    }
-+}
-+
-+fn quotactl<P: ?Sized + NixPath>(cmd: QuotaCmd, special: Option<&P>, id: c_int, addr: *mut c_char) -> Result<()> {
-+    unsafe {
-+        Errno::clear();
-+        let res = match special {
-+            Some(dev) => dev.with_nix_path(|path| libc::quotactl(cmd.as_int(), path.as_ptr(), id, addr)),
-+            None => Ok(libc::quotactl(cmd.as_int(), ptr::null(), id, addr)),
-+        }?;
-+
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+/// Turn on disk quotas for a block device.
-+pub fn quotactl_on<P: ?Sized + NixPath>(which: QuotaType, special: &P, format: QuotaFmt, quota_file: &P) -> Result<()> {
-+    quota_file.with_nix_path(|path| {
-+        let mut path_copy = path.to_bytes_with_nul().to_owned();
-+        let p: *mut c_char = path_copy.as_mut_ptr() as *mut c_char;
-+        quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAON, which), Some(special), format as c_int, p)
-+    })?
-+}
-+
-+/// Disable disk quotas for a block device.
-+pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Result<()> {
-+    quotactl(QuotaCmd(QuotaSubCmd::Q_QUOTAOFF, which), Some(special), 0, ptr::null_mut())
-+}
-+
-+/// Update the on-disk copy of quota usages for a filesystem.
-+pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
-+    quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
-+}
-+
-+/// Get disk quota limits and current usage for the given user/group id.
-+pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
-+    let mut dqblk = unsafe { mem::uninitialized() };
-+    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?;
-+    dqblk
-+}
-+
-+/// Configure quota values for the specified fields for a given user/group id.
-+pub fn quotactl_set<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int, dqblk: &Dqblk, fields: QuotaValidFlags) -> Result<()> {
-+    let mut dqblk_copy = *dqblk;
-+    dqblk_copy.0.dqb_valid = fields.bits();
-+    quotactl(QuotaCmd(QuotaSubCmd::Q_SETQUOTA, which), Some(special), id, &mut dqblk_copy as *mut _ as *mut c_char)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/reboot.rs b/third_party/rust/nix-0.15.0/src/sys/reboot.rs
-new file mode 100644
-index 0000000000000..bafa8fc11996d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/reboot.rs
-@@ -0,0 +1,45 @@
-+//! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
-+
-+use {Error, Result};
-+use errno::Errno;
-+use libc;
-+use void::Void;
-+use std::mem::drop;
-+
-+libc_enum! {
-+    /// How exactly should the system be rebooted.
-+    ///
-+    /// See [`set_cad_enabled()`](fn.set_cad_enabled.html) for
-+    /// enabling/disabling Ctrl-Alt-Delete.
-+    #[repr(i32)]
-+    pub enum RebootMode {
-+        RB_HALT_SYSTEM,
-+        RB_KEXEC,
-+        RB_POWER_OFF,
-+        RB_AUTOBOOT,
-+        // we do not support Restart2,
-+        RB_SW_SUSPEND,
-+    }
-+}
-+
-+pub fn reboot(how: RebootMode) -> Result<Void> {
-+    unsafe {
-+        libc::reboot(how as libc::c_int)
-+    };
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// Enable or disable the reboot keystroke (Ctrl-Alt-Delete).
-+///
-+/// Corresponds to calling `reboot(RB_ENABLE_CAD)` or `reboot(RB_DISABLE_CAD)` in C.
-+pub fn set_cad_enabled(enable: bool) -> Result<()> {
-+    let cmd = if enable {
-+        libc::RB_ENABLE_CAD
-+    } else {
-+        libc::RB_DISABLE_CAD
-+    };
-+    let res = unsafe {
-+        libc::reboot(cmd)
-+    };
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/select.rs b/third_party/rust/nix-0.15.0/src/sys/select.rs
-new file mode 100644
-index 0000000000000..1b518e29f67a6
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/select.rs
-@@ -0,0 +1,334 @@
-+use std::mem;
-+use std::os::unix::io::RawFd;
-+use std::ptr::{null, null_mut};
-+use libc::{self, c_int};
-+use Result;
-+use errno::Errno;
-+use sys::signal::SigSet;
-+use sys::time::{TimeSpec, TimeVal};
-+
-+pub use libc::FD_SETSIZE;
-+
-+// FIXME: Change to repr(transparent) once it's stable
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct FdSet(libc::fd_set);
-+
-+impl FdSet {
-+    pub fn new() -> FdSet {
-+        let mut fdset = unsafe { mem::uninitialized() };
-+        unsafe { libc::FD_ZERO(&mut fdset) };
-+        FdSet(fdset)
-+    }
-+
-+    pub fn insert(&mut self, fd: RawFd) {
-+        unsafe { libc::FD_SET(fd, &mut self.0) };
-+    }
-+
-+    pub fn remove(&mut self, fd: RawFd) {
-+        unsafe { libc::FD_CLR(fd, &mut self.0) };
-+    }
-+
-+    pub fn contains(&mut self, fd: RawFd) -> bool {
-+        unsafe { libc::FD_ISSET(fd, &mut self.0) }
-+    }
-+
-+    pub fn clear(&mut self) {
-+        unsafe { libc::FD_ZERO(&mut self.0) };
-+    }
-+
-+    /// Finds the highest file descriptor in the set.
-+    ///
-+    /// Returns `None` if the set is empty.
-+    ///
-+    /// This can be used to calculate the `nfds` parameter of the [`select`] function.
-+    ///
-+    /// # Example
-+    ///
-+    /// ```
-+    /// # extern crate nix;
-+    /// # use nix::sys::select::FdSet;
-+    /// # fn main() {
-+    /// let mut set = FdSet::new();
-+    /// set.insert(4);
-+    /// set.insert(9);
-+    /// assert_eq!(set.highest(), Some(9));
-+    /// # }
-+    /// ```
-+    ///
-+    /// [`select`]: fn.select.html
-+    pub fn highest(&mut self) -> Option<RawFd> {
-+        for i in (0..FD_SETSIZE).rev() {
-+            let i = i as RawFd;
-+            if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
-+                return Some(i)
-+            }
-+        }
-+
-+        None
-+    }
-+}
-+
-+/// Monitors file descriptors for readiness
-+///
-+/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-+/// file descriptors that are ready for the given operation are set.
-+///
-+/// When this function returns, `timeout` has an implementation-defined value.
-+///
-+/// # Parameters
-+///
-+/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-+///   is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-+///   to the maximum of that.
-+/// * `readfds`: File descriptors to check for being ready to read.
-+/// * `writefds`: File descriptors to check for being ready to write.
-+/// * `errorfds`: File descriptors to check for pending error conditions.
-+/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-+///   indefinitely).
-+///
-+/// # References
-+///
-+/// [select(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html)
-+///
-+/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-+pub fn select<'a, N, R, W, E, T>(nfds: N,
-+                                 readfds: R,
-+                                 writefds: W,
-+                                 errorfds: E,
-+                                 timeout: T) -> Result<c_int>
-+where
-+    N: Into<Option<c_int>>,
-+    R: Into<Option<&'a mut FdSet>>,
-+    W: Into<Option<&'a mut FdSet>>,
-+    E: Into<Option<&'a mut FdSet>>,
-+    T: Into<Option<&'a mut TimeVal>>,
-+{
-+    let mut readfds = readfds.into();
-+    let mut writefds = writefds.into();
-+    let mut errorfds = errorfds.into();
-+    let timeout = timeout.into();
-+
-+    let nfds = nfds.into().unwrap_or_else(|| {
-+        readfds.iter_mut()
-+            .chain(writefds.iter_mut())
-+            .chain(errorfds.iter_mut())
-+            .map(|set| set.highest().unwrap_or(-1))
-+            .max()
-+            .unwrap_or(-1) + 1
-+    });
-+
-+    let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
-+                         .unwrap_or(null_mut());
-+
-+    let res = unsafe {
-+        libc::select(nfds, readfds, writefds, errorfds, timeout)
-+    };
-+
-+    Errno::result(res)
-+}
-+
-+/// Monitors file descriptors for readiness with an altered signal mask.
-+///
-+/// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-+/// file descriptors that are ready for the given operation are set.
-+///
-+/// When this function returns, the original signal mask is restored.
-+///
-+/// Unlike [`select`](#fn.select), `pselect` does not mutate the `timeout` value.
-+///
-+/// # Parameters
-+///
-+/// * `nfds`: The highest file descriptor set in any of the passed `FdSet`s, plus 1. If `None`, this
-+///   is calculated automatically by calling [`FdSet::highest`] on all descriptor sets and adding 1
-+///   to the maximum of that.
-+/// * `readfds`: File descriptors to check for read readiness
-+/// * `writefds`: File descriptors to check for write readiness
-+/// * `errorfds`: File descriptors to check for pending error conditions.
-+/// * `timeout`: Maximum time to wait for descriptors to become ready (`None` to block
-+///   indefinitely).
-+/// * `sigmask`: Signal mask to activate while waiting for file descriptors to turn
-+///    ready (`None` to set no alternative signal mask).
-+///
-+/// # References
-+///
-+/// [pselect(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html)
-+///
-+/// [The new pselect() system call](https://lwn.net/Articles/176911/)
-+///
-+/// [`FdSet::highest`]: struct.FdSet.html#method.highest
-+pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
-+                                     readfds: R,
-+                                     writefds: W,
-+                                     errorfds: E,
-+                                     timeout: T,
-+                                     sigmask: S) -> Result<c_int>
-+where
-+    N: Into<Option<c_int>>,
-+    R: Into<Option<&'a mut FdSet>>,
-+    W: Into<Option<&'a mut FdSet>>,
-+    E: Into<Option<&'a mut FdSet>>,
-+    T: Into<Option<&'a TimeSpec>>,
-+    S: Into<Option<&'a SigSet>>,
-+{
-+    let mut readfds = readfds.into();
-+    let mut writefds = writefds.into();
-+    let mut errorfds = errorfds.into();
-+    let sigmask = sigmask.into();
-+    let timeout = timeout.into();
-+
-+    let nfds = nfds.into().unwrap_or_else(|| {
-+        readfds.iter_mut()
-+            .chain(writefds.iter_mut())
-+            .chain(errorfds.iter_mut())
-+            .map(|set| set.highest().unwrap_or(-1))
-+            .max()
-+            .unwrap_or(-1) + 1
-+    });
-+
-+    let readfds = readfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-+    let timeout = timeout.map(|ts| ts.as_ref() as *const libc::timespec).unwrap_or(null());
-+    let sigmask = sigmask.map(|sm| sm.as_ref() as *const libc::sigset_t).unwrap_or(null());
-+
-+    let res = unsafe {
-+        libc::pselect(nfds, readfds, writefds, errorfds, timeout, sigmask)
-+    };
-+
-+    Errno::result(res)
-+}
-+
-+
-+#[cfg(test)]
-+mod tests {
-+    use super::*;
-+    use std::os::unix::io::RawFd;
-+    use sys::time::{TimeVal, TimeValLike};
-+    use unistd::{write, pipe};
-+
-+    #[test]
-+    fn fdset_insert() {
-+        let mut fd_set = FdSet::new();
-+
-+        for i in 0..FD_SETSIZE {
-+            assert!(!fd_set.contains(i as RawFd));
-+        }
-+
-+        fd_set.insert(7);
-+
-+        assert!(fd_set.contains(7));
-+    }
-+
-+    #[test]
-+    fn fdset_remove() {
-+        let mut fd_set = FdSet::new();
-+
-+        for i in 0..FD_SETSIZE {
-+            assert!(!fd_set.contains(i as RawFd));
-+        }
-+
-+        fd_set.insert(7);
-+        fd_set.remove(7);
-+
-+        for i in 0..FD_SETSIZE {
-+            assert!(!fd_set.contains(i as RawFd));
-+        }
-+    }
-+
-+    #[test]
-+    fn fdset_clear() {
-+        let mut fd_set = FdSet::new();
-+        fd_set.insert(1);
-+        fd_set.insert((FD_SETSIZE / 2) as RawFd);
-+        fd_set.insert((FD_SETSIZE - 1) as RawFd);
-+
-+        fd_set.clear();
-+
-+        for i in 0..FD_SETSIZE {
-+            assert!(!fd_set.contains(i as RawFd));
-+        }
-+    }
-+
-+    #[test]
-+    fn fdset_highest() {
-+        let mut set = FdSet::new();
-+        assert_eq!(set.highest(), None);
-+        set.insert(0);
-+        assert_eq!(set.highest(), Some(0));
-+        set.insert(90);
-+        assert_eq!(set.highest(), Some(90));
-+        set.remove(0);
-+        assert_eq!(set.highest(), Some(90));
-+        set.remove(90);
-+        assert_eq!(set.highest(), None);
-+
-+        set.insert(4);
-+        set.insert(5);
-+        set.insert(7);
-+        assert_eq!(set.highest(), Some(7));
-+    }
-+
-+    #[test]
-+    fn test_select() {
-+        let (r1, w1) = pipe().unwrap();
-+        write(w1, b"hi!").unwrap();
-+        let (r2, _w2) = pipe().unwrap();
-+
-+        let mut fd_set = FdSet::new();
-+        fd_set.insert(r1);
-+        fd_set.insert(r2);
-+
-+        let mut timeout = TimeVal::seconds(10);
-+        assert_eq!(1, select(None,
-+                             &mut fd_set,
-+                             None,
-+                             None,
-+                             &mut timeout).unwrap());
-+        assert!(fd_set.contains(r1));
-+        assert!(!fd_set.contains(r2));
-+    }
-+
-+    #[test]
-+    fn test_select_nfds() {
-+        let (r1, w1) = pipe().unwrap();
-+        write(w1, b"hi!").unwrap();
-+        let (r2, _w2) = pipe().unwrap();
-+
-+        let mut fd_set = FdSet::new();
-+        fd_set.insert(r1);
-+        fd_set.insert(r2);
-+
-+        let mut timeout = TimeVal::seconds(10);
-+        assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
-+                             &mut fd_set,
-+                             None,
-+                             None,
-+                             &mut timeout).unwrap());
-+        assert!(fd_set.contains(r1));
-+        assert!(!fd_set.contains(r2));
-+    }
-+
-+    #[test]
-+    fn test_select_nfds2() {
-+        let (r1, w1) = pipe().unwrap();
-+        write(w1, b"hi!").unwrap();
-+        let (r2, _w2) = pipe().unwrap();
-+
-+        let mut fd_set = FdSet::new();
-+        fd_set.insert(r1);
-+        fd_set.insert(r2);
-+
-+        let mut timeout = TimeVal::seconds(10);
-+        assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
-+                             &mut fd_set,
-+                             None,
-+                             None,
-+                             &mut timeout).unwrap());
-+        assert!(fd_set.contains(r1));
-+        assert!(!fd_set.contains(r2));
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/sendfile.rs b/third_party/rust/nix-0.15.0/src/sys/sendfile.rs
-new file mode 100644
-index 0000000000000..a47d8962f73fb
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/sendfile.rs
-@@ -0,0 +1,200 @@
-+use std::os::unix::io::RawFd;
-+use std::ptr;
-+
-+use libc::{self, off_t};
-+
-+use Result;
-+use errno::Errno;
-+
-+/// 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.](http://man7.org/linux/man-pages/man2/sendfile.2.html)
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub fn sendfile(
-+    out_fd: RawFd,
-+    in_fd: RawFd,
-+    offset: Option<&mut off_t>,
-+    count: usize,
-+) -> Result<usize> {
-+    let offset = offset
-+        .map(|offset| offset as *mut _)
-+        .unwrap_or(ptr::null_mut());
-+    let ret = unsafe { libc::sendfile(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",
-+                 target_os = "macos"))] {
-+        use sys::uio::IoVec;
-+
-+        #[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+        struct SendfileHeaderTrailer<'a>(
-+            libc::sf_hdtr,
-+            Option<Vec<IoVec<&'a [u8]>>>,
-+            Option<Vec<IoVec<&'a [u8]>>>,
-+        );
-+
-+        impl<'a> SendfileHeaderTrailer<'a> {
-+            fn new(
-+                headers: Option<&'a [&'a [u8]]>,
-+                trailers: Option<&'a [&'a [u8]]>
-+            ) -> SendfileHeaderTrailer<'a> {
-+                let header_iovecs: Option<Vec<IoVec<&[u8]>>> =
-+                    headers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
-+                let trailer_iovecs: Option<Vec<IoVec<&[u8]>>> =
-+                    trailers.map(|s| s.iter().map(|b| IoVec::from_slice(b)).collect());
-+                SendfileHeaderTrailer(
-+                    libc::sf_hdtr {
-+                        headers: {
-+                            header_iovecs
-+                                .as_ref()
-+                                .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
-+                        },
-+                        hdr_cnt: header_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32,
-+                        trailers: {
-+                            trailer_iovecs
-+                                .as_ref()
-+                                .map_or(ptr::null(), |v| v.as_ptr()) as *mut libc::iovec
-+                        },
-+                        trl_cnt: trailer_iovecs.as_ref().map(|v| v.len()).unwrap_or(0) as i32
-+                    },
-+                    header_iovecs,
-+                    trailer_iovecs,
-+                )
-+            }
-+        }
-+    }
-+}
-+
-+cfg_if! {
-+    if #[cfg(target_os = "freebsd")] {
-+        use libc::c_int;
-+
-+        libc_bitflags!{
-+            /// Configuration options for [`sendfile`.](fn.sendfile.html)
-+            pub struct SfFlags: c_int {
-+                /// Causes `sendfile` to return EBUSY instead of blocking when attempting to read a
-+                /// busy page.
-+                SF_NODISKIO;
-+                /// Causes `sendfile` to sleep until the network stack releases its reference to the
-+                /// VM pages read. When `sendfile` returns, the data is not guaranteed to have been
-+                /// sent, but it is safe to modify the file.
-+                SF_SYNC;
-+                /// Causes `sendfile` to cache exactly the number of pages specified in the
-+                /// `readahead` parameter, disabling caching heuristics.
-+                SF_USER_READAHEAD;
-+                /// Causes `sendfile` not to cache the data read.
-+                SF_NOCACHE;
-+            }
-+        }
-+
-+        /// Read up to `count` bytes from `in_fd` starting at `offset` and write to `out_sock`.
-+        ///
-+        /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
-+        /// an error occurs.
-+        ///
-+        /// `in_fd` must describe a regular file or shared memory object. `out_sock` must describe a
-+        /// stream socket.
-+        ///
-+        /// If `offset` falls past the end of the file, the function returns success and zero bytes
-+        /// written.
-+        ///
-+        /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
-+        /// file (EOF).
-+        ///
-+        /// `headers` and `trailers` specify optional slices of byte slices to be sent before and
-+        /// after the data read from `in_fd`, respectively. The length of headers and trailers sent
-+        /// is included in the returned count of bytes written. The values of `offset` and `count`
-+        /// do not apply to headers or trailers.
-+        ///
-+        /// `readahead` specifies the minimum number of pages to cache in memory ahead of the page
-+        /// currently being sent.
-+        ///
-+        /// For more information, see
-+        /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
-+        pub fn sendfile(
-+            in_fd: RawFd,
-+            out_sock: RawFd,
-+            offset: off_t,
-+            count: Option<usize>,
-+            headers: Option<&[&[u8]]>,
-+            trailers: Option<&[&[u8]]>,
-+            flags: SfFlags,
-+            readahead: u16
-+        ) -> (Result<()>, off_t) {
-+            // Readahead goes in upper 16 bits
-+            // Flags goes in lower 16 bits
-+            // see `man 2 sendfile`
-+            let flags: u32 = ((readahead as u32) << 16) | (flags.bits() as u32);
-+            let mut bytes_sent: off_t = 0;
-+            let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
-+            let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
-+            let return_code = unsafe {
-+                libc::sendfile(in_fd,
-+                               out_sock,
-+                               offset,
-+                               count.unwrap_or(0),
-+                               hdtr_ptr as *mut libc::sf_hdtr,
-+                               &mut bytes_sent as *mut off_t,
-+                               flags as c_int)
-+            };
-+            (Errno::result(return_code).and(Ok(())), bytes_sent)
-+        }
-+    } else if #[cfg(any(target_os = "ios", target_os = "macos"))] {
-+        /// Read bytes from `in_fd` starting at `offset` and write up to `count` bytes to
-+        /// `out_sock`.
-+        ///
-+        /// Returns a `Result` and a count of bytes written. Bytes written may be non-zero even if
-+        /// an error occurs.
-+        ///
-+        /// `in_fd` must describe a regular file. `out_sock` must describe a stream socket.
-+        ///
-+        /// If `offset` falls past the end of the file, the function returns success and zero bytes
-+        /// written.
-+        ///
-+        /// If `count` is `None` or 0, bytes will be read from `in_fd` until reaching the end of
-+        /// file (EOF).
-+        ///
-+        /// `hdtr` specifies an optional list of headers and trailers to be sent before and after
-+        /// the data read from `in_fd`, respectively. The length of headers and trailers sent is
-+        /// included in the returned count of bytes written. If any headers are specified and
-+        /// `count` is non-zero, the length of the headers will be counted in the limit of total
-+        /// bytes sent. Trailers do not count toward the limit of bytes sent and will always be sent
-+        /// regardless. The value of `offset` does not affect headers or trailers.
-+        ///
-+        /// For more information, see
-+        /// [the sendfile(2) man page.](https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man2/sendfile.2.html)
-+        pub fn sendfile(
-+            in_fd: RawFd,
-+            out_sock: RawFd,
-+            offset: off_t,
-+            count: Option<off_t>,
-+            headers: Option<&[&[u8]]>,
-+            trailers: Option<&[&[u8]]>
-+        ) -> (Result<()>, off_t) {
-+            let mut len = count.unwrap_or(0);
-+            let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
-+            let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
-+            let return_code = unsafe {
-+                libc::sendfile(in_fd,
-+                               out_sock,
-+                               offset,
-+                               &mut len as *mut off_t,
-+                               hdtr_ptr as *mut libc::sf_hdtr,
-+                               0)
-+            };
-+            (Errno::result(return_code).and(Ok(())), len)
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/signal.rs b/third_party/rust/nix-0.15.0/src/sys/signal.rs
-new file mode 100644
-index 0000000000000..1013a77fd4b40
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/signal.rs
-@@ -0,0 +1,966 @@
-+// Portions of this file are Copyright 2014 The Rust Project Developers.
-+// See http://rust-lang.org/COPYRIGHT.
-+
-+///! Operating system signals.
-+
-+use libc;
-+use {Error, Result};
-+use errno::Errno;
-+use std::mem;
-+use std::fmt;
-+use std::str::FromStr;
-+#[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+use std::os::unix::io::RawFd;
-+use std::ptr;
-+
-+#[cfg(not(target_os = "openbsd"))]
-+pub use self::sigevent::*;
-+
-+libc_enum!{
-+    // Currently there is only one definition of c_int in libc, as well as only one
-+    // type for signal constants.
-+    // We would prefer to use the libc::c_int alias in the repr attribute. Unfortunately
-+    // this is not (yet) possible.
-+    #[repr(i32)]
-+    pub enum Signal {
-+        SIGHUP,
-+        SIGINT,
-+        SIGQUIT,
-+        SIGILL,
-+        SIGTRAP,
-+        SIGABRT,
-+        SIGBUS,
-+        SIGFPE,
-+        SIGKILL,
-+        SIGUSR1,
-+        SIGSEGV,
-+        SIGUSR2,
-+        SIGPIPE,
-+        SIGALRM,
-+        SIGTERM,
-+        #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
-+                  not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+        SIGSTKFLT,
-+        SIGCHLD,
-+        SIGCONT,
-+        SIGSTOP,
-+        SIGTSTP,
-+        SIGTTIN,
-+        SIGTTOU,
-+        SIGURG,
-+        SIGXCPU,
-+        SIGXFSZ,
-+        SIGVTALRM,
-+        SIGPROF,
-+        SIGWINCH,
-+        SIGIO,
-+        #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+        SIGPWR,
-+        SIGSYS,
-+        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+        SIGEMT,
-+        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+        SIGINFO,
-+    }
-+}
-+
-+impl FromStr for Signal {
-+    type Err = Error;
-+    fn from_str(s: &str) -> Result<Signal> {
-+        Ok(match s {
-+            "SIGHUP" => Signal::SIGHUP,
-+            "SIGINT" => Signal::SIGINT,
-+            "SIGQUIT" => Signal::SIGQUIT,
-+            "SIGILL" => Signal::SIGILL,
-+            "SIGTRAP" => Signal::SIGTRAP,
-+            "SIGABRT" => Signal::SIGABRT,
-+            "SIGBUS" => Signal::SIGBUS,
-+            "SIGFPE" => Signal::SIGFPE,
-+            "SIGKILL" => Signal::SIGKILL,
-+            "SIGUSR1" => Signal::SIGUSR1,
-+            "SIGSEGV" => Signal::SIGSEGV,
-+            "SIGUSR2" => Signal::SIGUSR2,
-+            "SIGPIPE" => Signal::SIGPIPE,
-+            "SIGALRM" => Signal::SIGALRM,
-+            "SIGTERM" => Signal::SIGTERM,
-+            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
-+                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+            "SIGSTKFLT" => Signal::SIGSTKFLT,
-+            "SIGCHLD" => Signal::SIGCHLD,
-+            "SIGCONT" => Signal::SIGCONT,
-+            "SIGSTOP" => Signal::SIGSTOP,
-+            "SIGTSTP" => Signal::SIGTSTP,
-+            "SIGTTIN" => Signal::SIGTTIN,
-+            "SIGTTOU" => Signal::SIGTTOU,
-+            "SIGURG" => Signal::SIGURG,
-+            "SIGXCPU" => Signal::SIGXCPU,
-+            "SIGXFSZ" => Signal::SIGXFSZ,
-+            "SIGVTALRM" => Signal::SIGVTALRM,
-+            "SIGPROF" => Signal::SIGPROF,
-+            "SIGWINCH" => Signal::SIGWINCH,
-+            "SIGIO" => Signal::SIGIO,
-+            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+            "SIGPWR" => Signal::SIGPWR,
-+            "SIGSYS" => Signal::SIGSYS,
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            "SIGEMT" => Signal::SIGEMT,
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            "SIGINFO" => Signal::SIGINFO,
-+            _ => return Err(Error::invalid_argument()),
-+        })
-+    }
-+}
-+
-+impl AsRef<str> for Signal {
-+    fn as_ref(&self) -> &str {
-+        match *self {
-+            Signal::SIGHUP => "SIGHUP",
-+            Signal::SIGINT => "SIGINT",
-+            Signal::SIGQUIT => "SIGQUIT",
-+            Signal::SIGILL => "SIGILL",
-+            Signal::SIGTRAP => "SIGTRAP",
-+            Signal::SIGABRT => "SIGABRT",
-+            Signal::SIGBUS => "SIGBUS",
-+            Signal::SIGFPE => "SIGFPE",
-+            Signal::SIGKILL => "SIGKILL",
-+            Signal::SIGUSR1 => "SIGUSR1",
-+            Signal::SIGSEGV => "SIGSEGV",
-+            Signal::SIGUSR2 => "SIGUSR2",
-+            Signal::SIGPIPE => "SIGPIPE",
-+            Signal::SIGALRM => "SIGALRM",
-+            Signal::SIGTERM => "SIGTERM",
-+            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
-+                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+            Signal::SIGSTKFLT => "SIGSTKFLT",
-+            Signal::SIGCHLD => "SIGCHLD",
-+            Signal::SIGCONT => "SIGCONT",
-+            Signal::SIGSTOP => "SIGSTOP",
-+            Signal::SIGTSTP => "SIGTSTP",
-+            Signal::SIGTTIN => "SIGTTIN",
-+            Signal::SIGTTOU => "SIGTTOU",
-+            Signal::SIGURG => "SIGURG",
-+            Signal::SIGXCPU => "SIGXCPU",
-+            Signal::SIGXFSZ => "SIGXFSZ",
-+            Signal::SIGVTALRM => "SIGVTALRM",
-+            Signal::SIGPROF => "SIGPROF",
-+            Signal::SIGWINCH => "SIGWINCH",
-+            Signal::SIGIO => "SIGIO",
-+            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+            Signal::SIGPWR => "SIGPWR",
-+            Signal::SIGSYS => "SIGSYS",
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            Signal::SIGEMT => "SIGEMT",
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            Signal::SIGINFO => "SIGINFO",
-+        }
-+    }
-+}
-+
-+impl fmt::Display for Signal {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        f.write_str(self.as_ref())
-+    }
-+}
-+
-+pub use self::Signal::*;
-+
-+#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+const SIGNALS: [Signal; 31] = [
-+    SIGHUP,
-+    SIGINT,
-+    SIGQUIT,
-+    SIGILL,
-+    SIGTRAP,
-+    SIGABRT,
-+    SIGBUS,
-+    SIGFPE,
-+    SIGKILL,
-+    SIGUSR1,
-+    SIGSEGV,
-+    SIGUSR2,
-+    SIGPIPE,
-+    SIGALRM,
-+    SIGTERM,
-+    SIGSTKFLT,
-+    SIGCHLD,
-+    SIGCONT,
-+    SIGSTOP,
-+    SIGTSTP,
-+    SIGTTIN,
-+    SIGTTOU,
-+    SIGURG,
-+    SIGXCPU,
-+    SIGXFSZ,
-+    SIGVTALRM,
-+    SIGPROF,
-+    SIGWINCH,
-+    SIGIO,
-+    SIGPWR,
-+    SIGSYS];
-+#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")))]
-+const SIGNALS: [Signal; 30] = [
-+    SIGHUP,
-+    SIGINT,
-+    SIGQUIT,
-+    SIGILL,
-+    SIGTRAP,
-+    SIGABRT,
-+    SIGBUS,
-+    SIGFPE,
-+    SIGKILL,
-+    SIGUSR1,
-+    SIGSEGV,
-+    SIGUSR2,
-+    SIGPIPE,
-+    SIGALRM,
-+    SIGTERM,
-+    SIGCHLD,
-+    SIGCONT,
-+    SIGSTOP,
-+    SIGTSTP,
-+    SIGTTIN,
-+    SIGTTOU,
-+    SIGURG,
-+    SIGXCPU,
-+    SIGXFSZ,
-+    SIGVTALRM,
-+    SIGPROF,
-+    SIGWINCH,
-+    SIGIO,
-+    SIGPWR,
-+    SIGSYS];
-+#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
-+const SIGNALS: [Signal; 31] = [
-+    SIGHUP,
-+    SIGINT,
-+    SIGQUIT,
-+    SIGILL,
-+    SIGTRAP,
-+    SIGABRT,
-+    SIGBUS,
-+    SIGFPE,
-+    SIGKILL,
-+    SIGUSR1,
-+    SIGSEGV,
-+    SIGUSR2,
-+    SIGPIPE,
-+    SIGALRM,
-+    SIGTERM,
-+    SIGCHLD,
-+    SIGCONT,
-+    SIGSTOP,
-+    SIGTSTP,
-+    SIGTTIN,
-+    SIGTTOU,
-+    SIGURG,
-+    SIGXCPU,
-+    SIGXFSZ,
-+    SIGVTALRM,
-+    SIGPROF,
-+    SIGWINCH,
-+    SIGIO,
-+    SIGSYS,
-+    SIGEMT,
-+    SIGINFO];
-+
-+pub const NSIG: libc::c_int = 32;
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct SignalIterator {
-+    next: usize,
-+}
-+
-+impl Iterator for SignalIterator {
-+    type Item = Signal;
-+
-+    fn next(&mut self) -> Option<Signal> {
-+        if self.next < SIGNALS.len() {
-+            let next_signal = SIGNALS[self.next];
-+            self.next += 1;
-+            Some(next_signal)
-+        } else {
-+            None
-+        }
-+    }
-+}
-+
-+impl Signal {
-+    pub fn iterator() -> SignalIterator {
-+        SignalIterator{next: 0}
-+    }
-+
-+    // We do not implement the From trait, because it is supposed to be infallible.
-+    // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
-+    // implemented, we'll replace this function.
-+    #[inline]
-+    pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
-+        if 0 < signum && signum < NSIG {
-+            Ok(unsafe { mem::transmute(signum) })
-+        } else {
-+            Err(Error::invalid_argument())
-+        }
-+    }
-+}
-+
-+pub const SIGIOT : Signal = SIGABRT;
-+pub const SIGPOLL : Signal = SIGIO;
-+pub const SIGUNUSED : Signal = SIGSYS;
-+
-+libc_bitflags!{
-+    pub struct SaFlags: libc::c_int {
-+        SA_NOCLDSTOP;
-+        SA_NOCLDWAIT;
-+        SA_NODEFER;
-+        SA_ONSTACK;
-+        SA_RESETHAND;
-+        SA_RESTART;
-+        SA_SIGINFO;
-+    }
-+}
-+
-+libc_enum! {
-+    #[repr(i32)]
-+    pub enum SigmaskHow {
-+        SIG_BLOCK,
-+        SIG_UNBLOCK,
-+        SIG_SETMASK,
-+    }
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct SigSet {
-+    sigset: libc::sigset_t
-+}
-+
-+
-+impl SigSet {
-+    pub fn all() -> SigSet {
-+        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
-+        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };
-+
-+        SigSet { sigset: sigset }
-+    }
-+
-+    pub fn empty() -> SigSet {
-+        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
-+        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
-+
-+        SigSet { sigset: sigset }
-+    }
-+
-+    pub fn add(&mut self, signal: Signal) {
-+        unsafe { libc::sigaddset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
-+    }
-+
-+    pub fn clear(&mut self) {
-+        unsafe { libc::sigemptyset(&mut self.sigset as *mut libc::sigset_t) };
-+    }
-+
-+    pub fn remove(&mut self, signal: Signal) {
-+        unsafe { libc::sigdelset(&mut self.sigset as *mut libc::sigset_t, signal as libc::c_int) };
-+    }
-+
-+    pub fn contains(&self, signal: Signal) -> bool {
-+        let res = unsafe { libc::sigismember(&self.sigset as *const libc::sigset_t, signal as libc::c_int) };
-+
-+        match res {
-+            1 => true,
-+            0 => false,
-+            _ => unreachable!("unexpected value from sigismember"),
-+        }
-+    }
-+
-+    pub fn extend(&mut self, other: &SigSet) {
-+        for signal in Signal::iterator() {
-+            if other.contains(signal) {
-+                self.add(signal);
-+            }
-+        }
-+    }
-+
-+    /// Gets the currently blocked (masked) set of signals for the calling thread.
-+    pub fn thread_get_mask() -> Result<SigSet> {
-+        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
-+        pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?;
-+        Ok(oldmask)
-+    }
-+
-+    /// Sets the set of signals as the signal mask for the calling thread.
-+    pub fn thread_set_mask(&self) -> Result<()> {
-+        pthread_sigmask(SigmaskHow::SIG_SETMASK, Some(self), None)
-+    }
-+
-+    /// Adds the set of signals to the signal mask for the calling thread.
-+    pub fn thread_block(&self) -> Result<()> {
-+        pthread_sigmask(SigmaskHow::SIG_BLOCK, Some(self), None)
-+    }
-+
-+    /// Removes the set of signals from the signal mask for the calling thread.
-+    pub fn thread_unblock(&self) -> Result<()> {
-+        pthread_sigmask(SigmaskHow::SIG_UNBLOCK, Some(self), None)
-+    }
-+
-+    /// Sets the set of signals as the signal mask, and returns the old mask.
-+    pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
-+        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
-+        pthread_sigmask(how, Some(self), Some(&mut oldmask))?;
-+        Ok(oldmask)
-+    }
-+
-+    /// Suspends execution of the calling thread until one of the signals in the
-+    /// signal mask becomes pending, and returns the accepted signal.
-+    pub fn wait(&self) -> Result<Signal> {
-+        let mut signum: libc::c_int = unsafe { mem::uninitialized() };
-+        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
-+
-+        Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
-+    }
-+}
-+
-+impl AsRef<libc::sigset_t> for SigSet {
-+    fn as_ref(&self) -> &libc::sigset_t {
-+        &self.sigset
-+    }
-+}
-+
-+/// A signal handler.
-+#[allow(unknown_lints)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum SigHandler {
-+    /// Default signal handling.
-+    SigDfl,
-+    /// Request that the signal be ignored.
-+    SigIgn,
-+    /// Use the given signal-catching function, which takes in the signal.
-+    Handler(extern fn(libc::c_int)),
-+    /// Use the given signal-catching function, which takes in the signal, information about how
-+    /// the signal was generated, and a pointer to the threads `ucontext_t`.
-+    SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
-+}
-+
-+/// Action to take on receipt of a signal. Corresponds to `sigaction`.
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct SigAction {
-+    sigaction: libc::sigaction
-+}
-+
-+impl SigAction {
-+    /// Creates a new action.
-+    ///
-+    /// The `SA_SIGINFO` bit in the `flags` argument is ignored (it will be set only if `handler`
-+    /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
-+    /// the signal-catching function.
-+    pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
-+        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
-+        s.sa_sigaction = match handler {
-+            SigHandler::SigDfl => libc::SIG_DFL,
-+            SigHandler::SigIgn => libc::SIG_IGN,
-+            SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
-+            SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
-+        };
-+        s.sa_flags = match handler {
-+            SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
-+            _ => (flags - SaFlags::SA_SIGINFO).bits(),
-+        };
-+        s.sa_mask = mask.sigset;
-+
-+        SigAction { sigaction: s }
-+    }
-+
-+    /// Returns the flags set on the action.
-+    pub fn flags(&self) -> SaFlags {
-+        SaFlags::from_bits_truncate(self.sigaction.sa_flags)
-+    }
-+
-+    /// Returns the set of signals that are blocked during execution of the action's
-+    /// signal-catching function.
-+    pub fn mask(&self) -> SigSet {
-+        SigSet { sigset: self.sigaction.sa_mask }
-+    }
-+
-+    /// Returns the action's handler.
-+    pub fn handler(&self) -> SigHandler {
-+        match self.sigaction.sa_sigaction {
-+            libc::SIG_DFL => SigHandler::SigDfl,
-+            libc::SIG_IGN => SigHandler::SigIgn,
-+            f if self.flags().contains(SaFlags::SA_SIGINFO) =>
-+                SigHandler::SigAction( unsafe { mem::transmute(f) } ),
-+            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
-+        }
-+    }
-+}
-+
-+/// Changes the action taken by a process on receipt of a specific signal.
-+///
-+/// `signal` can be any signal except `SIGKILL` or `SIGSTOP`. On success, it returns the previous
-+/// action for the given signal. If `sigaction` fails, no new signal handler is installed.
-+///
-+/// # Safety
-+///
-+/// Signal handlers may be called at any point during execution, which limits what is safe to do in
-+/// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
-+/// marked safe for signal handlers and only share global data using atomics.
-+pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
-+    let mut oldact = mem::uninitialized::<libc::sigaction>();
-+
-+    let res =
-+        libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
-+
-+    Errno::result(res).map(|_| SigAction { sigaction: oldact })
-+}
-+
-+/// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
-+///
-+/// Installs `handler` for the given `signal`, returning the previous signal
-+/// handler. `signal` should only be used following another call to `signal` or
-+/// if the current handler is the default. The return value of `signal` is
-+/// undefined after setting the handler with [`sigaction`][SigActionFn].
-+///
-+/// # Safety
-+///
-+/// If the pointer to the previous signal handler is invalid, undefined
-+/// behavior could be invoked when casting it back to a [`SigAction`][SigActionStruct].
-+///
-+/// # Examples
-+///
-+/// Ignore `SIGINT`:
-+///
-+/// ```no_run
-+/// # use nix::sys::signal::{self, Signal, SigHandler};
-+/// unsafe { signal::signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
-+/// ```
-+///
-+/// Use a signal handler to set a flag variable:
-+///
-+/// ```no_run
-+/// # #[macro_use] extern crate lazy_static;
-+/// # extern crate libc;
-+/// # extern crate nix;
-+/// # use std::sync::atomic::{AtomicBool, Ordering};
-+/// # use nix::sys::signal::{self, Signal, SigHandler};
-+/// lazy_static! {
-+///    static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-+/// }
-+///
-+/// extern fn handle_sigint(signal: libc::c_int) {
-+///     let signal = Signal::from_c_int(signal).unwrap();
-+///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
-+/// }
-+///
-+/// fn main() {
-+///     let handler = SigHandler::Handler(handle_sigint);
-+///     unsafe { signal::signal(Signal::SIGINT, handler) }.unwrap();
-+/// }
-+/// ```
-+///
-+/// # Errors
-+///
-+/// Returns [`Error::UnsupportedOperation`] if `handler` is
-+/// [`SigAction`][SigActionStruct]. Use [`sigaction`][SigActionFn] instead.
-+///
-+/// `signal` also returns any error from `libc::signal`, such as when an attempt
-+/// is made to catch a signal that cannot be caught or to ignore a signal that
-+/// cannot be ignored.
-+///
-+/// [`Error::UnsupportedOperation`]: ../../enum.Error.html#variant.UnsupportedOperation
-+/// [SigActionStruct]: struct.SigAction.html
-+/// [sigactionFn]: fn.sigaction.html
-+pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler> {
-+    let signal = signal as libc::c_int;
-+    let res = match handler {
-+        SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
-+        SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
-+        SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
-+        SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
-+    };
-+    Errno::result(res).map(|oldhandler| {
-+        match oldhandler {
-+            libc::SIG_DFL => SigHandler::SigDfl,
-+            libc::SIG_IGN => SigHandler::SigIgn,
-+            f => SigHandler::Handler(mem::transmute(f)),
-+        }
-+    })
-+}
-+
-+/// Manages the signal mask (set of blocked signals) for the calling thread.
-+///
-+/// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
-+/// The `how` flag decides the type of update. If `set` is `None`, `how` will be ignored,
-+/// and no modification will take place.
-+///
-+/// If the 'oldset' parameter is `Some(..)` then the current signal mask will be written into it.
-+///
-+/// If both `set` and `oldset` is `Some(..)`, the current signal mask will be written into oldset,
-+/// and then it will be updated with `set`.
-+///
-+/// 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.
-+pub fn pthread_sigmask(how: SigmaskHow,
-+                       set: Option<&SigSet>,
-+                       oldset: Option<&mut SigSet>) -> Result<()> {
-+    if set.is_none() && oldset.is_none() {
-+        return Ok(())
-+    }
-+
-+    let res = unsafe {
-+        // if set or oldset is None, pass in null pointers instead
-+        libc::pthread_sigmask(how as libc::c_int,
-+                             set.map_or_else(ptr::null::<libc::sigset_t>,
-+                                             |s| &s.sigset as *const libc::sigset_t),
-+                             oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
-+                                                |os| &mut os.sigset as *mut libc::sigset_t))
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Examine and change blocked signals.
-+///
-+/// For more informations see the [`sigprocmask` man
-+/// pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html).
-+pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut SigSet>) -> Result<()> {
-+    if set.is_none() && oldset.is_none() {
-+        return Ok(())
-+    }
-+
-+    let res = unsafe {
-+        // if set or oldset is None, pass in null pointers instead
-+        libc::sigprocmask(how as libc::c_int,
-+                          set.map_or_else(ptr::null::<libc::sigset_t>,
-+                                          |s| &s.sigset as *const libc::sigset_t),
-+                          oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
-+                                             |os| &mut os.sigset as *mut libc::sigset_t))
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
-+    let res = unsafe { libc::kill(pid.into(),
-+                                  match signal.into() {
-+                                      Some(s) => s as libc::c_int,
-+                                      None => 0,
-+                                  }) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Send a signal to a process group [(see
-+/// killpg(3))](http://pubs.opengroup.org/onlinepubs/9699919799/functions/killpg.html).
-+///
-+/// If `pgrp` less then or equal 1, the behavior is platform-specific.
-+/// If `signal` is `None`, `killpg` will only preform error checking and won't
-+/// send any signal.
-+pub fn killpg<T: Into<Option<Signal>>>(pgrp: ::unistd::Pid, signal: T) -> Result<()> {
-+    let res = unsafe { libc::killpg(pgrp.into(),
-+                                  match signal.into() {
-+                                      Some(s) => s as libc::c_int,
-+                                      None => 0,
-+                                  }) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+pub fn raise(signal: Signal) -> Result<()> {
-+    let res = unsafe { libc::raise(signal as libc::c_int) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+
-+#[cfg(target_os = "freebsd")]
-+pub type type_of_thread_id = libc::lwpid_t;
-+#[cfg(target_os = "linux")]
-+pub type type_of_thread_id = libc::pid_t;
-+
-+/// Used to request asynchronous notification of certain events, for example,
-+/// with POSIX AIO, POSIX message queues, and POSIX timers.
-+// sigval is actually a union of a int and a void*.  But it's never really used
-+// as a pointer, because neither libc nor the kernel ever dereference it.  nix
-+// therefore presents it as an intptr_t, which is how kevent uses it.
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum SigevNotify {
-+    /// No notification will be delivered
-+    SigevNone,
-+    /// The signal given by `signal` will be delivered to the process.  The
-+    /// value in `si_value` will be present in the `si_value` field of the
-+    /// `siginfo_t` structure of the queued signal.
-+    SigevSignal { signal: Signal, si_value: libc::intptr_t },
-+    // Note: SIGEV_THREAD is not implemented because libc::sigevent does not
-+    // expose a way to set the union members needed by SIGEV_THREAD.
-+    /// A new `kevent` is posted to the kqueue `kq`.  The `kevent`'s `udata`
-+    /// field will contain the value in `udata`.
-+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+    SigevKevent { kq: RawFd, udata: libc::intptr_t },
-+    /// The signal `signal` is queued to the thread whose LWP ID is given in
-+    /// `thread_id`.  The value stored in `si_value` will be present in the
-+    /// `si_value` of the `siginfo_t` structure of the queued signal.
-+    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
-+    SigevThreadId { signal: Signal, thread_id: type_of_thread_id,
-+                    si_value: libc::intptr_t },
-+}
-+
-+#[cfg(not(target_os = "openbsd"))]
-+mod sigevent {
-+    use libc;
-+    use std::mem;
-+    use std::ptr;
-+    use super::SigevNotify;
-+    #[cfg(any(target_os = "freebsd", target_os = "linux"))]
-+    use super::type_of_thread_id;
-+
-+    /// Used to request asynchronous notification of the completion of certain
-+    /// events, such as POSIX AIO and timers.
-+    #[repr(C)]
-+    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+    pub struct SigEvent {
-+        sigevent: libc::sigevent
-+    }
-+
-+    impl SigEvent {
-+        /// **Note:** this constructor does not allow the user to set the
-+        /// `sigev_notify_kevent_flags` field.  That's considered ok because on FreeBSD
-+        /// at least those flags don't do anything useful.  That field is part of a
-+        /// union that shares space with the more genuinely useful fields.
-+        ///
-+        /// **Note:** This constructor also doesn't allow the caller to set the
-+        /// `sigev_notify_function` or `sigev_notify_attributes` fields, which are
-+        /// required for `SIGEV_THREAD`.  That's considered ok because on no operating
-+        /// system is `SIGEV_THREAD` the most efficient way to deliver AIO
-+        /// notification.  FreeBSD and DragonFly BSD programs should prefer `SIGEV_KEVENT`.
-+        /// 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`
-+        pub fn new(sigev_notify: SigevNotify) -> SigEvent {
-+            let mut sev = unsafe { mem::zeroed::<libc::sigevent>()};
-+            sev.sigev_notify = match sigev_notify {
-+                SigevNotify::SigevNone => libc::SIGEV_NONE,
-+                SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
-+                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+                SigevNotify::SigevKevent{..} => libc::SIGEV_KEVENT,
-+                #[cfg(target_os = "freebsd")]
-+                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
-+                #[cfg(all(target_os = "linux", target_env = "gnu", not(target_arch = "mips")))]
-+                SigevNotify::SigevThreadId{..} => libc::SIGEV_THREAD_ID,
-+                #[cfg(any(all(target_os = "linux", target_env = "musl"), target_arch = "mips"))]
-+                SigevNotify::SigevThreadId{..} => 4  // No SIGEV_THREAD_ID defined
-+            };
-+            sev.sigev_signo = match sigev_notify {
-+                SigevNotify::SigevSignal{ signal, .. } => signal as libc::c_int,
-+                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+                SigevNotify::SigevKevent{ kq, ..} => kq,
-+                #[cfg(any(target_os = "linux", target_os = "freebsd"))]
-+                SigevNotify::SigevThreadId{ signal, .. } => signal as libc::c_int,
-+                _ => 0
-+            };
-+            sev.sigev_value.sival_ptr = match sigev_notify {
-+                SigevNotify::SigevNone => ptr::null_mut::<libc::c_void>(),
-+                SigevNotify::SigevSignal{ si_value, .. } => si_value as *mut libc::c_void,
-+                #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+                SigevNotify::SigevKevent{ udata, .. } => udata as *mut libc::c_void,
-+                #[cfg(any(target_os = "freebsd", target_os = "linux"))]
-+                SigevNotify::SigevThreadId{ si_value, .. } => si_value as *mut libc::c_void,
-+            };
-+            SigEvent::set_tid(&mut sev, &sigev_notify);
-+            SigEvent{sigevent: sev}
-+        }
-+
-+        #[cfg(any(target_os = "freebsd", target_os = "linux"))]
-+        fn set_tid(sev: &mut libc::sigevent, sigev_notify: &SigevNotify) {
-+            sev.sigev_notify_thread_id = match *sigev_notify {
-+                SigevNotify::SigevThreadId { thread_id, .. } => thread_id,
-+                _ => 0 as type_of_thread_id
-+            };
-+        }
-+
-+        #[cfg(not(any(target_os = "freebsd", target_os = "linux")))]
-+        fn set_tid(_sev: &mut libc::sigevent, _sigev_notify: &SigevNotify) {
-+        }
-+
-+        pub fn sigevent(&self) -> libc::sigevent {
-+            self.sigevent
-+        }
-+    }
-+
-+    impl<'a> From<&'a libc::sigevent> for SigEvent {
-+        fn from(sigevent: &libc::sigevent) -> Self {
-+            SigEvent{ sigevent: *sigevent }
-+        }
-+    }
-+}
-+
-+#[cfg(test)]
-+mod tests {
-+    use std::thread;
-+    use super::*;
-+
-+    #[test]
-+    fn test_contains() {
-+        let mut mask = SigSet::empty();
-+        mask.add(SIGUSR1);
-+
-+        assert!(mask.contains(SIGUSR1));
-+        assert!(!mask.contains(SIGUSR2));
-+
-+        let all = SigSet::all();
-+        assert!(all.contains(SIGUSR1));
-+        assert!(all.contains(SIGUSR2));
-+    }
-+
-+    #[test]
-+    fn test_clear() {
-+        let mut set = SigSet::all();
-+        set.clear();
-+        for signal in Signal::iterator() {
-+            assert!(!set.contains(signal));
-+        }
-+    }
-+
-+    #[test]
-+    fn test_from_str_round_trips() {
-+        for signal in Signal::iterator() {
-+            assert_eq!(signal.as_ref().parse::<Signal>().unwrap(), signal);
-+            assert_eq!(signal.to_string().parse::<Signal>().unwrap(), signal);
-+        }
-+    }
-+
-+    #[test]
-+    fn test_from_str_invalid_value() {
-+        let errval = Err(Error::Sys(Errno::EINVAL));
-+        assert_eq!("NOSIGNAL".parse::<Signal>(), errval);
-+        assert_eq!("kill".parse::<Signal>(), errval);
-+        assert_eq!("9".parse::<Signal>(), errval);
-+    }
-+
-+    #[test]
-+    fn test_extend() {
-+        let mut one_signal = SigSet::empty();
-+        one_signal.add(SIGUSR1);
-+
-+        let mut two_signals = SigSet::empty();
-+        two_signals.add(SIGUSR2);
-+        two_signals.extend(&one_signal);
-+
-+        assert!(two_signals.contains(SIGUSR1));
-+        assert!(two_signals.contains(SIGUSR2));
-+    }
-+
-+    #[test]
-+    fn test_thread_signal_set_mask() {
-+        thread::spawn(|| {
-+            let prev_mask = SigSet::thread_get_mask()
-+                .expect("Failed to get existing signal mask!");
-+
-+            let mut test_mask = prev_mask;
-+            test_mask.add(SIGUSR1);
-+
-+            assert!(test_mask.thread_set_mask().is_ok());
-+            let new_mask = SigSet::thread_get_mask()
-+                .expect("Failed to get new mask!");
-+
-+            assert!(new_mask.contains(SIGUSR1));
-+            assert!(!new_mask.contains(SIGUSR2));
-+
-+            prev_mask.thread_set_mask().expect("Failed to revert signal mask!");
-+        }).join().unwrap();
-+    }
-+
-+    #[test]
-+    fn test_thread_signal_block() {
-+        thread::spawn(|| {
-+            let mut mask = SigSet::empty();
-+            mask.add(SIGUSR1);
-+
-+            assert!(mask.thread_block().is_ok());
-+
-+            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-+        }).join().unwrap();
-+    }
-+
-+    #[test]
-+    fn test_thread_signal_unblock() {
-+        thread::spawn(|| {
-+            let mut mask = SigSet::empty();
-+            mask.add(SIGUSR1);
-+
-+            assert!(mask.thread_unblock().is_ok());
-+
-+            assert!(!SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-+        }).join().unwrap();
-+    }
-+
-+    #[test]
-+    fn test_thread_signal_swap() {
-+        thread::spawn(|| {
-+            let mut mask = SigSet::empty();
-+            mask.add(SIGUSR1);
-+            mask.thread_block().unwrap();
-+
-+            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR1));
-+
-+            let mut mask2 = SigSet::empty();
-+            mask2.add(SIGUSR2);
-+
-+            let oldmask = mask2.thread_swap_mask(SigmaskHow::SIG_SETMASK)
-+                .unwrap();
-+
-+            assert!(oldmask.contains(SIGUSR1));
-+            assert!(!oldmask.contains(SIGUSR2));
-+
-+            assert!(SigSet::thread_get_mask().unwrap().contains(SIGUSR2));
-+        }).join().unwrap();
-+    }
-+
-+    #[test]
-+    fn test_sigaction() {
-+        use libc;
-+        thread::spawn(|| {
-+            extern fn test_sigaction_handler(_: libc::c_int) {}
-+            extern fn test_sigaction_action(_: libc::c_int,
-+                _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
-+
-+            let handler_sig = SigHandler::Handler(test_sigaction_handler);
-+
-+            let flags = SaFlags::SA_ONSTACK | SaFlags::SA_RESTART |
-+                        SaFlags::SA_SIGINFO;
-+
-+            let mut mask = SigSet::empty();
-+            mask.add(SIGUSR1);
-+
-+            let action_sig = SigAction::new(handler_sig, flags, mask);
-+
-+            assert_eq!(action_sig.flags(),
-+                       SaFlags::SA_ONSTACK | SaFlags::SA_RESTART);
-+            assert_eq!(action_sig.handler(), handler_sig);
-+
-+            mask = action_sig.mask();
-+            assert!(mask.contains(SIGUSR1));
-+            assert!(!mask.contains(SIGUSR2));
-+
-+            let handler_act = SigHandler::SigAction(test_sigaction_action);
-+            let action_act = SigAction::new(handler_act, flags, mask);
-+            assert_eq!(action_act.handler(), handler_act);
-+
-+            let action_dfl = SigAction::new(SigHandler::SigDfl, flags, mask);
-+            assert_eq!(action_dfl.handler(), SigHandler::SigDfl);
-+
-+            let action_ign = SigAction::new(SigHandler::SigIgn, flags, mask);
-+            assert_eq!(action_ign.handler(), SigHandler::SigIgn);
-+        }).join().unwrap();
-+    }
-+
-+    #[test]
-+    fn test_sigwait() {
-+        thread::spawn(|| {
-+            let mut mask = SigSet::empty();
-+            mask.add(SIGUSR1);
-+            mask.add(SIGUSR2);
-+            mask.thread_block().unwrap();
-+
-+            raise(SIGUSR1).unwrap();
-+            assert_eq!(mask.wait().unwrap(), SIGUSR1);
-+        }).join().unwrap();
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/signalfd.rs b/third_party/rust/nix-0.15.0/src/sys/signalfd.rs
-new file mode 100644
-index 0000000000000..5425a27be9e52
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/signalfd.rs
-@@ -0,0 +1,170 @@
-+//! Interface for the `signalfd` syscall.
-+//!
-+//! # Signal discarding
-+//! When a signal can't be delivered to a process (or thread), it will become a pending signal.
-+//! Failure to deliver could happen if the signal is blocked by every thread in the process or if
-+//! the signal handler is still handling a previous signal.
-+//!
-+//! If a signal is sent to a process (or thread) that already has a pending signal of the same
-+//! type, it will be discarded. This means that if signals of the same type are received faster than
-+//! they are processed, some of those signals will be dropped. Because of this limitation,
-+//! `signalfd` in itself cannot be used for reliable communication between processes or threads.
-+//!
-+//! Once the signal is unblocked, or the signal handler is finished, and a signal is still pending
-+//! (ie. not consumed from a signalfd) it will be delivered to the signal handler.
-+//!
-+//! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
-+//! signal handlers.
-+use libc;
-+use unistd;
-+use {Error, Result};
-+use errno::Errno;
-+pub use sys::signal::{self, SigSet};
-+pub use libc::signalfd_siginfo as siginfo;
-+
-+use std::os::unix::io::{RawFd, AsRawFd};
-+use std::mem;
-+
-+
-+libc_bitflags!{
-+    pub struct SfdFlags: libc::c_int {
-+        SFD_NONBLOCK;
-+        SFD_CLOEXEC;
-+    }
-+}
-+
-+pub const SIGNALFD_NEW: RawFd = -1;
-+pub const SIGNALFD_SIGINFO_SIZE: usize = 128;
-+
-+/// Creates a new file descriptor for reading signals.
-+///
-+/// **Important:** please read the module level documentation about signal discarding before using
-+/// this function!
-+///
-+/// The `mask` parameter specifies the set of signals that can be accepted via this file descriptor.
-+///
-+/// 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)
-+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()))
-+    }
-+}
-+
-+/// A helper struct for creating, reading and closing a `signalfd` instance.
-+///
-+/// **Important:** please read the module level documentation about signal discarding before using
-+/// this struct!
-+///
-+/// # Examples
-+///
-+/// ```
-+/// # use nix::sys::signalfd::*;
-+/// // Set the thread to block the SIGUSR1 signal, otherwise the default handler will be used
-+/// let mut mask = SigSet::empty();
-+/// mask.add(signal::SIGUSR1);
-+/// mask.thread_block().unwrap();
-+///
-+/// // Signals are queued up on the file descriptor
-+/// let mut sfd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-+///
-+/// match sfd.read_signal() {
-+///     // we caught a signal
-+///     Ok(Some(sig)) => (),
-+///     // there were no signals waiting (only happens when the SFD_NONBLOCK flag is set,
-+///     // otherwise the read_signal call blocks)
-+///     Ok(None) => (),
-+///     Err(err) => (), // some error happend
-+/// }
-+/// ```
-+#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct SignalFd(RawFd);
-+
-+impl SignalFd {
-+    pub fn new(mask: &SigSet) -> Result<SignalFd> {
-+        Self::with_flags(mask, SfdFlags::empty())
-+    }
-+
-+    pub fn with_flags(mask: &SigSet, flags: SfdFlags) -> Result<SignalFd> {
-+        let fd = signalfd(SIGNALFD_NEW, mask, flags)?;
-+
-+        Ok(SignalFd(fd))
-+    }
-+
-+    pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
-+        signalfd(self.0, mask, SfdFlags::empty()).map(drop)
-+    }
-+
-+    pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
-+        let mut buffer: [u8; SIGNALFD_SIGINFO_SIZE] = unsafe { mem::uninitialized() };
-+
-+        match unistd::read(self.0, &mut buffer) {
-+            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer) })),
-+            Ok(_) => unreachable!("partial read on signalfd"),
-+            Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
-+            Err(error) => Err(error)
-+        }
-+    }
-+}
-+
-+impl Drop for SignalFd {
-+    fn drop(&mut self) {
-+        let _ = unistd::close(self.0);
-+    }
-+}
-+
-+impl AsRawFd for SignalFd {
-+    fn as_raw_fd(&self) -> RawFd {
-+        self.0
-+    }
-+}
-+
-+impl Iterator for SignalFd {
-+    type Item = siginfo;
-+
-+    fn next(&mut self) -> Option<Self::Item> {
-+        match self.read_signal() {
-+            Ok(Some(sig)) => Some(sig),
-+            Ok(None) | Err(_) => None,
-+        }
-+    }
-+}
-+
-+
-+#[cfg(test)]
-+mod tests {
-+    use super::*;
-+    use std::mem;
-+    use libc;
-+
-+
-+    #[test]
-+    fn check_siginfo_size() {
-+        assert_eq!(mem::size_of::<libc::signalfd_siginfo>(), SIGNALFD_SIGINFO_SIZE);
-+    }
-+
-+    #[test]
-+    fn create_signalfd() {
-+        let mask = SigSet::empty();
-+        let fd = SignalFd::new(&mask);
-+        assert!(fd.is_ok());
-+    }
-+
-+    #[test]
-+    fn create_signalfd_with_opts() {
-+        let mask = SigSet::empty();
-+        let fd = SignalFd::with_flags(&mask, SfdFlags::SFD_CLOEXEC | SfdFlags::SFD_NONBLOCK);
-+        assert!(fd.is_ok());
-+    }
-+
-+    #[test]
-+    fn read_empty_signalfd() {
-+        let mask = SigSet::empty();
-+        let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
-+
-+        let res = fd.read_signal();
-+        assert!(res.unwrap().is_none());
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs b/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
-new file mode 100644
-index 0000000000000..ed41441155361
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/socket/addr.rs
-@@ -0,0 +1,1278 @@
-+use super::sa_family_t;
-+use {Error, Result, NixPath};
-+use errno::Errno;
-+use libc;
-+use std::{fmt, mem, net, ptr, slice};
-+use std::ffi::OsStr;
-+use std::hash::{Hash, Hasher};
-+use std::path::Path;
-+use std::os::unix::ffi::OsStrExt;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use ::sys::socket::addr::netlink::NetlinkAddr;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use ::sys::socket::addr::alg::AlgAddr;
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+use std::os::unix::io::RawFd;
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+use ::sys::socket::addr::sys_control::SysControlAddr;
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub use self::datalink::LinkAddr;
-+#[cfg(target_os = "linux")]
-+pub use self::vsock::VsockAddr;
-+
-+/// These constants specify the protocol family to be used
-+/// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-+#[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))
-+    Unix = libc::AF_UNIX,
-+    /// IPv4 Internet protocols (see [`ip(7)`](http://man7.org/linux/man-pages/man7/ip.7.html))
-+    Inet = libc::AF_INET,
-+    /// IPv6 Internet protocols (see [`ipv6(7)`](http://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))
-+    #[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"))]
-+    Packet = libc::AF_PACKET,
-+    /// KEXT Controls and Notifications
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-+    System = libc::AF_SYSTEM,
-+    /// Amateur radio AX.25 protocol
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Ax25 = libc::AF_AX25,
-+    /// IPX - Novell protocols
-+    Ipx = libc::AF_IPX,
-+    /// AppleTalk
-+    AppleTalk = libc::AF_APPLETALK,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetRom = libc::AF_NETROM,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Bridge = libc::AF_BRIDGE,
-+    /// 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))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    X25 = libc::AF_X25,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Rose = libc::AF_ROSE,
-+    Decnet = libc::AF_DECnet,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetBeui = libc::AF_NETBEUI,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Security = libc::AF_SECURITY,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Key = libc::AF_KEY,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Ash = libc::AF_ASH,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Econet = libc::AF_ECONET,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    AtmSvc = libc::AF_ATMSVC,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Rds = libc::AF_RDS,
-+    Sna = libc::AF_SNA,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Irda = libc::AF_IRDA,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Pppox = libc::AF_PPPOX,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Wanpipe = libc::AF_WANPIPE,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Llc = libc::AF_LLC,
-+    #[cfg(target_os = "linux")]
-+    Ib = libc::AF_IB,
-+    #[cfg(target_os = "linux")]
-+    Mpls = libc::AF_MPLS,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    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")))]
-+    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,
-+    Isdn = libc::AF_ISDN,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Phonet = libc::AF_PHONET,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Ieee802154 = libc::AF_IEEE802154,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Caif = libc::AF_CAIF,
-+    /// Interface to kernel crypto API
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Alg = libc::AF_ALG,
-+    #[cfg(target_os = "linux")]
-+    Nfc = libc::AF_NFC,
-+    #[cfg(target_os = "linux")]
-+    Vsock = libc::AF_VSOCK,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    ImpLink = libc::AF_IMPLINK,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Pup = libc::AF_PUP,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Chaos = libc::AF_CHAOS,
-+    #[cfg(any(target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Ns = libc::AF_NS,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Iso = libc::AF_ISO,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Datakit = libc::AF_DATAKIT,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Ccitt = libc::AF_CCITT,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Dli = libc::AF_DLI,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Lat = libc::AF_LAT,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Hylink = libc::AF_HYLINK,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Link = libc::AF_LINK,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Coip = libc::AF_COIP,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Cnt = libc::AF_CNT,
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              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))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Unspec = libc::AF_UNSPEC,
-+}
-+
-+impl AddressFamily {
-+    /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
-+    /// the `sa_family` field of a `sockaddr`.
-+    ///
-+    /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
-+    /// and System. Returns None for unsupported or unknown address families.
-+    pub fn from_i32(family: i32) -> Option<AddressFamily> {
-+        match family {
-+            libc::AF_UNIX => Some(AddressFamily::Unix),
-+            libc::AF_INET => Some(AddressFamily::Inet),
-+            libc::AF_INET6 => Some(AddressFamily::Inet6),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            libc::AF_NETLINK => Some(AddressFamily::Netlink),
-+            #[cfg(any(target_os = "macos", target_os = "macos"))]
-+            libc::AF_SYSTEM => Some(AddressFamily::System),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            libc::AF_PACKET => Some(AddressFamily::Packet),
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "ios",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            libc::AF_LINK => Some(AddressFamily::Link),
-+            #[cfg(target_os = "linux")]
-+            libc::AF_VSOCK => Some(AddressFamily::Vsock),
-+            _ => None
-+        }
-+    }
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum InetAddr {
-+    V4(libc::sockaddr_in),
-+    V6(libc::sockaddr_in6),
-+}
-+
-+impl InetAddr {
-+    pub fn from_std(std: &net::SocketAddr) -> InetAddr {
-+        match *std {
-+            net::SocketAddr::V4(ref addr) => {
-+                InetAddr::V4(libc::sockaddr_in {
-+                    sin_family: AddressFamily::Inet as sa_family_t,
-+                    sin_port: addr.port().to_be(),  // network byte order
-+                    sin_addr: Ipv4Addr::from_std(addr.ip()).0,
-+                    .. unsafe { mem::zeroed() }
-+                })
-+            }
-+            net::SocketAddr::V6(ref addr) => {
-+                InetAddr::V6(libc::sockaddr_in6 {
-+                    sin6_family: AddressFamily::Inet6 as sa_family_t,
-+                    sin6_port: addr.port().to_be(),  // network byte order
-+                    sin6_addr: Ipv6Addr::from_std(addr.ip()).0,
-+                    sin6_flowinfo: addr.flowinfo(),  // host byte order
-+                    sin6_scope_id: addr.scope_id(),  // host byte order
-+                    .. unsafe { mem::zeroed() }
-+                })
-+            }
-+        }
-+    }
-+
-+    pub fn new(ip: IpAddr, port: u16) -> InetAddr {
-+        match ip {
-+            IpAddr::V4(ref ip) => {
-+                InetAddr::V4(libc::sockaddr_in {
-+                    sin_family: AddressFamily::Inet as sa_family_t,
-+                    sin_port: port.to_be(),
-+                    sin_addr: ip.0,
-+                    .. unsafe { mem::zeroed() }
-+                })
-+            }
-+            IpAddr::V6(ref ip) => {
-+                InetAddr::V6(libc::sockaddr_in6 {
-+                    sin6_family: AddressFamily::Inet6 as sa_family_t,
-+                    sin6_port: port.to_be(),
-+                    sin6_addr: ip.0,
-+                    .. unsafe { mem::zeroed() }
-+                })
-+            }
-+        }
-+    }
-+    /// Gets the IP address associated with this socket address.
-+    pub fn ip(&self) -> IpAddr {
-+        match *self {
-+            InetAddr::V4(ref sa) => IpAddr::V4(Ipv4Addr(sa.sin_addr)),
-+            InetAddr::V6(ref sa) => IpAddr::V6(Ipv6Addr(sa.sin6_addr)),
-+        }
-+    }
-+
-+    /// Gets the port number associated with this socket address
-+    pub fn port(&self) -> u16 {
-+        match *self {
-+            InetAddr::V6(ref sa) => u16::from_be(sa.sin6_port),
-+            InetAddr::V4(ref sa) => u16::from_be(sa.sin_port),
-+        }
-+    }
-+
-+    pub fn to_std(&self) -> net::SocketAddr {
-+        match *self {
-+            InetAddr::V4(ref sa) => net::SocketAddr::V4(
-+                net::SocketAddrV4::new(
-+                    Ipv4Addr(sa.sin_addr).to_std(),
-+                    self.port())),
-+            InetAddr::V6(ref sa) => net::SocketAddr::V6(
-+                net::SocketAddrV6::new(
-+                    Ipv6Addr(sa.sin6_addr).to_std(),
-+                    self.port(),
-+                    sa.sin6_flowinfo,
-+                    sa.sin6_scope_id)),
-+        }
-+    }
-+
-+    pub fn to_str(&self) -> String {
-+        format!("{}", self)
-+    }
-+}
-+
-+impl fmt::Display for InetAddr {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        match *self {
-+            InetAddr::V4(_) => write!(f, "{}:{}", self.ip(), self.port()),
-+            InetAddr::V6(_) => write!(f, "[{}]:{}", self.ip(), self.port()),
-+        }
-+    }
-+}
-+
-+/*
-+ *
-+ * ===== IpAddr =====
-+ *
-+ */
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum IpAddr {
-+    V4(Ipv4Addr),
-+    V6(Ipv6Addr),
-+}
-+
-+impl IpAddr {
-+    /// Create a new IpAddr that contains an IPv4 address.
-+    ///
-+    /// The result will represent the IP address a.b.c.d
-+    pub fn new_v4(a: u8, b: u8, c: u8, d: u8) -> IpAddr {
-+        IpAddr::V4(Ipv4Addr::new(a, b, c, d))
-+    }
-+
-+    /// Create a new IpAddr that contains an IPv6 address.
-+    ///
-+    /// The result will represent the IP address a:b:c:d:e:f
-+    pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
-+        IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
-+    }
-+
-+    pub fn from_std(std: &net::IpAddr) -> IpAddr {
-+        match *std {
-+            net::IpAddr::V4(ref std) => IpAddr::V4(Ipv4Addr::from_std(std)),
-+            net::IpAddr::V6(ref std) => IpAddr::V6(Ipv6Addr::from_std(std)),
-+        }
-+    }
-+
-+    pub fn to_std(&self) -> net::IpAddr {
-+        match *self {
-+            IpAddr::V4(ref ip) => net::IpAddr::V4(ip.to_std()),
-+            IpAddr::V6(ref ip) => net::IpAddr::V6(ip.to_std()),
-+        }
-+    }
-+}
-+
-+impl fmt::Display for IpAddr {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        match *self {
-+            IpAddr::V4(ref v4) => v4.fmt(f),
-+            IpAddr::V6(ref v6) => v6.fmt(f)
-+        }
-+    }
-+}
-+
-+/*
-+ *
-+ * ===== Ipv4Addr =====
-+ *
-+ */
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct Ipv4Addr(pub libc::in_addr);
-+
-+impl Ipv4Addr {
-+    pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
-+        let ip = (((a as u32) << 24) |
-+                  ((b as u32) << 16) |
-+                  ((c as u32) <<  8) |
-+                  ((d as u32) <<  0)).to_be();
-+
-+        Ipv4Addr(libc::in_addr { s_addr: ip })
-+    }
-+
-+    pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
-+        let bits = std.octets();
-+        Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
-+    }
-+
-+    pub fn any() -> Ipv4Addr {
-+        Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
-+    }
-+
-+    pub fn octets(&self) -> [u8; 4] {
-+        let bits = u32::from_be(self.0.s_addr);
-+        [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
-+    }
-+
-+    pub fn to_std(&self) -> net::Ipv4Addr {
-+        let bits = self.octets();
-+        net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
-+    }
-+}
-+
-+impl fmt::Display for Ipv4Addr {
-+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-+        let octets = self.octets();
-+        write!(fmt, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
-+    }
-+}
-+
-+/*
-+ *
-+ * ===== Ipv6Addr =====
-+ *
-+ */
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct Ipv6Addr(pub libc::in6_addr);
-+
-+// Note that IPv6 addresses are stored in big endian order on all architectures.
-+// See https://tools.ietf.org/html/rfc1700 or consult your favorite search
-+// engine.
-+
-+macro_rules! to_u8_array {
-+    ($($num:ident),*) => {
-+        [ $(($num>>8) as u8, ($num&0xff) as u8,)* ]
-+    }
-+}
-+
-+macro_rules! to_u16_array {
-+    ($slf:ident, $($first:expr, $second:expr),*) => {
-+        [$( (($slf.0.s6_addr[$first] as u16) << 8) + $slf.0.s6_addr[$second] as u16,)*]
-+    }
-+}
-+
-+impl Ipv6Addr {
-+    pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
-+        let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()};
-+        in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h);
-+        Ipv6Addr(in6_addr_var)
-+    }
-+
-+    pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
-+        let s = std.segments();
-+        Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
-+    }
-+
-+    /// Return the eight 16-bit segments that make up this address
-+    pub fn segments(&self) -> [u16; 8] {
-+        to_u16_array!(self, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
-+    }
-+
-+    pub fn to_std(&self) -> net::Ipv6Addr {
-+        let s = self.segments();
-+        net::Ipv6Addr::new(s[0], s[1], s[2], s[3], s[4], s[5], s[6], s[7])
-+    }
-+}
-+
-+impl fmt::Display for Ipv6Addr {
-+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-+        self.to_std().fmt(fmt)
-+    }
-+}
-+
-+/// A wrapper around `sockaddr_un`.
-+///
-+/// This also tracks the length of `sun_path` address (excluding
-+/// a terminating null), because it may not be null-terminated.  For example,
-+/// unconnected and Linux abstract sockets are never null-terminated, and POSIX
-+/// does not require that `sun_len` include the terminating null even for normal
-+/// sockets.  Note that the actual sockaddr length is greater by
-+/// `offset_of!(libc::sockaddr_un, sun_path)`
-+#[derive(Clone, Copy, Debug)]
-+pub struct UnixAddr(pub libc::sockaddr_un, pub usize);
-+
-+impl UnixAddr {
-+    /// Create a new sockaddr_un representing a filesystem path.
-+    pub fn new<P: ?Sized + NixPath>(path: &P) -> Result<UnixAddr> {
-+        path.with_nix_path(|cstr| {
-+            unsafe {
-+                let mut ret = libc::sockaddr_un {
-+                    sun_family: AddressFamily::Unix as sa_family_t,
-+                    .. mem::zeroed()
-+                };
-+
-+                let bytes = cstr.to_bytes();
-+
-+                if bytes.len() > ret.sun_path.len() {
-+                    return Err(Error::Sys(Errno::ENAMETOOLONG));
-+                }
-+
-+                ptr::copy_nonoverlapping(bytes.as_ptr(),
-+                                         ret.sun_path.as_mut_ptr() as *mut u8,
-+                                         bytes.len());
-+
-+                Ok(UnixAddr(ret, bytes.len()))
-+            }
-+        })?
-+    }
-+
-+    /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
-+    ///
-+    /// The leading null byte for the abstract namespace is automatically added;
-+    /// thus the input `path` is expected to be the bare name, not null-prefixed.
-+    /// This is a Linux-specific extension, primarily used to allow chrooted
-+    /// processes to communicate with processes having a different filesystem view.
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
-+        unsafe {
-+            let mut ret = libc::sockaddr_un {
-+                sun_family: AddressFamily::Unix as sa_family_t,
-+                .. mem::zeroed()
-+            };
-+
-+            if path.len() + 1 > ret.sun_path.len() {
-+                return Err(Error::Sys(Errno::ENAMETOOLONG));
-+            }
-+
-+            // Abstract addresses are represented by sun_path[0] ==
-+            // b'\0', so copy starting one byte in.
-+            ptr::copy_nonoverlapping(path.as_ptr(),
-+                                     ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
-+                                     path.len());
-+
-+            Ok(UnixAddr(ret, ret.sun_path.len()))
-+        }
-+    }
-+
-+    fn sun_path(&self) -> &[u8] {
-+        unsafe { slice::from_raw_parts(self.0.sun_path.as_ptr() as *const u8, self.1) }
-+    }
-+
-+    /// If this address represents a filesystem path, return that path.
-+    pub fn path(&self) -> Option<&Path> {
-+        if self.1 == 0 || self.0.sun_path[0] == 0 {
-+            // unnamed or abstract
-+            None
-+        } else {
-+            let p = self.sun_path();
-+            // POSIX only requires that `sun_len` be at least long enough to
-+            // contain the pathname, and it need not be null-terminated.  So we
-+            // need to create a string that is the shorter of the
-+            // null-terminated length or the full length.
-+            let ptr = &self.0.sun_path as *const libc::c_char;
-+            let reallen = unsafe { libc::strnlen(ptr, p.len()) };
-+            Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
-+        }
-+    }
-+
-+    /// If this address represents an abstract socket, return its name.
-+    ///
-+    /// For abstract sockets only the bare name is returned, without the
-+    /// leading null byte. `None` is returned for unnamed or path-backed sockets.
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    pub fn as_abstract(&self) -> Option<&[u8]> {
-+        if self.1 >= 1 && self.0.sun_path[0] == 0 {
-+            Some(&self.sun_path()[1..])
-+        } else {
-+            // unnamed or filesystem path
-+            None
-+        }
-+    }
-+}
-+
-+impl fmt::Display for UnixAddr {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        if self.1 == 0 {
-+            f.write_str("<unbound UNIX socket>")
-+        } else if let Some(path) = self.path() {
-+            path.display().fmt(f)
-+        } else {
-+            let display = String::from_utf8_lossy(&self.sun_path()[1..]);
-+            write!(f, "@{}", display)
-+        }
-+    }
-+}
-+
-+impl PartialEq for UnixAddr {
-+    fn eq(&self, other: &UnixAddr) -> bool {
-+        self.sun_path() == other.sun_path()
-+    }
-+}
-+
-+impl Eq for UnixAddr {}
-+
-+impl Hash for UnixAddr {
-+    fn hash<H: Hasher>(&self, s: &mut H) {
-+        ( self.0.sun_family, self.sun_path() ).hash(s)
-+    }
-+}
-+
-+/// Represents a socket address
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum SockAddr {
-+    Inet(InetAddr),
-+    Unix(UnixAddr),
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Netlink(NetlinkAddr),
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Alg(AlgAddr),
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-+    SysControl(SysControlAddr),
-+    /// Datalink address (MAC)
-+    #[cfg(any(target_os = "android",
-+              target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "linux",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    Link(LinkAddr),
-+    #[cfg(target_os = "linux")]
-+    Vsock(VsockAddr),
-+}
-+
-+impl SockAddr {
-+    pub fn new_inet(addr: InetAddr) -> SockAddr {
-+        SockAddr::Inet(addr)
-+    }
-+
-+    pub fn new_unix<P: ?Sized + NixPath>(path: &P) -> Result<SockAddr> {
-+        Ok(SockAddr::Unix(UnixAddr::new(path)?))
-+    }
-+
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    pub fn new_netlink(pid: u32, groups: u32) -> SockAddr {
-+        SockAddr::Netlink(NetlinkAddr::new(pid, groups))
-+    }
-+
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    pub fn new_alg(alg_type: &str, alg_name: &str) -> SockAddr {
-+        SockAddr::Alg(AlgAddr::new(alg_type, alg_name))
-+    }
-+
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-+    pub fn new_sys_control(sockfd: RawFd, name: &str, unit: u32) -> Result<SockAddr> {
-+        SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
-+    }
-+
-+    #[cfg(target_os = "linux")]
-+    pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
-+        SockAddr::Vsock(VsockAddr::new(cid, port))
-+    }
-+
-+    pub fn family(&self) -> AddressFamily {
-+        match *self {
-+            SockAddr::Inet(InetAddr::V4(..)) => AddressFamily::Inet,
-+            SockAddr::Inet(InetAddr::V6(..)) => AddressFamily::Inet6,
-+            SockAddr::Unix(..) => AddressFamily::Unix,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Netlink(..) => AddressFamily::Netlink,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Alg(..) => AddressFamily::Alg,
-+            #[cfg(any(target_os = "ios", target_os = "macos"))]
-+            SockAddr::SysControl(..) => AddressFamily::System,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Link(..) => AddressFamily::Packet,
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "ios",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            SockAddr::Link(..) => AddressFamily::Link,
-+            #[cfg(target_os = "linux")]
-+            SockAddr::Vsock(..) => AddressFamily::Vsock,
-+        }
-+    }
-+
-+    pub fn to_str(&self) -> String {
-+        format!("{}", self)
-+    }
-+
-+    /// Creates a `SockAddr` struct from libc's sockaddr.
-+    ///
-+    /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
-+    /// Returns None for unsupported families.
-+    pub unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
-+        if addr.is_null() {
-+            None
-+        } else {
-+            match AddressFamily::from_i32((*addr).sa_family as i32) {
-+                Some(AddressFamily::Unix) => None,
-+                Some(AddressFamily::Inet) => Some(SockAddr::Inet(
-+                    InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
-+                Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
-+                    InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
-+                #[cfg(any(target_os = "android", target_os = "linux"))]
-+                Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
-+                    NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
-+                #[cfg(any(target_os = "ios", target_os = "macos"))]
-+                Some(AddressFamily::System) => Some(SockAddr::SysControl(
-+                    SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
-+                #[cfg(any(target_os = "android", target_os = "linux"))]
-+                Some(AddressFamily::Packet) => Some(SockAddr::Link(
-+                    LinkAddr(*(addr as *const libc::sockaddr_ll)))),
-+                #[cfg(any(target_os = "dragonfly",
-+                          target_os = "freebsd",
-+                          target_os = "ios",
-+                          target_os = "macos",
-+                          target_os = "netbsd",
-+                          target_os = "openbsd"))]
-+                Some(AddressFamily::Link) => {
-+                    let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
-+                    if ether_addr.is_empty() {
-+                        None
-+                    } else {
-+                        Some(SockAddr::Link(ether_addr))
-+                    }
-+                },
-+                #[cfg(target_os = "linux")]
-+                Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
-+                    VsockAddr(*(addr as *const libc::sockaddr_vm)))),
-+                // Other address families are currently not supported and simply yield a None
-+                // entry instead of a proper conversion to a `SockAddr`.
-+                Some(_) | None => None,
-+            }
-+        }
-+    }
-+
-+    /// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
-+    ///
-+    /// This is useful for interfacing with other libc functions that don't yet have nix wrappers.
-+    /// Returns a reference to the underlying data type (as a sockaddr reference) along
-+    /// with the size of the actual data type. sockaddr is commonly used as a proxy for
-+    /// a superclass as C doesn't support inheritance, so many functions that take
-+    /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
-+    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
-+        match *self {
-+            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
-+            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
-+            SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Alg(AlgAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t),
-+            #[cfg(any(target_os = "ios", target_os = "macos"))]
-+            SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t),
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "ios",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t),
-+            #[cfg(target_os = "linux")]
-+            SockAddr::Vsock(VsockAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t),
-+        }
-+    }
-+}
-+
-+impl fmt::Display for SockAddr {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        match *self {
-+            SockAddr::Inet(ref inet) => inet.fmt(f),
-+            SockAddr::Unix(ref unix) => unix.fmt(f),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Netlink(ref nl) => nl.fmt(f),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Alg(ref nl) => nl.fmt(f),
-+            #[cfg(any(target_os = "ios", target_os = "macos"))]
-+            SockAddr::SysControl(ref sc) => sc.fmt(f),
-+            #[cfg(any(target_os = "android",
-+                      target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "ios",
-+                      target_os = "linux",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
-+            #[cfg(target_os = "linux")]
-+            SockAddr::Vsock(ref svm) => svm.fmt(f),
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod netlink {
-+    use ::sys::socket::addr::AddressFamily;
-+    use libc::{sa_family_t, sockaddr_nl};
-+    use std::{fmt, mem};
-+
-+    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+    pub struct NetlinkAddr(pub sockaddr_nl);
-+
-+    impl NetlinkAddr {
-+        pub fn new(pid: u32, groups: u32) -> NetlinkAddr {
-+            let mut addr: sockaddr_nl = unsafe { mem::zeroed() };
-+            addr.nl_family = AddressFamily::Netlink as sa_family_t;
-+            addr.nl_pid = pid;
-+            addr.nl_groups = groups;
-+
-+            NetlinkAddr(addr)
-+        }
-+
-+        pub fn pid(&self) -> u32 {
-+            self.0.nl_pid
-+        }
-+
-+        pub fn groups(&self) -> u32 {
-+            self.0.nl_groups
-+        }
-+    }
-+
-+    impl fmt::Display for NetlinkAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            write!(f, "pid: {} groups: {}", self.pid(), self.groups())
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub mod alg {
-+    use libc::{AF_ALG, sockaddr_alg, c_char};
-+    use std::{fmt, mem, str};
-+    use std::hash::{Hash, Hasher};
-+    use std::ffi::CStr;
-+
-+    #[derive(Copy, Clone)]
-+    pub struct AlgAddr(pub sockaddr_alg);
-+
-+    // , PartialEq, Eq, Debug, Hash
-+    impl PartialEq for AlgAddr {
-+        fn eq(&self, other: &Self) -> bool {
-+            let (inner, other) = (self.0, other.0);
-+            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]) ==
-+            (other.salg_family, &other.salg_type[..], other.salg_feat, other.salg_mask, &other.salg_name[..])
-+        }
-+    }
-+
-+    impl Eq for AlgAddr {}
-+
-+    impl Hash for AlgAddr {
-+        fn hash<H: Hasher>(&self, s: &mut H) {
-+            let inner = self.0;
-+            (inner.salg_family, &inner.salg_type[..], inner.salg_feat, inner.salg_mask, &inner.salg_name[..]).hash(s);
-+        }
-+    }
-+
-+    impl AlgAddr {
-+        pub fn new(alg_type: &str, alg_name: &str) -> AlgAddr {
-+            let mut addr: sockaddr_alg = unsafe { mem::zeroed() };
-+            addr.salg_family = AF_ALG as u16;
-+            addr.salg_type[..alg_type.len()].copy_from_slice(alg_type.to_string().as_bytes());
-+            addr.salg_name[..alg_name.len()].copy_from_slice(alg_name.to_string().as_bytes());
-+
-+            AlgAddr(addr)
-+        }
-+
-+
-+        pub fn alg_type(&self) -> &CStr {
-+            unsafe { CStr::from_ptr(self.0.salg_type.as_ptr() as *const c_char) }
-+        }
-+
-+        pub fn alg_name(&self) -> &CStr {
-+            unsafe { CStr::from_ptr(self.0.salg_name.as_ptr() as *const c_char) }
-+        }
-+    }
-+
-+    impl fmt::Display for AlgAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            write!(f, "type: {} alg: {}",
-+                   self.alg_name().to_string_lossy(),
-+                   self.alg_type().to_string_lossy())
-+        }
-+    }
-+
-+    impl fmt::Debug for AlgAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            fmt::Display::fmt(self, f)
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+pub mod sys_control {
-+    use ::sys::socket::addr::AddressFamily;
-+    use libc::{self, c_uchar};
-+    use std::{fmt, mem};
-+    use std::os::unix::io::RawFd;
-+    use {Errno, Error, Result};
-+
-+    // FIXME: Move type into `libc`
-+    #[repr(C)]
-+    #[derive(Clone, Copy)]
-+    #[allow(missing_debug_implementations)]
-+    pub struct ctl_ioc_info {
-+        pub ctl_id: u32,
-+        pub ctl_name: [c_uchar; MAX_KCTL_NAME],
-+    }
-+
-+    const CTL_IOC_MAGIC: u8 = 'N' as u8;
-+    const CTL_IOC_INFO: u8 = 3;
-+    const MAX_KCTL_NAME: usize = 96;
-+
-+    ioctl_readwrite!(ctl_info, CTL_IOC_MAGIC, CTL_IOC_INFO, ctl_ioc_info);
-+
-+    #[repr(C)]
-+    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+    pub struct SysControlAddr(pub libc::sockaddr_ctl);
-+
-+    impl SysControlAddr {
-+        pub fn new(id: u32, unit: u32) -> SysControlAddr {
-+            let addr = libc::sockaddr_ctl {
-+                sc_len: mem::size_of::<libc::sockaddr_ctl>() as c_uchar,
-+                sc_family: AddressFamily::System as c_uchar,
-+                ss_sysaddr: libc::AF_SYS_CONTROL as u16,
-+                sc_id: id,
-+                sc_unit: unit,
-+                sc_reserved: [0; 5]
-+            };
-+
-+            SysControlAddr(addr)
-+        }
-+
-+        pub fn from_name(sockfd: RawFd, name: &str, unit: u32) -> Result<SysControlAddr> {
-+            if name.len() > MAX_KCTL_NAME {
-+                return Err(Error::Sys(Errno::ENAMETOOLONG));
-+            }
-+
-+            let mut ctl_name = [0; MAX_KCTL_NAME];
-+            ctl_name[..name.len()].clone_from_slice(name.as_bytes());
-+            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
-+
-+            unsafe { ctl_info(sockfd, &mut info)?; }
-+
-+            Ok(SysControlAddr::new(info.ctl_id, unit))
-+        }
-+
-+        pub fn id(&self) -> u32 {
-+            self.0.sc_id
-+        }
-+
-+        pub fn unit(&self) -> u32 {
-+            self.0.sc_unit
-+        }
-+    }
-+
-+    impl fmt::Display for SysControlAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            fmt::Debug::fmt(self, f)
-+        }
-+    }
-+}
-+
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod datalink {
-+    use super::{libc, fmt, AddressFamily};
-+
-+    /// Hardware Address
-+    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+    pub struct LinkAddr(pub libc::sockaddr_ll);
-+
-+    impl LinkAddr {
-+        /// Always AF_PACKET
-+        pub fn family(&self) -> AddressFamily {
-+            assert_eq!(self.0.sll_family as i32, libc::AF_PACKET);
-+            AddressFamily::Packet
-+        }
-+
-+        /// Physical-layer protocol
-+        pub fn protocol(&self) -> u16 {
-+            self.0.sll_protocol
-+        }
-+
-+        /// Interface number
-+        pub fn ifindex(&self) -> usize {
-+            self.0.sll_ifindex as usize
-+        }
-+
-+        /// ARP hardware type
-+        pub fn hatype(&self) -> u16 {
-+            self.0.sll_hatype
-+        }
-+
-+        /// Packet type
-+        pub fn pkttype(&self) -> u8 {
-+            self.0.sll_pkttype
-+        }
-+
-+        /// Length of MAC address
-+        pub fn halen(&self) -> usize {
-+            self.0.sll_halen as usize
-+        }
-+
-+        /// Physical-layer address (MAC)
-+        pub fn addr(&self) -> [u8; 6] {
-+            let a = self.0.sll_addr[0] as u8;
-+            let b = self.0.sll_addr[1] as u8;
-+            let c = self.0.sll_addr[2] as u8;
-+            let d = self.0.sll_addr[3] as u8;
-+            let e = self.0.sll_addr[4] as u8;
-+            let f = self.0.sll_addr[5] as u8;
-+
-+            [a, b, c, d, e, f]
-+        }
-+    }
-+
-+    impl fmt::Display for LinkAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            let addr = self.addr();
-+            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
-+                addr[0],
-+                addr[1],
-+                addr[2],
-+                addr[3],
-+                addr[4],
-+                addr[5])
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+mod datalink {
-+    use super::{libc, fmt, AddressFamily};
-+
-+    /// Hardware Address
-+    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+    pub struct LinkAddr(pub libc::sockaddr_dl);
-+
-+    impl LinkAddr {
-+        /// Total length of sockaddr
-+        pub fn len(&self) -> usize {
-+            self.0.sdl_len as usize
-+        }
-+
-+        /// always == AF_LINK
-+        pub fn family(&self) -> AddressFamily {
-+            assert_eq!(self.0.sdl_family as i32, libc::AF_LINK);
-+            AddressFamily::Link
-+        }
-+
-+        /// interface index, if != 0, system given index for interface
-+        pub fn ifindex(&self) -> usize {
-+            self.0.sdl_index as usize
-+        }
-+
-+        /// Datalink type
-+        pub fn datalink_type(&self) -> u8 {
-+            self.0.sdl_type
-+        }
-+
-+        // MAC address start position
-+        pub fn nlen(&self) -> usize {
-+            self.0.sdl_nlen as usize
-+        }
-+
-+        /// link level address length
-+        pub fn alen(&self) -> usize {
-+            self.0.sdl_alen as usize
-+        }
-+
-+        /// link layer selector length
-+        pub fn slen(&self) -> usize {
-+            self.0.sdl_slen as usize
-+        }
-+
-+        /// if link level address length == 0,
-+        /// or `sdl_data` not be larger.
-+        pub fn is_empty(&self) -> bool {
-+            let nlen = self.nlen();
-+            let alen = self.alen();
-+            let data_len = self.0.sdl_data.len();
-+
-+            if alen > 0 && nlen + alen < data_len {
-+                false
-+            } else {
-+                true
-+            }
-+        }
-+
-+        /// Physical-layer address (MAC)
-+        pub fn addr(&self) -> [u8; 6] {
-+            let nlen = self.nlen();
-+            let data = self.0.sdl_data;
-+
-+            assert!(!self.is_empty());
-+
-+            let a = data[nlen] as u8;
-+            let b = data[nlen + 1] as u8;
-+            let c = data[nlen + 2] as u8;
-+            let d = data[nlen + 3] as u8;
-+            let e = data[nlen + 4] as u8;
-+            let f = data[nlen + 5] as u8;
-+
-+            [a, b, c, d, e, f]
-+        }
-+    }
-+
-+    impl fmt::Display for LinkAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            let addr = self.addr();
-+            write!(f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
-+                addr[0],
-+                addr[1],
-+                addr[2],
-+                addr[3],
-+                addr[4],
-+                addr[5])
-+        }
-+    }
-+}
-+
-+#[cfg(target_os = "linux")]
-+pub mod vsock {
-+    use ::sys::socket::addr::AddressFamily;
-+    use libc::{sa_family_t, sockaddr_vm};
-+    use std::{fmt, mem};
-+    use std::hash::{Hash, Hasher};
-+
-+    #[derive(Copy, Clone)]
-+    pub struct VsockAddr(pub sockaddr_vm);
-+
-+    impl PartialEq for VsockAddr {
-+        fn eq(&self, other: &Self) -> bool {
-+            let (inner, other) = (self.0, other.0);
-+            (inner.svm_family, inner.svm_cid, inner.svm_port) ==
-+            (other.svm_family, other.svm_cid, other.svm_port)
-+        }
-+    }
-+
-+    impl Eq for VsockAddr {}
-+
-+    impl Hash for VsockAddr {
-+        fn hash<H: Hasher>(&self, s: &mut H) {
-+            let inner = self.0;
-+            (inner.svm_family, inner.svm_cid, inner.svm_port).hash(s);
-+        }
-+    }
-+
-+    /// VSOCK Address
-+    ///
-+    /// The address for AF_VSOCK socket is defined as a combination of a
-+    /// 32-bit Context Identifier (CID) and a 32-bit port number.
-+    impl VsockAddr {
-+        pub fn new(cid: u32, port: u32) -> VsockAddr {
-+            let mut addr: sockaddr_vm = unsafe { mem::zeroed() };
-+            addr.svm_family = AddressFamily::Vsock as sa_family_t;
-+            addr.svm_cid = cid;
-+            addr.svm_port = port;
-+
-+            VsockAddr(addr)
-+        }
-+
-+        /// Context Identifier (CID)
-+        pub fn cid(&self) -> u32 {
-+            self.0.svm_cid
-+        }
-+
-+        /// Port number
-+        pub fn port(&self) -> u32 {
-+            self.0.svm_port
-+        }
-+    }
-+
-+    impl fmt::Display for VsockAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            write!(f, "cid: {} port: {}", self.cid(), self.port())
-+        }
-+    }
-+
-+    impl fmt::Debug for VsockAddr {
-+        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+            fmt::Display::fmt(self, f)
-+        }
-+    }
-+}
-+
-+#[cfg(test)]
-+mod tests {
-+    #[cfg(any(target_os = "android",
-+              target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "linux",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    use super::*;
-+
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    #[test]
-+    fn test_macos_loopback_datalink_addr() {
-+        let bytes = [20i8, 18, 1, 0, 24, 3, 0, 0, 108, 111, 48, 0, 0, 0, 0, 0];
-+        let sa = bytes.as_ptr() as *const libc::sockaddr;
-+        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
-+        assert!(_sock_addr.is_none());
-+    }
-+
-+    #[cfg(any(target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "openbsd"))]
-+    #[test]
-+    fn test_macos_tap_datalink_addr() {
-+        let bytes = [20i8, 18, 7, 0, 6, 3, 6, 0, 101, 110, 48, 24, 101, -112, -35, 76, -80];
-+        let ptr = bytes.as_ptr();
-+        let sa = ptr as *const libc::sockaddr;
-+        let _sock_addr = unsafe { SockAddr::from_libc_sockaddr(sa) };
-+
-+        assert!(_sock_addr.is_some());
-+
-+        let sock_addr = _sock_addr.unwrap();
-+
-+        assert_eq!(sock_addr.family(), AddressFamily::Link);
-+
-+        match sock_addr {
-+            SockAddr::Link(ether_addr) => {
-+                assert_eq!(ether_addr.addr(), [24u8, 101, 144, 221, 76, 176]);
-+            },
-+            _ => { unreachable!() }
-+        };
-+    }
-+
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    #[test]
-+    fn test_abstract_sun_path() {
-+        let name = String::from("nix\0abstract\0test");
-+        let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-+
-+        let sun_path1 = addr.sun_path();
-+        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-+        assert_eq!(sun_path1.len(), sun_path2.len());
-+        for i in 0..sun_path1.len() {
-+            assert_eq!(sun_path1[i], sun_path2[i]);
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs b/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
-new file mode 100644
-index 0000000000000..1c12c5f851734
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/socket/mod.rs
-@@ -0,0 +1,1294 @@
-+//! Socket interface functions
-+//!
-+//! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
-+use {Error, Result};
-+use errno::Errno;
-+use libc::{self, c_void, c_int, iovec, socklen_t, size_t,
-+        CMSG_FIRSTHDR, CMSG_NXTHDR, CMSG_DATA, CMSG_LEN};
-+use std::{mem, ptr, slice};
-+use std::os::unix::io::RawFd;
-+use sys::time::TimeVal;
-+use sys::uio::IoVec;
-+
-+mod addr;
-+pub mod sockopt;
-+
-+/*
-+ *
-+ * ===== Re-exports =====
-+ *
-+ */
-+
-+pub use self::addr::{
-+    AddressFamily,
-+    SockAddr,
-+    InetAddr,
-+    UnixAddr,
-+    IpAddr,
-+    Ipv4Addr,
-+    Ipv6Addr,
-+    LinkAddr,
-+};
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use ::sys::socket::addr::netlink::NetlinkAddr;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use sys::socket::addr::alg::AlgAddr;
-+#[cfg(target_os = "linux")]
-+pub use sys::socket::addr::vsock::VsockAddr;
-+
-+pub use libc::{
-+    cmsghdr,
-+    msghdr,
-+    sa_family_t,
-+    sockaddr,
-+    sockaddr_in,
-+    sockaddr_in6,
-+    sockaddr_storage,
-+    sockaddr_un,
-+};
-+
-+// Needed by the cmsg_space macro
-+#[doc(hidden)]
-+pub use libc::{c_uint, CMSG_SPACE};
-+
-+/// These constants are used to specify the communication semantics
-+/// when creating a socket with [`socket()`](fn.socket.html)
-+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-+#[repr(i32)]
-+pub enum SockType {
-+    /// Provides sequenced, reliable, two-way, connection-
-+    /// based byte streams.  An out-of-band data transmission
-+    /// mechanism may be supported.
-+    Stream = libc::SOCK_STREAM,
-+    /// Supports datagrams (connectionless, unreliable
-+    /// messages of a fixed maximum length).
-+    Datagram = libc::SOCK_DGRAM,
-+    /// Provides a sequenced, reliable, two-way connection-
-+    /// based data transmission path for datagrams of fixed
-+    /// maximum length; a consumer is required to read an
-+    /// entire packet with each input system call.
-+    SeqPacket = libc::SOCK_SEQPACKET,
-+    /// Provides raw network protocol access.
-+    Raw = libc::SOCK_RAW,
-+    /// Provides a reliable datagram layer that does not
-+    /// guarantee ordering.
-+    Rdm = libc::SOCK_RDM,
-+}
-+
-+/// Constants used in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
-+/// to specify the protocol to use.
-+#[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 = libc::IPPROTO_TCP,
-+    /// UDP protocol ([ip(7)](http://man7.org/linux/man-pages/man7/ip.7.html))
-+    Udp = libc::IPPROTO_UDP,
-+    /// Allows applications and other KEXTs to be notified when certain kernel events occur
-+    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-+    KextEvent = libc::SYSPROTO_EVENT,
-+    /// Allows applications to configure and control a KEXT
-+    /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-+    KextControl = libc::SYSPROTO_CONTROL,
-+}
-+
-+libc_bitflags!{
-+    /// Additional socket options
-+    pub struct SockFlag: c_int {
-+        /// Set non-blocking mode on the new socket
-+        #[cfg(any(target_os = "android",
-+                  target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        SOCK_NONBLOCK;
-+        /// Set close-on-exec on the new descriptor
-+        #[cfg(any(target_os = "android",
-+                  target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        SOCK_CLOEXEC;
-+        /// Return `EPIPE` instead of raising `SIGPIPE`
-+        #[cfg(target_os = "netbsd")]
-+        SOCK_NOSIGPIPE;
-+        /// For domains `AF_INET(6)`, only allow `connect(2)`, `sendto(2)`, or `sendmsg(2)`
-+        /// to the DNS port (typically 53)
-+        #[cfg(target_os = "openbsd")]
-+        SOCK_DNS;
-+    }
-+}
-+
-+libc_bitflags!{
-+    /// Flags for send/recv and their relatives
-+    pub struct MsgFlags: c_int {
-+        /// Sends or requests out-of-band data on sockets that support this notion
-+        /// (e.g., of type [`Stream`](enum.SockType.html)); the underlying protocol must also
-+        /// support out-of-band data.
-+        MSG_OOB;
-+        /// Peeks at an incoming message. The data is treated as unread and the next
-+        /// [`recv()`](fn.recv.html)
-+        /// or similar function shall still return this data.
-+        MSG_PEEK;
-+        /// Receive operation blocks until the full amount of data can be
-+        /// returned. The function may return smaller amount of data if a signal
-+        /// is caught, an error or disconnect occurs.
-+        MSG_WAITALL;
-+        /// Enables nonblocking operation; if the operation would block,
-+        /// `EAGAIN` or `EWOULDBLOCK` is returned.  This provides similar
-+        /// behavior to setting the `O_NONBLOCK` flag
-+        /// (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)),
-+        /// 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.
-+        MSG_DONTWAIT;
-+        /// Receive flags: Control Data was discarded (buffer too small)
-+        MSG_CTRUNC;
-+        /// For raw ([`Packet`](addr/enum.AddressFamily.html)), Internet datagram
-+        /// (since Linux 2.4.27/2.6.8),
-+        /// netlink (since Linux 2.6.22) and UNIX datagram (since Linux 3.4)
-+        /// sockets: return the real length of the packet or datagram, even
-+        /// when it was longer than the passed buffer. Not implemented for UNIX
-+        /// domain ([unix(7)](https://linux.die.net/man/7/unix)) sockets.
-+        ///
-+        /// For use with Internet stream sockets, see [tcp(7)](https://linux.die.net/man/7/tcp).
-+        MSG_TRUNC;
-+        /// Terminates a record (when this notion is supported, as for
-+        /// sockets of type [`SeqPacket`](enum.SockType.html)).
-+        MSG_EOR;
-+        /// This flag specifies that queued errors should be received from
-+        /// the socket error queue. (For more details, see
-+        /// [recvfrom(2)](https://linux.die.net/man/2/recvfrom))
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        MSG_ERRQUEUE;
-+        /// Set the `close-on-exec` flag for the file descriptor received via a UNIX domain
-+        /// 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).
-+        ///
-+        /// Only used in [`recvmsg`](fn.recvmsg.html) function.
-+        #[cfg(any(target_os = "android",
-+                  target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        MSG_CMSG_CLOEXEC;
-+    }
-+}
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        /// Unix credentials of the sending process.
-+        ///
-+        /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
-+        #[repr(C)]
-+        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+        pub struct UnixCredentials(libc::ucred);
-+
-+        impl UnixCredentials {
-+            /// Returns the process identifier
-+            pub fn pid(&self) -> libc::pid_t {
-+                self.0.pid
-+            }
-+
-+            /// Returns the user identifier
-+            pub fn uid(&self) -> libc::uid_t {
-+                self.0.uid
-+            }
-+
-+            /// Returns the group identifier
-+            pub fn gid(&self) -> libc::gid_t {
-+                self.0.gid
-+            }
-+        }
-+
-+        impl From<libc::ucred> for UnixCredentials {
-+            fn from(cred: libc::ucred) -> Self {
-+                UnixCredentials(cred)
-+            }
-+        }
-+
-+        impl Into<libc::ucred> for UnixCredentials {
-+            fn into(self) -> libc::ucred {
-+                self.0
-+            }
-+        }
-+    }
-+}
-+
-+/// Request for multicast socket operations
-+///
-+/// This is a wrapper type around `ip_mreq`.
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub struct IpMembershipRequest(libc::ip_mreq);
-+
-+impl IpMembershipRequest {
-+    /// Instantiate a new `IpMembershipRequest`
-+    ///
-+    /// If `interface` is `None`, then `Ipv4Addr::any()` will be used for the interface.
-+    pub fn new(group: Ipv4Addr, interface: Option<Ipv4Addr>) -> Self {
-+        IpMembershipRequest(libc::ip_mreq {
-+            imr_multiaddr: group.0,
-+            imr_interface: interface.unwrap_or_else(Ipv4Addr::any).0,
-+        })
-+    }
-+}
-+
-+/// Request for ipv6 multicast socket operations
-+///
-+/// This is a wrapper type around `ipv6_mreq`.
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
-+
-+impl Ipv6MembershipRequest {
-+    /// Instantiate a new `Ipv6MembershipRequest`
-+    pub fn new(group: Ipv6Addr) -> Self {
-+        Ipv6MembershipRequest(libc::ipv6_mreq {
-+            ipv6mr_multiaddr: group.0,
-+            ipv6mr_interface: 0,
-+        })
-+    }
-+}
-+
-+cfg_if! {
-+    // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
-+    if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
-+        type align_of_cmsg_data = u32;
-+    } else {
-+        type align_of_cmsg_data = size_t;
-+    }
-+}
-+
-+/// A type that can be used to store ancillary data received by
-+/// [`recvmsg`](fn.recvmsg.html)
-+pub trait CmsgBuffer {
-+    fn as_bytes_mut(&mut self) -> &mut [u8];
-+}
-+
-+/// Create a buffer large enough for storing some control messages as returned
-+/// by [`recvmsg`](fn.recvmsg.html).
-+///
-+/// # Examples
-+///
-+/// ```
-+/// # #[macro_use] extern crate nix;
-+/// # use nix::sys::time::TimeVal;
-+/// # use std::os::unix::io::RawFd;
-+/// # fn main() {
-+/// // Create a buffer for a `ControlMessageOwned::ScmTimestamp` message
-+/// let _ = cmsg_space!(TimeVal);
-+/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-+/// // with two file descriptors
-+/// let _ = cmsg_space!([RawFd; 2]);
-+/// // Create a buffer big enough for a `ControlMessageOwned::ScmRights` message
-+/// // and a `ControlMessageOwned::ScmTimestamp` message
-+/// let _ = cmsg_space!(RawFd, TimeVal);
-+/// # }
-+/// ```
-+// Unfortunately, CMSG_SPACE isn't a const_fn, or else we could return a
-+// stack-allocated array.
-+#[macro_export]
-+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)
-+                } as usize;
-+            )*
-+            let mut v = Vec::<u8>::with_capacity(space);
-+            // safe because any bit pattern is a valid u8
-+            unsafe {v.set_len(space)};
-+            v
-+        }
-+    }
-+}
-+
-+/// A structure used to make room in a cmsghdr passed to recvmsg. The
-+/// size and alignment match that of a cmsghdr followed by a T, but the
-+/// fields are not accessible, as the actual types will change on a call
-+/// to recvmsg.
-+///
-+/// To make room for multiple messages, nest the type parameter with
-+/// tuples:
-+///
-+/// ```
-+/// use std::os::unix::io::RawFd;
-+/// use nix::sys::socket::CmsgSpace;
-+/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
-+/// ```
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub struct CmsgSpace<T> {
-+    _hdr: cmsghdr,
-+    _pad: [align_of_cmsg_data; 0],
-+    _data: T,
-+}
-+
-+impl<T> CmsgSpace<T> {
-+    /// Create a CmsgSpace<T>. The structure is used only for space, so
-+    /// the fields are uninitialized.
-+    #[deprecated( since="0.14.0", note="Use the cmsg_space! macro instead")]
-+    pub fn new() -> Self {
-+        // Safe because the fields themselves aren't accessible.
-+        unsafe { mem::uninitialized() }
-+    }
-+}
-+
-+impl<T> CmsgBuffer for CmsgSpace<T> {
-+    fn as_bytes_mut(&mut self) -> &mut [u8] {
-+        // Safe because nothing ever attempts to access CmsgSpace's fields
-+        unsafe {
-+            slice::from_raw_parts_mut(self as *mut CmsgSpace<T> as *mut u8,
-+                                      mem::size_of::<Self>())
-+        }
-+    }
-+}
-+
-+impl CmsgBuffer for Vec<u8> {
-+    fn as_bytes_mut(&mut self) -> &mut [u8] {
-+        &mut self[..]
-+    }
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub struct RecvMsg<'a> {
-+    pub bytes: usize,
-+    cmsghdr: Option<&'a cmsghdr>,
-+    pub address: Option<SockAddr>,
-+    pub flags: MsgFlags,
-+    mhdr: msghdr,
-+}
-+
-+impl<'a> RecvMsg<'a> {
-+    /// Iterate over the valid control messages pointed to by this
-+    /// msghdr.
-+    pub fn cmsgs(&self) -> CmsgIterator {
-+        CmsgIterator {
-+            cmsghdr: self.cmsghdr,
-+            mhdr: &self.mhdr
-+        }
-+    }
-+}
-+
-+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+pub struct CmsgIterator<'a> {
-+    /// Control message buffer to decode from. Must adhere to cmsg alignment.
-+    cmsghdr: Option<&'a cmsghdr>,
-+    mhdr: &'a msghdr
-+}
-+
-+impl<'a> Iterator for CmsgIterator<'a> {
-+    type Item = ControlMessageOwned;
-+
-+    fn next(&mut self) -> Option<ControlMessageOwned> {
-+        match self.cmsghdr {
-+            None => None,   // No more messages
-+            Some(hdr) => {
-+                // Get the data.
-+                // Safe if cmsghdr points to valid data returned by recvmsg(2)
-+                let cm = unsafe { Some(ControlMessageOwned::decode_from(hdr))};
-+                // Advance the internal pointer.  Safe if mhdr and cmsghdr point
-+                // to valid data returned by recvmsg(2)
-+                self.cmsghdr = unsafe {
-+                    let p = CMSG_NXTHDR(self.mhdr as *const _, hdr as *const _);
-+                    p.as_ref()
-+                };
-+                cm
-+            }
-+        }
-+    }
-+}
-+
-+/// 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)
-+//  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
-+//  alignment issues.
-+//
-+//  See https://github.com/nix-rust/nix/issues/999
-+#[derive(Clone, Debug, Eq, PartialEq)]
-+pub enum ControlMessageOwned {
-+    /// Received version of
-+    /// [`ControlMessage::ScmRights`][#enum.ControlMessage.html#variant.ScmRights]
-+    ScmRights(Vec<RawFd>),
-+    /// Received version of
-+    /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    ScmCredentials(libc::ucred),
-+    /// A message of type `SCM_TIMESTAMP`, containing the time the
-+    /// packet was received by the kernel.
-+    ///
-+    /// See the kernel's explanation in "SO_TIMESTAMP" of
-+    /// [networking/timestamping](https://www.kernel.org/doc/Documentation/networking/timestamping.txt).
-+    ///
-+    /// # Examples
-+    ///
-+    // Disable this test on FreeBSD i386
-+    // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
-+    #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
-+    #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
-+    /// # #[macro_use] extern crate nix;
-+    /// # use nix::sys::socket::*;
-+    /// # use nix::sys::uio::IoVec;
-+    /// # use nix::sys::time::*;
-+    /// # use std::time::*;
-+    /// # fn main() {
-+    /// // Set up
-+    /// let message = "Ohayō!".as_bytes();
-+    /// let in_socket = socket(
-+    ///     AddressFamily::Inet,
-+    ///     SockType::Datagram,
-+    ///     SockFlag::empty(),
-+    ///     None).unwrap();
-+    /// setsockopt(in_socket, sockopt::ReceiveTimestamp, &true).unwrap();
-+    /// let localhost = InetAddr::new(IpAddr::new_v4(127, 0, 0, 1), 0);
-+    /// bind(in_socket, &SockAddr::new_inet(localhost)).unwrap();
-+    /// let address = getsockname(in_socket).unwrap();
-+    /// // Get initial time
-+    /// let time0 = SystemTime::now();
-+    /// // Send the message
-+    /// let iov = [IoVec::from_slice(message)];
-+    /// let flags = MsgFlags::empty();
-+    /// let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
-+    /// assert_eq!(message.len(), l);
-+    /// // Receive the message
-+    /// let mut buffer = vec![0u8; message.len()];
-+    /// let mut cmsgspace = cmsg_space!(TimeVal);
-+    /// let iov = [IoVec::from_mut_slice(&mut buffer)];
-+    /// let r = recvmsg(in_socket, &iov, Some(&mut cmsgspace), flags).unwrap();
-+    /// let rtime = match r.cmsgs().next() {
-+    ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
-+    ///     Some(_) => panic!("Unexpected control message"),
-+    ///     None => panic!("No control message")
-+    /// };
-+    /// // Check the final time
-+    /// let time1 = SystemTime::now();
-+    /// // the packet's received timestamp should lie in-between the two system
-+    /// // times, unless the system clock was adjusted in the meantime.
-+    /// let rduration = Duration::new(rtime.tv_sec() as u64,
-+    ///                               rtime.tv_usec() as u32 * 1000);
-+    /// assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
-+    /// assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
-+    /// // Close socket
-+    /// nix::unistd::close(in_socket).unwrap();
-+    /// # }
-+    /// ```
-+    ScmTimestamp(TimeVal),
-+    #[cfg(any(
-+        target_os = "android",
-+        target_os = "ios",
-+        target_os = "linux",
-+        target_os = "macos",
-+        target_os = "netbsd",
-+    ))]
-+    Ipv4PacketInfo(libc::in_pktinfo),
-+    #[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 = "netbsd",
-+    ))]
-+    Ipv6PacketInfo(libc::in6_pktinfo),
-+    #[cfg(any(
-+        target_os = "freebsd",
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "netbsd",
-+        target_os = "openbsd",
-+    ))]
-+    Ipv4RecvIf(libc::sockaddr_dl),
-+    #[cfg(any(
-+        target_os = "freebsd",
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "netbsd",
-+        target_os = "openbsd",
-+    ))]
-+    Ipv4RecvDstAddr(libc::in_addr),
-+    /// Catch-all variant for unimplemented cmsg types.
-+    #[doc(hidden)]
-+    Unknown(UnknownCmsg),
-+}
-+
-+impl ControlMessageOwned {
-+    /// Decodes a `ControlMessageOwned` from raw bytes.
-+    ///
-+    /// This is only safe to call if the data is correct for the message type
-+    /// specified in the header. Normally, the kernel ensures that this is the
-+    /// case. "Correct" in this case includes correct length, alignment and
-+    /// actual content.
-+    ///
-+    /// Returns `None` if the data may be unaligned.  In that case use
-+    /// `ControlMessageOwned::decode_from`.
-+    unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
-+    {
-+        let p = CMSG_DATA(header);
-+        let len = header as *const _ as usize + header.cmsg_len as usize
-+            - p as usize;
-+        match (header.cmsg_level, header.cmsg_type) {
-+            (libc::SOL_SOCKET, libc::SCM_RIGHTS) => {
-+                let n = len / mem::size_of::<RawFd>();
-+                let mut fds = Vec::with_capacity(n);
-+                for i in 0..n {
-+                    let fdp = (p as *const RawFd).offset(i as isize);
-+                    fds.push(ptr::read_unaligned(fdp));
-+                }
-+                let cmo = ControlMessageOwned::ScmRights(fds);
-+                cmo
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
-+                let cred: libc::ucred = ptr::read_unaligned(p as *const _);
-+                ControlMessageOwned::ScmCredentials(cred)
-+            }
-+            (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
-+                let tv: libc::timeval = ptr::read_unaligned(p as *const _);
-+                ControlMessageOwned::ScmTimestamp(TimeVal::from(tv))
-+            },
-+            #[cfg(any(
-+                target_os = "android",
-+                target_os = "freebsd",
-+                target_os = "ios",
-+                target_os = "linux",
-+                target_os = "macos"
-+            ))]
-+            (libc::IPPROTO_IPV6, libc::IPV6_PKTINFO) => {
-+                let info = ptr::read_unaligned(p as *const libc::in6_pktinfo);
-+                ControlMessageOwned::Ipv6PacketInfo(info)
-+            }
-+            #[cfg(any(
-+                target_os = "android",
-+                target_os = "ios",
-+                target_os = "linux",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+            ))]
-+            (libc::IPPROTO_IP, libc::IP_PKTINFO) => {
-+                let info = ptr::read_unaligned(p as *const libc::in_pktinfo);
-+                ControlMessageOwned::Ipv4PacketInfo(info)
-+            }
-+            #[cfg(any(
-+                target_os = "freebsd",
-+                target_os = "ios",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd",
-+            ))]
-+            (libc::IPPROTO_IP, libc::IP_RECVIF) => {
-+                let dl = ptr::read_unaligned(p as *const libc::sockaddr_dl);
-+                ControlMessageOwned::Ipv4RecvIf(dl)
-+            },
-+            #[cfg(any(
-+                target_os = "freebsd",
-+                target_os = "ios",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd",
-+            ))]
-+            (libc::IPPROTO_IP, libc::IP_RECVDSTADDR) => {
-+                let dl = ptr::read_unaligned(p as *const libc::in_addr);
-+                ControlMessageOwned::Ipv4RecvDstAddr(dl)
-+            },
-+            (_, _) => {
-+                let sl = slice::from_raw_parts(p, len);
-+                let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
-+                ControlMessageOwned::Unknown(ucmsg)
-+            }
-+        }
-+    }
-+}
-+
-+/// A type-safe zero-copy wrapper around a single control message, as used wih
-+/// [`sendmsg`](#fn.sendmsg).  More types may be added to this enum; do not
-+/// exhaustively pattern-match it.
-+///
-+/// [Further reading](http://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).
-+    ///
-+    /// Using multiple `ScmRights` messages for a single `sendmsg` call isn't
-+    /// recommended since it causes platform-dependent behaviour: It might
-+    /// swallow all but the first `ScmRights` message or fail with `EINVAL`.
-+    /// Instead, you can put all fds to be passed into a single `ScmRights`
-+    /// message.
-+    ScmRights(&'a [RawFd]),
-+    /// A message of type `SCM_CREDENTIALS`, containing the pid, uid and gid of
-+    /// a process connected to the socket.
-+    ///
-+    /// This is similar to the socket option `SO_PEERCRED`, but requires a
-+    /// process to explicitly send its credentials. A process running as root is
-+    /// allowed to specify any credentials, while credentials sent by other
-+    /// 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.
-+    // FIXME: When `#[repr(transparent)]` is stable, use it on `UnixCredentials`
-+    // and put that in here instead of a raw ucred.
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    ScmCredentials(&'a libc::ucred),
-+
-+    /// Set IV for `AF_ALG` crypto API.
-+    ///
-+    /// For further information, please refer to the
-+    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
-+    #[cfg(any(
-+        target_os = "android",
-+        target_os = "linux",
-+    ))]
-+    AlgSetIv(&'a [u8]),
-+    /// Set crypto operation for `AF_ALG` crypto API. It may be one of
-+    /// `ALG_OP_ENCRYPT` or `ALG_OP_DECRYPT`
-+    ///
-+    /// For further information, please refer to the
-+    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
-+    #[cfg(any(
-+        target_os = "android",
-+        target_os = "linux",
-+    ))]
-+    AlgSetOp(&'a libc::c_int),
-+    /// Set the length of associated authentication data (AAD) (applicable only to AEAD algorithms)
-+    /// for `AF_ALG` crypto API.
-+    ///
-+    /// For further information, please refer to the
-+    /// [`documentation`](https://kernel.readthedocs.io/en/sphinx-samples/crypto-API.html)
-+    #[cfg(any(
-+        target_os = "android",
-+        target_os = "linux",
-+    ))]
-+    AlgSetAeadAssoclen(&'a u32),
-+
-+}
-+
-+// An opaque structure used to prevent cmsghdr from being a public type
-+#[doc(hidden)]
-+#[derive(Clone, Debug, Eq, PartialEq)]
-+pub struct UnknownCmsg(cmsghdr, Vec<u8>);
-+
-+impl<'a> ControlMessage<'a> {
-+    /// The value of CMSG_SPACE on this message.
-+    /// Safe because CMSG_SPACE is always safe
-+    fn space(&self) -> usize {
-+        unsafe{CMSG_SPACE(self.len() as libc::c_uint) as usize}
-+    }
-+
-+    /// The value of CMSG_LEN on this message.
-+    /// Safe because CMSG_LEN is always safe
-+    #[cfg(any(target_os = "android",
-+              all(target_os = "linux", not(target_env = "musl"))))]
-+    fn cmsg_len(&self) -> usize {
-+        unsafe{CMSG_LEN(self.len() as libc::c_uint) as usize}
-+    }
-+
-+    #[cfg(not(any(target_os = "android",
-+                  all(target_os = "linux", not(target_env = "musl")))))]
-+    fn cmsg_len(&self) -> libc::c_uint {
-+        unsafe{CMSG_LEN(self.len() as libc::c_uint)}
-+    }
-+
-+    /// Return a reference to the payload data as a byte pointer
-+    fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
-+        let data_ptr = match self {
-+            &ControlMessage::ScmRights(fds) => {
-+                fds as *const _ as *const u8
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::ScmCredentials(creds) => {
-+                creds as *const libc::ucred as *const u8
-+            }
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetIv(iv) => {
-+                unsafe {
-+                    let alg_iv = cmsg_data as *mut libc::af_alg_iv;
-+                    (*alg_iv).ivlen = iv.len() as u32;
-+                    ptr::copy_nonoverlapping(
-+                        iv.as_ptr(),
-+                        (*alg_iv).iv.as_mut_ptr(),
-+                        iv.len()
-+                    );
-+                };
-+                return
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetOp(op) => {
-+                op as *const _ as *const u8
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetAeadAssoclen(len) => {
-+                len as *const _ as *const u8
-+            },
-+        };
-+        unsafe {
-+            ptr::copy_nonoverlapping(
-+                data_ptr,
-+                cmsg_data,
-+                self.len()
-+            )
-+        };
-+    }
-+
-+    /// The size of the payload, excluding its cmsghdr
-+    fn len(&self) -> usize {
-+        match self {
-+            &ControlMessage::ScmRights(fds) => {
-+                mem::size_of_val(fds)
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::ScmCredentials(creds) => {
-+                mem::size_of_val(creds)
-+            }
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetIv(iv) => {
-+                mem::size_of::<libc::af_alg_iv>() + iv.len()
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetOp(op) => {
-+                mem::size_of_val(op)
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetAeadAssoclen(len) => {
-+                mem::size_of_val(len)
-+            },
-+        }
-+    }
-+
-+    /// Returns the value to put into the `cmsg_level` field of the header.
-+    fn cmsg_level(&self) -> libc::c_int {
-+        match self {
-+            &ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetIv(_) | &ControlMessage::AlgSetOp(_) | &ControlMessage::AlgSetAeadAssoclen(_) => {
-+                libc::SOL_ALG
-+            },
-+        }
-+    }
-+
-+    /// Returns the value to put into the `cmsg_type` field of the header.
-+    fn cmsg_type(&self) -> libc::c_int {
-+        match self {
-+            &ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetIv(_) => {
-+                libc::ALG_SET_IV
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetOp(_) => {
-+                libc::ALG_SET_OP
-+            },
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            &ControlMessage::AlgSetAeadAssoclen(_) => {
-+                libc::ALG_SET_AEAD_ASSOCLEN
-+            },
-+        }
-+    }
-+
-+    // Unsafe: cmsg must point to a valid cmsghdr with enough space to
-+    // encode self.
-+    unsafe fn encode_into(&self, cmsg: *mut cmsghdr) {
-+        (*cmsg).cmsg_level = self.cmsg_level();
-+        (*cmsg).cmsg_type = self.cmsg_type();
-+        (*cmsg).cmsg_len = self.cmsg_len();
-+        self.copy_to_cmsg_data(CMSG_DATA(cmsg));
-+    }
-+}
-+
-+
-+/// Send data in scatter-gather vectors to a socket, possibly accompanied
-+/// by ancillary data. Optionally direct the message at the given address,
-+/// as with sendto.
-+///
-+/// Allocates if cmsgs is nonempty.
-+pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
-+               flags: MsgFlags, addr: Option<&SockAddr>) -> Result<usize>
-+{
-+    let capacity = cmsgs.iter().map(|c| c.space()).sum();
-+
-+    // First size the buffer needed to hold the cmsgs.  It must be zeroed,
-+    // because subsequent code will not clear the padding bytes.
-+    let cmsg_buffer = vec![0u8; capacity];
-+
-+    // Next encode the sending address, if provided
-+    let (name, namelen) = match addr {
-+        Some(addr) => {
-+            let (x, y) = unsafe { addr.as_ffi_pair() };
-+            (x as *const _, y)
-+        },
-+        None => (ptr::null(), 0),
-+    };
-+
-+    // The message header must be initialized before the individual cmsgs.
-+    let cmsg_ptr = if capacity > 0 {
-+        cmsg_buffer.as_ptr() as *mut c_void
-+    } else {
-+        ptr::null_mut()
-+    };
-+
-+    let mhdr = {
-+        // Musl's msghdr has private fields, so this is the only way to
-+        // initialize it.
-+        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
-+        mhdr.msg_name = name as *mut _;
-+        mhdr.msg_namelen = namelen;
-+        // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
-+        // the buffer, but the standard says that it takes a mutable pointer
-+        mhdr.msg_iov = iov.as_ptr() as *mut _;
-+        mhdr.msg_iovlen = iov.len() as _;
-+        mhdr.msg_control = cmsg_ptr;
-+        mhdr.msg_controllen = capacity as _;
-+        mhdr.msg_flags = 0;
-+        mhdr
-+    };
-+
-+    // Encode each cmsg.  This must happen after initializing the header because
-+    // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
-+    // CMSG_FIRSTHDR is always safe
-+    let mut pmhdr: *mut cmsghdr = unsafe{CMSG_FIRSTHDR(&mhdr as *const msghdr)};
-+    for cmsg in cmsgs {
-+        assert_ne!(pmhdr, ptr::null_mut());
-+        // Safe because we know that pmhdr is valid, and we initialized it with
-+        // sufficient space
-+        unsafe { cmsg.encode_into(pmhdr) };
-+        // Safe because mhdr is valid
-+        pmhdr = unsafe{CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr)};
-+    }
-+
-+    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
-+
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+/// Receive message in scatter-gather vectors from a socket, and
-+/// optionally receive ancillary data into the provided buffer.
-+/// If no ancillary data is desired, use () as the type parameter.
-+///
-+/// # References
-+/// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
-+pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
-+                   cmsg_buffer: Option<&'a mut dyn CmsgBuffer>,
-+                   flags: MsgFlags) -> Result<RecvMsg<'a>>
-+{
-+    let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
-+    let (msg_control, msg_controllen) = match cmsg_buffer {
-+        Some(cmsgspace) => {
-+            let msg_buf = cmsgspace.as_bytes_mut();
-+            (msg_buf.as_mut_ptr(), msg_buf.len())
-+        },
-+        None => (ptr::null_mut(), 0),
-+    };
-+    let mut mhdr = {
-+        // Musl's msghdr has private fields, so this is the only way to
-+        // initialize it.
-+        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
-+        mhdr.msg_name = &mut address as *mut sockaddr_storage as *mut c_void;
-+        mhdr.msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
-+        mhdr.msg_iov = iov.as_ptr() as *mut iovec;
-+        mhdr.msg_iovlen = iov.len() as _;
-+        mhdr.msg_control = msg_control as *mut c_void;
-+        mhdr.msg_controllen = msg_controllen as _;
-+        mhdr.msg_flags = 0;
-+        mhdr
-+    };
-+
-+    let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
-+
-+    Errno::result(ret).map(|r| {
-+        let cmsghdr = unsafe {
-+            if mhdr.msg_controllen > 0 {
-+                // got control message(s)
-+                debug_assert!(!mhdr.msg_control.is_null());
-+                debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
-+                CMSG_FIRSTHDR(&mhdr as *const msghdr)
-+            } else {
-+                ptr::null()
-+            }.as_ref()
-+        };
-+
-+        let address = unsafe {
-+            sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok()
-+        };
-+        RecvMsg {
-+            bytes: r as usize,
-+            cmsghdr,
-+            address,
-+            flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
-+            mhdr,
-+        }
-+    })
-+}
-+
-+
-+/// Create an endpoint for communication
-+///
-+/// The `protocol` specifies a particular protocol to be used with the
-+/// socket.  Normally only a single protocol exists to support a
-+/// particular socket type within a given protocol family, in which case
-+/// protocol can be specified as `None`.  However, it is possible that many
-+/// 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)
-+pub fn socket<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, flags: SockFlag, protocol: T) -> Result<RawFd> {
-+    let protocol = match protocol.into() {
-+        None => 0,
-+        Some(p) => p as c_int,
-+    };
-+
-+    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
-+    // little easier to understand by separating it out. So we have to merge these bitfields
-+    // here.
-+    let mut ty = ty as c_int;
-+    ty |= flags.bits();
-+
-+    let res = unsafe { libc::socket(domain as c_int, ty, protocol) };
-+
-+    Errno::result(res)
-+}
-+
-+/// Create a pair of connected sockets
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/socketpair.html)
-+pub fn socketpair<T: Into<Option<SockProtocol>>>(domain: AddressFamily, ty: SockType, protocol: T,
-+                  flags: SockFlag) -> Result<(RawFd, RawFd)> {
-+    let protocol = match protocol.into() {
-+        None => 0,
-+        Some(p) => p as c_int,
-+    };
-+
-+    // SockFlags are usually embedded into `ty`, but we don't do that in `nix` because it's a
-+    // little easier to understand by separating it out. So we have to merge these bitfields
-+    // here.
-+    let mut ty = ty as c_int;
-+    ty |= flags.bits();
-+
-+    let mut fds = [-1, -1];
-+
-+    let res = unsafe { libc::socketpair(domain as c_int, ty, protocol, fds.as_mut_ptr()) };
-+    Errno::result(res)?;
-+
-+    Ok((fds[0], fds[1]))
-+}
-+
-+/// Listen for connections on a socket
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/listen.html)
-+pub fn listen(sockfd: RawFd, backlog: usize) -> Result<()> {
-+    let res = unsafe { libc::listen(sockfd, backlog as c_int) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Bind a name to a socket
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/bind.html)
-+pub fn bind(fd: RawFd, addr: &SockAddr) -> Result<()> {
-+    let res = unsafe {
-+        let (ptr, len) = addr.as_ffi_pair();
-+        libc::bind(fd, ptr, len)
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Accept a connection on a socket
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html)
-+pub fn accept(sockfd: RawFd) -> Result<RawFd> {
-+    let res = unsafe { libc::accept(sockfd, ptr::null_mut(), ptr::null_mut()) };
-+
-+    Errno::result(res)
-+}
-+
-+/// Accept a connection on a socket
-+///
-+/// [Further reading](http://man7.org/linux/man-pages/man2/accept.2.html)
-+#[cfg(any(target_os = "android",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "openbsd"))]
-+pub fn accept4(sockfd: RawFd, flags: SockFlag) -> Result<RawFd> {
-+    let res = unsafe { libc::accept4(sockfd, ptr::null_mut(), ptr::null_mut(), flags.bits()) };
-+
-+    Errno::result(res)
-+}
-+
-+/// Initiate a connection on a socket
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html)
-+pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
-+    let res = unsafe {
-+        let (ptr, len) = addr.as_ffi_pair();
-+        libc::connect(fd, ptr, len)
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Receive data from a connection-oriented socket. Returns the number of
-+/// bytes read
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
-+pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
-+    unsafe {
-+        let ret = libc::recv(
-+            sockfd,
-+            buf.as_ptr() as *mut c_void,
-+            buf.len() as size_t,
-+            flags.bits());
-+
-+        Errno::result(ret).map(|r| r as usize)
-+    }
-+}
-+
-+/// Receive data from a connectionless or connection-oriented socket. Returns
-+/// the number of bytes read and the socket address of the sender.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html)
-+pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
-+    unsafe {
-+        let addr: sockaddr_storage = mem::zeroed();
-+        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-+
-+        let ret = Errno::result(libc::recvfrom(
-+            sockfd,
-+            buf.as_ptr() as *mut c_void,
-+            buf.len() as size_t,
-+            0,
-+            mem::transmute(&addr),
-+            &mut len as *mut socklen_t))?;
-+
-+        sockaddr_storage_to_addr(&addr, len as usize)
-+            .map(|addr| (ret as usize, addr))
-+    }
-+}
-+
-+/// Send a message to a socket
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html)
-+pub fn sendto(fd: RawFd, buf: &[u8], addr: &SockAddr, flags: MsgFlags) -> Result<usize> {
-+    let ret = unsafe {
-+        let (ptr, len) = addr.as_ffi_pair();
-+        libc::sendto(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits(), ptr, len)
-+    };
-+
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+/// Send data to a connection-oriented socket. Returns the number of bytes read
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/send.html)
-+pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
-+    let ret = unsafe {
-+        libc::send(fd, buf.as_ptr() as *const c_void, buf.len() as size_t, flags.bits())
-+    };
-+
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+/*
-+ *
-+ * ===== Socket Options =====
-+ *
-+ */
-+
-+/// The protocol level at which to get / set socket options. Used as an
-+/// argument to `getsockopt` and `setsockopt`.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
-+#[repr(i32)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum SockLevel {
-+    Socket = libc::SOL_SOCKET,
-+    Tcp = libc::IPPROTO_TCP,
-+    Ip = libc::IPPROTO_IP,
-+    Ipv6 = libc::IPPROTO_IPV6,
-+    Udp = libc::IPPROTO_UDP,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Netlink = libc::SOL_NETLINK,
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    Alg = libc::SOL_ALG,
-+}
-+
-+/// Represents a socket option that can be accessed or set. Used as an argument
-+/// to `getsockopt`
-+pub trait GetSockOpt : Copy {
-+    type Val;
-+
-+    #[doc(hidden)]
-+    fn get(&self, fd: RawFd) -> Result<Self::Val>;
-+}
-+
-+/// Represents a socket option that can be accessed or set. Used as an argument
-+/// to `setsockopt`
-+pub trait SetSockOpt : Clone {
-+    type Val;
-+
-+    #[doc(hidden)]
-+    fn set(&self, fd: RawFd, val: &Self::Val) -> Result<()>;
-+}
-+
-+/// Get the current value for the requested socket option
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockopt.html)
-+pub fn getsockopt<O: GetSockOpt>(fd: RawFd, opt: O) -> Result<O::Val> {
-+    opt.get(fd)
-+}
-+
-+/// Sets the value for the requested socket option
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
-+///
-+/// # Examples
-+///
-+/// ```
-+/// use nix::sys::socket::setsockopt;
-+/// use nix::sys::socket::sockopt::KeepAlive;
-+/// use std::net::TcpListener;
-+/// use std::os::unix::io::AsRawFd;
-+///
-+/// let listener = TcpListener::bind("0.0.0.0:0").unwrap();
-+/// let fd = listener.as_raw_fd();
-+/// let res = setsockopt(fd, KeepAlive, &true);
-+/// assert!(res.is_ok());
-+/// ```
-+pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()> {
-+    opt.set(fd, val)
-+}
-+
-+/// Get the address of the peer connected to the socket `fd`.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
-+pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
-+    unsafe {
-+        let addr: sockaddr_storage = mem::uninitialized();
-+        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-+
-+        let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
-+
-+        Errno::result(ret)?;
-+
-+        sockaddr_storage_to_addr(&addr, len as usize)
-+    }
-+}
-+
-+/// Get the current address to which the socket `fd` is bound.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
-+pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
-+    unsafe {
-+        let addr: sockaddr_storage = mem::uninitialized();
-+        let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
-+
-+        let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
-+
-+        Errno::result(ret)?;
-+
-+        sockaddr_storage_to_addr(&addr, len as usize)
-+    }
-+}
-+
-+/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
-+/// size.  In C this would usually be done by casting.  The `len` argument
-+/// should be the number of bytes in the `sockaddr_storage` that are actually
-+/// allocated and valid.  It must be at least as large as all the useful parts
-+/// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
-+/// include the terminating null.
-+pub unsafe fn sockaddr_storage_to_addr(
-+    addr: &sockaddr_storage,
-+    len: usize) -> Result<SockAddr> {
-+
-+    if len < mem::size_of_val(&addr.ss_family) {
-+        return Err(Error::Sys(Errno::ENOTCONN));
-+    }
-+
-+    match addr.ss_family as c_int {
-+        libc::AF_INET => {
-+            assert!(len as usize == mem::size_of::<sockaddr_in>());
-+            let ret = *(addr as *const _ as *const sockaddr_in);
-+            Ok(SockAddr::Inet(InetAddr::V4(ret)))
-+        }
-+        libc::AF_INET6 => {
-+            assert!(len as usize == mem::size_of::<sockaddr_in6>());
-+            Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
-+        }
-+        libc::AF_UNIX => {
-+            let sun = *(addr as *const _ as *const sockaddr_un);
-+            let pathlen = len - offset_of!(sockaddr_un, sun_path);
-+            Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
-+        }
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        libc::AF_NETLINK => {
-+            use libc::sockaddr_nl;
-+            Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
-+        }
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        libc::AF_ALG => {
-+            use libc::sockaddr_alg;
-+            Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
-+        }
-+        #[cfg(target_os = "linux")]
-+        libc::AF_VSOCK => {
-+            use libc::sockaddr_vm;
-+            Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
-+        }
-+        af => panic!("unexpected address family {}", af),
-+    }
-+}
-+
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum Shutdown {
-+    /// Further receptions will be disallowed.
-+    Read,
-+    /// Further  transmissions will be disallowed.
-+    Write,
-+    /// Further receptions and transmissions will be disallowed.
-+    Both,
-+}
-+
-+/// Shut down part of a full-duplex connection.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/shutdown.html)
-+pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> {
-+    unsafe {
-+        use libc::shutdown;
-+
-+        let how = match how {
-+            Shutdown::Read  => libc::SHUT_RD,
-+            Shutdown::Write => libc::SHUT_WR,
-+            Shutdown::Both  => libc::SHUT_RDWR,
-+        };
-+
-+        Errno::result(shutdown(df, how)).map(drop)
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs b/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
-new file mode 100644
-index 0000000000000..a996010018d5b
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/socket/sockopt.rs
-@@ -0,0 +1,680 @@
-+use super::{GetSockOpt, SetSockOpt};
-+use Result;
-+use errno::Errno;
-+use sys::time::TimeVal;
-+use libc::{self, c_int, c_void, socklen_t};
-+use std::mem;
-+use std::os::unix::io::RawFd;
-+use std::ffi::{OsStr, OsString};
-+#[cfg(target_family = "unix")]
-+use std::os::unix::ffi::OsStrExt;
-+
-+// Constants
-+// TCP_CA_NAME_MAX isn't defined in user space include files
-+#[cfg(any(target_os = "freebsd", target_os = "linux"))] 
-+const TCP_CA_NAME_MAX: usize = 16;
-+
-+/// Helper for implementing `SetSockOpt` for a given socket option. See
-+/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-+///
-+/// This macro aims to help implementing `SetSockOpt` for different socket options that accept
-+/// different kinds of data to be used with `setsockopt`.
-+///
-+/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-+/// you are implementing represents a simple type.
-+///
-+/// # Arguments
-+///
-+/// * `$name:ident`: name of the type you want to implement `SetSockOpt` for.
-+/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
-+///    (`libc::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-+///    and more. Please refer to your system manual for more options. Will be passed as the second
-+///    argument (`level`) to the `setsockopt` call.
-+/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-+///    `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-+///    to the `setsockopt` call.
-+/// * Type of the value that you are going to set.
-+/// * Type that implements the `Set` trait for the type from the previous item (like `SetBool` for
-+///    `bool`, `SetUsize` for `usize`, etc.).
-+macro_rules! setsockopt_impl {
-+    ($name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
-+        impl SetSockOpt for $name {
-+            type Val = $ty;
-+
-+            fn set(&self, fd: RawFd, val: &$ty) -> Result<()> {
-+                unsafe {
-+                    let setter: $setter = Set::new(val);
-+
-+                    let res = libc::setsockopt(fd, $level, $flag,
-+                                               setter.ffi_ptr(),
-+                                               setter.ffi_len());
-+                    Errno::result(res).map(drop)
-+                }
-+            }
-+        }
-+    }
-+}
-+
-+/// Helper for implementing `GetSockOpt` for a given socket option. See
-+/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html).
-+///
-+/// This macro aims to help implementing `GetSockOpt` for different socket options that accept
-+/// different kinds of data to be use with `getsockopt`.
-+///
-+/// Instead of using this macro directly consider using `sockopt_impl!`, especially if the option
-+/// you are implementing represents a simple type.
-+///
-+/// # Arguments
-+///
-+/// * Name of the type you want to implement `GetSockOpt` for.
-+/// * Socket layer, or a `protocol level`: could be *raw sockets* (`lic::SOL_SOCKET`),  *ip
-+///    protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),  and more. Please refer
-+///    to your system manual for more options. Will be passed as the second argument (`level`) to
-+///    the `getsockopt` call.
-+/// * A flag to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-+///    `libc::SO_ORIGINAL_DST` and others. Will be passed as the third argument (`option_name`) to
-+///    the `getsockopt` call.
-+/// * Type of the value that you are going to get.
-+/// * Type that implements the `Get` trait for the type from the previous item (`GetBool` for
-+///    `bool`, `GetUsize` for `usize`, etc.).
-+macro_rules! getsockopt_impl {
-+    ($name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
-+        impl GetSockOpt for $name {
-+            type Val = $ty;
-+
-+            fn get(&self, fd: RawFd) -> Result<$ty> {
-+                unsafe {
-+                    let mut getter: $getter = Get::blank();
-+
-+                    let res = libc::getsockopt(fd, $level, $flag,
-+                                               getter.ffi_ptr(),
-+                                               getter.ffi_len());
-+                    Errno::result(res)?;
-+
-+                    Ok(getter.unwrap())
-+                }
-+            }
-+        }
-+    }
-+}
-+
-+/// Helper to generate the sockopt accessors. See
-+/// [`::sys::socket::GetSockOpt`](sys/socket/trait.GetSockOpt.html) and
-+/// [`::sys::socket::SetSockOpt`](sys/socket/trait.SetSockOpt.html).
-+///
-+/// This macro aims to help implementing `GetSockOpt` and `SetSockOpt` for different socket options
-+/// that accept different kinds of data to be use with `getsockopt` and `setsockopt` respectively.
-+///
-+/// Basically this macro wraps up the [`getsockopt_impl!`](macro.getsockopt_impl.html) and
-+/// [`setsockopt_impl!`](macro.setsockopt_impl.html) macros.
-+///
-+/// # Arguments
-+///
-+/// * `GetOnly`, `SetOnly` or `Both`: whether you want to implement only getter, only setter or
-+///    both of them.
-+/// * `$name:ident`: name of type `GetSockOpt`/`SetSockOpt` will be implemented for.
-+/// * `$level:path` : socket layer, or a `protocol level`: could be *raw sockets*
-+///    (`lic::SOL_SOCKET`), *ip protocol* (libc::IPPROTO_IP), *tcp protocol* (`libc::IPPROTO_TCP`),
-+///    and more. Please refer to your system manual for more options. Will be passed as the second
-+///    argument (`level`) to the `getsockopt`/`setsockopt` call.
-+/// * `$flag:path`: a flag name to set. Some examples: `libc::SO_REUSEADDR`, `libc::TCP_NODELAY`,
-+///    `libc::IP_ADD_MEMBERSHIP` and others. Will be passed as the third argument (`option_name`)
-+///    to the `setsockopt`/`getsockopt` call.
-+/// * `$ty:ty`: type of the value that will be get/set.
-+/// * `$getter:ty`: `Get` implementation; optional; only for `GetOnly` and `Both`.
-+/// * `$setter:ty`: `Set` implementation; optional; only for `SetOnly` and `Both`.
-+macro_rules! sockopt_impl {
-+    (GetOnly, $name:ident, $level:path, $flag:path, bool) => {
-+        sockopt_impl!(GetOnly, $name, $level, $flag, bool, GetBool);
-+    };
-+
-+    (GetOnly, $name:ident, $level:path, $flag:path, u8) => {
-+        sockopt_impl!(GetOnly, $name, $level, $flag, u8, GetU8);
-+    };
-+
-+    (GetOnly, $name:ident, $level:path, $flag:path, usize) => {
-+        sockopt_impl!(GetOnly, $name, $level, $flag, usize, GetUsize);
-+    };
-+
-+    (SetOnly, $name:ident, $level:path, $flag:path, bool) => {
-+        sockopt_impl!(SetOnly, $name, $level, $flag, bool, SetBool);
-+    };
-+
-+    (SetOnly, $name:ident, $level:path, $flag:path, u8) => {
-+        sockopt_impl!(SetOnly, $name, $level, $flag, u8, SetU8);
-+    };
-+
-+    (SetOnly, $name:ident, $level:path, $flag:path, usize) => {
-+        sockopt_impl!(SetOnly, $name, $level, $flag, usize, SetUsize);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, bool) => {
-+        sockopt_impl!(Both, $name, $level, $flag, bool, GetBool, SetBool);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, u8) => {
-+        sockopt_impl!(Both, $name, $level, $flag, u8, GetU8, SetU8);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, usize) => {
-+        sockopt_impl!(Both, $name, $level, $flag, usize, GetUsize, SetUsize);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, OsString<$array:ty>) => {
-+        sockopt_impl!(Both, $name, $level, $flag, OsString, GetOsString<$array>, SetOsString);
-+    };
-+
-+    /*
-+     * Matchers with generic getter types must be placed at the end, so
-+     * they'll only match _after_ specialized matchers fail
-+     */
-+    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
-+        sockopt_impl!(GetOnly, $name, $level, $flag, $ty, GetStruct<$ty>);
-+    };
-+
-+    (GetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty) => {
-+        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+        pub struct $name;
-+
-+        getsockopt_impl!($name, $level, $flag, $ty, $getter);
-+    };
-+
-+    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty) => {
-+        sockopt_impl!(SetOnly, $name, $level, $flag, $ty, SetStruct<$ty>);
-+    };
-+
-+    (SetOnly, $name:ident, $level:path, $flag:path, $ty:ty, $setter:ty) => {
-+        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+        pub struct $name;
-+
-+        setsockopt_impl!($name, $level, $flag, $ty, $setter);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, $ty:ty, $getter:ty, $setter:ty) => {
-+        #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+        pub struct $name;
-+
-+        setsockopt_impl!($name, $level, $flag, $ty, $setter);
-+        getsockopt_impl!($name, $level, $flag, $ty, $getter);
-+    };
-+
-+    (Both, $name:ident, $level:path, $flag:path, $ty:ty) => {
-+        sockopt_impl!(Both, $name, $level, $flag, $ty, GetStruct<$ty>, SetStruct<$ty>);
-+    };
-+}
-+
-+/*
-+ *
-+ * ===== Define sockopts =====
-+ *
-+ */
-+
-+sockopt_impl!(Both, ReuseAddr, libc::SOL_SOCKET, libc::SO_REUSEADDR, bool);
-+sockopt_impl!(Both, ReusePort, libc::SOL_SOCKET, libc::SO_REUSEPORT, bool);
-+sockopt_impl!(Both, TcpNoDelay, libc::IPPROTO_TCP, libc::TCP_NODELAY, bool);
-+sockopt_impl!(Both, Linger, libc::SOL_SOCKET, libc::SO_LINGER, libc::linger);
-+sockopt_impl!(SetOnly, IpAddMembership, libc::IPPROTO_IP, libc::IP_ADD_MEMBERSHIP, super::IpMembershipRequest);
-+sockopt_impl!(SetOnly, IpDropMembership, libc::IPPROTO_IP, libc::IP_DROP_MEMBERSHIP, super::IpMembershipRequest);
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_ADD_MEMBERSHIP, super::Ipv6MembershipRequest);
-+        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_DROP_MEMBERSHIP, super::Ipv6MembershipRequest);
-+    } else if #[cfg(any(target_os = "dragonfly",
-+                        target_os = "freebsd",
-+                        target_os = "ios",
-+                        target_os = "macos",
-+                        target_os = "netbsd",
-+                        target_os = "openbsd"))] {
-+        sockopt_impl!(SetOnly, Ipv6AddMembership, libc::IPPROTO_IPV6, libc::IPV6_JOIN_GROUP, super::Ipv6MembershipRequest);
-+        sockopt_impl!(SetOnly, Ipv6DropMembership, libc::IPPROTO_IPV6, libc::IPV6_LEAVE_GROUP, super::Ipv6MembershipRequest);
-+    }
-+}
-+sockopt_impl!(Both, IpMulticastTtl, libc::IPPROTO_IP, libc::IP_MULTICAST_TTL, u8);
-+sockopt_impl!(Both, IpMulticastLoop, libc::IPPROTO_IP, libc::IP_MULTICAST_LOOP, bool);
-+sockopt_impl!(Both, ReceiveTimeout, libc::SOL_SOCKET, libc::SO_RCVTIMEO, TimeVal);
-+sockopt_impl!(Both, SendTimeout, libc::SOL_SOCKET, libc::SO_SNDTIMEO, TimeVal);
-+sockopt_impl!(Both, Broadcast, libc::SOL_SOCKET, libc::SO_BROADCAST, bool);
-+sockopt_impl!(Both, OobInline, libc::SOL_SOCKET, libc::SO_OOBINLINE, bool);
-+sockopt_impl!(GetOnly, SocketError, libc::SOL_SOCKET, libc::SO_ERROR, i32);
-+sockopt_impl!(Both, KeepAlive, libc::SOL_SOCKET, libc::SO_KEEPALIVE, bool);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(GetOnly, PeerCredentials, libc::SOL_SOCKET, libc::SO_PEERCRED, super::UnixCredentials);
-+#[cfg(any(target_os = "ios",
-+          target_os = "macos"))]
-+sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "nacl"))]
-+sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
-+sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
-+sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(SetOnly, RcvBufForce, libc::SOL_SOCKET, libc::SO_RCVBUFFORCE, usize);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usize);
-+sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
-+sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(GetOnly, OriginalDst, libc::SOL_IP, libc::SO_ORIGINAL_DST, libc::sockaddr_in);
-+sockopt_impl!(Both, ReceiveTimestamp, libc::SOL_SOCKET, libc::SO_TIMESTAMP, bool);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(Both, IpTransparent, libc::SOL_IP, libc::IP_TRANSPARENT, bool);
-+#[cfg(target_os = "openbsd")]
-+sockopt_impl!(Both, BindAny, libc::SOL_SOCKET, libc::SO_BINDANY, bool);
-+#[cfg(target_os = "freebsd")]
-+sockopt_impl!(Both, BindAny, libc::IPPROTO_IP, libc::IP_BINDANY, bool);
-+#[cfg(target_os = "linux")]
-+sockopt_impl!(Both, Mark, libc::SOL_SOCKET, libc::SO_MARK, u32);
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(Both, PassCred, libc::SOL_SOCKET, libc::SO_PASSCRED, bool);
-+#[cfg(any(target_os = "freebsd", target_os = "linux"))] 
-+sockopt_impl!(Both, TcpCongestion, libc::IPPROTO_TCP, libc::TCP_CONGESTION, OsString<[u8; TCP_CA_NAME_MAX]>);
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "ios",
-+    target_os = "linux",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+))]
-+sockopt_impl!(Both, Ipv4PacketInfo, libc::IPPROTO_IP, libc::IP_PKTINFO, bool);
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "linux",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+sockopt_impl!(Both, Ipv6RecvPacketInfo, libc::IPPROTO_IPV6, libc::IPV6_RECVPKTINFO, bool);
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
-+
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[derive(Copy, Clone, Debug)]
-+pub struct AlgSetAeadAuthSize;
-+
-+// ALG_SET_AEAD_AUTH_SIZE read the length from passed `option_len`
-+// See https://elixir.bootlin.com/linux/v4.4/source/crypto/af_alg.c#L222
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+impl SetSockOpt for AlgSetAeadAuthSize {
-+    type Val = usize;
-+
-+    fn set(&self, fd: RawFd, val: &usize) -> Result<()> {
-+        unsafe {
-+            let res = libc::setsockopt(fd,
-+                                       libc::SOL_ALG,
-+                                       libc::ALG_SET_AEAD_AUTHSIZE,
-+                                       ::std::ptr::null(),
-+                                       *val as libc::socklen_t);
-+            Errno::result(res).map(drop)
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[derive(Clone, Debug)]
-+pub struct AlgSetKey<T>(::std::marker::PhantomData<T>);
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+impl<T> Default for AlgSetKey<T> {
-+    fn default() -> Self {
-+        AlgSetKey(Default::default())
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
-+    type Val = T;
-+
-+    fn set(&self, fd: RawFd, val: &T) -> Result<()> {
-+        unsafe {
-+            let res = libc::setsockopt(fd,
-+                                       libc::SOL_ALG,
-+                                       libc::ALG_SET_KEY,
-+                                       val.as_ref().as_ptr() as *const _,
-+                                       val.as_ref().len() as libc::socklen_t);
-+            Errno::result(res).map(drop)
-+        }
-+    }
-+}
-+
-+/*
-+ *
-+ * ===== Accessor helpers =====
-+ *
-+ */
-+
-+/// Helper trait that describes what is expected from a `GetSockOpt` getter.
-+unsafe trait Get<T> {
-+    /// Returns an empty value.
-+    unsafe fn blank() -> Self;
-+    /// Returns a pointer to the stored value. This pointer will be passed to the system's
-+    /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
-+    fn ffi_ptr(&mut self) -> *mut c_void;
-+    /// Returns length of the stored value. This pointer will be passed to the system's
-+    /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
-+    fn ffi_len(&mut self) -> *mut socklen_t;
-+    /// Returns the stored value.
-+    unsafe fn unwrap(self) -> T;
-+}
-+
-+/// Helper trait that describes what is expected from a `SetSockOpt` setter.
-+unsafe trait Set<'a, T> {
-+    /// Initialize the setter with a given value.
-+    fn new(val: &'a T) -> Self;
-+    /// Returns a pointer to the stored value. This pointer will be passed to the system's
-+    /// `setsockopt` call (`man 3p setsockopt`, argument `option_value`).
-+    fn ffi_ptr(&self) -> *const c_void;
-+    /// Returns length of the stored value. This pointer will be passed to the system's
-+    /// `setsockopt` call (`man 3p setsockopt`, argument `option_len`).
-+    fn ffi_len(&self) -> socklen_t;
-+}
-+
-+/// Getter for an arbitrary `struct`.
-+struct GetStruct<T> {
-+    len: socklen_t,
-+    val: T,
-+}
-+
-+unsafe impl<T> Get<T> for GetStruct<T> {
-+    unsafe fn blank() -> Self {
-+        GetStruct {
-+            len: mem::size_of::<T>() as socklen_t,
-+            val: mem::zeroed(),
-+        }
-+    }
-+
-+    fn ffi_ptr(&mut self) -> *mut c_void {
-+        &mut self.val as *mut T as *mut c_void
-+    }
-+
-+    fn ffi_len(&mut self) -> *mut socklen_t {
-+        &mut self.len
-+    }
-+
-+    unsafe fn unwrap(self) -> T {
-+        assert!(self.len as usize == mem::size_of::<T>(), "invalid getsockopt implementation");
-+        self.val
-+    }
-+}
-+
-+/// Setter for an arbitrary `struct`.
-+struct SetStruct<'a, T: 'static> {
-+    ptr: &'a T,
-+}
-+
-+unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
-+    fn new(ptr: &'a T) -> SetStruct<'a, T> {
-+        SetStruct { ptr: ptr }
-+    }
-+
-+    fn ffi_ptr(&self) -> *const c_void {
-+        self.ptr as *const T as *const c_void
-+    }
-+
-+    fn ffi_len(&self) -> socklen_t {
-+        mem::size_of::<T>() as socklen_t
-+    }
-+}
-+
-+/// Getter for a boolean value.
-+struct GetBool {
-+    len: socklen_t,
-+    val: c_int,
-+}
-+
-+unsafe impl Get<bool> for GetBool {
-+    unsafe fn blank() -> Self {
-+        GetBool {
-+            len: mem::size_of::<c_int>() as socklen_t,
-+            val: mem::zeroed(),
-+        }
-+    }
-+
-+    fn ffi_ptr(&mut self) -> *mut c_void {
-+        &mut self.val as *mut c_int as *mut c_void
-+    }
-+
-+    fn ffi_len(&mut self) -> *mut socklen_t {
-+        &mut self.len
-+    }
-+
-+    unsafe fn unwrap(self) -> bool {
-+        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
-+        self.val != 0
-+    }
-+}
-+
-+/// Setter for a boolean value.
-+struct SetBool {
-+    val: c_int,
-+}
-+
-+unsafe impl<'a> Set<'a, bool> for SetBool {
-+    fn new(val: &'a bool) -> SetBool {
-+        SetBool { val: if *val { 1 } else { 0 } }
-+    }
-+
-+    fn ffi_ptr(&self) -> *const c_void {
-+        &self.val as *const c_int as *const c_void
-+    }
-+
-+    fn ffi_len(&self) -> socklen_t {
-+        mem::size_of::<c_int>() as socklen_t
-+    }
-+}
-+
-+/// Getter for an `u8` value.
-+struct GetU8 {
-+    len: socklen_t,
-+    val: u8,
-+}
-+
-+unsafe impl Get<u8> for GetU8 {
-+    unsafe fn blank() -> Self {
-+        GetU8 {
-+            len: mem::size_of::<u8>() as socklen_t,
-+            val: mem::zeroed(),
-+        }
-+    }
-+
-+    fn ffi_ptr(&mut self) -> *mut c_void {
-+        &mut self.val as *mut u8 as *mut c_void
-+    }
-+
-+    fn ffi_len(&mut self) -> *mut socklen_t {
-+        &mut self.len
-+    }
-+
-+    unsafe fn unwrap(self) -> u8 {
-+        assert!(self.len as usize == mem::size_of::<u8>(), "invalid getsockopt implementation");
-+        self.val as u8
-+    }
-+}
-+
-+/// Setter for an `u8` value.
-+struct SetU8 {
-+    val: u8,
-+}
-+
-+unsafe impl<'a> Set<'a, u8> for SetU8 {
-+    fn new(val: &'a u8) -> SetU8 {
-+        SetU8 { val: *val as u8 }
-+    }
-+
-+    fn ffi_ptr(&self) -> *const c_void {
-+        &self.val as *const u8 as *const c_void
-+    }
-+
-+    fn ffi_len(&self) -> socklen_t {
-+        mem::size_of::<c_int>() as socklen_t
-+    }
-+}
-+
-+/// Getter for an `usize` value.
-+struct GetUsize {
-+    len: socklen_t,
-+    val: c_int,
-+}
-+
-+unsafe impl Get<usize> for GetUsize {
-+    unsafe fn blank() -> Self {
-+        GetUsize {
-+            len: mem::size_of::<c_int>() as socklen_t,
-+            val: mem::zeroed(),
-+        }
-+    }
-+
-+    fn ffi_ptr(&mut self) -> *mut c_void {
-+        &mut self.val as *mut c_int as *mut c_void
-+    }
-+
-+    fn ffi_len(&mut self) -> *mut socklen_t {
-+        &mut self.len
-+    }
-+
-+    unsafe fn unwrap(self) -> usize {
-+        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
-+        self.val as usize
-+    }
-+}
-+
-+/// Setter for an `usize` value.
-+struct SetUsize {
-+    val: c_int,
-+}
-+
-+unsafe impl<'a> Set<'a, usize> for SetUsize {
-+    fn new(val: &'a usize) -> SetUsize {
-+        SetUsize { val: *val as c_int }
-+    }
-+
-+    fn ffi_ptr(&self) -> *const c_void {
-+        &self.val as *const c_int as *const c_void
-+    }
-+
-+    fn ffi_len(&self) -> socklen_t {
-+        mem::size_of::<c_int>() as socklen_t
-+    }
-+}
-+
-+/// Getter for a `OsString` value.
-+struct GetOsString<T: AsMut<[u8]>> {
-+    len: socklen_t,
-+    val: T,
-+}
-+
-+unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
-+    unsafe fn blank() -> Self {
-+        GetOsString {
-+            len: mem::size_of::<T>() as socklen_t,
-+            val: mem::zeroed(),
-+        }
-+    }
-+
-+    fn ffi_ptr(&mut self) -> *mut c_void {
-+        &mut self.val as *mut T as *mut c_void
-+    }
-+
-+    fn ffi_len(&mut self) -> *mut socklen_t {
-+        &mut self.len
-+    }
-+
-+    unsafe fn unwrap(mut self) -> OsString {
-+        OsStr::from_bytes(self.val.as_mut()).to_owned()
-+    }
-+}
-+
-+/// Setter for a `OsString` value.
-+struct SetOsString<'a> {
-+    val: &'a OsStr,
-+}
-+
-+unsafe impl<'a> Set<'a, OsString> for SetOsString<'a> {
-+    fn new(val: &'a OsString) -> SetOsString {
-+        SetOsString { val: val.as_os_str() }
-+    }
-+
-+    fn ffi_ptr(&self) -> *const c_void {
-+        self.val.as_bytes().as_ptr() as *const c_void
-+    }
-+
-+    fn ffi_len(&self) -> socklen_t {
-+        self.val.len() as socklen_t
-+    }
-+}
-+
-+
-+#[cfg(test)]
-+mod test {
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    #[test]
-+    fn can_get_peercred_on_unix_socket() {
-+        use super::super::*;
-+
-+        let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
-+        let a_cred = getsockopt(a, super::PeerCredentials).unwrap();
-+        let b_cred = getsockopt(b, super::PeerCredentials).unwrap();
-+        assert_eq!(a_cred, b_cred);
-+        assert!(a_cred.pid() != 0);
-+    }
-+
-+    #[test]
-+    fn is_socket_type_unix() {
-+        use super::super::*;
-+        use ::unistd::close;
-+
-+        let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
-+        let a_type = getsockopt(a, super::SockType).unwrap();
-+        assert!(a_type == SockType::Stream);
-+        close(a).unwrap();
-+        close(b).unwrap();
-+    }
-+
-+    #[test]
-+    fn is_socket_type_dgram() {
-+        use super::super::*;
-+        use ::unistd::close;
-+
-+        let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
-+        let s_type = getsockopt(s, super::SockType).unwrap();
-+        assert!(s_type == SockType::Datagram);
-+        close(s).unwrap();
-+    }
-+
-+    #[cfg(any(target_os = "freebsd",
-+              target_os = "linux",
-+              target_os = "nacl"))]
-+    #[test]
-+    fn can_get_listen_on_tcp_socket() {
-+        use super::super::*;
-+        use ::unistd::close;
-+
-+        let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-+        let s_listening = getsockopt(s, super::AcceptConn).unwrap();
-+        assert!(!s_listening);
-+        listen(s, 10).unwrap();
-+        let s_listening2 = getsockopt(s, super::AcceptConn).unwrap();
-+        assert!(s_listening2);
-+        close(s).unwrap();
-+    }
-+
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/stat.rs b/third_party/rust/nix-0.15.0/src/sys/stat.rs
-new file mode 100644
-index 0000000000000..66c8c9dd1b720
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/stat.rs
-@@ -0,0 +1,294 @@
-+pub use libc::{dev_t, mode_t};
-+pub use libc::stat as FileStat;
-+
-+use {Result, NixPath};
-+use errno::Errno;
-+use fcntl::{AtFlags, at_rawfd};
-+use libc;
-+use std::mem;
-+use std::os::unix::io::RawFd;
-+use sys::time::{TimeSpec, TimeVal};
-+
-+libc_bitflags!(
-+    pub struct SFlag: mode_t {
-+        S_IFIFO;
-+        S_IFCHR;
-+        S_IFDIR;
-+        S_IFBLK;
-+        S_IFREG;
-+        S_IFLNK;
-+        S_IFSOCK;
-+        S_IFMT;
-+    }
-+);
-+
-+libc_bitflags! {
-+    pub struct Mode: mode_t {
-+        S_IRWXU;
-+        S_IRUSR;
-+        S_IWUSR;
-+        S_IXUSR;
-+        S_IRWXG;
-+        S_IRGRP;
-+        S_IWGRP;
-+        S_IXGRP;
-+        S_IRWXO;
-+        S_IROTH;
-+        S_IWOTH;
-+        S_IXOTH;
-+        S_ISUID as mode_t;
-+        S_ISGID as mode_t;
-+        S_ISVTX as mode_t;
-+    }
-+}
-+
-+pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
-+        }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+#[cfg(target_os = "linux")]
-+pub fn major(dev: dev_t) -> u64 {
-+    ((dev >> 32) & 0xffff_f000) |
-+    ((dev >>  8) & 0x0000_0fff)
-+}
-+
-+#[cfg(target_os = "linux")]
-+pub fn minor(dev: dev_t) -> u64 {
-+    ((dev >> 12) & 0xffff_ff00) |
-+    ((dev      ) & 0x0000_00ff)
-+}
-+
-+#[cfg(target_os = "linux")]
-+pub fn makedev(major: u64, minor: u64) -> dev_t {
-+    ((major & 0xffff_f000) << 32) |
-+    ((major & 0x0000_0fff) <<  8) |
-+    ((minor & 0xffff_ff00) << 12) |
-+     (minor & 0x0000_00ff)
-+}
-+
-+pub fn umask(mode: Mode) -> Mode {
-+    let prev = unsafe { libc::umask(mode.bits() as mode_t) };
-+    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
-+}
-+
-+pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
-+    let mut dst = unsafe { mem::uninitialized() };
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
-+        }
-+    })?;
-+
-+    Errno::result(res)?;
-+
-+    Ok(dst)
-+}
-+
-+pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
-+    let mut dst = unsafe { mem::uninitialized() };
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
-+        }
-+    })?;
-+
-+    Errno::result(res)?;
-+
-+    Ok(dst)
-+}
-+
-+pub fn fstat(fd: RawFd) -> Result<FileStat> {
-+    let mut dst = unsafe { mem::uninitialized() };
-+    let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) };
-+
-+    Errno::result(res)?;
-+
-+    Ok(dst)
-+}
-+
-+pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
-+    let mut dst = unsafe { mem::uninitialized() };
-+    let res = pathname.with_nix_path(|cstr| {
-+        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) }
-+    })?;
-+
-+    Errno::result(res)?;
-+
-+    Ok(dst)
-+}
-+
-+/// Change the file permission bits of the file specified by a file descriptor.
-+///
-+/// # References
-+///
-+/// [fchmod(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmod.html).
-+pub fn fchmod(fd: RawFd, mode: Mode) -> Result<()> {
-+    let res = unsafe { libc::fchmod(fd, mode.bits() as mode_t) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Flags for `fchmodat` function.
-+#[derive(Clone, Copy, Debug)]
-+pub enum FchmodatFlags {
-+    FollowSymlink,
-+    NoFollowSymlink,
-+}
-+
-+/// Change the file permission bits.
-+///
-+/// The file to be changed is determined relative to the directory associated
-+/// with the file descriptor `dirfd` or the current working directory
-+/// if `dirfd` is `None`.
-+///
-+/// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
-+/// then the mode of the symbolic link is changed.
-+///
-+/// `fchmod(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
-+/// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
-+/// in the `nix` crate.
-+///
-+/// # References
-+///
-+/// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
-+pub fn fchmodat<P: ?Sized + NixPath>(
-+    dirfd: Option<RawFd>,
-+    path: &P,
-+    mode: Mode,
-+    flag: FchmodatFlags,
-+) -> Result<()> {
-+    let atflag =
-+        match flag {
-+            FchmodatFlags::FollowSymlink => AtFlags::empty(),
-+            FchmodatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
-+        };
-+    let res = path.with_nix_path(|cstr| unsafe {
-+        libc::fchmodat(
-+            at_rawfd(dirfd),
-+            cstr.as_ptr(),
-+            mode.bits() as mode_t,
-+            atflag.bits() as libc::c_int,
-+        )
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Change the access and modification times of a file.
-+///
-+/// `utimes(path, times)` is identical to
-+/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)`. The former
-+/// is a deprecated API so prefer using the latter if the platforms you care
-+/// about support it.
-+///
-+/// # References
-+///
-+/// [utimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimes.html).
-+pub fn utimes<P: ?Sized + NixPath>(path: &P, atime: &TimeVal, mtime: &TimeVal) -> Result<()> {
-+    let times: [libc::timeval; 2] = [*atime.as_ref(), *mtime.as_ref()];
-+    let res = path.with_nix_path(|cstr| unsafe {
-+        libc::utimes(cstr.as_ptr(), &times[0])
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Change the access and modification times of a file without following symlinks.
-+///
-+/// `lutimes(path, times)` is identical to
-+/// `utimensat(None, path, times, UtimensatFlags::NoFollowSymlink)`. The former
-+/// is a deprecated API so prefer using the latter if the platforms you care
-+/// about support it.
-+///
-+/// # References
-+///
-+/// [lutimes(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lutimes.html).
-+#[cfg(any(target_os = "linux",
-+          target_os = "haiku",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "freebsd",
-+          target_os = "netbsd"))]
-+pub fn lutimes<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 {
-+        libc::lutimes(cstr.as_ptr(), &times[0])
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Change the access and modification times of the file specified by a file descriptor.
-+///
-+/// # References
-+///
-+/// [futimens(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html).
-+#[inline]
-+pub fn futimens(fd: RawFd, atime: &TimeSpec, mtime: &TimeSpec) -> Result<()> {
-+    let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
-+    let res = unsafe { libc::futimens(fd, &times[0]) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Flags for `utimensat` function.
-+#[derive(Clone, Copy, Debug)]
-+pub enum UtimensatFlags {
-+    FollowSymlink,
-+    NoFollowSymlink,
-+}
-+
-+/// Change the access and modification times of a file.
-+///
-+/// The file to be changed is determined relative to the directory associated
-+/// with the file descriptor `dirfd` or the current working directory
-+/// if `dirfd` is `None`.
-+///
-+/// If `flag` is `UtimensatFlags::NoFollowSymlink` and `path` names a symbolic link,
-+/// then the mode of the symbolic link is changed.
-+///
-+/// `utimensat(None, path, times, UtimensatFlags::FollowSymlink)` is identical to
-+/// `utimes(path, times)`. The latter is a deprecated API so prefer using the
-+/// former if the platforms you care about support it.
-+///
-+/// # References
-+///
-+/// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
-+pub fn utimensat<P: ?Sized + NixPath>(
-+    dirfd: Option<RawFd>,
-+    path: &P,
-+    atime: &TimeSpec,
-+    mtime: &TimeSpec,
-+    flag: UtimensatFlags
-+) -> Result<()> {
-+    let atflag =
-+        match flag {
-+            UtimensatFlags::FollowSymlink => AtFlags::empty(),
-+            UtimensatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
-+        };
-+    let times: [libc::timespec; 2] = [*atime.as_ref(), *mtime.as_ref()];
-+    let res = path.with_nix_path(|cstr| unsafe {
-+        libc::utimensat(
-+            at_rawfd(dirfd),
-+            cstr.as_ptr(),
-+            &times[0],
-+            atflag.bits() as libc::c_int,
-+        )
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/statfs.rs b/third_party/rust/nix-0.15.0/src/sys/statfs.rs
-new file mode 100644
-index 0000000000000..d4596bf336958
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/statfs.rs
-@@ -0,0 +1,548 @@
-+use std::fmt::{self, Debug};
-+use std::mem;
-+use std::os::unix::io::AsRawFd;
-+#[cfg(not(any(target_os = "linux", target_os = "android")))]
-+use std::ffi::CStr;
-+
-+use libc;
-+
-+use {NixPath, Result};
-+use errno::Errno;
-+
-+#[cfg(target_os = "android")]
-+pub type fsid_t = libc::__fsid_t;
-+#[cfg(not(target_os = "android"))]
-+pub type fsid_t = libc::fsid_t;
-+
-+#[derive(Clone, Copy)]
-+pub struct Statfs(libc::statfs);
-+
-+#[cfg(target_os = "freebsd")]
-+#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-+pub struct FsType(u32);
-+#[cfg(target_os = "android")]
-+#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-+pub struct FsType(libc::c_ulong);
-+#[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-+pub struct FsType(u32);
-+#[cfg(all(target_os = "linux", target_env = "musl"))]
-+#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-+pub struct FsType(libc::c_ulong);
-+#[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+#[derive(Eq, Copy, Clone, PartialEq, Debug)]
-+pub struct FsType(libc::c_long);
-+
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
-+#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
-+pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
-+
-+impl Statfs {
-+    /// Magic code defining system type
-+    #[cfg(not(any(
-+        target_os = "openbsd",
-+        target_os = "ios",
-+        target_os = "macos"
-+    )))]
-+    pub fn filesystem_type(&self) -> FsType {
-+        FsType(self.0.f_type)
-+    }
-+
-+    /// Magic code defining system type
-+    #[cfg(not(any(target_os = "linux", target_os = "android")))]
-+    pub fn filesystem_type_name(&self) -> &str {
-+        let c_str = unsafe { CStr::from_ptr(self.0.f_fstypename.as_ptr()) };
-+        c_str.to_str().unwrap()
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
-+    pub fn optimal_transfer_size(&self) -> i32 {
-+        self.0.f_iosize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+    pub fn optimal_transfer_size(&self) -> u32 {
-+        self.0.f_bsize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
-+        self.0.f_bsize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+    pub fn optimal_transfer_size(&self) -> libc::c_long {
-+        self.0.f_bsize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(target_os = "android")]
-+    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
-+        self.0.f_bsize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn optimal_transfer_size(&self) -> libc::c_long {
-+        self.0.f_iosize
-+    }
-+
-+    /// Optimal transfer block size
-+    #[cfg(target_os = "freebsd")]
-+    pub fn optimal_transfer_size(&self) -> u64 {
-+        self.0.f_iosize
-+    }
-+
-+    /// Size of a block
-+    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
-+    pub fn block_size(&self) -> u32 {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
-+    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+    pub fn block_size(&self) -> u32 {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn block_size(&self) -> libc::c_ulong {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
-+    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+    pub fn block_size(&self) -> libc::c_long {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    #[cfg(target_os = "freebsd")]
-+    pub fn block_size(&self) -> u64 {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    #[cfg(target_os = "android")]
-+    pub fn block_size(&self) -> libc::c_ulong {
-+        self.0.f_bsize
-+    }
-+
-+    /// Size of a block
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn block_size(&self) -> libc::c_long {
-+        self.0.f_bsize
-+    }
-+
-+    /// Maximum length of filenames
-+    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
-+    pub fn maximum_name_length(&self) -> u32 {
-+        self.0.f_namemax
-+    }
-+
-+    /// Maximum length of filenames
-+    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+    pub fn maximum_name_length(&self) -> u32 {
-+        self.0.f_namelen
-+    }
-+
-+    /// Maximum length of filenames
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn maximum_name_length(&self) -> libc::c_ulong {
-+        self.0.f_namelen
-+    }
-+
-+    /// Maximum length of filenames
-+    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+    pub fn maximum_name_length(&self) -> libc::c_long {
-+        self.0.f_namelen
-+    }
-+
-+    /// Maximum length of filenames
-+    #[cfg(target_os = "android")]
-+    pub fn maximum_name_length(&self) -> libc::c_ulong {
-+        self.0.f_namelen
-+    }
-+
-+    /// Total data blocks in filesystem
-+    #[cfg(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+    ))]
-+    pub fn blocks(&self) -> u64 {
-+        self.0.f_blocks
-+    }
-+
-+    /// Total data blocks in filesystem
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn blocks(&self) -> libc::c_long {
-+        self.0.f_blocks
-+    }
-+
-+    /// Total data blocks in filesystem
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn blocks(&self) -> u64 {
-+        self.0.f_blocks
-+    }
-+
-+    /// Total data blocks in filesystem
-+    #[cfg(not(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+        target_os = "dragonfly",
-+        all(target_os = "linux", target_env = "musl")
-+    )))]
-+    pub fn blocks(&self) -> libc::c_ulong {
-+        self.0.f_blocks
-+    }
-+
-+    /// Free blocks in filesystem
-+    #[cfg(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+    ))]
-+    pub fn blocks_free(&self) -> u64 {
-+        self.0.f_bfree
-+    }
-+
-+    /// Free blocks in filesystem
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn blocks_free(&self) -> libc::c_long {
-+        self.0.f_bfree
-+    }
-+
-+    /// Free blocks in filesystem
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn blocks_free(&self) -> u64 {
-+        self.0.f_bfree
-+    }
-+
-+    /// Free blocks in filesystem
-+    #[cfg(not(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+        target_os = "dragonfly",
-+        all(target_os = "linux", target_env = "musl")
-+    )))]
-+    pub fn blocks_free(&self) -> libc::c_ulong {
-+        self.0.f_bfree
-+    }
-+
-+    /// Free blocks available to unprivileged user
-+    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
-+    pub fn blocks_available(&self) -> u64 {
-+        self.0.f_bavail
-+    }
-+
-+    /// Free blocks available to unprivileged user
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn blocks_available(&self) -> libc::c_long {
-+        self.0.f_bavail
-+    }
-+
-+    /// Free blocks available to unprivileged user
-+    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
-+    pub fn blocks_available(&self) -> i64 {
-+        self.0.f_bavail
-+    }
-+
-+    /// Free blocks available to unprivileged user
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn blocks_available(&self) -> u64 {
-+        self.0.f_bavail
-+    }
-+
-+    /// Free blocks available to unprivileged user
-+    #[cfg(not(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+        target_os = "dragonfly",
-+        all(target_os = "linux", target_env = "musl")
-+    )))]
-+    pub fn blocks_available(&self) -> libc::c_ulong {
-+        self.0.f_bavail
-+    }
-+
-+    /// Total file nodes in filesystem
-+    #[cfg(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+    ))]
-+    pub fn files(&self) -> u64 {
-+        self.0.f_files
-+    }
-+
-+    /// Total file nodes in filesystem
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn files(&self) -> libc::c_long {
-+        self.0.f_files
-+    }
-+
-+    /// Total file nodes in filesystem
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn files(&self) -> u64 {
-+        self.0.f_files
-+    }
-+
-+    /// Total file nodes in filesystem
-+    #[cfg(not(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+        target_os = "dragonfly",
-+        all(target_os = "linux", target_env = "musl")
-+    )))]
-+    pub fn files(&self) -> libc::c_ulong {
-+        self.0.f_files
-+    }
-+
-+    /// Free file nodes in filesystem
-+    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
-+    pub fn files_free(&self) -> u64 {
-+        self.0.f_ffree
-+    }
-+
-+    /// Free file nodes in filesystem
-+    #[cfg(target_os = "dragonfly")]
-+    pub fn files_free(&self) -> libc::c_long {
-+        self.0.f_ffree
-+    }
-+
-+    /// Free file nodes in filesystem
-+    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
-+    pub fn files_free(&self) -> i64 {
-+        self.0.f_ffree
-+    }
-+
-+    /// Free file nodes in filesystem
-+    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    pub fn files_free(&self) -> u64 {
-+        self.0.f_ffree
-+    }
-+
-+    /// Free file nodes in filesystem
-+    #[cfg(not(any(
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "openbsd",
-+        target_os = "dragonfly",
-+        all(target_os = "linux", target_env = "musl")
-+    )))]
-+    pub fn files_free(&self) -> libc::c_ulong {
-+        self.0.f_ffree
-+    }
-+
-+    /// Filesystem ID
-+    pub fn filesystem_id(&self) -> fsid_t {
-+        self.0.f_fsid
-+    }
-+}
-+
-+impl Debug for Statfs {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        f.debug_struct("Statfs")
-+            .field("optimal_transfer_size", &self.optimal_transfer_size())
-+            .field("block_size", &self.block_size())
-+            .field("blocks", &self.blocks())
-+            .field("blocks_free", &self.blocks_free())
-+            .field("blocks_available", &self.blocks_available())
-+            .field("files", &self.files())
-+            .field("files_free", &self.files_free())
-+            .field("filesystem_id", &self.filesystem_id())
-+            .finish()
-+    }
-+}
-+
-+pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
-+    unsafe {
-+        let mut stat: Statfs = mem::uninitialized();
-+        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), &mut stat.0))?;
-+        Errno::result(res).map(|_| stat)
-+    }
-+}
-+
-+pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
-+    unsafe {
-+        let mut stat: Statfs = mem::uninitialized();
-+        Errno::result(libc::fstatfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
-+    }
-+}
-+
-+#[cfg(test)]
-+mod test {
-+    use std::fs::File;
-+
-+    use sys::statfs::*;
-+    use sys::statvfs::*;
-+    use std::path::Path;
-+
-+    #[test]
-+    fn statfs_call() {
-+        check_statfs("/tmp");
-+        check_statfs("/dev");
-+        check_statfs("/run");
-+        check_statfs("/");
-+    }
-+
-+    #[test]
-+    fn fstatfs_call() {
-+        check_fstatfs("/tmp");
-+        check_fstatfs("/dev");
-+        check_fstatfs("/run");
-+        check_fstatfs("/");
-+    }
-+
-+    fn check_fstatfs(path: &str) {
-+        if !Path::new(path).exists() {
-+            return;
-+        }
-+        let vfs = statvfs(path.as_bytes()).unwrap();
-+        let file = File::open(path).unwrap();
-+        let fs = fstatfs(&file).unwrap();
-+        assert_fs_equals(fs, vfs);
-+    }
-+
-+    fn check_statfs(path: &str) {
-+        if !Path::new(path).exists() {
-+            return;
-+        }
-+        let vfs = statvfs(path.as_bytes()).unwrap();
-+        let fs = statfs(path.as_bytes()).unwrap();
-+        assert_fs_equals(fs, vfs);
-+    }
-+
-+    fn assert_fs_equals(fs: Statfs, vfs: Statvfs) {
-+        assert_eq!(fs.files() as u64, vfs.files() as u64);
-+        assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
-+        assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
-+    }
-+
-+    // This test is ignored because files_free/blocks_free can change after statvfs call and before
-+    // statfs call.
-+    #[test]
-+    #[ignore]
-+    fn statfs_call_strict() {
-+        check_statfs_strict("/tmp");
-+        check_statfs_strict("/dev");
-+        check_statfs_strict("/run");
-+        check_statfs_strict("/");
-+    }
-+
-+    // This test is ignored because files_free/blocks_free can change after statvfs call and before
-+    // fstatfs call.
-+    #[test]
-+    #[ignore]
-+    fn fstatfs_call_strict() {
-+        check_fstatfs_strict("/tmp");
-+        check_fstatfs_strict("/dev");
-+        check_fstatfs_strict("/run");
-+        check_fstatfs_strict("/");
-+    }
-+
-+    fn check_fstatfs_strict(path: &str) {
-+        if !Path::new(path).exists() {
-+            return;
-+        }
-+        let vfs = statvfs(path.as_bytes());
-+        let file = File::open(path).unwrap();
-+        let fs = fstatfs(&file);
-+        assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
-+    }
-+
-+    fn check_statfs_strict(path: &str) {
-+        if !Path::new(path).exists() {
-+            return;
-+        }
-+        let vfs = statvfs(path.as_bytes());
-+        let fs = statfs(path.as_bytes());
-+        assert_fs_equals_strict(fs.unwrap(), vfs.unwrap())
-+    }
-+
-+    fn assert_fs_equals_strict(fs: Statfs, vfs: Statvfs) {
-+        assert_eq!(fs.files_free() as u64, vfs.files_free() as u64);
-+        assert_eq!(fs.blocks_free() as u64, vfs.blocks_free() as u64);
-+        assert_eq!(fs.blocks_available() as u64, vfs.blocks_available() as u64);
-+        assert_eq!(fs.files() as u64, vfs.files() as u64);
-+        assert_eq!(fs.blocks() as u64, vfs.blocks() as u64);
-+        assert_eq!(fs.block_size() as u64, vfs.fragment_size() as u64);
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/statvfs.rs b/third_party/rust/nix-0.15.0/src/sys/statvfs.rs
-new file mode 100644
-index 0000000000000..e5980369d5119
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/statvfs.rs
-@@ -0,0 +1,160 @@
-+//! Get filesystem statistics
-+//!
-+//! See [the man pages](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html)
-+//! for more details.
-+use std::mem;
-+use std::os::unix::io::AsRawFd;
-+
-+use libc::{self, c_ulong};
-+
-+use {Result, NixPath};
-+use errno::Errno;
-+
-+libc_bitflags!(
-+    /// File system mount Flags
-+    #[repr(C)]
-+    #[derive(Default)]
-+    pub struct FsFlags: c_ulong {
-+        /// Read Only
-+        ST_RDONLY;
-+        /// Do not allow the set-uid bits to have an effect
-+        ST_NOSUID;
-+        /// Do not interpret character or block-special devices
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_NODEV;
-+        /// Do not allow execution of binaries on the filesystem
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_NOEXEC;
-+        /// All IO should be done synchronously
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_SYNCHRONOUS;
-+        /// Allow mandatory locks on the filesystem
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_MANDLOCK;
-+        /// Write on file/directory/symlink
-+        #[cfg(target_os = "linux")]
-+        ST_WRITE;
-+        /// Append-only file
-+        #[cfg(target_os = "linux")]
-+        ST_APPEND;
-+        /// Immutable file
-+        #[cfg(target_os = "linux")]
-+        ST_IMMUTABLE;
-+        /// Do not update access times on files
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_NOATIME;
-+        /// Do not update access times on files
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        ST_NODIRATIME;
-+        /// Update access time relative to modify/change time
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_env = "musl"))))]
-+        ST_RELATIME;
-+    }
-+);
-+
-+/// 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).
-+// FIXME: Replace with repr(transparent)
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct Statvfs(libc::statvfs);
-+
-+impl Statvfs {
-+    /// get the file system block size
-+    pub fn block_size(&self) -> c_ulong {
-+        self.0.f_bsize
-+    }
-+
-+    /// Get the fundamental file system block size
-+    pub fn fragment_size(&self) -> c_ulong {
-+        self.0.f_frsize
-+    }
-+
-+    /// Get the number of blocks.
-+    ///
-+    /// Units are in units of `fragment_size()`
-+    pub fn blocks(&self) -> libc::fsblkcnt_t {
-+        self.0.f_blocks
-+    }
-+
-+    /// Get the number of free blocks in the file system
-+    pub fn blocks_free(&self) -> libc::fsblkcnt_t {
-+        self.0.f_bfree
-+    }
-+
-+    /// Get the number of free blocks for unprivileged users
-+    pub fn blocks_available(&self) -> libc::fsblkcnt_t {
-+        self.0.f_bavail
-+    }
-+
-+    /// Get the total number of file inodes
-+    pub fn files(&self) -> libc::fsfilcnt_t {
-+        self.0.f_files
-+    }
-+
-+    /// Get the number of free file inodes
-+    pub fn files_free(&self) -> libc::fsfilcnt_t {
-+        self.0.f_ffree
-+    }
-+
-+    /// Get the number of free file inodes for unprivileged users
-+    pub fn files_available(&self) -> libc::fsfilcnt_t {
-+        self.0.f_favail
-+    }
-+
-+    /// Get the file system id
-+    pub fn filesystem_id(&self) -> c_ulong {
-+        self.0.f_fsid
-+    }
-+
-+    /// Get the mount flags
-+    pub fn flags(&self) -> FsFlags {
-+        FsFlags::from_bits_truncate(self.0.f_flag)
-+    }
-+
-+    /// Get the maximum filename length
-+    pub fn name_max(&self) -> c_ulong {
-+        self.0.f_namemax
-+    }
-+
-+}
-+
-+/// Return a `Statvfs` object with information about the `path`
-+pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
-+    unsafe {
-+        Errno::clear();
-+        let mut stat: Statvfs = mem::uninitialized();
-+        let res = path.with_nix_path(|path|
-+            libc::statvfs(path.as_ptr(), &mut stat.0)
-+        )?;
-+
-+        Errno::result(res).map(|_| stat)
-+    }
-+}
-+
-+/// Return a `Statvfs` object with information about `fd`
-+pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
-+    unsafe {
-+        Errno::clear();
-+        let mut stat: Statvfs = mem::uninitialized();
-+        Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
-+    }
-+}
-+
-+#[cfg(test)]
-+mod test {
-+    use std::fs::File;
-+    use sys::statvfs::*;
-+
-+    #[test]
-+    fn statvfs_call() {
-+        statvfs("/".as_bytes()).unwrap();
-+    }
-+
-+    #[test]
-+    fn fstatvfs_call() {
-+        let root = File::open("/").unwrap();
-+        fstatvfs(&root).unwrap();
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs b/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
-new file mode 100644
-index 0000000000000..4c8e38988886d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/sysinfo.rs
-@@ -0,0 +1,72 @@
-+use libc::{self, SI_LOAD_SHIFT};
-+use std::{cmp, mem};
-+use std::time::Duration;
-+
-+use Result;
-+use errno::Errno;
-+
-+/// System info structure returned by `sysinfo`.
-+#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+pub struct SysInfo(libc::sysinfo);
-+
-+impl SysInfo {
-+    /// Returns the load average tuple.
-+    ///
-+    /// The returned values represent the load average over time intervals of
-+    /// 1, 5, and 15 minutes, respectively.
-+    pub fn load_average(&self) -> (f64, f64, f64) {
-+        (
-+            self.0.loads[0] as f64 / (1 << SI_LOAD_SHIFT) as f64,
-+            self.0.loads[1] as f64 / (1 << SI_LOAD_SHIFT) as f64,
-+            self.0.loads[2] as f64 / (1 << SI_LOAD_SHIFT) as f64,
-+        )
-+    }
-+
-+    /// Returns the time since system boot.
-+    pub fn uptime(&self) -> Duration {
-+        // Truncate negative values to 0
-+        Duration::from_secs(cmp::max(self.0.uptime, 0) as u64)
-+    }
-+
-+    /// Current number of processes.
-+    pub fn process_count(&self) -> u16 {
-+        self.0.procs
-+    }
-+
-+    /// Returns the amount of swap memory in Bytes.
-+    pub fn swap_total(&self) -> u64 {
-+        self.scale_mem(self.0.totalswap)
-+    }
-+
-+    /// Returns the amount of unused swap memory in Bytes.
-+    pub fn swap_free(&self) -> u64 {
-+        self.scale_mem(self.0.freeswap)
-+    }
-+
-+    /// Returns the total amount of installed RAM in Bytes.
-+    pub fn ram_total(&self) -> u64 {
-+        self.scale_mem(self.0.totalram)
-+    }
-+
-+    /// Returns the amount of completely unused RAM in Bytes.
-+    ///
-+    /// "Unused" in this context means that the RAM in neither actively used by
-+    /// programs, nor by the operating system as disk cache or buffer. It is
-+    /// "wasted" RAM since it currently serves no purpose.
-+    pub fn ram_unused(&self) -> u64 {
-+        self.scale_mem(self.0.freeram)
-+    }
-+
-+    fn scale_mem(&self, units: libc::c_ulong) -> u64 {
-+        units as u64 * self.0.mem_unit as u64
-+    }
-+}
-+
-+/// Returns system information.
-+///
-+/// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
-+pub fn sysinfo() -> Result<SysInfo> {
-+    let mut info: libc::sysinfo = unsafe { mem::uninitialized() };
-+    let res = unsafe { libc::sysinfo(&mut info) };
-+    Errno::result(res).map(|_| SysInfo(info))
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/termios.rs b/third_party/rust/nix-0.15.0/src/sys/termios.rs
-new file mode 100644
-index 0000000000000..c7cdf10b461c1
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/termios.rs
-@@ -0,0 +1,1107 @@
-+//! An interface for controlling asynchronous communication ports
-+//!
-+//! This interface provides a safe wrapper around the termios subsystem defined by POSIX. The
-+//! underlying types are all implemented in libc for most platforms and either wrapped in safer
-+//! 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
-+//! 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.
-+//! As this interface is not used with high-bandwidth information, this should be fine in most
-+//! cases. The primary cost when using this API is that the `Termios` datatype here duplicates the
-+//! standard fields of the underlying `termios` struct and uses safe type wrappers for those fields.
-+//! This means that when crossing the FFI interface to the underlying C library, data is first
-+//! copied into the underlying `termios` struct, then the operation is done, and the data is copied
-+//! back (with additional sanity checking) into the safe wrapper types. The `termios` struct is
-+//! relatively small across all platforms (on the order of 32-64 bytes).
-+//!
-+//! The following examples highlight some of the API use cases such that users coming from using C
-+//! or reading the standard documentation will understand how to use the safe API exposed here.
-+//!
-+//! Example disabling processing of the end-of-file control character:
-+//!
-+//! ```
-+//! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
-+//! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
-+//! # let mut termios = unsafe { Termios::default_uninit() };
-+//! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
-+//! ```
-+//!
-+//! The flags within `Termios` are defined as bitfields using the `bitflags` crate. This provides
-+//! an interface for working with bitfields that is similar to working with the raw unsigned
-+//! integer types but offers type safety because of the internal checking that values will always
-+//! be a valid combination of the defined flags.
-+//!
-+//! An example showing some of the basic operations for interacting with the control flags:
-+//!
-+//! ```
-+//! # use self::nix::sys::termios::{ControlFlags, Termios};
-+//! # let mut termios = unsafe { Termios::default_uninit() };
-+//! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
-+//! termios.control_flags |= ControlFlags::CS5;
-+//! ```
-+//!
-+//! # Baud rates
-+//!
-+//! This API is not consistent across platforms when it comes to `BaudRate`: Android and Linux both
-+//! only support the rates specified by the `BaudRate` enum through their termios API while the BSDs
-+//! support arbitrary baud rates as the values of the `BaudRate` enum constants are the same integer
-+//! value of the constant (`B9600` == `9600`). Therefore the `nix::termios` API uses the following
-+//! conventions:
-+//!
-+//! * `cfgetispeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-+//! * `cfgetospeed()` - Returns `u32` on BSDs, `BaudRate` on Android/Linux
-+//! * `cfsetispeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-+//! * `cfsetospeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-+//! * `cfsetspeed()` - Takes `u32` or `BaudRate` on BSDs, `BaudRate` on Android/Linux
-+//!
-+//! The most common use case of specifying a baud rate using the enum will work the same across
-+//! platforms:
-+//!
-+//! ```rust
-+//! # #[macro_use] extern crate nix;
-+//! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! cfsetispeed(&mut t, BaudRate::B9600);
-+//! cfsetospeed(&mut t, BaudRate::B9600);
-+//! cfsetspeed(&mut t, BaudRate::B9600);
-+//! # }
-+//! ```
-+//!
-+//! Additionally round-tripping baud rates is consistent across platforms:
-+//!
-+//! ```rust
-+//! # extern crate nix;
-+//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # cfsetspeed(&mut t, BaudRate::B9600);
-+//! let speed = cfgetispeed(&t);
-+//! assert!(speed == cfgetospeed(&t));
-+//! cfsetispeed(&mut t, speed);
-+//! # }
-+//! ```
-+//!
-+//! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
-+//!
-+// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
-+#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-+            doc = " ```rust,ignore")]
-+#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-+            doc = " ```rust")]
-+//! # extern crate nix;
-+//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # cfsetspeed(&mut t, BaudRate::B9600);
-+//! assert!(cfgetispeed(&t) == BaudRate::B9600);
-+//! assert!(cfgetospeed(&t) == BaudRate::B9600);
-+//! # }
-+//! ```
-+//!
-+//! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
-+//!
-+// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
-+#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-+            doc = " ```rust")]
-+#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-+            doc = " ```rust,ignore")]
-+//! # extern crate nix;
-+//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # cfsetspeed(&mut t, 9600u32);
-+//! assert!(cfgetispeed(&t) == 9600u32);
-+//! assert!(cfgetospeed(&t) == 9600u32);
-+//! # }
-+//! ```
-+//!
-+//! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
-+//!
-+// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
-+#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-+            doc = " ```rust")]
-+#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-+            doc = " ```rust,ignore")]
-+//! # extern crate nix;
-+//! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # cfsetspeed(&mut t, 9600u32);
-+//! assert!(cfgetispeed(&t) == BaudRate::B9600.into());
-+//! assert!(u32::from(BaudRate::B9600) == 9600u32);
-+//! # }
-+//! ```
-+//!
-+//! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
-+//! by specifying baud rates directly using `u32`s:
-+//!
-+// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
-+#![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-+            doc = " ```rust")]
-+#![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-+                    target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-+            doc = " ```rust,ignore")]
-+//! # extern crate nix;
-+//! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
-+//! # fn main() {
-+//! # let mut t = unsafe { Termios::default_uninit() };
-+//! cfsetispeed(&mut t, 9600u32);
-+//! cfsetospeed(&mut t, 9600u32);
-+//! cfsetspeed(&mut t, 9600u32);
-+//! # }
-+//! ```
-+use Result;
-+use errno::Errno;
-+use libc::{self, c_int, tcflag_t};
-+use std::cell::{Ref, RefCell};
-+use std::convert::From;
-+use std::mem;
-+use std::os::unix::io::RawFd;
-+
-+use ::unistd::Pid;
-+
-+/// Stores settings for the termios API
-+///
-+/// This is a wrapper around the `libc::termios` struct that provides a safe interface for the
-+/// standard fields. The only safe way to obtain an instance of this struct is to extract it from
-+/// an open port using `tcgetattr()`.
-+#[derive(Clone, Debug, Eq, PartialEq)]
-+pub struct Termios {
-+    inner: RefCell<libc::termios>,
-+    /// Input mode flags (see `termios.c_iflag` documentation)
-+    pub input_flags: InputFlags,
-+    /// Output mode flags (see `termios.c_oflag` documentation)
-+    pub output_flags: OutputFlags,
-+    /// Control mode flags (see `termios.c_cflag` documentation)
-+    pub control_flags: ControlFlags,
-+    /// Local mode flags (see `termios.c_lflag` documentation)
-+    pub local_flags: LocalFlags,
-+    /// Control characters (see `termios.c_cc` documentation)
-+    pub control_chars: [libc::cc_t; NCCS],
-+}
-+
-+impl Termios {
-+    /// Exposes an immutable reference to the underlying `libc::termios` data structure.
-+    ///
-+    /// This can be used for interfacing with other FFI functions like:
-+    ///
-+    /// ```rust
-+    /// # extern crate libc;
-+    /// # extern crate nix;
-+    /// # fn main() {
-+    /// # use nix::sys::termios::Termios;
-+    /// # let mut termios = unsafe { Termios::default_uninit() };
-+    /// let inner_termios = termios.get_libc_termios();
-+    /// unsafe { libc::cfgetispeed(&*inner_termios) };
-+    /// # }
-+    /// ```
-+    ///
-+    /// There is no public API exposed for functions that modify the underlying `libc::termios`
-+    /// data because it requires additional work to maintain type safety.
-+    // FIXME: Switch this over to use pub(crate)
-+    #[doc(hidden)]
-+    pub fn get_libc_termios(&self) -> Ref<libc::termios> {
-+        {
-+            let mut termios = self.inner.borrow_mut();
-+            termios.c_iflag = self.input_flags.bits();
-+            termios.c_oflag = self.output_flags.bits();
-+            termios.c_cflag = self.control_flags.bits();
-+            termios.c_lflag = self.local_flags.bits();
-+            termios.c_cc = self.control_chars;
-+        }
-+        self.inner.borrow()
-+    }
-+
-+    /// Exposes the inner `libc::termios` datastore within `Termios`.
-+    ///
-+    /// This is unsafe because if this is used to modify the inner libc::termios struct, it will not
-+    /// automatically update the safe wrapper type around it. Therefore we disable docs to
-+    /// effectively limit its use to nix internals. In this case it should also be paired with a
-+    /// call to `update_wrapper()` so that the wrapper-type and internal representation stay
-+    /// consistent.
-+    unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
-+        {
-+            let mut termios = self.inner.borrow_mut();
-+            termios.c_iflag = self.input_flags.bits();
-+            termios.c_oflag = self.output_flags.bits();
-+            termios.c_cflag = self.control_flags.bits();
-+            termios.c_lflag = self.local_flags.bits();
-+            termios.c_cc = self.control_chars;
-+        }
-+        self.inner.as_ptr()
-+    }
-+
-+    /// Allows for easily creating new `Termios` structs that will be overwritten with real data.
-+    ///
-+    /// This should only be used when the inner libc::termios struct will be overwritten before it's
-+    /// read.
-+    // FIXME: Switch this over to use pub(crate)
-+    #[doc(hidden)]
-+    pub unsafe fn default_uninit() -> Self {
-+        Termios {
-+            inner: RefCell::new(mem::uninitialized()),
-+            input_flags: InputFlags::empty(),
-+            output_flags: OutputFlags::empty(),
-+            control_flags: ControlFlags::empty(),
-+            local_flags: LocalFlags::empty(),
-+            control_chars: [0 as libc::cc_t; NCCS],
-+        }
-+    }
-+
-+    /// Updates the wrapper values from the internal `libc::termios` data structure.
-+    #[doc(hidden)]
-+    pub fn update_wrapper(&mut self) {
-+        let termios = *self.inner.borrow_mut();
-+        self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
-+        self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
-+        self.control_flags = ControlFlags::from_bits_truncate(termios.c_cflag);
-+        self.local_flags = LocalFlags::from_bits_truncate(termios.c_lflag);
-+        self.control_chars = termios.c_cc;
-+    }
-+}
-+
-+impl From<libc::termios> for Termios {
-+    fn from(termios: libc::termios) -> Self {
-+        Termios {
-+            inner: RefCell::new(termios),
-+            input_flags: InputFlags::from_bits_truncate(termios.c_iflag),
-+            output_flags: OutputFlags::from_bits_truncate(termios.c_oflag),
-+            control_flags: ControlFlags::from_bits_truncate(termios.c_cflag),
-+            local_flags: LocalFlags::from_bits_truncate(termios.c_lflag),
-+            control_chars: termios.c_cc,
-+        }
-+    }
-+}
-+
-+impl From<Termios> for libc::termios {
-+    fn from(termios: Termios) -> Self {
-+        termios.inner.into_inner()
-+    }
-+}
-+
-+libc_enum!{
-+    /// Baud rates supported by the system.
-+    ///
-+    /// For the BSDs, arbitrary baud rates can be specified by using `u32`s directly instead of this
-+    /// enum.
-+    ///
-+    /// B0 is special and will disable the port.
-+    #[cfg_attr(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64"), repr(u64))]
-+    #[cfg_attr(not(all(any(target_os = "ios", target_os = "macos"), target_pointer_width = "64")), repr(u32))]
-+    pub enum BaudRate {
-+        B0,
-+        B50,
-+        B75,
-+        B110,
-+        B134,
-+        B150,
-+        B200,
-+        B300,
-+        B600,
-+        B1200,
-+        B1800,
-+        B2400,
-+        B4800,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        B7200,
-+        B9600,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        B14400,
-+        B19200,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        B28800,
-+        B38400,
-+        B57600,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        B76800,
-+        B115200,
-+        B230400,
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd"))]
-+        B460800,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B500000,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B576000,
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd"))]
-+        B921600,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B1000000,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B1152000,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B1500000,
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        B2000000,
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+        B2500000,
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+        B3000000,
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+        B3500000,
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+        B4000000,
-+    }
-+}
-+
-+impl From<libc::speed_t> for BaudRate {
-+    fn from(s: libc::speed_t) -> BaudRate {
-+
-+        use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
-+                   B9600, B19200, B38400, B57600, B115200, B230400};
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        use libc::{B500000, B576000, B1000000, B1152000, B1500000, B2000000};
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+        use libc::{B2500000, B3000000, B3500000, B4000000};
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        use libc::{B7200, B14400, B28800, B76800};
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "linux",
-+                  target_os = "netbsd"))]
-+        use libc::{B460800, B921600};
-+
-+        match s {
-+            B0 => BaudRate::B0,
-+            B50 => BaudRate::B50,
-+            B75 => BaudRate::B75,
-+            B110 => BaudRate::B110,
-+            B134 => BaudRate::B134,
-+            B150 => BaudRate::B150,
-+            B200 => BaudRate::B200,
-+            B300 => BaudRate::B300,
-+            B600 => BaudRate::B600,
-+            B1200 => BaudRate::B1200,
-+            B1800 => BaudRate::B1800,
-+            B2400 => BaudRate::B2400,
-+            B4800 => BaudRate::B4800,
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            B7200 => BaudRate::B7200,
-+            B9600 => BaudRate::B9600,
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            B14400 => BaudRate::B14400,
-+            B19200 => BaudRate::B19200,
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            B28800 => BaudRate::B28800,
-+            B38400 => BaudRate::B38400,
-+            B57600 => BaudRate::B57600,
-+            #[cfg(any(target_os = "dragonfly",
-+                      target_os = "freebsd",
-+                      target_os = "macos",
-+                      target_os = "netbsd",
-+                      target_os = "openbsd"))]
-+            B76800 => BaudRate::B76800,
-+            B115200 => BaudRate::B115200,
-+            B230400 => BaudRate::B230400,
-+            #[cfg(any(target_os = "android",
-+                      target_os = "freebsd",
-+                      target_os = "linux",
-+                      target_os = "netbsd"))]
-+            B460800 => BaudRate::B460800,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B500000 => BaudRate::B500000,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B576000 => BaudRate::B576000,
-+            #[cfg(any(target_os = "android",
-+                      target_os = "freebsd",
-+                      target_os = "linux",
-+                      target_os = "netbsd"))]
-+            B921600 => BaudRate::B921600,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B1000000 => BaudRate::B1000000,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B1152000 => BaudRate::B1152000,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B1500000 => BaudRate::B1500000,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            B2000000 => BaudRate::B2000000,
-+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+            B2500000 => BaudRate::B2500000,
-+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+            B3000000 => BaudRate::B3000000,
-+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+            B3500000 => BaudRate::B3500000,
-+            #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
-+            B4000000 => BaudRate::B4000000,
-+            b => unreachable!("Invalid baud constant: {}", b),
-+        }
-+    }
-+}
-+
-+// TODO: Include `TryFrom<u32> for BaudRate` once that API stabilizes
-+#[cfg(any(target_os = "freebsd",
-+          target_os = "dragonfly",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+impl From<BaudRate> for u32 {
-+    fn from(b: BaudRate) -> u32 {
-+        b as u32
-+    }
-+}
-+
-+// TODO: Add TCSASOFT, which will require treating this as a bitfield.
-+libc_enum! {
-+    /// Specify when a port configuration change should occur.
-+    ///
-+    /// Used as an argument to `tcsetattr()`
-+    #[repr(i32)]
-+    pub enum SetArg {
-+        /// The change will occur immediately
-+        TCSANOW,
-+        /// The change occurs after all output has been written
-+        TCSADRAIN,
-+        /// Same as `TCSADRAIN`, but will also flush the input buffer
-+        TCSAFLUSH,
-+    }
-+}
-+
-+libc_enum! {
-+    /// Specify a combination of the input and output buffers to flush
-+    ///
-+    /// Used as an argument to `tcflush()`.
-+    #[repr(i32)]
-+    pub enum FlushArg {
-+        /// Flush data that was received but not read
-+        TCIFLUSH,
-+        /// Flush data written but not transmitted
-+        TCOFLUSH,
-+        /// Flush both received data not read and written data not transmitted
-+        TCIOFLUSH,
-+    }
-+}
-+
-+libc_enum! {
-+    /// Specify how transmission flow should be altered
-+    ///
-+    /// Used as an argument to `tcflow()`.
-+    #[repr(i32)]
-+    pub enum FlowArg {
-+        /// Suspend transmission
-+        TCOOFF,
-+        /// Resume transmission
-+        TCOON,
-+        /// Transmit a STOP character, which should disable a connected terminal device
-+        TCIOFF,
-+        /// Transmit a START character, which should re-enable a connected terminal device
-+        TCION,
-+    }
-+}
-+
-+// TODO: Make this usable directly as a slice index.
-+libc_enum! {
-+    /// Indices into the `termios.c_cc` array for special characters.
-+    #[repr(usize)]
-+    pub enum SpecialCharacterIndices {
-+        VDISCARD,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        VDSUSP,
-+        VEOF,
-+        VEOL,
-+        VEOL2,
-+        VERASE,
-+        #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+        VERASE2,
-+        VINTR,
-+        VKILL,
-+        VLNEXT,
-+        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
-+        VMIN,
-+        VQUIT,
-+        VREPRINT,
-+        VSTART,
-+        #[cfg(any(target_os = "dragonfly",
-+                target_os = "freebsd",
-+                target_os = "macos",
-+                target_os = "netbsd",
-+                target_os = "openbsd"))]
-+        VSTATUS,
-+        VSTOP,
-+        VSUSP,
-+        #[cfg(target_os = "linux")]
-+        VSWTC,
-+        #[cfg(target_os = "haiku")]
-+        VSWTCH,
-+        #[cfg(not(all(target_os = "linux", target_arch = "sparc64")))]
-+        VTIME,
-+        VWERASE,
-+        #[cfg(target_os = "dragonfly")]
-+        VCHECKPT,
-+    }
-+}
-+
-+pub use libc::NCCS;
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub use libc::_POSIX_VDISABLE;
-+
-+libc_bitflags! {
-+    /// Flags for configuring the input mode of a terminal
-+    pub struct InputFlags: tcflag_t {
-+        IGNBRK;
-+        BRKINT;
-+        IGNPAR;
-+        PARMRK;
-+        INPCK;
-+        ISTRIP;
-+        INLCR;
-+        IGNCR;
-+        ICRNL;
-+        IXON;
-+        IXOFF;
-+        IXANY;
-+        IMAXBEL;
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
-+        IUTF8;
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Flags for configuring the output mode of a terminal
-+    pub struct OutputFlags: tcflag_t {
-+        OPOST;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "linux",
-+                  target_os = "openbsd"))]
-+        OLCUC;
-+        ONLCR;
-+        OCRNL as tcflag_t;
-+        ONOCR as tcflag_t;
-+        ONLRET as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        OFILL as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        OFDEL as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        NL0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        NL1 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        CR0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        CR1 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        CR2 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        CR3 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        TAB0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        TAB1 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        TAB2 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        TAB3 as tcflag_t;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        XTABS;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        BS0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        BS1 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        VT0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        VT1 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        FF0 as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        FF1 as tcflag_t;
-+        #[cfg(any(target_os = "freebsd",
-+                  target_os = "dragonfly",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        OXTABS;
-+        #[cfg(any(target_os = "freebsd",
-+                  target_os = "dragonfly",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        ONOEOT as tcflag_t;
-+
-+        // Bitmasks for use with OutputFlags to select specific settings
-+        // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
-+        // is resolved.
-+
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        NLDLY as tcflag_t; // FIXME: Datatype needs to be corrected in libc for mac
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        CRDLY as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        TABDLY as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        BSDLY as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        VTDLY as tcflag_t;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos"))]
-+        FFDLY as tcflag_t;
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Flags for setting the control mode of a terminal
-+    pub struct ControlFlags: tcflag_t {
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        CIGNORE;
-+        CS5;
-+        CS6;
-+        CS7;
-+        CS8;
-+        CSTOPB;
-+        CREAD;
-+        PARENB;
-+        PARODD;
-+        HUPCL;
-+        CLOCAL;
-+        CRTSCTS;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        CBAUD;
-+        #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "mips"))))]
-+        CMSPAR;
-+        #[cfg(any(target_os = "android",
-+                  all(target_os = "linux",
-+                      not(any(target_arch = "powerpc", target_arch = "powerpc64")))))]
-+        CIBAUD;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        CBAUDEX;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        MDMBUF;
-+        #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
-+        CHWFLOW;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        CCTS_OFLOW;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        CRTS_IFLOW;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd"))]
-+        CDTR_IFLOW;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd"))]
-+        CDSR_OFLOW;
-+        #[cfg(any(target_os = "dragonfly",
-+                  target_os = "freebsd"))]
-+        CCAR_OFLOW;
-+
-+        // Bitmasks for use with ControlFlags to select specific settings
-+        // These should be moved to be a mask once https://github.com/rust-lang-nursery/bitflags/issues/110
-+        // is resolved.
-+
-+        CSIZE;
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Flags for setting any local modes
-+    pub struct LocalFlags: tcflag_t {
-+        ECHOKE;
-+        ECHOE;
-+        ECHOK;
-+        ECHO;
-+        ECHONL;
-+        ECHOPRT;
-+        ECHOCTL;
-+        ISIG;
-+        ICANON;
-+        #[cfg(any(target_os = "freebsd",
-+                  target_os = "dragonfly",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        ALTWERASE;
-+        IEXTEN;
-+        EXTPROC;
-+        TOSTOP;
-+        FLUSHO;
-+        #[cfg(any(target_os = "freebsd",
-+                  target_os = "dragonfly",
-+                  target_os = "ios",
-+                  target_os = "macos",
-+                  target_os = "netbsd",
-+                  target_os = "openbsd"))]
-+        NOKERNINFO;
-+        PENDIN;
-+        NOFLSH;
-+    }
-+}
-+
-+cfg_if!{
-+    if #[cfg(any(target_os = "freebsd",
-+                 target_os = "dragonfly",
-+                 target_os = "ios",
-+                 target_os = "macos",
-+                 target_os = "netbsd",
-+                 target_os = "openbsd"))] {
-+        /// Get input baud rate (see
-+        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
-+        ///
-+        /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
-+        pub fn cfgetispeed(termios: &Termios) -> u32 {
-+            let inner_termios = termios.get_libc_termios();
-+            unsafe { libc::cfgetispeed(&*inner_termios) as u32 }
-+        }
-+
-+        /// Get output baud rate (see
-+        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
-+        ///
-+        /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
-+        pub fn cfgetospeed(termios: &Termios) -> u32 {
-+            let inner_termios = termios.get_libc_termios();
-+            unsafe { libc::cfgetospeed(&*inner_termios) as u32 }
-+        }
-+
-+        /// Set input baud rate (see
-+        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
-+        ///
-+        /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
-+        pub fn cfsetispeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetispeed(inner_termios, baud.into() as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+
-+        /// Set output baud rate (see
-+        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
-+        ///
-+        /// `cfsetospeed()` sets the output baud rate in the given termios structure.
-+        pub fn cfsetospeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetospeed(inner_termios, baud.into() as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+
-+        /// Set both the input and output baud rates (see
-+        /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
-+        ///
-+        /// `cfsetspeed()` sets the input and output baud rate in the given termios structure. Note that
-+        /// this is part of the 4.4BSD standard and not part of POSIX.
-+        pub fn cfsetspeed<T: Into<u32>>(termios: &mut Termios, baud: T) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetspeed(inner_termios, baud.into() as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+    } else {
-+        /// Get input baud rate (see
-+        /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
-+        ///
-+        /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
-+        pub fn cfgetispeed(termios: &Termios) -> BaudRate {
-+            let inner_termios = termios.get_libc_termios();
-+            unsafe { libc::cfgetispeed(&*inner_termios) }.into()
-+        }
-+
-+        /// Get output baud rate (see
-+        /// [cfgetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetospeed.html)).
-+        ///
-+        /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
-+        pub fn cfgetospeed(termios: &Termios) -> BaudRate {
-+            let inner_termios = termios.get_libc_termios();
-+            unsafe { libc::cfgetospeed(&*inner_termios) }.into()
-+        }
-+
-+        /// Set input baud rate (see
-+        /// [cfsetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetispeed.html)).
-+        ///
-+        /// `cfsetispeed()` sets the intput baud rate in the given `Termios` structure.
-+        pub fn cfsetispeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetispeed(inner_termios, baud as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+
-+        /// Set output baud rate (see
-+        /// [cfsetospeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfsetospeed.html)).
-+        ///
-+        /// `cfsetospeed()` sets the output baud rate in the given `Termios` structure.
-+        pub fn cfsetospeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetospeed(inner_termios, baud as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+
-+        /// Set both the input and output baud rates (see
-+        /// [termios(3)](https://www.freebsd.org/cgi/man.cgi?query=cfsetspeed)).
-+        ///
-+        /// `cfsetspeed()` sets the input and output baud rate in the given `Termios` structure. Note that
-+        /// this is part of the 4.4BSD standard and not part of POSIX.
-+        pub fn cfsetspeed(termios: &mut Termios, baud: BaudRate) -> Result<()> {
-+            let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+            let res = unsafe { libc::cfsetspeed(inner_termios, baud as libc::speed_t) };
-+            termios.update_wrapper();
-+            Errno::result(res).map(drop)
-+        }
-+    }
-+}
-+
-+/// 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)).
-+///
-+/// `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
-+/// that this is a non-standard function, but is available on Linux and BSDs.
-+pub fn cfmakeraw(termios: &mut Termios) {
-+    let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+    unsafe {
-+        libc::cfmakeraw(inner_termios);
-+    }
-+    termios.update_wrapper();
-+}
-+
-+/// Configures the port to "sane" mode (like the configuration of a newly created terminal) (see
-+/// [tcsetattr(3)](https://www.freebsd.org/cgi/man.cgi?query=tcsetattr)).
-+///
-+/// Note that this is a non-standard function, available on FreeBSD.
-+#[cfg(target_os = "freebsd")]
-+pub fn cfmakesane(termios: &mut Termios) {
-+    let inner_termios = unsafe { termios.get_libc_termios_mut() };
-+    unsafe {
-+        libc::cfmakesane(inner_termios);
-+    }
-+    termios.update_wrapper();
-+}
-+
-+/// Return the configuration of a port
-+/// [tcgetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)).
-+///
-+/// `tcgetattr()` returns a `Termios` structure with the current configuration for a port. Modifying
-+/// this structure *will not* reconfigure the port, instead the modifications should be done to
-+/// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
-+pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
-+    let mut termios: libc::termios = unsafe { mem::uninitialized() };
-+
-+    let res = unsafe { libc::tcgetattr(fd, &mut termios) };
-+
-+    Errno::result(res)?;
-+
-+    Ok(termios.into())
-+}
-+
-+/// Set the configuration for a terminal (see
-+/// [tcsetattr(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetattr.html)).
-+///
-+/// `tcsetattr()` reconfigures the given port based on a given `Termios` structure. This change
-+/// takes affect at a time specified by `actions`. Note that this function may return success if
-+/// *any* of the parameters were successfully set, not only if all were set successfully.
-+pub fn tcsetattr(fd: RawFd, actions: SetArg, termios: &Termios) -> Result<()> {
-+    let inner_termios = termios.get_libc_termios();
-+    Errno::result(unsafe { libc::tcsetattr(fd, actions as c_int, &*inner_termios) }).map(drop)
-+}
-+
-+/// Block until all output data is written (see
-+/// [tcdrain(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcdrain.html)).
-+pub fn tcdrain(fd: RawFd) -> Result<()> {
-+    Errno::result(unsafe { libc::tcdrain(fd) }).map(drop)
-+}
-+
-+/// Suspend or resume the transmission or reception of data (see
-+/// [tcflow(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflow.html)).
-+///
-+/// `tcflow()` suspends of resumes the transmission or reception of data for the given port
-+/// depending on the value of `action`.
-+pub fn tcflow(fd: RawFd, action: FlowArg) -> Result<()> {
-+    Errno::result(unsafe { libc::tcflow(fd, action as c_int) }).map(drop)
-+}
-+
-+/// Discard data in the output or input queue (see
-+/// [tcflush(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcflush.html)).
-+///
-+/// `tcflush()` will discard data for a terminal port in the input queue, output queue, or both
-+/// depending on the value of `action`.
-+pub fn tcflush(fd: RawFd, action: FlushArg) -> Result<()> {
-+    Errno::result(unsafe { libc::tcflush(fd, action as c_int) }).map(drop)
-+}
-+
-+/// Send a break for a specific duration (see
-+/// [tcsendbreak(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsendbreak.html)).
-+///
-+/// When using asynchronous data transmission `tcsendbreak()` will transmit a continuous stream
-+/// of zero-valued bits for an implementation-defined duration.
-+pub fn tcsendbreak(fd: RawFd, duration: c_int) -> Result<()> {
-+    Errno::result(unsafe { libc::tcsendbreak(fd, duration) }).map(drop)
-+}
-+
-+/// Get the session controlled by the given terminal (see
-+/// [tcgetsid(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetsid.html)).
-+pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
-+    let res = unsafe { libc::tcgetsid(fd) };
-+
-+    Errno::result(res).map(Pid::from_raw)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/time.rs b/third_party/rust/nix-0.15.0/src/sys/time.rs
-new file mode 100644
-index 0000000000000..3ad57543b18a7
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/time.rs
-@@ -0,0 +1,542 @@
-+use std::{cmp, fmt, ops};
-+use std::convert::From;
-+use libc::{c_long, timespec, timeval};
-+pub use libc::{time_t, suseconds_t};
-+
-+pub trait TimeValLike: Sized {
-+    #[inline]
-+    fn zero() -> Self {
-+        Self::seconds(0)
-+    }
-+
-+    #[inline]
-+    fn hours(hours: i64) -> Self {
-+        let secs = hours.checked_mul(SECS_PER_HOUR)
-+            .expect("TimeValLike::hours ouf of bounds");
-+        Self::seconds(secs)
-+    }
-+
-+    #[inline]
-+    fn minutes(minutes: i64) -> Self {
-+        let secs = minutes.checked_mul(SECS_PER_MINUTE)
-+            .expect("TimeValLike::minutes out of bounds");
-+        Self::seconds(secs)
-+    }
-+
-+    fn seconds(seconds: i64) -> Self;
-+    fn milliseconds(milliseconds: i64) -> Self;
-+    fn microseconds(microseconds: i64) -> Self;
-+    fn nanoseconds(nanoseconds: i64) -> Self;
-+
-+    #[inline]
-+    fn num_hours(&self) -> i64 {
-+        self.num_seconds() / 3600
-+    }
-+
-+    #[inline]
-+    fn num_minutes(&self) -> i64 {
-+        self.num_seconds() / 60
-+    }
-+
-+    fn num_seconds(&self) -> i64;
-+    fn num_milliseconds(&self) -> i64;
-+    fn num_microseconds(&self) -> i64;
-+    fn num_nanoseconds(&self) -> i64;
-+}
-+
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct TimeSpec(timespec);
-+
-+const NANOS_PER_SEC: i64 = 1_000_000_000;
-+const SECS_PER_MINUTE: i64 = 60;
-+const SECS_PER_HOUR: i64 = 3600;
-+
-+#[cfg(target_pointer_width = "64")]
-+const TS_MAX_SECONDS: i64 = (::std::i64::MAX / NANOS_PER_SEC) - 1;
-+
-+#[cfg(target_pointer_width = "32")]
-+const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
-+
-+const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
-+
-+
-+impl AsRef<timespec> for TimeSpec {
-+    fn as_ref(&self) -> &timespec {
-+        &self.0
-+    }
-+}
-+
-+impl Ord for TimeSpec {
-+    // The implementation of cmp is simplified by assuming that the struct is
-+    // normalized.  That is, tv_nsec must always be within [0, 1_000_000_000)
-+    fn cmp(&self, other: &TimeSpec) -> cmp::Ordering {
-+        if self.tv_sec() == other.tv_sec() {
-+            self.tv_nsec().cmp(&other.tv_nsec())
-+        } else {
-+            self.tv_sec().cmp(&other.tv_sec())
-+        }
-+    }
-+}
-+
-+impl PartialOrd for TimeSpec {
-+    fn partial_cmp(&self, other: &TimeSpec) -> Option<cmp::Ordering> {
-+        Some(self.cmp(other))
-+    }
-+}
-+
-+impl TimeValLike for TimeSpec {
-+    #[inline]
-+    fn seconds(seconds: i64) -> TimeSpec {
-+        assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
-+                "TimeSpec out of bounds; seconds={}", seconds);
-+        TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
-+    }
-+
-+    #[inline]
-+    fn milliseconds(milliseconds: i64) -> TimeSpec {
-+        let nanoseconds = milliseconds.checked_mul(1_000_000)
-+            .expect("TimeSpec::milliseconds out of bounds");
-+
-+        TimeSpec::nanoseconds(nanoseconds)
-+    }
-+
-+    /// Makes a new `TimeSpec` with given number of microseconds.
-+    #[inline]
-+    fn microseconds(microseconds: i64) -> TimeSpec {
-+        let nanoseconds = microseconds.checked_mul(1_000)
-+            .expect("TimeSpec::milliseconds out of bounds");
-+
-+        TimeSpec::nanoseconds(nanoseconds)
-+    }
-+
-+    /// Makes a new `TimeSpec` with given number of nanoseconds.
-+    #[inline]
-+    fn nanoseconds(nanoseconds: i64) -> TimeSpec {
-+        let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
-+        assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
-+                "TimeSpec out of bounds");
-+        TimeSpec(timespec {tv_sec: secs as time_t,
-+                           tv_nsec: nanos as c_long })
-+    }
-+
-+    fn num_seconds(&self) -> i64 {
-+        if self.tv_sec() < 0 && self.tv_nsec() > 0 {
-+            (self.tv_sec() + 1) as i64
-+        } else {
-+            self.tv_sec() as i64
-+        }
-+    }
-+
-+    fn num_milliseconds(&self) -> i64 {
-+        self.num_nanoseconds() / 1_000_000
-+    }
-+
-+    fn num_microseconds(&self) -> i64 {
-+        self.num_nanoseconds() / 1_000_000_000
-+    }
-+
-+    fn num_nanoseconds(&self) -> i64 {
-+        let secs = self.num_seconds() * 1_000_000_000;
-+        let nsec = self.nanos_mod_sec();
-+        secs + nsec as i64
-+    }
-+}
-+
-+impl TimeSpec {
-+    fn nanos_mod_sec(&self) -> c_long {
-+        if self.tv_sec() < 0 && self.tv_nsec() > 0 {
-+            self.tv_nsec() - NANOS_PER_SEC as c_long
-+        } else {
-+            self.tv_nsec()
-+        }
-+    }
-+
-+    pub fn tv_sec(&self) -> time_t {
-+        self.0.tv_sec
-+    }
-+
-+    pub fn tv_nsec(&self) -> c_long {
-+        self.0.tv_nsec
-+    }
-+}
-+
-+impl ops::Neg for TimeSpec {
-+    type Output = TimeSpec;
-+
-+    fn neg(self) -> TimeSpec {
-+        TimeSpec::nanoseconds(-self.num_nanoseconds())
-+    }
-+}
-+
-+impl ops::Add for TimeSpec {
-+    type Output = TimeSpec;
-+
-+    fn add(self, rhs: TimeSpec) -> TimeSpec {
-+        TimeSpec::nanoseconds(
-+            self.num_nanoseconds() + rhs.num_nanoseconds())
-+    }
-+}
-+
-+impl ops::Sub for TimeSpec {
-+    type Output = TimeSpec;
-+
-+    fn sub(self, rhs: TimeSpec) -> TimeSpec {
-+        TimeSpec::nanoseconds(
-+            self.num_nanoseconds() - rhs.num_nanoseconds())
-+    }
-+}
-+
-+impl ops::Mul<i32> for TimeSpec {
-+    type Output = TimeSpec;
-+
-+    fn mul(self, rhs: i32) -> TimeSpec {
-+        let usec = self.num_nanoseconds().checked_mul(rhs as i64)
-+            .expect("TimeSpec multiply out of bounds");
-+
-+        TimeSpec::nanoseconds(usec)
-+    }
-+}
-+
-+impl ops::Div<i32> for TimeSpec {
-+    type Output = TimeSpec;
-+
-+    fn div(self, rhs: i32) -> TimeSpec {
-+        let usec = self.num_nanoseconds() / rhs as i64;
-+        TimeSpec::nanoseconds(usec)
-+    }
-+}
-+
-+impl fmt::Display for TimeSpec {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        let (abs, sign) = if self.tv_sec() < 0 {
-+            (-*self, "-")
-+        } else {
-+            (*self, "")
-+        };
-+
-+        let sec = abs.tv_sec();
-+
-+        write!(f, "{}", sign)?;
-+
-+        if abs.tv_nsec() == 0 {
-+            if abs.tv_sec() == 1 {
-+                write!(f, "{} second", sec)?;
-+            } else {
-+                write!(f, "{} seconds", sec)?;
-+            }
-+        } else if abs.tv_nsec() % 1_000_000 == 0 {
-+            write!(f, "{}.{:03} seconds", sec, abs.tv_nsec() / 1_000_000)?;
-+        } else if abs.tv_nsec() % 1_000 == 0 {
-+            write!(f, "{}.{:06} seconds", sec, abs.tv_nsec() / 1_000)?;
-+        } else {
-+            write!(f, "{}.{:09} seconds", sec, abs.tv_nsec())?;
-+        }
-+
-+        Ok(())
-+    }
-+}
-+
-+
-+
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct TimeVal(timeval);
-+
-+const MICROS_PER_SEC: i64 = 1_000_000;
-+
-+#[cfg(target_pointer_width = "64")]
-+const TV_MAX_SECONDS: i64 = (::std::i64::MAX / MICROS_PER_SEC) - 1;
-+
-+#[cfg(target_pointer_width = "32")]
-+const TV_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
-+
-+const TV_MIN_SECONDS: i64 = -TV_MAX_SECONDS;
-+
-+impl AsRef<timeval> for TimeVal {
-+    fn as_ref(&self) -> &timeval {
-+        &self.0
-+    }
-+}
-+
-+impl Ord for TimeVal {
-+    // The implementation of cmp is simplified by assuming that the struct is
-+    // normalized.  That is, tv_usec must always be within [0, 1_000_000)
-+    fn cmp(&self, other: &TimeVal) -> cmp::Ordering {
-+        if self.tv_sec() == other.tv_sec() {
-+            self.tv_usec().cmp(&other.tv_usec())
-+        } else {
-+            self.tv_sec().cmp(&other.tv_sec())
-+        }
-+    }
-+}
-+
-+impl PartialOrd for TimeVal {
-+    fn partial_cmp(&self, other: &TimeVal) -> Option<cmp::Ordering> {
-+        Some(self.cmp(other))
-+    }
-+}
-+
-+impl TimeValLike for TimeVal {
-+    #[inline]
-+    fn seconds(seconds: i64) -> TimeVal {
-+        assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
-+                "TimeVal out of bounds; seconds={}", seconds);
-+        TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
-+    }
-+
-+    #[inline]
-+    fn milliseconds(milliseconds: i64) -> TimeVal {
-+        let microseconds = milliseconds.checked_mul(1_000)
-+            .expect("TimeVal::milliseconds out of bounds");
-+
-+        TimeVal::microseconds(microseconds)
-+    }
-+
-+    /// Makes a new `TimeVal` with given number of microseconds.
-+    #[inline]
-+    fn microseconds(microseconds: i64) -> TimeVal {
-+        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
-+        assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
-+                "TimeVal out of bounds");
-+        TimeVal(timeval {tv_sec: secs as time_t,
-+                           tv_usec: micros as suseconds_t })
-+    }
-+
-+    /// Makes a new `TimeVal` with given number of nanoseconds.  Some precision
-+    /// will be lost
-+    #[inline]
-+    fn nanoseconds(nanoseconds: i64) -> TimeVal {
-+        let microseconds = nanoseconds / 1000;
-+        let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
-+        assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
-+                "TimeVal out of bounds");
-+        TimeVal(timeval {tv_sec: secs as time_t,
-+                           tv_usec: micros as suseconds_t })
-+    }
-+
-+    fn num_seconds(&self) -> i64 {
-+        if self.tv_sec() < 0 && self.tv_usec() > 0 {
-+            (self.tv_sec() + 1) as i64
-+        } else {
-+            self.tv_sec() as i64
-+        }
-+    }
-+
-+    fn num_milliseconds(&self) -> i64 {
-+        self.num_microseconds() / 1_000
-+    }
-+
-+    fn num_microseconds(&self) -> i64 {
-+        let secs = self.num_seconds() * 1_000_000;
-+        let usec = self.micros_mod_sec();
-+        secs + usec as i64
-+    }
-+
-+    fn num_nanoseconds(&self) -> i64 {
-+        self.num_microseconds() * 1_000
-+    }
-+}
-+
-+impl TimeVal {
-+    fn micros_mod_sec(&self) -> suseconds_t {
-+        if self.tv_sec() < 0 && self.tv_usec() > 0 {
-+            self.tv_usec() - MICROS_PER_SEC as suseconds_t
-+        } else {
-+            self.tv_usec()
-+        }
-+    }
-+
-+    pub fn tv_sec(&self) -> time_t {
-+        self.0.tv_sec
-+    }
-+
-+    pub fn tv_usec(&self) -> suseconds_t {
-+        self.0.tv_usec
-+    }
-+}
-+
-+impl ops::Neg for TimeVal {
-+    type Output = TimeVal;
-+
-+    fn neg(self) -> TimeVal {
-+        TimeVal::microseconds(-self.num_microseconds())
-+    }
-+}
-+
-+impl ops::Add for TimeVal {
-+    type Output = TimeVal;
-+
-+    fn add(self, rhs: TimeVal) -> TimeVal {
-+        TimeVal::microseconds(
-+            self.num_microseconds() + rhs.num_microseconds())
-+    }
-+}
-+
-+impl ops::Sub for TimeVal {
-+    type Output = TimeVal;
-+
-+    fn sub(self, rhs: TimeVal) -> TimeVal {
-+        TimeVal::microseconds(
-+            self.num_microseconds() - rhs.num_microseconds())
-+    }
-+}
-+
-+impl ops::Mul<i32> for TimeVal {
-+    type Output = TimeVal;
-+
-+    fn mul(self, rhs: i32) -> TimeVal {
-+        let usec = self.num_microseconds().checked_mul(rhs as i64)
-+            .expect("TimeVal multiply out of bounds");
-+
-+        TimeVal::microseconds(usec)
-+    }
-+}
-+
-+impl ops::Div<i32> for TimeVal {
-+    type Output = TimeVal;
-+
-+    fn div(self, rhs: i32) -> TimeVal {
-+        let usec = self.num_microseconds() / rhs as i64;
-+        TimeVal::microseconds(usec)
-+    }
-+}
-+
-+impl fmt::Display for TimeVal {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        let (abs, sign) = if self.tv_sec() < 0 {
-+            (-*self, "-")
-+        } else {
-+            (*self, "")
-+        };
-+
-+        let sec = abs.tv_sec();
-+
-+        write!(f, "{}", sign)?;
-+
-+        if abs.tv_usec() == 0 {
-+            if abs.tv_sec() == 1 {
-+                write!(f, "{} second", sec)?;
-+            } else {
-+                write!(f, "{} seconds", sec)?;
-+            }
-+        } else if abs.tv_usec() % 1000 == 0 {
-+            write!(f, "{}.{:03} seconds", sec, abs.tv_usec() / 1000)?;
-+        } else {
-+            write!(f, "{}.{:06} seconds", sec, abs.tv_usec())?;
-+        }
-+
-+        Ok(())
-+    }
-+}
-+
-+impl From<timeval> for TimeVal {
-+    fn from(tv: timeval) -> Self {
-+        TimeVal(tv)
-+    }
-+}
-+
-+#[inline]
-+fn div_mod_floor_64(this: i64, other: i64) -> (i64, i64) {
-+    (div_floor_64(this, other), mod_floor_64(this, other))
-+}
-+
-+#[inline]
-+fn div_floor_64(this: i64, other: i64) -> i64 {
-+    match div_rem_64(this, other) {
-+        (d, r) if (r > 0 && other < 0)
-+               || (r < 0 && other > 0) => d - 1,
-+        (d, _)                         => d,
-+    }
-+}
-+
-+#[inline]
-+fn mod_floor_64(this: i64, other: i64) -> i64 {
-+    match this % other {
-+        r if (r > 0 && other < 0)
-+          || (r < 0 && other > 0) => r + other,
-+        r                         => r,
-+    }
-+}
-+
-+#[inline]
-+fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
-+    (this / other, this % other)
-+}
-+
-+#[cfg(test)]
-+mod test {
-+    use super::{TimeSpec, TimeVal, TimeValLike};
-+
-+    #[test]
-+    pub fn test_timespec() {
-+        assert!(TimeSpec::seconds(1) != TimeSpec::zero());
-+        assert_eq!(TimeSpec::seconds(1) + TimeSpec::seconds(2),
-+                   TimeSpec::seconds(3));
-+        assert_eq!(TimeSpec::minutes(3) + TimeSpec::seconds(2),
-+                   TimeSpec::seconds(182));
-+    }
-+
-+    #[test]
-+    pub fn test_timespec_neg() {
-+        let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
-+        let b = TimeSpec::seconds(-1) + TimeSpec::nanoseconds(-123);
-+
-+        assert_eq!(a, -b);
-+    }
-+
-+    #[test]
-+    pub fn test_timespec_ord() {
-+        assert!(TimeSpec::seconds(1) == TimeSpec::nanoseconds(1_000_000_000));
-+        assert!(TimeSpec::seconds(1) < TimeSpec::nanoseconds(1_000_000_001));
-+        assert!(TimeSpec::seconds(1) > TimeSpec::nanoseconds(999_999_999));
-+        assert!(TimeSpec::seconds(-1) < TimeSpec::nanoseconds(-999_999_999));
-+        assert!(TimeSpec::seconds(-1) > TimeSpec::nanoseconds(-1_000_000_001));
-+    }
-+
-+    #[test]
-+    pub fn test_timespec_fmt() {
-+        assert_eq!(TimeSpec::zero().to_string(), "0 seconds");
-+        assert_eq!(TimeSpec::seconds(42).to_string(), "42 seconds");
-+        assert_eq!(TimeSpec::milliseconds(42).to_string(), "0.042 seconds");
-+        assert_eq!(TimeSpec::microseconds(42).to_string(), "0.000042 seconds");
-+        assert_eq!(TimeSpec::nanoseconds(42).to_string(), "0.000000042 seconds");
-+        assert_eq!(TimeSpec::seconds(-86401).to_string(), "-86401 seconds");
-+    }
-+
-+    #[test]
-+    pub fn test_timeval() {
-+        assert!(TimeVal::seconds(1) != TimeVal::zero());
-+        assert_eq!(TimeVal::seconds(1) + TimeVal::seconds(2),
-+                   TimeVal::seconds(3));
-+        assert_eq!(TimeVal::minutes(3) + TimeVal::seconds(2),
-+                   TimeVal::seconds(182));
-+    }
-+
-+    #[test]
-+    pub fn test_timeval_ord() {
-+        assert!(TimeVal::seconds(1) == TimeVal::microseconds(1_000_000));
-+        assert!(TimeVal::seconds(1) < TimeVal::microseconds(1_000_001));
-+        assert!(TimeVal::seconds(1) > TimeVal::microseconds(999_999));
-+        assert!(TimeVal::seconds(-1) < TimeVal::microseconds(-999_999));
-+        assert!(TimeVal::seconds(-1) > TimeVal::microseconds(-1_000_001));
-+    }
-+
-+    #[test]
-+    pub fn test_timeval_neg() {
-+        let a = TimeVal::seconds(1) + TimeVal::microseconds(123);
-+        let b = TimeVal::seconds(-1) + TimeVal::microseconds(-123);
-+
-+        assert_eq!(a, -b);
-+    }
-+
-+    #[test]
-+    pub fn test_timeval_fmt() {
-+        assert_eq!(TimeVal::zero().to_string(), "0 seconds");
-+        assert_eq!(TimeVal::seconds(42).to_string(), "42 seconds");
-+        assert_eq!(TimeVal::milliseconds(42).to_string(), "0.042 seconds");
-+        assert_eq!(TimeVal::microseconds(42).to_string(), "0.000042 seconds");
-+        assert_eq!(TimeVal::nanoseconds(1402).to_string(), "0.000001 seconds");
-+        assert_eq!(TimeVal::seconds(-86401).to_string(), "-86401 seconds");
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/uio.rs b/third_party/rust/nix-0.15.0/src/sys/uio.rs
-new file mode 100644
-index 0000000000000..d089084eed711
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/uio.rs
-@@ -0,0 +1,194 @@
-+// Silence invalid warnings due to rust-lang/rust#16719
-+#![allow(improper_ctypes)]
-+
-+use Result;
-+use errno::Errno;
-+use libc::{self, c_int, c_void, size_t, off_t};
-+use std::marker::PhantomData;
-+use std::os::unix::io::RawFd;
-+
-+pub fn writev(fd: RawFd, iov: &[IoVec<&[u8]>]) -> Result<usize> {
-+    let res = unsafe { libc::writev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+pub fn readv(fd: RawFd, iov: &mut [IoVec<&mut [u8]>]) -> Result<usize> {
-+    let res = unsafe { libc::readv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int) };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Write to `fd` at `offset` from buffers in `iov`.
-+///
-+/// Buffers in `iov` will be written in order until all buffers have been written
-+/// or an error occurs. The file offset is not changed.
-+///
-+/// See also: [`writev`](fn.writev.html) and [`pwrite`](fn.pwrite.html)
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub fn pwritev(fd: RawFd, iov: &[IoVec<&[u8]>],
-+               offset: off_t) -> Result<usize> {
-+    let res = unsafe {
-+        libc::pwritev(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Read from `fd` at `offset` filling buffers in `iov`.
-+///
-+/// Buffers in `iov` will be filled in order until all buffers have been filled,
-+/// no more bytes are available, or an error occurs. The file offset is not
-+/// changed.
-+///
-+/// See also: [`readv`](fn.readv.html) and [`pread`](fn.pread.html)
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub fn preadv(fd: RawFd, iov: &[IoVec<&mut [u8]>],
-+              offset: off_t) -> Result<usize> {
-+    let res = unsafe {
-+        libc::preadv(fd, iov.as_ptr() as *const libc::iovec, iov.len() as c_int, offset)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+pub fn pwrite(fd: RawFd, buf: &[u8], offset: off_t) -> Result<usize> {
-+    let res = unsafe {
-+        libc::pwrite(fd, buf.as_ptr() as *const c_void, buf.len() as size_t,
-+                    offset)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+pub fn pread(fd: RawFd, buf: &mut [u8], offset: off_t) -> Result<usize>{
-+    let res = unsafe {
-+        libc::pread(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t,
-+                   offset)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// A slice of memory in a remote process, starting at address `base`
-+/// and consisting of `len` bytes.
-+///
-+/// This is the same underlying C structure as [`IoVec`](struct.IoVec.html),
-+/// except that it refers to memory in some other process, and is
-+/// therefore not represented in Rust by an actual slice as `IoVec` is. It
-+/// is used with [`process_vm_readv`](fn.process_vm_readv.html)
-+/// and [`process_vm_writev`](fn.process_vm_writev.html).
-+#[cfg(target_os = "linux")]
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct RemoteIoVec {
-+    /// The starting address of this slice (`iov_base`).
-+    pub base: usize,
-+    /// The number of bytes in this slice (`iov_len`).
-+    pub len: usize,
-+}
-+
-+/// Write data directly to another process's virtual memory
-+/// (see [`process_vm_writev`(2)]).
-+///
-+/// `local_iov` is a list of [`IoVec`]s containing the data to be written,
-+/// and `remote_iov` is a list of [`RemoteIoVec`]s identifying where the
-+/// data should be written in the target process. On success, returns the
-+/// number of bytes written, which will always be a whole
-+/// number of `remote_iov` chunks.
-+///
-+/// This requires the same permissions as debugging the process using
-+/// [ptrace]: you must either be a privileged process (with
-+/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-+/// target process and the OS must have unprivileged debugging enabled.
-+///
-+/// This function is only available on Linux.
-+///
-+/// [`process_vm_writev`(2)]: http://man7.org/linux/man-pages/man2/process_vm_writev.2.html
-+/// [ptrace]: ../ptrace/index.html
-+/// [`IoVec`]: struct.IoVec.html
-+/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-+#[cfg(target_os = "linux")]
-+pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
-+    let res = unsafe {
-+        libc::process_vm_writev(pid.into(),
-+                                local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
-+                                remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Read data directly from another process's virtual memory
-+/// (see [`process_vm_readv`(2)]).
-+///
-+/// `local_iov` is a list of [`IoVec`]s containing the buffer to copy
-+/// data into, and `remote_iov` is a list of [`RemoteIoVec`]s identifying
-+/// where the source data is in the target process. On success,
-+/// returns the number of bytes written, which will always be a whole
-+/// number of `remote_iov` chunks.
-+///
-+/// This requires the same permissions as debugging the process using
-+/// [`ptrace`]: you must either be a privileged process (with
-+/// `CAP_SYS_PTRACE`), or you must be running as the same user as the
-+/// target process and the OS must have unprivileged debugging enabled.
-+///
-+/// This function is only available on Linux.
-+///
-+/// [`process_vm_readv`(2)]: http://man7.org/linux/man-pages/man2/process_vm_readv.2.html
-+/// [`ptrace`]: ../ptrace/index.html
-+/// [`IoVec`]: struct.IoVec.html
-+/// [`RemoteIoVec`]: struct.RemoteIoVec.html
-+#[cfg(any(target_os = "linux"))]
-+pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
-+    let res = unsafe {
-+        libc::process_vm_readv(pid.into(),
-+                               local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
-+                               remote_iov.as_ptr() as *const libc::iovec, remote_iov.len() as libc::c_ulong, 0)
-+    };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct IoVec<T>(libc::iovec, PhantomData<T>);
-+
-+impl<T> IoVec<T> {
-+    #[inline]
-+    pub fn as_slice(&self) -> &[u8] {
-+        use std::slice;
-+
-+        unsafe {
-+            slice::from_raw_parts(
-+                self.0.iov_base as *const u8,
-+                self.0.iov_len as usize)
-+        }
-+    }
-+}
-+
-+impl<'a> IoVec<&'a [u8]> {
-+    pub fn from_slice(buf: &'a [u8]) -> IoVec<&'a [u8]> {
-+        IoVec(libc::iovec {
-+            iov_base: buf.as_ptr() as *mut c_void,
-+            iov_len: buf.len() as size_t,
-+        }, PhantomData)
-+    }
-+}
-+
-+impl<'a> IoVec<&'a mut [u8]> {
-+    pub fn from_mut_slice(buf: &'a mut [u8]) -> IoVec<&'a mut [u8]> {
-+        IoVec(libc::iovec {
-+            iov_base: buf.as_ptr() as *mut c_void,
-+            iov_len: buf.len() as size_t,
-+        }, PhantomData)
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/utsname.rs b/third_party/rust/nix-0.15.0/src/sys/utsname.rs
-new file mode 100644
-index 0000000000000..ab09c7d23232a
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/utsname.rs
-@@ -0,0 +1,67 @@
-+use std::mem;
-+use libc::{self, c_char};
-+use std::ffi::CStr;
-+use std::str::from_utf8_unchecked;
-+
-+#[repr(C)]
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct UtsName(libc::utsname);
-+
-+impl UtsName {
-+    pub fn sysname(&self) -> &str {
-+        to_str(&(&self.0.sysname as *const c_char ) as *const *const c_char)
-+    }
-+
-+    pub fn nodename(&self) -> &str {
-+        to_str(&(&self.0.nodename as *const c_char ) as *const *const c_char)
-+    }
-+
-+    pub fn release(&self) -> &str {
-+        to_str(&(&self.0.release as *const c_char ) as *const *const c_char)
-+    }
-+
-+    pub fn version(&self) -> &str {
-+        to_str(&(&self.0.version as *const c_char ) as *const *const c_char)
-+    }
-+
-+    pub fn machine(&self) -> &str {
-+        to_str(&(&self.0.machine as *const c_char ) as *const *const c_char)
-+    }
-+}
-+
-+pub fn uname() -> UtsName {
-+    unsafe {
-+        let mut ret: UtsName = mem::uninitialized();
-+        libc::uname(&mut ret.0);
-+        ret
-+    }
-+}
-+
-+#[inline]
-+fn to_str<'a>(s: *const *const c_char) -> &'a str {
-+    unsafe {
-+        let res = CStr::from_ptr(*s).to_bytes();
-+        from_utf8_unchecked(res)
-+    }
-+}
-+
-+#[cfg(test)]
-+mod test {
-+    #[cfg(target_os = "linux")]
-+    #[test]
-+    pub fn test_uname_linux() {
-+        assert_eq!(super::uname().sysname(), "Linux");
-+    }
-+
-+    #[cfg(any(target_os = "macos", target_os = "ios"))]
-+    #[test]
-+    pub fn test_uname_darwin() {
-+        assert_eq!(super::uname().sysname(), "Darwin");
-+    }
-+
-+    #[cfg(target_os = "freebsd")]
-+    #[test]
-+    pub fn test_uname_freebsd() {
-+        assert_eq!(super::uname().sysname(), "FreeBSD");
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/sys/wait.rs b/third_party/rust/nix-0.15.0/src/sys/wait.rs
-new file mode 100644
-index 0000000000000..c54f7ec579667
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/sys/wait.rs
-@@ -0,0 +1,239 @@
-+use libc::{self, c_int};
-+use Result;
-+use errno::Errno;
-+use unistd::Pid;
-+
-+use sys::signal::Signal;
-+
-+libc_bitflags!(
-+    pub struct WaitPidFlag: c_int {
-+        WNOHANG;
-+        WUNTRACED;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd"))]
-+        WEXITED;
-+        WCONTINUED;
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd"))]
-+        WSTOPPED;
-+        /// Don't reap, just poll status.
-+        #[cfg(any(target_os = "android",
-+                  target_os = "freebsd",
-+                  target_os = "haiku",
-+                  target_os = "ios",
-+                  target_os = "linux",
-+                  target_os = "macos",
-+                  target_os = "netbsd"))]
-+        WNOWAIT;
-+        /// Don't wait on children of other threads in this group
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        __WNOTHREAD;
-+        /// Wait on all children, regardless of type
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        __WALL;
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        __WCLONE;
-+    }
-+);
-+
-+/// Possible return values from `wait()` or `waitpid()`.
-+///
-+/// Each status (other than `StillAlive`) describes a state transition
-+/// in a child process `Pid`, such as the process exiting or stopping,
-+/// plus additional data about the transition if any.
-+///
-+/// Note that there are two Linux-specific enum variants, `PtraceEvent`
-+/// and `PtraceSyscall`. Portable code should avoid exhaustively
-+/// matching on `WaitStatus`.
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub enum WaitStatus {
-+    /// The process exited normally (as with `exit()` or returning from
-+    /// `main`) with the given exit code. This case matches the C macro
-+    /// `WIFEXITED(status)`; the second field is `WEXITSTATUS(status)`.
-+    Exited(Pid, i32),
-+    /// The process was killed by the given signal. The third field
-+    /// indicates whether the signal generated a core dump. This case
-+    /// matches the C macro `WIFSIGNALED(status)`; the last two fields
-+    /// correspond to `WTERMSIG(status)` and `WCOREDUMP(status)`.
-+    Signaled(Pid, Signal, bool),
-+    /// The process is alive, but was stopped by the given signal. This
-+    /// is only reported if `WaitPidFlag::WUNTRACED` was passed. This
-+    /// case matches the C macro `WIFSTOPPED(status)`; the second field
-+    /// is `WSTOPSIG(status)`.
-+    Stopped(Pid, Signal),
-+    /// The traced process was stopped by a `PTRACE_EVENT_*` event. See
-+    /// [`nix::sys::ptrace`] and [`ptrace`(2)] for more information. All
-+    /// currently-defined events use `SIGTRAP` as the signal; the third
-+    /// 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
-+    #[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
-+    #[cfg(any(target_os = "linux", target_os = "android"))]
-+    PtraceSyscall(Pid),
-+    /// The process was previously stopped but has resumed execution
-+    /// after receiving a `SIGCONT` signal. This is only reported if
-+    /// `WaitPidFlag::WCONTINUED` was passed. This case matches the C
-+    /// macro `WIFCONTINUED(status)`.
-+    Continued(Pid),
-+    /// There are currently no state changes to report in any awaited
-+    /// child process. This is only returned if `WaitPidFlag::WNOHANG`
-+    /// was used (otherwise `wait()` or `waitpid()` would block until
-+    /// there was something to report).
-+    StillAlive,
-+}
-+
-+impl WaitStatus {
-+    /// Extracts the PID from the WaitStatus unless it equals StillAlive.
-+    pub fn pid(&self) -> Option<Pid> {
-+        use self::WaitStatus::*;
-+        match *self {
-+            Exited(p, _)  | Signaled(p, _, _) |
-+                Stopped(p, _) | Continued(p) => Some(p),
-+            StillAlive => None,
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
-+        }
-+    }
-+}
-+
-+fn exited(status: i32) -> bool {
-+    unsafe { libc::WIFEXITED(status) }
-+}
-+
-+fn exit_status(status: i32) -> i32 {
-+    unsafe { libc::WEXITSTATUS(status) }
-+}
-+
-+fn signaled(status: i32) -> bool {
-+    unsafe { libc::WIFSIGNALED(status) }
-+}
-+
-+fn term_signal(status: i32) -> Result<Signal> {
-+    Signal::from_c_int(unsafe { libc::WTERMSIG(status) })
-+}
-+
-+fn dumped_core(status: i32) -> bool {
-+    unsafe { libc::WCOREDUMP(status) }
-+}
-+
-+fn stopped(status: i32) -> bool {
-+    unsafe { libc::WIFSTOPPED(status) }
-+}
-+
-+fn stop_signal(status: i32) -> Result<Signal> {
-+    Signal::from_c_int(unsafe { libc::WSTOPSIG(status) })
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn syscall_stop(status: i32) -> bool {
-+    // From ptrace(2), setting PTRACE_O_TRACESYSGOOD has the effect
-+    // of delivering SIGTRAP | 0x80 as the signal number for syscall
-+    // stops. This allows easily distinguishing syscall stops from
-+    // genuine SIGTRAP signals.
-+    unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn stop_additional(status: i32) -> c_int {
-+    (status >> 16) as c_int
-+}
-+
-+fn continued(status: i32) -> bool {
-+    unsafe { libc::WIFCONTINUED(status) }
-+}
-+
-+impl WaitStatus {
-+    /// Convert a raw `wstatus` as returned by `waitpid`/`wait` into a `WaitStatus`
-+    ///
-+    /// # Errors
-+    ///
-+    /// Returns an `Error` corresponding to `EINVAL` for invalid status values.
-+    ///
-+    /// # Examples
-+    ///
-+    /// Convert a `wstatus` obtained from `libc::waitpid` into a `WaitStatus`:
-+    ///
-+    /// ```
-+    /// use nix::sys::wait::WaitStatus;
-+    /// use nix::sys::signal::Signal;
-+    /// let pid = nix::unistd::Pid::from_raw(1);
-+    /// let status = WaitStatus::from_raw(pid, 0x0002);
-+    /// assert_eq!(status, Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
-+    /// ```
-+    pub fn from_raw(pid: Pid, status: i32) -> Result<WaitStatus> {
-+        Ok(if exited(status) {
-+            WaitStatus::Exited(pid, exit_status(status))
-+        } else if signaled(status) {
-+            WaitStatus::Signaled(pid, term_signal(status)?, dumped_core(status))
-+        } else if stopped(status) {
-+            cfg_if! {
-+                if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+                    fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
-+                        let status_additional = stop_additional(status);
-+                        Ok(if syscall_stop(status) {
-+                            WaitStatus::PtraceSyscall(pid)
-+                        } else if status_additional == 0 {
-+                            WaitStatus::Stopped(pid, stop_signal(status)?)
-+                        } else {
-+                            WaitStatus::PtraceEvent(pid, stop_signal(status)?,
-+                                                    stop_additional(status))
-+                        })
-+                    }
-+                } else {
-+                    fn decode_stopped(pid: Pid, status: i32) -> Result<WaitStatus> {
-+                        Ok(WaitStatus::Stopped(pid, stop_signal(status)?))
-+                    }
-+                }
-+            }
-+            return decode_stopped(pid, status);
-+        } else {
-+            assert!(continued(status));
-+            WaitStatus::Continued(pid)
-+        })
-+    }
-+}
-+
-+pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Result<WaitStatus> {
-+    use self::WaitStatus::*;
-+
-+    let mut status: i32 = 0;
-+
-+    let option_bits = match options {
-+        Some(bits) => bits.bits(),
-+        None => 0,
-+    };
-+
-+    let res = unsafe {
-+        libc::waitpid(
-+            pid.into().unwrap_or(Pid::from_raw(-1)).into(),
-+            &mut status as *mut c_int,
-+            option_bits,
-+        )
-+    };
-+
-+    match Errno::result(res)? {
-+        0 => Ok(StillAlive),
-+        res => WaitStatus::from_raw(Pid::from_raw(res), status),
-+    }
-+}
-+
-+pub fn wait() -> Result<WaitStatus> {
-+    waitpid(None, None)
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/ucontext.rs b/third_party/rust/nix-0.15.0/src/ucontext.rs
-new file mode 100644
-index 0000000000000..5e10e7d1f8934
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/ucontext.rs
-@@ -0,0 +1,39 @@
-+use libc;
-+#[cfg(not(target_env = "musl"))]
-+use Result;
-+#[cfg(not(target_env = "musl"))]
-+use errno::Errno;
-+use std::mem;
-+use sys::signal::SigSet;
-+
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+pub struct UContext {
-+    context: libc::ucontext_t,
-+}
-+
-+impl UContext {
-+    #[cfg(not(target_env = "musl"))]
-+    pub fn get() -> Result<UContext> {
-+        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
-+        let res = unsafe {
-+            libc::getcontext(&mut context as *mut libc::ucontext_t)
-+        };
-+        Errno::result(res).map(|_| UContext { context: context })
-+    }
-+
-+    #[cfg(not(target_env = "musl"))]
-+    pub fn set(&self) -> Result<()> {
-+        let res = unsafe {
-+            libc::setcontext(&self.context as *const libc::ucontext_t)
-+        };
-+        Errno::result(res).map(drop)
-+    }
-+
-+    pub fn sigmask_mut(&mut self) -> &mut SigSet {
-+        unsafe { mem::transmute(&mut self.context.uc_sigmask) }
-+    }
-+
-+    pub fn sigmask(&self) -> &SigSet {
-+        unsafe { mem::transmute(&self.context.uc_sigmask) }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/src/unistd.rs b/third_party/rust/nix-0.15.0/src/unistd.rs
-new file mode 100644
-index 0000000000000..f422f09198655
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/src/unistd.rs
-@@ -0,0 +1,2394 @@
-+//! Safe wrappers around functions found in libc "unistd.h" header
-+
-+use errno::{self, Errno};
-+use {Error, Result, NixPath};
-+use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag};
-+use fcntl::FcntlArg::F_SETFD;
-+use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
-+           uid_t, gid_t, mode_t};
-+use std::{fmt, mem, ptr};
-+use std::ffi::{CString, CStr, OsString, OsStr};
-+use std::os::unix::ffi::{OsStringExt, OsStrExt};
-+use std::os::unix::io::RawFd;
-+use std::path::PathBuf;
-+use void::Void;
-+use sys::stat::Mode;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use self::pivot_root::*;
-+
-+#[cfg(any(target_os = "android", target_os = "freebsd",
-+          target_os = "linux", target_os = "openbsd"))]
-+pub use self::setres::*;
-+
-+/// User identifier
-+///
-+/// Newtype pattern around `uid_t` (which is just alias). It prevents bugs caused by accidentally
-+/// passing wrong value.
-+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-+pub struct Uid(uid_t);
-+
-+impl Uid {
-+    /// Creates `Uid` from raw `uid_t`.
-+    pub fn from_raw(uid: uid_t) -> Self {
-+        Uid(uid)
-+    }
-+
-+    /// Returns Uid of calling process. This is practically a more Rusty alias for `getuid`.
-+    pub fn current() -> Self {
-+        getuid()
-+    }
-+
-+    /// Returns effective Uid of calling process. This is practically a more Rusty alias for `geteuid`.
-+    pub fn effective() -> Self {
-+        geteuid()
-+    }
-+
-+    /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
-+    pub fn is_root(&self) -> bool {
-+        *self == ROOT
-+    }
-+
-+    /// Get the raw `uid_t` wrapped by `self`.
-+    pub fn as_raw(&self) -> uid_t {
-+        self.0
-+    }
-+}
-+
-+impl From<Uid> for uid_t {
-+    fn from(uid: Uid) -> Self {
-+        uid.0
-+    }
-+}
-+
-+impl fmt::Display for Uid {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        fmt::Display::fmt(&self.0, f)
-+    }
-+}
-+
-+/// Constant for UID = 0
-+pub const ROOT: Uid = Uid(0);
-+
-+/// Group identifier
-+///
-+/// Newtype pattern around `gid_t` (which is just alias). It prevents bugs caused by accidentally
-+/// passing wrong value.
-+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-+pub struct Gid(gid_t);
-+
-+impl Gid {
-+    /// Creates `Gid` from raw `gid_t`.
-+    pub fn from_raw(gid: gid_t) -> Self {
-+        Gid(gid)
-+    }
-+
-+    /// Returns Gid of calling process. This is practically a more Rusty alias for `getgid`.
-+    pub fn current() -> Self {
-+        getgid()
-+    }
-+
-+    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getgid`.
-+    pub fn effective() -> Self {
-+        getegid()
-+    }
-+
-+    /// Get the raw `gid_t` wrapped by `self`.
-+    pub fn as_raw(&self) -> gid_t {
-+        self.0
-+    }
-+}
-+
-+impl From<Gid> for gid_t {
-+    fn from(gid: Gid) -> Self {
-+        gid.0
-+    }
-+}
-+
-+impl fmt::Display for Gid {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        fmt::Display::fmt(&self.0, f)
-+    }
-+}
-+
-+/// Process identifier
-+///
-+/// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
-+/// passing wrong value.
-+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-+pub struct Pid(pid_t);
-+
-+impl Pid {
-+    /// Creates `Pid` from raw `pid_t`.
-+    pub fn from_raw(pid: pid_t) -> Self {
-+        Pid(pid)
-+    }
-+
-+    /// Returns PID of calling process
-+    pub fn this() -> Self {
-+        getpid()
-+    }
-+
-+    /// Returns PID of parent of calling process
-+    pub fn parent() -> Self {
-+        getppid()
-+    }
-+
-+    /// Get the raw `pid_t` wrapped by `self`.
-+    pub fn as_raw(&self) -> pid_t {
-+        self.0
-+    }
-+}
-+
-+impl From<Pid> for pid_t {
-+    fn from(pid: Pid) -> Self {
-+        pid.0
-+    }
-+}
-+
-+impl fmt::Display for Pid {
-+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-+        fmt::Display::fmt(&self.0, f)
-+    }
-+}
-+
-+
-+/// Represents the successful result of calling `fork`
-+///
-+/// When `fork` is called, the process continues execution in the parent process
-+/// and in the new child.  This return type can be examined to determine whether
-+/// you are now executing in the parent process or in the child.
-+#[derive(Clone, Copy, Debug)]
-+pub enum ForkResult {
-+    Parent { child: Pid },
-+    Child,
-+}
-+
-+impl ForkResult {
-+
-+    /// Return `true` if this is the child process of the `fork()`
-+    #[inline]
-+    pub fn is_child(&self) -> bool {
-+        match *self {
-+            ForkResult::Child => true,
-+            _ => false
-+        }
-+    }
-+
-+    /// Returns `true` if this is the parent process of the `fork()`
-+    #[inline]
-+    pub fn is_parent(&self) -> bool {
-+        !self.is_child()
-+    }
-+}
-+
-+/// Create a new child process duplicating the parent process ([see
-+/// fork(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fork.html)).
-+///
-+/// After calling the fork system call (successfully) two processes will
-+/// be created that are identical with the exception of their pid and the
-+/// return value of this function.  As an example:
-+///
-+/// ```no_run
-+/// use nix::unistd::{fork, ForkResult};
-+///
-+/// match fork() {
-+///    Ok(ForkResult::Parent { child, .. }) => {
-+///        println!("Continuing execution in parent process, new child has pid: {}", child);
-+///    }
-+///    Ok(ForkResult::Child) => println!("I'm a new child process"),
-+///    Err(_) => println!("Fork failed"),
-+/// }
-+/// ```
-+///
-+/// This will print something like the following (order indeterministic).  The
-+/// thing to note is that you end up with two processes continuing execution
-+/// immediately after the fork call but with different match arms.
-+///
-+/// ```text
-+/// Continuing execution in parent process, new child has pid: 1234
-+/// I'm a new child process
-+/// ```
-+///
-+/// # 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]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
-+#[inline]
-+pub fn fork() -> Result<ForkResult> {
-+    use self::ForkResult::*;
-+    let res = unsafe { libc::fork() };
-+
-+    Errno::result(res).map(|res| match res {
-+        0 => Child,
-+        res => Parent { child: Pid(res) },
-+    })
-+}
-+
-+/// Get the pid of this process (see
-+/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpid.html)).
-+///
-+/// Since you are running code, there is always a pid to return, so there
-+/// is no error case that needs to be handled.
-+#[inline]
-+pub fn getpid() -> Pid {
-+    Pid(unsafe { libc::getpid() })
-+}
-+
-+/// Get the pid of this processes' parent (see
-+/// [getpid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getppid.html)).
-+///
-+/// There is always a parent pid to return, so there is no error case that needs
-+/// to be handled.
-+#[inline]
-+pub fn getppid() -> Pid {
-+    Pid(unsafe { libc::getppid() }) // no error handling, according to man page: "These functions are always successful."
-+}
-+
-+/// Set a process group ID (see
-+/// [setpgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setpgid.html)).
-+///
-+/// Set the process group id (PGID) of a particular process.  If a pid of zero
-+/// is specified, then the pid of the calling process is used.  Process groups
-+/// may be used to group together a set of processes in order for the OS to
-+/// apply some operations across the group.
-+///
-+/// `setsid()` may be used to create a new process group.
-+#[inline]
-+pub fn setpgid(pid: Pid, pgid: Pid) -> Result<()> {
-+    let res = unsafe { libc::setpgid(pid.into(), pgid.into()) };
-+    Errno::result(res).map(drop)
-+}
-+#[inline]
-+pub fn getpgid(pid: Option<Pid>) -> Result<Pid> {
-+    let res = unsafe { libc::getpgid(pid.unwrap_or(Pid(0)).into()) };
-+    Errno::result(res).map(Pid)
-+}
-+
-+/// Create new session and set process group id (see
-+/// [setsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsid.html)).
-+#[inline]
-+pub fn setsid() -> Result<Pid> {
-+    Errno::result(unsafe { libc::setsid() }).map(Pid)
-+}
-+
-+/// Get the process group ID of a session leader
-+/// [getsid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsid.html).
-+///
-+/// Obtain the process group ID of the process that is the session leader of the process specified
-+/// by pid. If pid is zero, it specifies the calling process.
-+#[inline]
-+pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
-+    let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
-+    Errno::result(res).map(Pid)
-+}
-+
-+
-+/// Get the terminal foreground process group (see
-+/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetpgrp.html)).
-+///
-+/// Get the group process id (GPID) of the foreground process group on the
-+/// terminal associated to file descriptor (FD).
-+#[inline]
-+pub fn tcgetpgrp(fd: c_int) -> Result<Pid> {
-+    let res = unsafe { libc::tcgetpgrp(fd) };
-+    Errno::result(res).map(Pid)
-+}
-+/// Set the terminal foreground process group (see
-+/// [tcgetpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/tcsetpgrp.html)).
-+///
-+/// Get the group process id (PGID) to the foreground process group on the
-+/// terminal associated to file descriptor (FD).
-+#[inline]
-+pub fn tcsetpgrp(fd: c_int, pgrp: Pid) -> Result<()> {
-+    let res = unsafe { libc::tcsetpgrp(fd, pgrp.into()) };
-+    Errno::result(res).map(drop)
-+}
-+
-+
-+/// Get the group id of the calling process (see
-+///[getpgrp(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpgrp.html)).
-+///
-+/// Get the process group id (PGID) of the calling process.
-+/// According to the man page it is always successful.
-+#[inline]
-+pub fn getpgrp() -> Pid {
-+    Pid(unsafe { libc::getpgrp() })
-+}
-+
-+/// Get the caller's thread ID (see
-+/// [gettid(2)](http://man7.org/linux/man-pages/man2/gettid.2.html).
-+///
-+/// This function is only available on Linux based systems.  In a single
-+/// threaded process, the main thread will have the same ID as the process.  In
-+/// a multithreaded process, each thread will have a unique thread id but the
-+/// same process ID.
-+///
-+/// No error handling is required as a thread id should always exist for any
-+/// process, even if threads are not being used.
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+#[inline]
-+pub fn gettid() -> Pid {
-+    Pid(unsafe { libc::syscall(libc::SYS_gettid) as pid_t })
-+}
-+
-+/// Create a copy of the specified file descriptor (see
-+/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
-+///
-+/// The new file descriptor will be have a new index but refer to the same
-+/// resource as the old file descriptor and the old and new file descriptors may
-+/// be used interchangeably.  The new and old file descriptor share the same
-+/// underlying resource, offset, and file status flags.  The actual index used
-+/// for the file descriptor will be the lowest fd index that is available.
-+///
-+/// The two file descriptors do not share file descriptor flags (e.g. `OFlag::FD_CLOEXEC`).
-+#[inline]
-+pub fn dup(oldfd: RawFd) -> Result<RawFd> {
-+    let res = unsafe { libc::dup(oldfd) };
-+
-+    Errno::result(res)
-+}
-+
-+/// Create a copy of the specified file descriptor using the specified fd (see
-+/// [dup(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dup.html)).
-+///
-+/// This function behaves similar to `dup()` except that it will try to use the
-+/// specified fd instead of allocating a new one.  See the man pages for more
-+/// detail on the exact behavior of this function.
-+#[inline]
-+pub fn dup2(oldfd: RawFd, newfd: RawFd) -> Result<RawFd> {
-+    let res = unsafe { libc::dup2(oldfd, newfd) };
-+
-+    Errno::result(res)
-+}
-+
-+/// 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)).
-+///
-+/// This function behaves similar to `dup2()` but allows for flags to be
-+/// specified.
-+pub fn dup3(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
-+    dup3_polyfill(oldfd, newfd, flags)
-+}
-+
-+#[inline]
-+fn dup3_polyfill(oldfd: RawFd, newfd: RawFd, flags: OFlag) -> Result<RawFd> {
-+    if oldfd == newfd {
-+        return Err(Error::Sys(Errno::EINVAL));
-+    }
-+
-+    let fd = dup2(oldfd, newfd)?;
-+
-+    if flags.contains(OFlag::O_CLOEXEC) {
-+        if let Err(e) = fcntl(fd, F_SETFD(FdFlag::FD_CLOEXEC)) {
-+            let _ = close(fd);
-+            return Err(e);
-+        }
-+    }
-+
-+    Ok(fd)
-+}
-+
-+/// Change the current working directory of the calling process (see
-+/// [chdir(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/chdir.html)).
-+///
-+/// This function may fail in a number of different scenarios.  See the man
-+/// pages for additional details on possible failure cases.
-+#[inline]
-+pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::chdir(cstr.as_ptr()) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// 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)).
-+///
-+/// This function may fail in a number of different scenarios.  See the man
-+/// pages for additional details on possible failure cases.
-+#[inline]
-+pub fn fchdir(dirfd: RawFd) -> Result<()> {
-+    let res = unsafe { libc::fchdir(dirfd) };
-+
-+    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))
-+///
-+/// # Errors
-+///
-+/// There are several situations where mkdir might fail:
-+///
-+/// - current user has insufficient rights in the parent directory
-+/// - the path already exists
-+/// - the path name is too long (longer than `PATH_MAX`, usually 4096 on linux, 1024 on OS X)
-+///
-+/// # Example
-+///
-+/// ```rust
-+/// extern crate tempfile;
-+/// extern crate nix;
-+///
-+/// use nix::unistd;
-+/// use nix::sys::stat;
-+/// use tempfile::tempdir;
-+///
-+/// fn main() {
-+///     let tmp_dir1 = tempdir().unwrap();
-+///     let tmp_dir2 = tmp_dir1.path().join("new_dir");
-+///
-+///     // create new directory and give read, write and execute rights to the owner
-+///     match unistd::mkdir(&tmp_dir2, stat::Mode::S_IRWXU) {
-+///        Ok(_) => println!("created {:?}", tmp_dir2),
-+///        Err(err) => println!("Error creating directory: {}", err),
-+///     }
-+/// }
-+/// ```
-+#[inline]
-+pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::mkdir(cstr.as_ptr(), mode.bits() as mode_t) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
-+///
-+/// # Errors
-+///
-+/// There are several situations where mkfifo might fail:
-+///
-+/// - current user has insufficient rights in the parent directory
-+/// - the path already exists
-+/// - 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)
-+///
-+/// # Example
-+///
-+/// ```rust
-+/// extern crate tempfile;
-+/// extern crate nix;
-+///
-+/// use nix::unistd;
-+/// use nix::sys::stat;
-+/// use tempfile::tempdir;
-+///
-+/// fn main() {
-+///     let tmp_dir = tempdir().unwrap();
-+///     let fifo_path = tmp_dir.path().join("foo.pipe");
-+///
-+///     // create new fifo and give read, write and execute rights to the owner
-+///     match unistd::mkfifo(&fifo_path, stat::Mode::S_IRWXU) {
-+///        Ok(_) => println!("created {:?}", fifo_path),
-+///        Err(err) => println!("Error creating fifo: {}", err),
-+///     }
-+/// }
-+/// ```
-+#[inline]
-+pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Creates a symbolic link at `path2` which points to `path1`.
-+///
-+/// If `dirfd` has a value, then `path2` is relative to directory associated
-+/// with the file descriptor.
-+///
-+/// 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).
-+pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-+    path1: &P1,
-+    dirfd: Option<RawFd>,
-+    path2: &P2) -> Result<()> {
-+    let res =
-+        path1.with_nix_path(|path1| {
-+            path2.with_nix_path(|path2| {
-+                unsafe {
-+                    libc::symlinkat(
-+                        path1.as_ptr(),
-+                        dirfd.unwrap_or(libc::AT_FDCWD),
-+                        path2.as_ptr()
-+                    )
-+                }
-+            })
-+        })??;
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Returns the current directory as a `PathBuf`
-+///
-+/// Err is returned if the current user doesn't have the permission to read or search a component
-+/// of the current path.
-+///
-+/// # Example
-+///
-+/// ```rust
-+/// extern crate nix;
-+///
-+/// 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);
-+/// }
-+/// ```
-+#[inline]
-+pub fn getcwd() -> Result<PathBuf> {
-+    let mut buf = Vec::with_capacity(512);
-+    loop {
-+        unsafe {
-+            let ptr = buf.as_mut_ptr() as *mut c_char;
-+
-+            // The buffer must be large enough to store the absolute pathname plus
-+            // a terminating null byte, or else null is returned.
-+            // To safely handle this we start with a reasonable size (512 bytes)
-+            // and double the buffer size upon every error
-+            if !libc::getcwd(ptr, buf.capacity()).is_null() {
-+                let len = CStr::from_ptr(buf.as_ptr() as *const c_char).to_bytes().len();
-+                buf.set_len(len);
-+                buf.shrink_to_fit();
-+                return Ok(PathBuf::from(OsString::from_vec(buf)));
-+            } else {
-+                let error = Errno::last();
-+                // ERANGE means buffer was too small to store directory name
-+                if error != Errno::ERANGE {
-+                    return Err(Error::Sys(error));
-+                }
-+            }
-+
-+            // Trigger the internal buffer resizing logic of `Vec` by requiring
-+            // more space than the current capacity.
-+            let cap = buf.capacity();
-+            buf.set_len(cap);
-+            buf.reserve(1);
-+        }
-+    }
-+}
-+
-+/// Computes the raw UID and GID values to pass to a `*chown` call.
-+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
-+    // around to get -1.
-+    let uid = owner.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1));
-+    let gid = group.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1));
-+    (uid, gid)
-+}
-+
-+/// 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)).
-+///
-+/// 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
-+/// only if `Some` owner/group is provided.
-+#[inline]
-+pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        let (uid, gid) = chown_raw_ids(owner, group);
-+        unsafe { libc::chown(cstr.as_ptr(), uid, gid) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Flags for `fchownat` function.
-+#[derive(Clone, Copy, Debug)]
-+pub enum FchownatFlags {
-+    FollowSymlink,
-+    NoFollowSymlink,
-+}
-+
-+/// Change the ownership of the file at `path` to be owned by the specified
-+/// `owner` (user) and `group`.
-+///
-+/// 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
-+/// only if `Some` owner/group is provided.
-+///
-+/// The file to be changed is determined relative to the directory associated
-+/// with the file descriptor `dirfd` or the current working directory
-+/// if `dirfd` is `None`.
-+///
-+/// If `flag` is `FchownatFlags::NoFollowSymlink` and `path` names a symbolic link,
-+/// then the mode of the symbolic link is changed.
-+///
-+/// `fchownat(None, path, mode, FchownatFlags::NoFollowSymlink)` is identical to
-+/// a call `libc::lchown(path, mode)`.  That's why `lchmod` is unimplemented in
-+/// the `nix` crate.
-+///
-+/// # References
-+///
-+/// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
-+pub fn fchownat<P: ?Sized + NixPath>(
-+    dirfd: Option<RawFd>,
-+    path: &P,
-+    owner: Option<Uid>,
-+    group: Option<Gid>,
-+    flag: FchownatFlags,
-+) -> Result<()> {
-+    let atflag =
-+        match flag {
-+            FchownatFlags::FollowSymlink => AtFlags::empty(),
-+            FchownatFlags::NoFollowSymlink => AtFlags::AT_SYMLINK_NOFOLLOW,
-+        };
-+    let res = path.with_nix_path(|cstr| unsafe {
-+        let (uid, gid) = chown_raw_ids(owner, group);
-+        libc::fchownat(at_rawfd(dirfd), cstr.as_ptr(), uid, gid,
-+                       atflag.bits() as libc::c_int)
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
-+    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
-+    args_p.push(ptr::null());
-+    args_p
-+}
-+
-+/// Replace the current process image with a new one (see
-+/// [exec(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
-+///
-+/// See the `::nix::unistd::execve` system call for additional details.  `execv`
-+/// performs the same action but does not allow for customization of the
-+/// environment for the new process.
-+#[inline]
-+pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
-+    let args_p = to_exec_array(argv);
-+
-+    unsafe {
-+        libc::execv(path.as_ptr(), args_p.as_ptr())
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+
-+/// Replace the current process image with a new one (see
-+/// [execve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html)).
-+///
-+/// The execve system call allows for another process to be "called" which will
-+/// replace the current process image.  That is, this process becomes the new
-+/// command that is run. On success, this function will not return. Instead,
-+/// the new program will run until it exits.
-+///
-+/// `::nix::unistd::execv` and `::nix::unistd::execve` take as arguments a slice
-+/// of `::std::ffi::CString`s for `args` and `env` (for `execve`). Each element
-+/// in the `args` list is an argument to the new process. Each element in the
-+/// `env` list should be a string in the form "key=value".
-+#[inline]
-+pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
-+    let args_p = to_exec_array(args);
-+    let env_p = to_exec_array(env);
-+
-+    unsafe {
-+        libc::execve(path.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// 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)).
-+///
-+/// See `::nix::unistd::execve` for additional details.  `execvp` behaves the
-+/// same as execv except that it will examine the `PATH` environment variables
-+/// for file names not specified with a leading slash.  For example, `execv`
-+/// would not work if "bash" was specified for the path argument, but `execvp`
-+/// would assuming that a bash executable was on the system `PATH`.
-+#[inline]
-+pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
-+    let args_p = to_exec_array(args);
-+
-+    unsafe {
-+        libc::execvp(filename.as_ptr(), args_p.as_ptr())
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// 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)).
-+///
-+/// 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
-+/// information.
-+#[cfg(any(target_os = "haiku",
-+          target_os = "linux",
-+          target_os = "openbsd"))]
-+pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
-+    let args_p = to_exec_array(args);
-+    let env_p = to_exec_array(env);
-+
-+    unsafe {
-+        libc::execvpe(filename.as_ptr(), args_p.as_ptr(), env_p.as_ptr())
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// Replace the current process image with a new one (see
-+/// [fexecve(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fexecve.html)).
-+///
-+/// The `fexecve` function allows for another process to be "called" which will
-+/// replace the current process image.  That is, this process becomes the new
-+/// command that is run. On success, this function will not return. Instead,
-+/// the new program will run until it exits.
-+///
-+/// This function is similar to `execve`, except that the program to be executed
-+/// is referenced as a file descriptor instead of a path.
-+// Note for NetBSD and OpenBSD: although rust-lang/libc includes it (under
-+// unix/bsd/netbsdlike/) fexecve is not currently implemented on NetBSD nor on
-+// OpenBSD.
-+#[cfg(any(target_os = "android",
-+          target_os = "linux",
-+          target_os = "freebsd"))]
-+#[inline]
-+pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
-+    let args_p = to_exec_array(args);
-+    let env_p = to_exec_array(env);
-+
-+    unsafe {
-+        libc::fexecve(fd, args_p.as_ptr(), env_p.as_ptr())
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// Execute program relative to a directory file descriptor (see
-+/// [execveat(2)](http://man7.org/linux/man-pages/man2/execveat.2.html)).
-+///
-+/// The `execveat` function allows for another process to be "called" which will
-+/// replace the current process image.  That is, this process becomes the new
-+/// command that is run. On success, this function will not return. Instead,
-+/// the new program will run until it exits.
-+///
-+/// This function is similar to `execve`, except that the program to be executed
-+/// is referenced as a file descriptor to the base directory plus a path.
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[inline]
-+pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
-+                env: &[CString], flags: super::fcntl::AtFlags) -> Result<Void> {
-+    let args_p = to_exec_array(args);
-+    let env_p = to_exec_array(env);
-+
-+    unsafe {
-+        libc::syscall(libc::SYS_execveat, dirfd, pathname.as_ptr(),
-+                      args_p.as_ptr(), env_p.as_ptr(), flags);
-+    };
-+
-+    Err(Error::Sys(Errno::last()))
-+}
-+
-+/// Daemonize this process by detaching from the controlling terminal (see
-+/// [daemon(3)](http://man7.org/linux/man-pages/man3/daemon.3.html)).
-+///
-+/// When a process is launched it is typically associated with a parent and it,
-+/// in turn, by its controlling terminal/process.  In order for a process to run
-+/// in the "background" it must daemonize itself by detaching itself.  Under
-+/// posix, this is done by doing the following:
-+///
-+/// 1. Parent process (this one) forks
-+/// 2. Parent process exits
-+/// 3. Child process continues to run.
-+///
-+/// `nochdir`:
-+///
-+/// * `nochdir = true`: The current working directory after daemonizing will
-+///    be the current working directory.
-+/// *  `nochdir = false`: The current working directory after daemonizing will
-+///    be the root direcory, `/`.
-+///
-+/// `noclose`:
-+///
-+/// * `noclose = true`: The process' current stdin, stdout, and stderr file
-+///   descriptors will remain identical after daemonizing.
-+/// * `noclose = false`: The process' stdin, stdout, and stderr will point to
-+///   `/dev/null` after daemonizing.
-+#[cfg_attr(any(target_os = "macos", target_os = "ios"), deprecated(
-+    since="0.14.0",
-+    note="Deprecated in MacOSX 10.5"
-+))]
-+#[cfg_attr(any(target_os = "macos", target_os = "ios"), allow(deprecated))]
-+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)).
-+///
-+/// 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
-+/// will be return if the name is not valid or the current process does not have
-+/// permissions to update the host name.
-+pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
-+    // Handle some differences in type of the len arg across platforms.
-+    cfg_if! {
-+        if #[cfg(any(target_os = "dragonfly",
-+                     target_os = "freebsd",
-+                     target_os = "ios",
-+                     target_os = "macos", ))] {
-+            type sethostname_len_t = c_int;
-+        } else {
-+            type sethostname_len_t = size_t;
-+        }
-+    }
-+    let ptr = name.as_ref().as_bytes().as_ptr() as *const c_char;
-+    let len = name.as_ref().len() as sethostname_len_t;
-+
-+    let res = unsafe { libc::sethostname(ptr, len) };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// 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)).
-+///
-+/// 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
-+/// to the length of the provided slice including a NUL terminating byte.  If
-+/// the hostname is longer than the length provided, no error will be provided.
-+/// The posix specification does not specify whether implementations will
-+/// null-terminate in this case, but the nix implementation will ensure that the
-+/// buffer is null terminated in this case.
-+///
-+/// ```no_run
-+/// use nix::unistd;
-+///
-+/// let mut buf = [0u8; 64];
-+/// let hostname_cstr = unistd::gethostname(&mut buf).expect("Failed getting hostname");
-+/// let hostname = hostname_cstr.to_str().expect("Hostname wasn't valid UTF-8");
-+/// println!("Hostname: {}", hostname);
-+/// ```
-+pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
-+    let ptr = buffer.as_mut_ptr() as *mut c_char;
-+    let len = buffer.len() as size_t;
-+
-+    let res = unsafe { libc::gethostname(ptr, len) };
-+    Errno::result(res).map(|_| {
-+        buffer[len - 1] = 0; // ensure always null-terminated
-+        unsafe { CStr::from_ptr(buffer.as_ptr() as *const c_char) }
-+    })
-+}
-+
-+/// Close a raw file descriptor
-+///
-+/// Be aware that many Rust types implicitly close-on-drop, including
-+/// `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).
-+///
-+/// # Examples
-+///
-+/// ```no_run
-+/// extern crate tempfile;
-+/// extern crate nix;
-+///
-+/// 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!
-+/// }
-+/// ```
-+///
-+/// ```rust
-+/// extern crate tempfile;
-+/// extern crate nix;
-+///
-+/// 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
-+/// }
-+/// ```
-+pub fn close(fd: RawFd) -> Result<()> {
-+    let res = unsafe { libc::close(fd) };
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Read from a raw file descriptor.
-+///
-+/// See also [read(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html)
-+pub fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize> {
-+    let res = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len() as size_t) };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Write to a raw file descriptor.
-+///
-+/// See also [write(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html)
-+pub fn write(fd: RawFd, buf: &[u8]) -> Result<usize> {
-+    let res = unsafe { libc::write(fd, buf.as_ptr() as *const c_void, buf.len() as size_t) };
-+
-+    Errno::result(res).map(|r| r as usize)
-+}
-+
-+/// Directive that tells [`lseek`] and [`lseek64`] what the offset is relative to.
-+///
-+/// [`lseek`]: ./fn.lseek.html
-+/// [`lseek64`]: ./fn.lseek64.html
-+#[repr(i32)]
-+#[derive(Clone, Copy, Debug)]
-+pub enum Whence {
-+    /// Specify an offset relative to the start of the file.
-+    SeekSet = libc::SEEK_SET,
-+    /// Specify an offset relative to the current file location.
-+    SeekCur = libc::SEEK_CUR,
-+    /// Specify an offset relative to the end of the file.
-+    SeekEnd = libc::SEEK_END,
-+    /// 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",
-+          all(target_os = "linux", not(any(target_env = "musl",
-+                                           target_arch = "mips",
-+                                           target_arch = "mips64")))))]
-+    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",
-+          all(target_os = "linux", not(any(target_env = "musl",
-+                                           target_arch = "mips",
-+                                           target_arch = "mips64")))))]
-+    SeekHole = libc::SEEK_HOLE
-+}
-+
-+/// Move the read/write file offset.
-+///
-+/// See also [lseek(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html)
-+pub fn lseek(fd: RawFd, offset: off_t, whence: Whence) -> Result<off_t> {
-+    let res = unsafe { libc::lseek(fd, offset, whence as i32) };
-+
-+    Errno::result(res).map(|r| r as off_t)
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc::off64_t> {
-+    let res = unsafe { libc::lseek64(fd, offset, whence as i32) };
-+
-+    Errno::result(res).map(|r| r as libc::off64_t)
-+}
-+
-+/// Create an interprocess channel.
-+///
-+/// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
-+pub fn pipe() -> Result<(RawFd, RawFd)> {
-+    unsafe {
-+        let mut fds: [c_int; 2] = mem::uninitialized();
-+
-+        let res = libc::pipe(fds.as_mut_ptr());
-+
-+        Errno::result(res)?;
-+
-+        Ok((fds[0], fds[1]))
-+    }
-+}
-+
-+/// Like `pipe`, but allows setting certain file descriptor flags.
-+///
-+/// 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_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)
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "emscripten",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
-+    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
-+
-+    let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) };
-+
-+    Errno::result(res)?;
-+
-+    Ok((fds[0], fds[1]))
-+}
-+
-+/// Like `pipe`, but allows setting certain file descriptor flags.
-+///
-+/// The following flags are supported, and will be set after the pipe is
-+/// created:
-+///
-+/// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
-+/// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+#[deprecated(
-+    since="0.10.0",
-+    note="pipe2(2) is not actually atomic on these platforms.  Use pipe(2) and fcntl(2) instead"
-+)]
-+pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
-+    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
-+
-+    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
-+
-+    Errno::result(res)?;
-+
-+    pipe2_setflags(fds[0], fds[1], flags)?;
-+
-+    Ok((fds[0], fds[1]))
-+}
-+
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
-+    use fcntl::FcntlArg::F_SETFL;
-+
-+    let mut res = Ok(0);
-+
-+    if flags.contains(OFlag::O_CLOEXEC) {
-+        res = res
-+            .and_then(|_| fcntl(fd1, F_SETFD(FdFlag::FD_CLOEXEC)))
-+            .and_then(|_| fcntl(fd2, F_SETFD(FdFlag::FD_CLOEXEC)));
-+    }
-+
-+    if flags.contains(OFlag::O_NONBLOCK) {
-+        res = res
-+            .and_then(|_| fcntl(fd1, F_SETFL(OFlag::O_NONBLOCK)))
-+            .and_then(|_| fcntl(fd2, F_SETFL(OFlag::O_NONBLOCK)));
-+    }
-+
-+    match res {
-+        Ok(_) => Ok(()),
-+        Err(e) => {
-+            let _ = close(fd1);
-+            let _ = close(fd2);
-+            Err(e)
-+        }
-+    }
-+}
-+
-+/// Truncate a file to a specified length
-+///
-+/// See also
-+/// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
-+pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::truncate(cstr.as_ptr(), len)
-+        }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Truncate a file to a specified length
-+///
-+/// See also
-+/// [ftruncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html)
-+pub fn ftruncate(fd: RawFd, len: off_t) -> Result<()> {
-+    Errno::result(unsafe { libc::ftruncate(fd, len) }).map(drop)
-+}
-+
-+pub fn isatty(fd: RawFd) -> Result<bool> {
-+    unsafe {
-+        // ENOTTY means `fd` is a valid file descriptor, but not a TTY, so
-+        // we return `Ok(false)`
-+        if libc::isatty(fd) == 1 {
-+            Ok(true)
-+        } else {
-+            match Errno::last() {
-+                Errno::ENOTTY => Ok(false),
-+                err => Err(Error::Sys(err)),
-+            }
-+        }
-+    }
-+}
-+
-+/// Remove a directory entry
-+///
-+/// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
-+pub fn unlink<P: ?Sized + NixPath>(path: &P) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::unlink(cstr.as_ptr())
-+        }
-+    })?;
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Flags for `unlinkat` function.
-+#[derive(Clone, Copy, Debug)]
-+pub enum UnlinkatFlags {
-+    RemoveDir,
-+    NoRemoveDir,
-+}
-+
-+/// Remove a directory entry
-+///
-+/// In the case of a relative path, the directory entry to be removed is determined relative to
-+/// the directory associated with the file descriptor `dirfd` or the current working directory
-+/// if `dirfd` is `None`. In the case of an absolute `path` `dirfd` is ignored. If `flag` is
-+/// `UnlinkatFlags::RemoveDir` then removal of the directory entry specified by `dirfd` and `path`
-+/// is performed.
-+///
-+/// # References
-+/// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
-+pub fn unlinkat<P: ?Sized + NixPath>(
-+    dirfd: Option<RawFd>,
-+    path: &P,
-+    flag: UnlinkatFlags,
-+) -> Result<()> {
-+    let atflag =
-+        match flag {
-+            UnlinkatFlags::RemoveDir => AtFlags::AT_REMOVEDIR,
-+            UnlinkatFlags::NoRemoveDir => AtFlags::empty(),
-+        };
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::unlinkat(at_rawfd(dirfd), cstr.as_ptr(), atflag.bits() as libc::c_int)
-+        }
-+    })?;
-+    Errno::result(res).map(drop)
-+}
-+
-+
-+#[inline]
-+pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe { libc::chroot(cstr.as_ptr()) }
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Commit filesystem caches to disk
-+///
-+/// See also [sync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
-+#[cfg(any(
-+    target_os = "dragonfly",
-+    target_os = "freebsd",
-+    target_os = "linux",
-+    target_os = "netbsd",
-+    target_os = "openbsd"
-+))]
-+pub fn sync() -> () {
-+    unsafe { libc::sync() };
-+}
-+
-+/// Synchronize changes to a file
-+///
-+/// See also [fsync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html)
-+#[inline]
-+pub fn fsync(fd: RawFd) -> Result<()> {
-+    let res = unsafe { libc::fsync(fd) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Synchronize the data of a file
-+///
-+/// See also
-+/// [fdatasync(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html)
-+// `fdatasync(2) is in POSIX, but in libc it is only defined in `libc::notbsd`.
-+// TODO: exclude only Apple systems after https://github.com/rust-lang/libc/pull/211
-+#[cfg(any(target_os = "linux",
-+          target_os = "android",
-+          target_os = "emscripten"))]
-+#[inline]
-+pub fn fdatasync(fd: RawFd) -> Result<()> {
-+    let res = unsafe { libc::fdatasync(fd) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Get a real user ID
-+///
-+/// See also [getuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getuid.html)
-+// POSIX requires that getuid is always successful, so no need to check return
-+// value or errno.
-+#[inline]
-+pub fn getuid() -> Uid {
-+    Uid(unsafe { libc::getuid() })
-+}
-+
-+/// Get the effective user ID
-+///
-+/// See also [geteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/geteuid.html)
-+// POSIX requires that geteuid is always successful, so no need to check return
-+// value or errno.
-+#[inline]
-+pub fn geteuid() -> Uid {
-+    Uid(unsafe { libc::geteuid() })
-+}
-+
-+/// Get the real group ID
-+///
-+/// See also [getgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getgid.html)
-+// POSIX requires that getgid is always successful, so no need to check return
-+// value or errno.
-+#[inline]
-+pub fn getgid() -> Gid {
-+    Gid(unsafe { libc::getgid() })
-+}
-+
-+/// Get the effective group ID
-+///
-+/// See also [getegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getegid.html)
-+// POSIX requires that getegid is always successful, so no need to check return
-+// value or errno.
-+#[inline]
-+pub fn getegid() -> Gid {
-+    Gid(unsafe { libc::getegid() })
-+}
-+
-+/// Set the effective user ID
-+///
-+/// See also [seteuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/seteuid.html)
-+#[inline]
-+pub fn seteuid(euid: Uid) -> Result<()> {
-+    let res = unsafe { libc::seteuid(euid.into()) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Set the effective group ID
-+///
-+/// See also [setegid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setegid.html)
-+#[inline]
-+pub fn setegid(egid: Gid) -> Result<()> {
-+    let res = unsafe { libc::setegid(egid.into()) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Set the user ID
-+///
-+/// See also [setuid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html)
-+#[inline]
-+pub fn setuid(uid: Uid) -> Result<()> {
-+    let res = unsafe { libc::setuid(uid.into()) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Set the group ID
-+///
-+/// See also [setgid(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html)
-+#[inline]
-+pub fn setgid(gid: Gid) -> Result<()> {
-+    let res = unsafe { libc::setgid(gid.into()) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Get the list of supplementary group IDs of the calling process.
-+///
-+/// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
-+///
-+/// **Note:** This function is not available for Apple platforms. On those
-+/// platforms, checking group membership should be achieved via communication
-+/// with the `opendirectoryd` service.
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+pub fn getgroups() -> Result<Vec<Gid>> {
-+    // First get the number of groups so we can size our Vec
-+    let ret = unsafe { libc::getgroups(0, ptr::null_mut()) };
-+
-+    // Now actually get the groups. We try multiple times in case the number of
-+    // groups has changed since the first call to getgroups() and the buffer is
-+    // now too small.
-+    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ret)? as usize);
-+    loop {
-+        // FIXME: On the platforms we currently support, the `Gid` struct has
-+        // the same representation in memory as a bare `gid_t`. This is not
-+        // necessarily the case on all Rust platforms, though. See RFC 1785.
-+        let ret = unsafe {
-+            libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
-+        };
-+
-+        match Errno::result(ret) {
-+            Ok(s) => {
-+                unsafe { groups.set_len(s as usize) };
-+                return Ok(groups);
-+            },
-+            Err(Error::Sys(Errno::EINVAL)) => {
-+                // EINVAL indicates that the buffer size was too small. Trigger
-+                // the internal buffer resizing logic of `Vec` by requiring
-+                // more space than the current capacity.
-+                let cap = groups.capacity();
-+                unsafe { groups.set_len(cap) };
-+                groups.reserve(1);
-+            },
-+            Err(e) => return Err(e)
-+        }
-+    }
-+}
-+
-+/// Set the list of supplementary group IDs for the calling process.
-+///
-+/// [Further reading](http://man7.org/linux/man-pages/man2/getgroups.2.html)
-+///
-+/// **Note:** This function is not available for Apple platforms. On those
-+/// platforms, group membership management should be achieved via communication
-+/// with the `opendirectoryd` service.
-+///
-+/// # Examples
-+///
-+/// `setgroups` can be used when dropping privileges from the root user to a
-+/// specific user and group. For example, given the user `www-data` with UID
-+/// `33` and the group `backup` with the GID `34`, one could switch the user as
-+/// follows:
-+///
-+/// ```rust,no_run
-+/// # use std::error::Error;
-+/// # use nix::unistd::*;
-+/// #
-+/// # fn try_main() -> Result<(), Box<Error>> {
-+/// let uid = Uid::from_raw(33);
-+/// let gid = Gid::from_raw(34);
-+/// setgroups(&[gid])?;
-+/// setgid(gid)?;
-+/// setuid(uid)?;
-+/// #
-+/// #     Ok(())
-+/// # }
-+/// #
-+/// # fn main() {
-+/// #     try_main().unwrap();
-+/// # }
-+/// ```
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+pub fn setgroups(groups: &[Gid]) -> Result<()> {
-+    cfg_if! {
-+        if #[cfg(any(target_os = "dragonfly",
-+                     target_os = "freebsd",
-+                     target_os = "ios",
-+                     target_os = "macos",
-+                     target_os = "netbsd",
-+                     target_os = "openbsd"))] {
-+            type setgroups_ngroups_t = c_int;
-+        } else {
-+            type setgroups_ngroups_t = size_t;
-+        }
-+    }
-+    // FIXME: On the platforms we currently support, the `Gid` struct has the
-+    // same representation in memory as a bare `gid_t`. This is not necessarily
-+    // the case on all Rust platforms, though. See RFC 1785.
-+    let res = unsafe {
-+        libc::setgroups(groups.len() as setgroups_ngroups_t, groups.as_ptr() as *const gid_t)
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Calculate the supplementary group access list.
-+///
-+/// 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)
-+///
-+/// **Note:** This function is not available for Apple platforms. On those
-+/// platforms, checking group membership should be achieved via communication
-+/// with the `opendirectoryd` service.
-+///
-+/// # Errors
-+///
-+/// Although the `getgrouplist()` call does not return any specific
-+/// errors on any known platforms, this implementation will return a system
-+/// error of `EINVAL` if the number of groups to be fetched exceeds the
-+/// `NGROUPS_MAX` sysconf value. This mimics the behaviour of `getgroups()`
-+/// 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")))]
-+pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
-+    let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
-+        Ok(Some(n)) => n as c_int,
-+        Ok(None) | Err(_) => <c_int>::max_value(),
-+    };
-+    use std::cmp::min;
-+    let mut ngroups = min(ngroups_max, 8);
-+    let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
-+    cfg_if! {
-+        if #[cfg(any(target_os = "ios", target_os = "macos"))] {
-+            type getgrouplist_group_t = c_int;
-+        } else {
-+            type getgrouplist_group_t = gid_t;
-+        }
-+    }
-+    let gid: gid_t = group.into();
-+    loop {
-+        let ret = unsafe {
-+            libc::getgrouplist(user.as_ptr(),
-+                               gid as getgrouplist_group_t,
-+                               groups.as_mut_ptr() as *mut getgrouplist_group_t,
-+                               &mut ngroups)
-+        };
-+
-+        // BSD systems only return 0 or -1, Linux returns ngroups on success.
-+        if ret >= 0 {
-+            unsafe { groups.set_len(ngroups as usize) };
-+            return Ok(groups);
-+        } else if ret == -1 {
-+            // Returns -1 if ngroups is too small, but does not set errno.
-+            // BSD systems will still fill the groups buffer with as many
-+            // groups as possible, but Linux manpages do not mention this
-+            // behavior.
-+
-+            let cap = groups.capacity();
-+            if cap >= ngroups_max as usize {
-+                // We already have the largest capacity we can, give up
-+                return Err(Error::invalid_argument());
-+            }
-+
-+            // Reserve space for at least ngroups
-+            groups.reserve(ngroups as usize);
-+
-+            // Even if the buffer gets resized to bigger than ngroups_max,
-+            // don't ever ask for more than ngroups_max groups
-+            ngroups = min(ngroups_max, groups.capacity() as c_int);
-+        }
-+    }
-+}
-+
-+/// Initialize the supplementary group access list.
-+///
-+/// Sets the supplementary group IDs for the calling process using 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/initgroups.3.html)
-+///
-+/// **Note:** This function is not available for Apple platforms. On those
-+/// platforms, group membership management should be achieved via communication
-+/// with the `opendirectoryd` service.
-+///
-+/// # Examples
-+///
-+/// `initgroups` can be used when dropping privileges from the root user to
-+/// another user. For example, given the user `www-data`, we could look up the
-+/// UID and GID for the user in the system's password database (usually found
-+/// in `/etc/passwd`). If the `www-data` user's UID and GID were `33` and `33`,
-+/// respectively, one could switch the user as follows:
-+///
-+/// ```rust,no_run
-+/// # use std::error::Error;
-+/// # use std::ffi::CString;
-+/// # use nix::unistd::*;
-+/// #
-+/// # fn try_main() -> Result<(), Box<Error>> {
-+/// let user = CString::new("www-data").unwrap();
-+/// let uid = Uid::from_raw(33);
-+/// let gid = Gid::from_raw(33);
-+/// initgroups(&user, gid)?;
-+/// setgid(gid)?;
-+/// setuid(uid)?;
-+/// #
-+/// #     Ok(())
-+/// # }
-+/// #
-+/// # fn main() {
-+/// #     try_main().unwrap();
-+/// # }
-+/// ```
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
-+    cfg_if! {
-+        if #[cfg(any(target_os = "ios", target_os = "macos"))] {
-+            type initgroups_group_t = c_int;
-+        } else {
-+            type initgroups_group_t = gid_t;
-+        }
-+    }
-+    let gid: gid_t = group.into();
-+    let res = unsafe { libc::initgroups(user.as_ptr(), gid as initgroups_group_t) };
-+
-+    Errno::result(res).map(drop)
-+}
-+
-+/// Suspend the thread until a signal is received.
-+///
-+/// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
-+#[inline]
-+pub fn pause() {
-+    unsafe { libc::pause() };
-+}
-+
-+pub mod alarm {
-+    //! Alarm signal scheduling.
-+    //!
-+    //! Scheduling an alarm will trigger a `SIGALRM` signal when the time has
-+    //! elapsed, which has to be caught, because the default action for the
-+    //! signal is to terminate the program. This signal also can't be ignored
-+    //! because the system calls like `pause` will not be interrupted, see the
-+    //! second example below.
-+    //!
-+    //! # Examples
-+    //!
-+    //! Canceling an alarm:
-+    //!
-+    //! ```
-+    //! use nix::unistd::alarm;
-+    //!
-+    //! // Set an alarm for 60 seconds from now.
-+    //! alarm::set(60);
-+    //!
-+    //! // Cancel the above set alarm, which returns the number of seconds left
-+    //! // of the previously set alarm.
-+    //! assert_eq!(alarm::cancel(), Some(60));
-+    //! ```
-+    //!
-+    //! Scheduling an alarm and waiting for the signal:
-+    //!
-+    //! ```
-+    //! use std::time::{Duration, Instant};
-+    //!
-+    //! use nix::unistd::{alarm, pause};
-+    //! use nix::sys::signal::*;
-+    //!
-+    //! // We need to setup an empty signal handler to catch the alarm signal,
-+    //! // otherwise the program will be terminated once the signal is delivered.
-+    //! extern fn signal_handler(_: nix::libc::c_int) { }
-+    //! unsafe { sigaction(Signal::SIGALRM, &SigAction::new(SigHandler::Handler(signal_handler), SaFlags::empty(), SigSet::empty())); }
-+    //!
-+    //! // Set an alarm for 1 second from now.
-+    //! alarm::set(1);
-+    //!
-+    //! let start = Instant::now();
-+    //! // Pause the process until the alarm signal is received.
-+    //! pause();
-+    //!
-+    //! assert!(start.elapsed() >= Duration::from_secs(1));
-+    //! ```
-+    //!
-+    //! # References
-+    //!
-+    //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
-+
-+    use libc;
-+
-+    /// Schedule an alarm signal.
-+    ///
-+    /// This will cause the system to generate a `SIGALRM` signal for the
-+    /// process after the specified number of seconds have elapsed.
-+    ///
-+    /// Returns the leftover time of a previously set alarm if there was one.
-+    pub fn set(secs: libc::c_uint) -> Option<libc::c_uint> {
-+        assert!(secs != 0, "passing 0 to `alarm::set` is not allowed, to cancel an alarm use `alarm::cancel`");
-+        alarm(secs)
-+    }
-+
-+    /// Cancel an previously set alarm signal.
-+    ///
-+    /// Returns the leftover time of a previously set alarm if there was one.
-+    pub fn cancel() -> Option<libc::c_uint> {
-+        alarm(0)
-+    }
-+
-+    fn alarm(secs: libc::c_uint) -> Option<libc::c_uint> {
-+        match unsafe { libc::alarm(secs) } {
-+            0 => None,
-+            secs => Some(secs),
-+        }
-+    }
-+}
-+
-+/// Suspend execution for an interval of time
-+///
-+/// See also [sleep(2)](http://pubs.opengroup.org/onlinepubs/009695399/functions/sleep.html#tag_03_705_05)
-+// Per POSIX, does not fail
-+#[inline]
-+pub fn sleep(seconds: c_uint) -> c_uint {
-+    unsafe { libc::sleep(seconds) }
-+}
-+
-+pub mod acct {
-+    use libc;
-+    use {Result, NixPath};
-+    use errno::Errno;
-+    use std::ptr;
-+
-+    /// Enable process accounting
-+    ///
-+    /// See also [acct(2)](https://linux.die.net/man/2/acct)
-+    pub fn enable<P: ?Sized + NixPath>(filename: &P) -> Result<()> {
-+        let res = filename.with_nix_path(|cstr| {
-+            unsafe { libc::acct(cstr.as_ptr()) }
-+        })?;
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    /// Disable process accounting
-+    pub fn disable() -> Result<()> {
-+        let res = unsafe { libc::acct(ptr::null()) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+/// Creates a regular file which persists even after process termination
-+///
-+/// * `template`: a path whose 6 rightmost characters must be X, e.g. `/tmp/tmpfile_XXXXXX`
-+/// * returns: tuple of file descriptor and filename
-+///
-+/// 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)
-+///
-+/// # Example
-+///
-+/// ```rust
-+/// use nix::unistd;
-+///
-+/// let _ = match unistd::mkstemp("/tmp/tempfile_XXXXXX") {
-+///     Ok((fd, path)) => {
-+///         unistd::unlink(path.as_path()).unwrap(); // flag file to be deleted at app termination
-+///         fd
-+///     }
-+///     Err(e) => panic!("mkstemp failed: {}", e)
-+/// };
-+/// // do something with fd
-+/// ```
-+#[inline]
-+pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
-+    let mut path = template.with_nix_path(|path| {path.to_bytes_with_nul().to_owned()})?;
-+    let p = path.as_mut_ptr() as *mut _;
-+    let fd = unsafe { libc::mkstemp(p) };
-+    let last = path.pop(); // drop the trailing nul
-+    debug_assert!(last == Some(b'\0'));
-+    let pathname = OsString::from_vec(path);
-+    Errno::result(fd)?;
-+    Ok((fd, PathBuf::from(pathname)))
-+}
-+
-+/// 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.
-+/// 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_`.
-+///
-+/// POSIX 1003.1-2008 standardizes all of these variables, but some OSes choose
-+/// not to implement variables that cannot change at runtime.
-+///
-+/// # 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)
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+#[repr(i32)]
-+pub enum PathconfVar {
-+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
-+              target_os = "netbsd", target_os = "openbsd"))]
-+    /// Minimum number of bits needed to represent, as a signed integer value,
-+    /// the maximum size of a regular file allowed in the specified directory.
-+    FILESIZEBITS = libc::_PC_FILESIZEBITS,
-+    /// Maximum number of links to a single file.
-+    LINK_MAX = libc::_PC_LINK_MAX,
-+    /// Maximum number of bytes in a terminal canonical input line.
-+    MAX_CANON = libc::_PC_MAX_CANON,
-+    /// Minimum number of bytes for which space is available in a terminal input
-+    /// queue; therefore, the maximum number of bytes a conforming application
-+    /// may require to be typed as input before reading them.
-+    MAX_INPUT = libc::_PC_MAX_INPUT,
-+    /// Maximum number of bytes in a filename (not including the terminating
-+    /// null of a filename string).
-+    NAME_MAX = libc::_PC_NAME_MAX,
-+    /// Maximum number of bytes the implementation will store as a pathname in a
-+    /// user-supplied buffer of unspecified size, including the terminating null
-+    /// character. Minimum number the implementation will accept as the maximum
-+    /// number of bytes in a pathname.
-+    PATH_MAX = libc::_PC_PATH_MAX,
-+    /// 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"))]
-+    /// Symbolic links can be created.
-+    POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
-+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-+              target_os = "linux", target_os = "openbsd"))]
-+    /// Minimum number of bytes of storage actually allocated for any portion of
-+    /// a file.
-+    POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
-+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-+              target_os = "linux", target_os = "openbsd"))]
-+    /// Recommended increment for file transfer sizes between the
-+    /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
-+    POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
-+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-+              target_os = "linux", target_os = "openbsd"))]
-+    /// Maximum recommended file transfer size.
-+    POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
-+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-+              target_os = "linux", target_os = "openbsd"))]
-+    /// Minimum recommended file transfer size.
-+    POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
-+    #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
-+              target_os = "linux", target_os = "openbsd"))]
-+    ///  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"))]
-+    /// 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
-+    /// appropriate privileges, and to changing the group ID of a file only to
-+    /// the effective group ID of the process or to one of its supplementary
-+    /// group IDs.
-+    _POSIX_CHOWN_RESTRICTED = libc::_PC_CHOWN_RESTRICTED,
-+    /// Pathname components longer than {NAME_MAX} generate an error.
-+    _POSIX_NO_TRUNC = libc::_PC_NO_TRUNC,
-+    /// This symbol shall be defined to be the value of a character that shall
-+    /// 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"))]
-+    /// 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"))]
-+    /// 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"))]
-+    /// Synchronized input or output operations may be performed for the
-+    /// associated file.
-+    _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
-+    #[cfg(any(target_os = "dragonfly", target_os = "openbsd"))]
-+    /// The resolution in nanoseconds for all file timestamps.
-+    _POSIX_TIMESTAMP_RESOLUTION = libc::_PC_TIMESTAMP_RESOLUTION
-+}
-+
-+/// Like `pathconf`, but works with file descriptors instead of paths (see
-+/// [fpathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
-+///
-+/// # Parameters
-+///
-+/// - `fd`:   The file descriptor whose variable should be interrogated
-+/// - `var`:  The pathconf variable to lookup
-+///
-+/// # Returns
-+///
-+/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-+///     implementation level (for option variables).  Implementation levels are
-+///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
-+/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-+///     unsupported (for option variables)
-+/// - `Err(x)`: an error occurred
-+pub fn fpathconf(fd: RawFd, var: PathconfVar) -> Result<Option<c_long>> {
-+    let raw = unsafe {
-+        Errno::clear();
-+        libc::fpathconf(fd, var as c_int)
-+    };
-+    if raw == -1 {
-+        if errno::errno() == 0 {
-+            Ok(None)
-+        } else {
-+            Err(Error::Sys(Errno::last()))
-+        }
-+    } else {
-+        Ok(Some(raw))
-+    }
-+}
-+
-+/// Get path-dependent configurable system variables (see
-+/// [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html))
-+///
-+/// Returns the value of a path-dependent configurable system variable.  Most
-+/// supported variables also have associated compile-time constants, but POSIX
-+/// allows their values to change at runtime.  There are generally two types of
-+/// `pathconf` variables: options and limits.  See [pathconf(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pathconf.html) for more details.
-+///
-+/// # Parameters
-+///
-+/// - `path`: Lookup the value of `var` for this file or directory
-+/// - `var`:  The `pathconf` variable to lookup
-+///
-+/// # Returns
-+///
-+/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-+///     implementation level (for option variables).  Implementation levels are
-+///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
-+/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-+///     unsupported (for option variables)
-+/// - `Err(x)`: an error occurred
-+pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Option<c_long>> {
-+    let raw = path.with_nix_path(|cstr| {
-+        unsafe {
-+            Errno::clear();
-+            libc::pathconf(cstr.as_ptr(), var as c_int)
-+        }
-+    })?;
-+    if raw == -1 {
-+        if errno::errno() == 0 {
-+            Ok(None)
-+        } else {
-+            Err(Error::Sys(Errno::last()))
-+        }
-+    } else {
-+        Ok(Some(raw))
-+    }
-+}
-+
-+/// 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.
-+/// 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_`.
-+///
-+/// All of these symbols are standardized by POSIX 1003.1-2008, but haven't been
-+/// implemented by all platforms.
-+///
-+/// # 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)
-+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+#[repr(i32)]
-+pub enum SysconfVar {
-+    /// Maximum number of I/O operations in a single list I/O call supported by
-+    /// the implementation.
-+    AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
-+    /// Maximum number of outstanding asynchronous I/O operations supported by
-+    /// the implementation.
-+    AIO_MAX = libc::_SC_AIO_MAX,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The maximum amount by which a process can decrease its asynchronous I/O
-+    /// priority level from its own scheduling priority.
-+    AIO_PRIO_DELTA_MAX = libc::_SC_AIO_PRIO_DELTA_MAX,
-+    /// Maximum length of argument to the exec functions including environment data.
-+    ARG_MAX = libc::_SC_ARG_MAX,
-+    /// Maximum number of functions that may be registered with `atexit`.
-+    ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
-+    /// Maximum obase values allowed by the bc utility.
-+    BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
-+    /// Maximum number of elements permitted in an array by the bc utility.
-+    BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
-+    /// Maximum scale value allowed by the bc utility.
-+    BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
-+    /// Maximum length of a string constant accepted by the bc utility.
-+    BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
-+    /// Maximum number of simultaneous processes per real user ID.
-+    CHILD_MAX = libc::_SC_CHILD_MAX,
-+    // _SC_CLK_TCK is obsolete
-+    /// Maximum number of weights that can be assigned to an entry of the
-+    /// LC_COLLATE order keyword in the locale definition file
-+    COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
-+    /// Maximum number of timer expiration overruns.
-+    DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
-+    /// Maximum number of expressions that can be nested within parentheses by
-+    /// the expr utility.
-+    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"))]
-+    /// 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,
-+    /// Maximum number of iovec structures that one process has available for
-+    /// use with `readv` or `writev`.
-+    IOV_MAX = libc::_SC_IOV_MAX,
-+    /// Unless otherwise noted, the maximum length, in bytes, of a utility's
-+    /// input line (either standard input or another file), when the utility is
-+    /// described as processing text files. The length includes room for the
-+    /// trailing <newline>.
-+    LINE_MAX = libc::_SC_LINE_MAX,
-+    /// Maximum length of a login name.
-+    LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
-+    /// Maximum number of simultaneous supplementary group IDs per process.
-+    NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
-+    /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
-+    GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
-+    /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
-+    GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
-+    /// The maximum number of open message queue descriptors a process may hold.
-+    MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
-+    /// The maximum number of message priorities supported by the implementation.
-+    MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
-+    /// A value one greater than the maximum value that the system may assign to
-+    /// a newly-created file descriptor.
-+    OPEN_MAX = libc::_SC_OPEN_MAX,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              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"))]
-+    /// The implementation supports barriers.
-+    _POSIX_BARRIERS = libc::_SC_BARRIERS,
-+    /// The implementation supports asynchronous input and output.
-+    _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"))]
-+    /// 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"))]
-+    /// The implementation supports the Process CPU-Time Clocks option.
-+    _POSIX_CPUTIME = libc::_SC_CPUTIME,
-+    /// The implementation supports the File Synchronization option.
-+    _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"))]
-+    /// The implementation supports the IPv6 option.
-+    _POSIX_IPV6 = libc::_SC_IPV6,
-+    /// The implementation supports job control.
-+    _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
-+    /// The implementation supports memory mapped Files.
-+    _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
-+    /// The implementation supports the Process Memory Locking option.
-+    _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
-+    /// The implementation supports the Range Memory Locking option.
-+    _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
-+    /// The implementation supports memory protection.
-+    _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
-+    /// The implementation supports the Message Passing option.
-+    _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
-+    /// The implementation supports the Monotonic Clock option.
-+    _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"))]
-+    /// The implementation supports the Prioritized Input and Output option.
-+    _POSIX_PRIORITIZED_IO = libc::_SC_PRIORITIZED_IO,
-+    /// The implementation supports the Process Scheduling option.
-+    _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"))]
-+    /// 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"))]
-+    /// 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",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              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"))]
-+    /// 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.
-+    _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
-+    /// The implementation supports semaphores.
-+    _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
-+    /// The implementation supports the Shared Memory Objects option.
-+    _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the POSIX shell.
-+    _POSIX_SHELL = libc::_SC_SHELL,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Spawn option.
-+    _POSIX_SPAWN = libc::_SC_SPAWN,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports spin locks.
-+    _POSIX_SPIN_LOCKS = libc::_SC_SPIN_LOCKS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Process Sporadic Server option.
-+    _POSIX_SPORADIC_SERVER = libc::_SC_SPORADIC_SERVER,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
-+    /// The implementation supports the Synchronized Input and Output option.
-+    _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
-+    /// The implementation supports the Thread Stack Address Attribute option.
-+    _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
-+    /// The implementation supports the Thread Stack Size Attribute option.
-+    _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="netbsd", target_os="openbsd"))]
-+    /// The implementation supports the Thread CPU-Time Clocks option.
-+    _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
-+    /// The implementation supports the Non-Robust Mutex Priority Inheritance
-+    /// option.
-+    _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
-+    /// The implementation supports the Non-Robust Mutex Priority Protection option.
-+    _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
-+    /// The implementation supports the Thread Execution Scheduling option.
-+    _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Thread Process-Shared Synchronization
-+    /// option.
-+    _POSIX_THREAD_PROCESS_SHARED = libc::_SC_THREAD_PROCESS_SHARED,
-+    #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
-+    /// The implementation supports the Robust Mutex Priority Inheritance option.
-+    _POSIX_THREAD_ROBUST_PRIO_INHERIT = libc::_SC_THREAD_ROBUST_PRIO_INHERIT,
-+    #[cfg(any(target_os="dragonfly", target_os="linux", target_os="openbsd"))]
-+    /// The implementation supports the Robust Mutex Priority Protection option.
-+    _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
-+    /// The implementation supports thread-safe functions.
-+    _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Thread Sporadic Server option.
-+    _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
-+    /// The implementation supports threads.
-+    _POSIX_THREADS = libc::_SC_THREADS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports timeouts.
-+    _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
-+    /// The implementation supports timers.
-+    _POSIX_TIMERS = libc::_SC_TIMERS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Trace option.
-+    _POSIX_TRACE = libc::_SC_TRACE,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Trace Event Filter option.
-+    _POSIX_TRACE_EVENT_FILTER = libc::_SC_TRACE_EVENT_FILTER,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _POSIX_TRACE_EVENT_NAME_MAX = libc::_SC_TRACE_EVENT_NAME_MAX,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Trace Inherit option.
-+    _POSIX_TRACE_INHERIT = libc::_SC_TRACE_INHERIT,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Trace Log option.
-+    _POSIX_TRACE_LOG = libc::_SC_TRACE_LOG,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _POSIX_TRACE_NAME_MAX = libc::_SC_TRACE_NAME_MAX,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _POSIX_TRACE_SYS_MAX = libc::_SC_TRACE_SYS_MAX,
-+    #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _POSIX_TRACE_USER_EVENT_MAX = libc::_SC_TRACE_USER_EVENT_MAX,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the Typed Memory Objects option.
-+    _POSIX_TYPED_MEMORY_OBJECTS = libc::_SC_TYPED_MEMORY_OBJECTS,
-+    /// Integer value indicating version of this standard (C-language binding)
-+    /// to which the implementation conforms. For implementations conforming to
-+    /// POSIX.1-2008, the value shall be 200809L.
-+    _POSIX_VERSION = libc::_SC_VERSION,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation provides a C-language compilation environment with
-+    /// 32-bit `int`, `long`, `pointer`, and `off_t` types.
-+    _POSIX_V6_ILP32_OFF32 = libc::_SC_V6_ILP32_OFF32,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation provides a C-language compilation environment with
-+    /// 32-bit `int`, `long`, and pointer types and an `off_t` type using at
-+    /// least 64 bits.
-+    _POSIX_V6_ILP32_OFFBIG = libc::_SC_V6_ILP32_OFFBIG,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation provides a C-language compilation environment with
-+    /// 32-bit `int` and 64-bit `long`, `pointer`, and `off_t` types.
-+    _POSIX_V6_LP64_OFF64 = libc::_SC_V6_LP64_OFF64,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation provides a C-language compilation environment with an
-+    /// `int` type using at least 32 bits and `long`, pointer, and `off_t` types
-+    /// using at least 64 bits.
-+    _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
-+    /// The implementation supports the C-Language Binding option.
-+    _POSIX2_C_BIND = libc::_SC_2_C_BIND,
-+    /// The implementation supports the C-Language Development Utilities option.
-+    _POSIX2_C_DEV = libc::_SC_2_C_DEV,
-+    /// The implementation supports the Terminal Characteristics option.
-+    _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
-+    /// The implementation supports the FORTRAN Development Utilities option.
-+    _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
-+    /// The implementation supports the FORTRAN Runtime Utilities option.
-+    _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
-+    /// The implementation supports the creation of locales by the localedef
-+    /// utility.
-+    _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Batch Environment Services and Utilities
-+    /// option.
-+    _POSIX2_PBS = libc::_SC_2_PBS,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Batch Accounting option.
-+    _POSIX2_PBS_ACCOUNTING = libc::_SC_2_PBS_ACCOUNTING,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Batch Checkpoint/Restart option.
-+    _POSIX2_PBS_CHECKPOINT = libc::_SC_2_PBS_CHECKPOINT,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Locate Batch Job Request option.
-+    _POSIX2_PBS_LOCATE = libc::_SC_2_PBS_LOCATE,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Batch Job Message Request option.
-+    _POSIX2_PBS_MESSAGE = libc::_SC_2_PBS_MESSAGE,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Track Batch Job Request option.
-+    _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
-+    /// The implementation supports the Software Development Utilities option.
-+    _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
-+    /// The implementation supports the User Portability Utilities option.
-+    _POSIX2_UPE = libc::_SC_2_UPE,
-+    /// Integer value indicating version of the Shell and Utilities volume of
-+    /// POSIX.1 to which the implementation conforms.
-+    _POSIX2_VERSION = libc::_SC_2_VERSION,
-+    /// The size of a system page in bytes.
-+    ///
-+    /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
-+    /// enum constants to have the same value, so nix omits `PAGESIZE`.
-+    PAGE_SIZE = libc::_SC_PAGE_SIZE,
-+    PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
-+    PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
-+    PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
-+    PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
-+    RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    RTSIG_MAX = libc::_SC_RTSIG_MAX,
-+    SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    SEM_VALUE_MAX = libc::_SC_SEM_VALUE_MAX,
-+    #[cfg(any(target_os = "android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os = "openbsd"))]
-+    SIGQUEUE_MAX = libc::_SC_SIGQUEUE_MAX,
-+    STREAM_MAX = libc::_SC_STREAM_MAX,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="netbsd",
-+              target_os="openbsd"))]
-+    SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
-+    TIMER_MAX = libc::_SC_TIMER_MAX,
-+    TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
-+    TZNAME_MAX = libc::_SC_TZNAME_MAX,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The implementation supports the X/Open Encryption Option Group.
-+    _XOPEN_CRYPT = libc::_SC_XOPEN_CRYPT,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The implementation supports the Issue 4, Version 2 Enhanced
-+    /// Internationalization Option Group.
-+    _XOPEN_ENH_I18N = libc::_SC_XOPEN_ENH_I18N,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    _XOPEN_LEGACY = libc::_SC_XOPEN_LEGACY,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The implementation supports the X/Open Realtime Option Group.
-+    _XOPEN_REALTIME = libc::_SC_XOPEN_REALTIME,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The implementation supports the X/Open Realtime Threads Option Group.
-+    _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
-+    /// The implementation supports the Issue 4, Version 2 Shared Memory Option
-+    /// Group.
-+    _XOPEN_SHM = libc::_SC_XOPEN_SHM,
-+    #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-+              target_os="linux", target_os = "macos", target_os="openbsd"))]
-+    /// The implementation supports the XSI STREAMS Option Group.
-+    _XOPEN_STREAMS = libc::_SC_XOPEN_STREAMS,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// The implementation supports the XSI option
-+    _XOPEN_UNIX = libc::_SC_XOPEN_UNIX,
-+    #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-+              target_os = "ios", target_os="linux", target_os = "macos",
-+              target_os="openbsd"))]
-+    /// Integer value indicating version of the X/Open Portability Guide to
-+    /// which the implementation conforms.
-+    _XOPEN_VERSION = libc::_SC_XOPEN_VERSION,
-+}
-+
-+/// Get configurable system variables (see
-+/// [sysconf(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html))
-+///
-+/// Returns the value of a configurable system variable.  Most supported
-+/// variables also have associated compile-time constants, but POSIX
-+/// allows their values to change at runtime.  There are generally two types of
-+/// sysconf variables: options and limits.  See sysconf(3) for more details.
-+///
-+/// # Returns
-+///
-+/// - `Ok(Some(x))`: the variable's limit (for limit variables) or its
-+///     implementation level (for option variables).  Implementation levels are
-+///     usually a decimal-coded date, such as 200112 for POSIX 2001.12
-+/// - `Ok(None)`: the variable has no limit (for limit variables) or is
-+///     unsupported (for option variables)
-+/// - `Err(x)`: an error occurred
-+pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
-+    let raw = unsafe {
-+        Errno::clear();
-+        libc::sysconf(var as c_int)
-+    };
-+    if raw == -1 {
-+        if errno::errno() == 0 {
-+            Ok(None)
-+        } else {
-+            Err(Error::Sys(Errno::last()))
-+        }
-+    } else {
-+        Ok(Some(raw))
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod pivot_root {
-+    use libc;
-+    use {Result, NixPath};
-+    use errno::Errno;
-+
-+    pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-+            new_root: &P1, put_old: &P2) -> Result<()> {
-+        let res = new_root.with_nix_path(|new_root| {
-+            put_old.with_nix_path(|put_old| {
-+                unsafe {
-+                    libc::syscall(libc::SYS_pivot_root, new_root.as_ptr(), put_old.as_ptr())
-+                }
-+            })
-+        })??;
-+
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "freebsd",
-+          target_os = "linux", target_os = "openbsd"))]
-+mod setres {
-+    use libc;
-+    use Result;
-+    use errno::Errno;
-+    use super::{Uid, Gid};
-+
-+    /// Sets the real, effective, and saved uid.
-+    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
-+    ///
-+    /// * `ruid`: real user id
-+    /// * `euid`: effective user id
-+    /// * `suid`: saved user id
-+    /// * returns: Ok or libc error code.
-+    ///
-+    /// Err is returned if the user doesn't have permission to set this UID.
-+    #[inline]
-+    pub fn setresuid(ruid: Uid, euid: Uid, suid: Uid) -> Result<()> {
-+        let res = unsafe { libc::setresuid(ruid.into(), euid.into(), suid.into()) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+
-+    /// Sets the real, effective, and saved gid.
-+    /// ([see setresuid(2)](http://man7.org/linux/man-pages/man2/setresuid.2.html))
-+    ///
-+    /// * `rgid`: real group id
-+    /// * `egid`: effective group id
-+    /// * `sgid`: saved group id
-+    /// * returns: Ok or libc error code.
-+    ///
-+    /// Err is returned if the user doesn't have permission to set this GID.
-+    #[inline]
-+    pub fn setresgid(rgid: Gid, egid: Gid, sgid: Gid) -> Result<()> {
-+        let res = unsafe { libc::setresgid(rgid.into(), egid.into(), sgid.into()) };
-+
-+        Errno::result(res).map(drop)
-+    }
-+}
-+
-+libc_bitflags!{
-+    /// Options for access()
-+    pub struct AccessFlags : c_int {
-+        /// Test for existence of file.
-+        F_OK;
-+        /// Test for read permission.
-+        R_OK;
-+        /// Test for write permission.
-+        W_OK;
-+        /// Test for execute (search) permission.
-+        X_OK;
-+    }
-+}
-+
-+/// 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)
-+pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| {
-+        unsafe {
-+            libc::access(cstr.as_ptr(), amode.bits)
-+        }
-+    })?;
-+    Errno::result(res).map(drop)
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/mod.rs b/third_party/rust/nix-0.15.0/test/sys/mod.rs
-new file mode 100644
-index 0000000000000..60a58dd106f19
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/mod.rs
-@@ -0,0 +1,38 @@
-+mod test_signal;
-+
-+// NOTE: DragonFly lacks a kernel-level implementation of Posix AIO as of
-+// this writing. There is an user-level implementation, but whether aio
-+// works or not heavily depends on which pthread implementation is chosen
-+// by the user at link time. For this reason we do not want to run aio test
-+// cases on DragonFly.
-+#[cfg(any(target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd"))]
-+mod test_aio;
-+#[cfg(target_os = "linux")]
-+mod test_signalfd;
-+mod test_socket;
-+mod test_sockopt;
-+mod test_select;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod test_sysinfo;
-+mod test_termios;
-+mod test_ioctl;
-+mod test_wait;
-+mod test_uio;
-+
-+#[cfg(target_os = "linux")]
-+mod test_epoll;
-+#[cfg(target_os = "linux")]
-+mod test_inotify;
-+mod test_pthread;
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+mod test_ptrace;
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_aio.rs b/third_party/rust/nix-0.15.0/test/sys/test_aio.rs
-new file mode 100644
-index 0000000000000..d4b09b0b81905
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_aio.rs
-@@ -0,0 +1,654 @@
-+use bytes::{Bytes, BytesMut};
-+use libc::{c_int, c_void};
-+use nix::{Error, Result};
-+use nix::errno::*;
-+use nix::sys::aio::*;
-+use nix::sys::signal::{SaFlags, SigAction, sigaction, SigevNotify, SigHandler, Signal, SigSet};
-+use nix::sys::time::{TimeSpec, TimeValLike};
-+use std::io::{Write, Read, Seek, SeekFrom};
-+use std::ops::Deref;
-+use std::os::unix::io::AsRawFd;
-+use std::sync::atomic::{AtomicBool, Ordering};
-+use std::{thread, time};
-+use tempfile::tempfile;
-+
-+// Helper that polls an AioCb for completion or error
-+fn poll_aio(aiocb: &mut AioCb) -> Result<()> {
-+    loop {
-+        let err = aiocb.error();
-+        if err != Err(Error::from(Errno::EINPROGRESS)) { return err; };
-+        thread::sleep(time::Duration::from_millis(10));
-+    }
-+}
-+
-+#[test]
-+fn test_accessors() {
-+    let mut rbuf = vec![0; 4];
-+    let aiocb = AioCb::from_mut_slice( 1001,
-+                           2,   //offset
-+                           &mut rbuf,
-+                           42,   //priority
-+                           SigevNotify::SigevSignal {
-+                               signal: Signal::SIGUSR2,
-+                               si_value: 99
-+                           },
-+                           LioOpcode::LIO_NOP);
-+    assert_eq!(1001, aiocb.fd());
-+    assert_eq!(Some(LioOpcode::LIO_NOP), aiocb.lio_opcode());
-+    assert_eq!(4, aiocb.nbytes());
-+    assert_eq!(2, aiocb.offset());
-+    assert_eq!(42, aiocb.priority());
-+    let sev = aiocb.sigevent().sigevent();
-+    assert_eq!(Signal::SIGUSR2 as i32, sev.sigev_signo);
-+    assert_eq!(99, sev.sigev_value.sival_ptr as i64);
-+}
-+
-+// Tests AioCb.cancel.  We aren't trying to test the OS's implementation, only
-+// our bindings.  So it's sufficient to check that AioCb.cancel returned any
-+// AioCancelStat value.
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_cancel() {
-+    let wbuf: &[u8] = b"CDEF";
-+
-+    let f = tempfile().unwrap();
-+    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+                            0,   //offset
-+                            wbuf,
-+                            0,   //priority
-+                            SigevNotify::SigevNone,
-+                            LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+    let err = aiocb.error();
-+    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
-+
-+    let cancelstat = aiocb.cancel();
-+    assert!(cancelstat.is_ok());
-+
-+    // Wait for aiocb to complete, but don't care whether it succeeded
-+    let _ = poll_aio(&mut aiocb);
-+    let _ = aiocb.aio_return();
-+}
-+
-+// Tests using aio_cancel_all for all outstanding IOs.
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_aio_cancel_all() {
-+    let wbuf: &[u8] = b"CDEF";
-+
-+    let f = tempfile().unwrap();
-+    let mut aiocb = AioCb::from_slice(f.as_raw_fd(),
-+                            0,   //offset
-+                            wbuf,
-+                            0,   //priority
-+                            SigevNotify::SigevNone,
-+                            LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+    let err = aiocb.error();
-+    assert!(err == Ok(()) || err == Err(Error::from(Errno::EINPROGRESS)));
-+
-+    let cancelstat = aio_cancel_all(f.as_raw_fd());
-+    assert!(cancelstat.is_ok());
-+
-+    // Wait for aiocb to complete, but don't care whether it succeeded
-+    let _ = poll_aio(&mut aiocb);
-+    let _ = aiocb.aio_return();
-+}
-+
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_fsync() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
-+                            0,   //priority
-+                            SigevNotify::SigevNone);
-+    let err = aiocb.fsync(AioFsyncMode::O_SYNC);
-+    assert!(err.is_ok());
-+    poll_aio(&mut aiocb).unwrap();
-+    aiocb.aio_return().unwrap();
-+}
-+
-+/// `AioCb::fsync` should not modify the `AioCb` object if `libc::aio_fsync` returns
-+/// an error
-+// Skip on Linux, because Linux's AIO implementation can't detect errors
-+// synchronously
-+#[test]
-+#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-+fn test_fsync_error() {
-+    use std::mem;
-+
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    // Create an invalid AioFsyncMode
-+    let mode = unsafe { mem::transmute(666) };
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_fd( f.as_raw_fd(),
-+                            0,   //priority
-+                            SigevNotify::SigevNone);
-+    let err = aiocb.fsync(mode);
-+    assert!(err.is_err());
-+}
-+
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_aio_suspend() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    const WBUF: &[u8] = b"CDEFG";
-+    let timeout = TimeSpec::seconds(10);
-+    let mut rbuf = vec![0; 4];
-+    let rlen = rbuf.len();
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+
-+    let mut wcb = AioCb::from_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           WBUF,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_WRITE);
-+
-+    let mut rcb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                            8,   //offset
-+                            &mut rbuf,
-+                            0,   //priority
-+                            SigevNotify::SigevNone,
-+                            LioOpcode::LIO_READ);
-+    wcb.write().unwrap();
-+    rcb.read().unwrap();
-+    loop {
-+        {
-+            let cbbuf = [&wcb, &rcb];
-+            assert!(aio_suspend(&cbbuf[..], Some(timeout)).is_ok());
-+        }
-+        if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
-+           wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
-+            break
-+        }
-+    }
-+
-+    assert!(wcb.aio_return().unwrap() as usize == WBUF.len());
-+    assert!(rcb.aio_return().unwrap() as usize == rlen);
-+}
-+
-+// Test a simple aio operation with no completion notification.  We must poll
-+// for completion
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_read() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let mut rbuf = vec![0; 4];
-+    const EXPECT: &[u8] = b"cdef";
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    {
-+        let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                               2,   //offset
-+                               &mut rbuf,
-+                               0,   //priority
-+                               SigevNotify::SigevNone,
-+                               LioOpcode::LIO_NOP);
-+        aiocb.read().unwrap();
-+
-+        let err = poll_aio(&mut aiocb);
-+        assert!(err == Ok(()));
-+        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+    }
-+
-+    assert!(EXPECT == rbuf.deref().deref());
-+}
-+
-+/// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
-+/// returns an error
-+// Skip on Linux, because Linux's AIO implementation can't detect errors
-+// synchronously
-+#[test]
-+#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-+fn test_read_error() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let mut rbuf = vec![0; 4];
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                           -1,   //an invalid offset
-+                           &mut rbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    assert!(aiocb.read().is_err());
-+}
-+
-+// Tests from_mut_slice
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_read_into_mut_slice() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let mut rbuf = vec![0; 4];
-+    const EXPECT: &[u8] = b"cdef";
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    {
-+        let mut aiocb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                               2,   //offset
-+                               &mut rbuf,
-+                               0,   //priority
-+                               SigevNotify::SigevNone,
-+                               LioOpcode::LIO_NOP);
-+        aiocb.read().unwrap();
-+
-+        let err = poll_aio(&mut aiocb);
-+        assert!(err == Ok(()));
-+        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+    }
-+
-+    assert!(rbuf == EXPECT);
-+}
-+
-+// Tests from_ptr
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_read_into_pointer() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let mut rbuf = vec![0; 4];
-+    const EXPECT: &[u8] = b"cdef";
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    {
-+        // Safety: ok because rbuf lives until after poll_aio
-+        let mut aiocb = unsafe {
-+            AioCb::from_mut_ptr( f.as_raw_fd(),
-+                                 2,   //offset
-+                                 rbuf.as_mut_ptr() as *mut c_void,
-+                                 rbuf.len(),
-+                                 0,   //priority
-+                                 SigevNotify::SigevNone,
-+                                 LioOpcode::LIO_NOP)
-+        };
-+        aiocb.read().unwrap();
-+
-+        let err = poll_aio(&mut aiocb);
-+        assert!(err == Ok(()));
-+        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+    }
-+
-+    assert!(rbuf == EXPECT);
-+}
-+
-+// Test reading into an immutable buffer.  It should fail
-+// FIXME: This test fails to panic on Linux/musl
-+#[test]
-+#[should_panic(expected = "Can't read into an immutable buffer")]
-+#[cfg_attr(target_env = "musl", ignore)]
-+fn test_read_immutable_buffer() {
-+    let rbuf: &[u8] = b"CDEF";
-+    let f = tempfile().unwrap();
-+    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           rbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    aiocb.read().unwrap();
-+}
-+
-+
-+// Test a simple aio operation with no completion notification.  We must poll
-+// for completion.  Unlike test_aio_read, this test uses AioCb::from_slice
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_write() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let wbuf = "CDEF".to_string().into_bytes();
-+    let mut rbuf = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           &wbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+
-+    let err = poll_aio(&mut aiocb);
-+    assert!(err == Ok(()));
-+    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf == EXPECT);
-+}
-+
-+// Tests `AioCb::from_boxed_slice` with `Bytes`
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_write_bytes() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let wbuf = Box::new(Bytes::from(&b"CDEF"[..]));
-+    let mut rbuf = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+    let expected_len = wbuf.len();
-+
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_boxed_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           wbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+
-+    let err = poll_aio(&mut aiocb);
-+    assert!(err == Ok(()));
-+    assert!(aiocb.aio_return().unwrap() as usize == expected_len);
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf == EXPECT);
-+}
-+
-+// Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_read_bytes_mut_small() {
-+    const INITIAL: &[u8] = b"abcdef";
-+    let rbuf = Box::new(BytesMut::from(vec![0; 4]));
-+    const EXPECT: &[u8] = b"cdef";
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+
-+    let mut aiocb = AioCb::from_boxed_mut_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           rbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    aiocb.read().unwrap();
-+
-+    let err = poll_aio(&mut aiocb);
-+    assert_eq!(err, Ok(()));
-+    assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-+    let buffer = aiocb.boxed_mut_slice().unwrap();
-+    assert_eq!(buffer.borrow(), EXPECT);
-+}
-+
-+// Tests `AioCb::from_ptr`
-+#[test]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_write_from_pointer() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    let wbuf = "CDEF".to_string().into_bytes();
-+    let mut rbuf = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    // Safety: ok because aiocb outlives poll_aio
-+    let mut aiocb = unsafe {
-+        AioCb::from_ptr( f.as_raw_fd(),
-+                         2,   //offset
-+                         wbuf.as_ptr() as *const c_void,
-+                         wbuf.len(),
-+                         0,   //priority
-+                         SigevNotify::SigevNone,
-+                         LioOpcode::LIO_NOP)
-+    };
-+    aiocb.write().unwrap();
-+
-+    let err = poll_aio(&mut aiocb);
-+    assert!(err == Ok(()));
-+    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf == EXPECT);
-+}
-+
-+/// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
-+/// returns an error
-+// Skip on Linux, because Linux's AIO implementation can't detect errors
-+// synchronously
-+#[test]
-+#[cfg(any(target_os = "freebsd", target_os = "macos"))]
-+fn test_write_error() {
-+    let wbuf = "CDEF".to_string().into_bytes();
-+    let mut aiocb = AioCb::from_slice( 666, // An invalid file descriptor
-+                           0,   //offset
-+                           &wbuf,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    assert!(aiocb.write().is_err());
-+}
-+
-+lazy_static! {
-+    pub static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-+}
-+
-+extern fn sigfunc(_: c_int) {
-+    SIGNALED.store(true, Ordering::Relaxed);
-+}
-+
-+// Test an aio operation with completion delivered by a signal
-+// FIXME: This test is ignored on mips because of failures in qemu in CI
-+#[test]
-+#[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
-+fn test_write_sigev_signal() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let sa = SigAction::new(SigHandler::Handler(sigfunc),
-+                            SaFlags::SA_RESETHAND,
-+                            SigSet::empty());
-+    SIGNALED.store(false, Ordering::Relaxed);
-+    unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
-+
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    const WBUF: &[u8] = b"CDEF";
-+    let mut rbuf = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+
-+    let mut f = tempfile().unwrap();
-+    f.write_all(INITIAL).unwrap();
-+    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           WBUF,
-+                           0,   //priority
-+                           SigevNotify::SigevSignal {
-+                               signal: Signal::SIGUSR2,
-+                               si_value: 0  //TODO: validate in sigfunc
-+                           },
-+                           LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+    while !SIGNALED.load(Ordering::Relaxed) {
-+        thread::sleep(time::Duration::from_millis(10));
-+    }
-+
-+    assert!(aiocb.aio_return().unwrap() as usize == WBUF.len());
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf == EXPECT);
-+}
-+
-+// Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
-+// time listio returns.
-+#[test]
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_liocb_listio_wait() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    const WBUF: &[u8] = b"CDEF";
-+    let mut rbuf = vec![0; 4];
-+    let rlen = rbuf.len();
-+    let mut rbuf2 = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+    let mut f = tempfile().unwrap();
-+
-+    f.write_all(INITIAL).unwrap();
-+
-+    {
-+        let wcb = AioCb::from_slice( f.as_raw_fd(),
-+                               2,   //offset
-+                               WBUF,
-+                               0,   //priority
-+                               SigevNotify::SigevNone,
-+                               LioOpcode::LIO_WRITE);
-+
-+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                                8,   //offset
-+                                &mut rbuf,
-+                                0,   //priority
-+                                SigevNotify::SigevNone,
-+                                LioOpcode::LIO_READ);
-+        let mut liocb = LioCb::with_capacity(2);
-+        liocb.aiocbs.push(wcb);
-+        liocb.aiocbs.push(rcb);
-+        let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
-+        err.expect("lio_listio");
-+
-+        assert!(liocb.aio_return(0).unwrap() as usize == WBUF.len());
-+        assert!(liocb.aio_return(1).unwrap() as usize == rlen);
-+    }
-+    assert!(rbuf.deref().deref() == b"3456");
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf2).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf2 == EXPECT);
-+}
-+
-+// Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
-+// mechanism to check for the individual AioCb's completion.
-+#[test]
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+fn test_liocb_listio_nowait() {
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    const WBUF: &[u8] = b"CDEF";
-+    let mut rbuf = vec![0; 4];
-+    let rlen = rbuf.len();
-+    let mut rbuf2 = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+    let mut f = tempfile().unwrap();
-+
-+    f.write_all(INITIAL).unwrap();
-+
-+    {
-+        let wcb = AioCb::from_slice( f.as_raw_fd(),
-+                               2,   //offset
-+                               WBUF,
-+                               0,   //priority
-+                               SigevNotify::SigevNone,
-+                               LioOpcode::LIO_WRITE);
-+
-+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                                8,   //offset
-+                                &mut rbuf,
-+                                0,   //priority
-+                                SigevNotify::SigevNone,
-+                                LioOpcode::LIO_READ);
-+        let mut liocb = LioCb::with_capacity(2);
-+        liocb.aiocbs.push(wcb);
-+        liocb.aiocbs.push(rcb);
-+        let err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
-+        err.expect("lio_listio");
-+
-+        poll_aio(&mut liocb.aiocbs[0]).unwrap();
-+        poll_aio(&mut liocb.aiocbs[1]).unwrap();
-+        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
-+        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
-+    }
-+    assert!(rbuf.deref().deref() == b"3456");
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf2).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf2 == EXPECT);
-+}
-+
-+// Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
-+// AioCb's are complete.
-+// FIXME: This test is ignored on mips/mips64 because of failures in qemu in CI.
-+#[test]
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
-+fn test_liocb_listio_signal() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    const INITIAL: &[u8] = b"abcdef123456";
-+    const WBUF: &[u8] = b"CDEF";
-+    let mut rbuf = vec![0; 4];
-+    let rlen = rbuf.len();
-+    let mut rbuf2 = Vec::new();
-+    const EXPECT: &[u8] = b"abCDEF123456";
-+    let mut f = tempfile().unwrap();
-+    let sa = SigAction::new(SigHandler::Handler(sigfunc),
-+                            SaFlags::SA_RESETHAND,
-+                            SigSet::empty());
-+    let sigev_notify = SigevNotify::SigevSignal { signal: Signal::SIGUSR2,
-+                                                  si_value: 0 };
-+
-+    f.write_all(INITIAL).unwrap();
-+
-+    {
-+        let wcb = AioCb::from_slice( f.as_raw_fd(),
-+                               2,   //offset
-+                               WBUF,
-+                               0,   //priority
-+                               SigevNotify::SigevNone,
-+                               LioOpcode::LIO_WRITE);
-+
-+        let rcb = AioCb::from_mut_slice( f.as_raw_fd(),
-+                                8,   //offset
-+                                &mut rbuf,
-+                                0,   //priority
-+                                SigevNotify::SigevNone,
-+                                LioOpcode::LIO_READ);
-+        let mut liocb = LioCb::with_capacity(2);
-+        liocb.aiocbs.push(wcb);
-+        liocb.aiocbs.push(rcb);
-+        SIGNALED.store(false, Ordering::Relaxed);
-+        unsafe { sigaction(Signal::SIGUSR2, &sa) }.unwrap();
-+        let err = liocb.listio(LioMode::LIO_NOWAIT, sigev_notify);
-+        err.expect("lio_listio");
-+        while !SIGNALED.load(Ordering::Relaxed) {
-+            thread::sleep(time::Duration::from_millis(10));
-+        }
-+
-+        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
-+        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
-+    }
-+    assert!(rbuf.deref().deref() == b"3456");
-+
-+    f.seek(SeekFrom::Start(0)).unwrap();
-+    let len = f.read_to_end(&mut rbuf2).unwrap();
-+    assert!(len == EXPECT.len());
-+    assert!(rbuf2 == EXPECT);
-+}
-+
-+// Try to use LioCb::listio to read into an immutable buffer.  It should fail
-+// FIXME: This test fails to panic on Linux/musl
-+#[test]
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[should_panic(expected = "Can't read into an immutable buffer")]
-+#[cfg_attr(target_env = "musl", ignore)]
-+fn test_liocb_listio_read_immutable() {
-+    let rbuf: &[u8] = b"abcd";
-+    let f = tempfile().unwrap();
-+
-+
-+    let mut liocb = LioCb::from(vec![
-+        AioCb::from_slice( f.as_raw_fd(),
-+            2,   //offset
-+            rbuf,
-+            0,   //priority
-+            SigevNotify::SigevNone,
-+            LioOpcode::LIO_READ)
-+    ]);
-+    let _ = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs b/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
-new file mode 100644
-index 0000000000000..492da401ef726
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_aio_drop.rs
-@@ -0,0 +1,32 @@
-+extern crate nix;
-+extern crate tempfile;
-+
-+// Test dropping an AioCb that hasn't yet finished.
-+// This must happen in its own process, because on OSX this test seems to hose
-+// the AIO subsystem and causes subsequent tests to fail
-+#[test]
-+#[should_panic(expected = "Dropped an in-progress AioCb")]
-+#[cfg(all(not(target_env = "musl"),
-+          any(target_os = "linux",
-+              target_os = "ios",
-+              target_os = "macos",
-+              target_os = "freebsd",
-+              target_os = "netbsd")))]
-+fn test_drop() {
-+    use nix::sys::aio::*;
-+    use nix::sys::signal::*;
-+    use std::os::unix::io::AsRawFd;
-+    use tempfile::tempfile;
-+
-+    const WBUF: &[u8] = b"CDEF";
-+
-+    let f = tempfile().unwrap();
-+    f.set_len(6).unwrap();
-+    let mut aiocb = AioCb::from_slice( f.as_raw_fd(),
-+                           2,   //offset
-+                           WBUF,
-+                           0,   //priority
-+                           SigevNotify::SigevNone,
-+                           LioOpcode::LIO_NOP);
-+    aiocb.write().unwrap();
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs b/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
-new file mode 100644
-index 0000000000000..e0dc5131defe0
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_epoll.rs
-@@ -0,0 +1,24 @@
-+use nix::sys::epoll::{EpollCreateFlags, EpollFlags, EpollOp, EpollEvent};
-+use nix::sys::epoll::{epoll_create1, epoll_ctl};
-+use nix::Error;
-+use nix::errno::Errno;
-+
-+#[test]
-+pub fn test_epoll_errno() {
-+    let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
-+    let result = epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None);
-+    assert!(result.is_err());
-+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
-+
-+    let result = epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, None);
-+    assert!(result.is_err());
-+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
-+}
-+
-+#[test]
-+pub fn test_epoll_ctl() {
-+    let efd = epoll_create1(EpollCreateFlags::empty()).unwrap();
-+    let mut event = EpollEvent::new(EpollFlags::EPOLLIN | EpollFlags::EPOLLERR, 1);
-+    epoll_ctl(efd, EpollOp::EpollCtlAdd, 1, &mut event).unwrap();
-+    epoll_ctl(efd, EpollOp::EpollCtlDel, 1, None).unwrap();
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs b/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
-new file mode 100644
-index 0000000000000..a8ead46d487ba
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_inotify.rs
-@@ -0,0 +1,65 @@
-+use nix::sys::inotify::{AddWatchFlags,InitFlags,Inotify};
-+use nix::Error;
-+use nix::errno::Errno;
-+use tempfile;
-+use std::ffi::OsString;
-+use std::fs::{rename, File};
-+
-+#[test]
-+pub fn test_inotify() {
-+    let instance = Inotify::init(InitFlags::IN_NONBLOCK)
-+        .unwrap();
-+    let tempdir = tempfile::tempdir().unwrap();
-+
-+    instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
-+
-+    let events = instance.read_events();
-+    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
-+
-+    File::create(tempdir.path().join("test")).unwrap();
-+
-+    let events = instance.read_events().unwrap();
-+    assert_eq!(events[0].name, Some(OsString::from("test")));
-+}
-+
-+#[test]
-+pub fn test_inotify_multi_events() {
-+    let instance = Inotify::init(InitFlags::IN_NONBLOCK)
-+        .unwrap();
-+    let tempdir = tempfile::tempdir().unwrap();
-+
-+    instance.add_watch(tempdir.path(), AddWatchFlags::IN_ALL_EVENTS).unwrap();
-+
-+    let events = instance.read_events();
-+    assert_eq!(events.unwrap_err(), Error::Sys(Errno::EAGAIN));
-+
-+    File::create(tempdir.path().join("test")).unwrap();
-+    rename(tempdir.path().join("test"), tempdir.path().join("test2")).unwrap();
-+
-+    // Now there should be 5 events in queue:
-+    //   - IN_CREATE on test
-+    //   - IN_OPEN on test
-+    //   - IN_CLOSE_WRITE on test
-+    //   - IN_MOVED_FROM on test with a cookie
-+    //   - IN_MOVED_TO on test2 with the same cookie
-+
-+    let events = instance.read_events().unwrap();
-+    assert_eq!(events.len(), 5);
-+
-+    assert_eq!(events[0].mask, AddWatchFlags::IN_CREATE);
-+    assert_eq!(events[0].name, Some(OsString::from("test")));
-+
-+    assert_eq!(events[1].mask, AddWatchFlags::IN_OPEN);
-+    assert_eq!(events[1].name, Some(OsString::from("test")));
-+
-+    assert_eq!(events[2].mask, AddWatchFlags::IN_CLOSE_WRITE);
-+    assert_eq!(events[2].name, Some(OsString::from("test")));
-+
-+    assert_eq!(events[3].mask, AddWatchFlags::IN_MOVED_FROM);
-+    assert_eq!(events[3].name, Some(OsString::from("test")));
-+
-+    assert_eq!(events[4].mask, AddWatchFlags::IN_MOVED_TO);
-+    assert_eq!(events[4].name, Some(OsString::from("test2")));
-+
-+    assert_eq!(events[3].cookie, events[4].cookie);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs b/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
-new file mode 100644
-index 0000000000000..0a439b3346f53
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_ioctl.rs
-@@ -0,0 +1,334 @@
-+#![allow(dead_code)]
-+
-+// Simple tests to ensure macro generated fns compile
-+ioctl_none_bad!(do_bad, 0x1234);
-+ioctl_read_bad!(do_bad_read, 0x1234, u16);
-+ioctl_write_int_bad!(do_bad_write_int, 0x1234);
-+ioctl_write_ptr_bad!(do_bad_write_ptr, 0x1234, u8);
-+ioctl_readwrite_bad!(do_bad_readwrite, 0x1234, u32);
-+ioctl_none!(do_none, 0, 0);
-+ioctl_read!(read_test, 0, 0, u32);
-+ioctl_write_int!(write_ptr_int, 0, 0);
-+ioctl_write_ptr!(write_ptr_u8, 0, 0, u8);
-+ioctl_write_ptr!(write_ptr_u32, 0, 0, u32);
-+ioctl_write_ptr!(write_ptr_u64, 0, 0, u64);
-+ioctl_readwrite!(readwrite_test, 0, 0, u64);
-+ioctl_read_buf!(readbuf_test, 0, 0, u32);
-+const SPI_IOC_MAGIC: u8 = b'k';
-+const SPI_IOC_MESSAGE: u8 = 0;
-+ioctl_write_buf!(writebuf_test_consts, SPI_IOC_MAGIC, SPI_IOC_MESSAGE, u8);
-+ioctl_write_buf!(writebuf_test_u8, 0, 0, u8);
-+ioctl_write_buf!(writebuf_test_u32, 0, 0, u32);
-+ioctl_write_buf!(writebuf_test_u64, 0, 0, u64);
-+ioctl_readwrite_buf!(readwritebuf_test, 0, 0, u32);
-+
-+// See C code for source of values for op calculations (does NOT work for mips/powerpc):
-+// https://gist.github.com/posborne/83ea6880770a1aef332e
-+//
-+// TODO:  Need a way to compute these constants at test time.  Using precomputed
-+// values is fragile and needs to be maintained.
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+mod linux {
-+    #[test]
-+    fn test_op_none() {
-+        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
-+            assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
-+            assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
-+        } else {
-+            assert_eq!(request_code_none!(b'q', 10), 0x0000_710A);
-+            assert_eq!(request_code_none!(b'a', 255), 0x0000_61FF);
-+        }
-+    }
-+
-+    #[test]
-+    fn test_op_write() {
-+        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
-+            assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
-+        } else {
-+            assert_eq!(request_code_write!(b'z', 10, 1), 0x4001_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 512), 0x4200_7A0A);
-+        }
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_write_64() {
-+        if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
-+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
-+        } else {
-+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
-+        }
-+
-+    }
-+
-+    #[test]
-+    fn test_op_read() {
-+        if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
-+            assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
-+        } else {
-+            assert_eq!(request_code_read!(b'z', 10, 1), 0x8001_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 512), 0x8200_7A0A);
-+        }
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_read_64() {
-+        if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
-+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
-+        } else {
-+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
-+        }
-+    }
-+
-+    #[test]
-+    fn test_op_read_write() {
-+        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
-+        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_read_write_64() {
-+        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
-+    }
-+}
-+
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
-+mod bsd {
-+    #[test]
-+    fn test_op_none() {
-+        assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
-+        assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
-+    }
-+
-+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd"))]
-+    #[test]
-+    fn test_op_write_int() {
-+        assert_eq!(request_code_write_int!(b'v', 4), 0x2004_7604);
-+        assert_eq!(request_code_write_int!(b'p', 2), 0x2004_7002);
-+    }
-+
-+    #[test]
-+    fn test_op_write() {
-+        assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
-+        assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_write_64() {
-+        assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
-+    }
-+
-+    #[test]
-+    fn test_op_read() {
-+        assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
-+        assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_read_64() {
-+        assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
-+    }
-+
-+    #[test]
-+    fn test_op_read_write() {
-+        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
-+        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
-+    }
-+
-+    #[cfg(target_pointer_width = "64")]
-+    #[test]
-+    fn test_op_read_write_64() {
-+        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod linux_ioctls {
-+    use std::mem;
-+    use std::os::unix::io::AsRawFd;
-+
-+    use tempfile::tempfile;
-+    use libc::{TCGETS, TCSBRK, TCSETS, TIOCNXCL, termios};
-+
-+    use nix::Error::Sys;
-+    use nix::errno::Errno::{ENOTTY, ENOSYS};
-+
-+    ioctl_none_bad!(tiocnxcl, TIOCNXCL);
-+    #[test]
-+    fn test_ioctl_none_bad() {
-+        let file = tempfile().unwrap();
-+        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    ioctl_read_bad!(tcgets, TCGETS, termios);
-+    #[test]
-+    fn test_ioctl_read_bad() {
-+        let file = tempfile().unwrap();
-+        let mut termios = unsafe { mem::uninitialized() };
-+        let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    ioctl_write_int_bad!(tcsbrk, TCSBRK);
-+    #[test]
-+    fn test_ioctl_write_int_bad() {
-+        let file = tempfile().unwrap();
-+        let res = unsafe { tcsbrk(file.as_raw_fd(), 0) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    ioctl_write_ptr_bad!(tcsets, TCSETS, termios);
-+    #[test]
-+    fn test_ioctl_write_ptr_bad() {
-+        let file = tempfile().unwrap();
-+        let termios: termios = unsafe { mem::uninitialized() };
-+        let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    // FIXME: Find a suitable example for `ioctl_readwrite_bad`
-+
-+    // From linux/videodev2.h
-+    ioctl_none!(log_status, b'V', 70);
-+    #[test]
-+    fn test_ioctl_none() {
-+        let file = tempfile().unwrap();
-+        let res = unsafe { log_status(file.as_raw_fd()) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    #[repr(C)]
-+    pub struct v4l2_audio {
-+        index: u32,
-+        name: [u8; 32],
-+        capability: u32,
-+        mode: u32,
-+        reserved: [u32; 2],
-+    }
-+
-+    // From linux/videodev2.h
-+    ioctl_write_ptr!(s_audio, b'V', 34, v4l2_audio);
-+    #[test]
-+    fn test_ioctl_write_ptr() {
-+        let file = tempfile().unwrap();
-+        let data: v4l2_audio = unsafe { mem::zeroed() };
-+        let res = unsafe { s_audio(file.as_raw_fd(), &data) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    // From linux/net/bluetooth/hci_sock.h
-+    const HCI_IOC_MAGIC: u8 = b'H';
-+    const HCI_IOC_HCIDEVUP: u8 = 201;
-+    ioctl_write_int!(hcidevup, HCI_IOC_MAGIC, HCI_IOC_HCIDEVUP);
-+    #[test]
-+    fn test_ioctl_write_int() {
-+        let file = tempfile().unwrap();
-+        let res = unsafe { hcidevup(file.as_raw_fd(), 0) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    // From linux/videodev2.h
-+    ioctl_read!(g_audio, b'V', 33, v4l2_audio);
-+    #[test]
-+    fn test_ioctl_read() {
-+        let file = tempfile().unwrap();
-+        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
-+        let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    // From linux/videodev2.h
-+    ioctl_readwrite!(enum_audio,  b'V', 65, v4l2_audio);
-+    #[test]
-+    fn test_ioctl_readwrite() {
-+        let file = tempfile().unwrap();
-+        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
-+        let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    // FIXME: Find a suitable example for `ioctl_read_buf`.
-+
-+    #[repr(C)]
-+    pub struct spi_ioc_transfer {
-+        tx_buf: u64,
-+        rx_buf: u64,
-+        len: u32,
-+        speed_hz: u32,
-+        delay_usecs: u16,
-+        bits_per_word: u8,
-+        cs_change: u8,
-+        tx_nbits: u8,
-+        rx_nbits: u8,
-+        pad: u16,
-+    }
-+
-+    // From linux/spi/spidev.h
-+    ioctl_write_buf!(spi_ioc_message, super::SPI_IOC_MAGIC, super::SPI_IOC_MESSAGE, spi_ioc_transfer);
-+    #[test]
-+    fn test_ioctl_write_buf() {
-+        let file = tempfile().unwrap();
-+        let data: [spi_ioc_transfer; 4] = unsafe { mem::zeroed() };
-+        let res = unsafe { spi_ioc_message(file.as_raw_fd(), &data[..]) };
-+        assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-+    }
-+
-+    // FIXME: Find a suitable example for `ioctl_readwrite_buf`.
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+mod freebsd_ioctls {
-+    use std::mem;
-+    use std::os::unix::io::AsRawFd;
-+
-+    use tempfile::tempfile;
-+    use libc::termios;
-+
-+    use nix::Error::Sys;
-+    use nix::errno::Errno::ENOTTY;
-+
-+    // From sys/sys/ttycom.h
-+    const TTY_IOC_MAGIC: u8 = b't';
-+    const TTY_IOC_TYPE_NXCL: u8 = 14;
-+    const TTY_IOC_TYPE_GETA: u8 = 19;
-+    const TTY_IOC_TYPE_SETA: u8 = 20;
-+
-+    ioctl_none!(tiocnxcl, TTY_IOC_MAGIC, TTY_IOC_TYPE_NXCL);
-+    #[test]
-+    fn test_ioctl_none() {
-+        let file = tempfile().unwrap();
-+        let res = unsafe { tiocnxcl(file.as_raw_fd()) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    ioctl_read!(tiocgeta, TTY_IOC_MAGIC, TTY_IOC_TYPE_GETA, termios);
-+    #[test]
-+    fn test_ioctl_read() {
-+        let file = tempfile().unwrap();
-+        let mut termios = unsafe { mem::uninitialized() };
-+        let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+
-+    ioctl_write_ptr!(tiocseta, TTY_IOC_MAGIC, TTY_IOC_TYPE_SETA, termios);
-+    #[test]
-+    fn test_ioctl_write_ptr() {
-+        let file = tempfile().unwrap();
-+        let termios: termios = unsafe { mem::uninitialized() };
-+        let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
-+        assert_eq!(res, Err(Sys(ENOTTY)));
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs b/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
-new file mode 100644
-index 0000000000000..19ee3facf87d7
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_lio_listio_resubmit.rs
-@@ -0,0 +1,111 @@
-+// vim: tw=80
-+
-+// Annoyingly, Cargo is unable to conditionally build an entire test binary.  So
-+// we must disable the test here rather than in Cargo.toml
-+#![cfg(target_os = "freebsd")]
-+
-+extern crate nix;
-+extern crate sysctl;
-+extern crate tempfile;
-+
-+use nix::Error;
-+use nix::errno::*;
-+use nix::libc::off_t;
-+use nix::sys::aio::*;
-+use nix::sys::signal::SigevNotify;
-+use nix::unistd::{SysconfVar, sysconf};
-+use std::os::unix::io::AsRawFd;
-+use std::{thread, time};
-+use sysctl::CtlValue;
-+use tempfile::tempfile;
-+
-+const BYTES_PER_OP: usize = 512;
-+
-+/// Attempt to collect final status for all of `liocb`'s operations, freeing
-+/// system resources
-+fn finish_liocb(liocb: &mut LioCb) {
-+    for j in 0..liocb.aiocbs.len() {
-+        loop {
-+            let e = liocb.error(j);
-+            match e {
-+                Ok(()) => break,
-+                Err(Error::Sys(Errno::EINPROGRESS)) =>
-+                    thread::sleep(time::Duration::from_millis(10)),
-+                Err(x) => panic!("aio_error({:?})", x)
-+            }
-+        }
-+        assert_eq!(liocb.aio_return(j).unwrap(), BYTES_PER_OP as isize);
-+    }
-+}
-+
-+// Deliberately exceed system resource limits, causing lio_listio to return EIO.
-+// This test must run in its own process since it deliberately uses all AIO
-+// resources.  ATM it is only enabled on FreeBSD, because I don't know how to
-+// check system AIO limits on other operating systems.
-+#[test]
-+fn test_lio_listio_resubmit() {
-+    let mut resubmit_count = 0;
-+
-+    // Lookup system resource limits
-+    let alm = sysconf(SysconfVar::AIO_LISTIO_MAX)
-+        .expect("sysconf").unwrap() as usize;
-+    let maqpp = if let CtlValue::Int(x) = sysctl::value(
-+            "vfs.aio.max_aio_queue_per_proc").unwrap(){
-+        x as usize
-+    } else {
-+        panic!("unknown sysctl");
-+    };
-+
-+    // Find lio_listio sizes that satisfy the AIO_LISTIO_MAX constraint and also
-+    // result in a final lio_listio call that can only partially be queued
-+    let target_ops = maqpp + alm / 2;
-+    let num_listios = (target_ops + alm - 3) / (alm - 2);
-+    let ops_per_listio = (target_ops + num_listios - 1) / num_listios;
-+    assert!((num_listios - 1) * ops_per_listio < maqpp,
-+        "the last lio_listio won't make any progress; fix the algorithm");
-+    println!("Using {:?} LioCbs of {:?} operations apiece", num_listios,
-+             ops_per_listio);
-+
-+    let f = tempfile().unwrap();
-+    let buffer_set = (0..num_listios).map(|_| {
-+        (0..ops_per_listio).map(|_| {
-+            vec![0u8; BYTES_PER_OP]
-+        }).collect::<Vec<_>>()
-+    }).collect::<Vec<_>>();
-+
-+    let mut liocbs = (0..num_listios).map(|i| {
-+        let mut liocb = LioCb::with_capacity(ops_per_listio);
-+        for j in 0..ops_per_listio {
-+            let offset = (BYTES_PER_OP * (i * ops_per_listio + j)) as off_t;
-+            let wcb = AioCb::from_slice( f.as_raw_fd(),
-+                                   offset,
-+                                   &buffer_set[i][j][..],
-+                                   0,   //priority
-+                                   SigevNotify::SigevNone,
-+                                   LioOpcode::LIO_WRITE);
-+            liocb.aiocbs.push(wcb);
-+        }
-+        let mut err = liocb.listio(LioMode::LIO_NOWAIT, SigevNotify::SigevNone);
-+        while err == Err(Error::Sys(Errno::EIO)) ||
-+              err == Err(Error::Sys(Errno::EAGAIN)) ||
-+              err == Err(Error::Sys(Errno::EINTR)) {
-+            // 
-+            thread::sleep(time::Duration::from_millis(10));
-+            resubmit_count += 1;
-+            err = liocb.listio_resubmit(LioMode::LIO_NOWAIT,
-+                                        SigevNotify::SigevNone);
-+        }
-+        liocb
-+    }).collect::<Vec<_>>();
-+
-+    // Ensure that every AioCb completed
-+    for liocb in liocbs.iter_mut() {
-+        finish_liocb(liocb);
-+    }
-+
-+    if resubmit_count > 0 {
-+        println!("Resubmitted {:?} times, test passed", resubmit_count);
-+    } else {
-+        println!("Never resubmitted.  Test ambiguous");
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs b/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
-new file mode 100644
-index 0000000000000..8928010087a13
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_pthread.rs
-@@ -0,0 +1,15 @@
-+use nix::sys::pthread::*;
-+
-+#[cfg(target_env = "musl")]
-+#[test]
-+fn test_pthread_self() {
-+    let tid = pthread_self();
-+    assert!(tid != ::std::ptr::null_mut());
-+}
-+
-+#[cfg(not(target_env = "musl"))]
-+#[test]
-+fn test_pthread_self() {
-+    let tid = pthread_self();
-+    assert!(tid != 0);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs b/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
-new file mode 100644
-index 0000000000000..24d9b522ee4e5
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_ptrace.rs
-@@ -0,0 +1,107 @@
-+use nix::Error;
-+use nix::errno::Errno;
-+use nix::unistd::getpid;
-+use nix::sys::ptrace;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use nix::sys::ptrace::Options;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use std::mem;
-+
-+#[test]
-+fn test_ptrace() {
-+    // Just make sure ptrace can be called at all, for now.
-+    // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
-+    let err = ptrace::attach(getpid()).unwrap_err();
-+    assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
-+            err == Error::Sys(Errno::ENOSYS));
-+}
-+
-+// Just make sure ptrace_setoptions can be called at all, for now.
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptrace_setoptions() {
-+    let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
-+    assert!(err != Error::UnsupportedOperation);
-+}
-+
-+// Just make sure ptrace_getevent can be called at all, for now.
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptrace_getevent() {
-+    let err = ptrace::getevent(getpid()).unwrap_err();
-+    assert!(err != Error::UnsupportedOperation);
-+}
-+
-+// Just make sure ptrace_getsiginfo can be called at all, for now.
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptrace_getsiginfo() {
-+    if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
-+        panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
-+    }
-+}
-+
-+// Just make sure ptrace_setsiginfo can be called at all, for now.
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptrace_setsiginfo() {
-+    let siginfo = unsafe { mem::uninitialized() };
-+    if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
-+        panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
-+    }
-+}
-+
-+
-+#[test]
-+fn test_ptrace_cont() {
-+    use nix::sys::ptrace;
-+    use nix::sys::signal::{raise, Signal};
-+    use nix::sys::wait::{waitpid, WaitPidFlag, WaitStatus};
-+    use nix::unistd::fork;
-+    use nix::unistd::ForkResult::*;
-+
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // FIXME: qemu-user doesn't implement ptrace on all architectures
-+    // and retunrs ENOSYS in this case.
-+    // We (ab)use this behavior to detect the affected platforms
-+    // and skip the test then.
-+    // On valid platforms the ptrace call should return Errno::EPERM, this
-+    // is already tested by `test_ptrace`.
-+    let err = ptrace::attach(getpid()).unwrap_err();
-+    if err == Error::Sys(Errno::ENOSYS) {
-+        return;
-+    }
-+
-+    match fork().expect("Error: Fork Failed") {
-+        Child => {
-+            ptrace::traceme().unwrap();
-+            // As recommended by ptrace(2), raise SIGTRAP to pause the child
-+            // until the parent is ready to continue
-+            loop {
-+                raise(Signal::SIGTRAP).unwrap();
-+            }
-+
-+        },
-+        Parent { child } => {
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
-+            ptrace::cont(child, None).unwrap();
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTRAP)));
-+            ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
-+            match waitpid(child, None) {
-+                Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
-+                    // FIXME It's been observed on some systems (apple) the 
-+                    // tracee may not be killed but remain as a zombie process
-+                    // affecting other wait based tests. Add an extra kill just
-+                    // to make sure there are no zombies.
-+                    let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
-+                    while ptrace::cont(child, Some(Signal::SIGKILL)).is_ok() {
-+                        let _ = waitpid(child, Some(WaitPidFlag::WNOHANG));
-+                    }
-+                }
-+                _ => panic!("The process should have been killed"),
-+            }
-+        },
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_select.rs b/third_party/rust/nix-0.15.0/test/sys/test_select.rs
-new file mode 100644
-index 0000000000000..cf68700c5e16f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_select.rs
-@@ -0,0 +1,54 @@
-+use nix::sys::select::*;
-+use nix::unistd::{pipe, write};
-+use nix::sys::signal::SigSet;
-+use nix::sys::time::{TimeSpec, TimeValLike};
-+
-+#[test]
-+pub fn test_pselect() {
-+    let _mtx = ::SIGNAL_MTX
-+        .lock()
-+        .expect("Mutex got poisoned by another test");
-+
-+    let (r1, w1) = pipe().unwrap();
-+    write(w1, b"hi!").unwrap();
-+    let (r2, _w2) = pipe().unwrap();
-+
-+    let mut fd_set = FdSet::new();
-+    fd_set.insert(r1);
-+    fd_set.insert(r2);
-+
-+    let timeout = TimeSpec::seconds(10);
-+    let sigmask = SigSet::empty();
-+    assert_eq!(
-+        1,
-+        pselect(None, &mut fd_set, None, None, &timeout, &sigmask).unwrap()
-+    );
-+    assert!(fd_set.contains(r1));
-+    assert!(!fd_set.contains(r2));
-+}
-+
-+#[test]
-+pub fn test_pselect_nfds2() {
-+    let (r1, w1) = pipe().unwrap();
-+    write(w1, b"hi!").unwrap();
-+    let (r2, _w2) = pipe().unwrap();
-+
-+    let mut fd_set = FdSet::new();
-+    fd_set.insert(r1);
-+    fd_set.insert(r2);
-+
-+    let timeout = TimeSpec::seconds(10);
-+    assert_eq!(
-+        1,
-+        pselect(
-+            ::std::cmp::max(r1, r2) + 1,
-+            &mut fd_set,
-+            None,
-+            None,
-+            &timeout,
-+            None
-+        ).unwrap()
-+    );
-+    assert!(fd_set.contains(r1));
-+    assert!(!fd_set.contains(r2));
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_signal.rs b/third_party/rust/nix-0.15.0/test/sys/test_signal.rs
-new file mode 100644
-index 0000000000000..8780763f773ef
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_signal.rs
-@@ -0,0 +1,104 @@
-+use libc;
-+use nix::Error;
-+use nix::sys::signal::*;
-+use nix::unistd::*;
-+use std::sync::atomic::{AtomicBool, Ordering};
-+
-+#[test]
-+fn test_kill_none() {
-+    kill(getpid(), None).expect("Should be able to send signal to myself.");
-+}
-+
-+#[test]
-+fn test_killpg_none() {
-+    killpg(getpgrp(), None)
-+        .expect("Should be able to send signal to my process group.");
-+}
-+
-+#[test]
-+fn test_old_sigaction_flags() {
-+    extern "C" fn handler(_: ::libc::c_int) {}
-+    let act = SigAction::new(
-+        SigHandler::Handler(handler),
-+        SaFlags::empty(),
-+        SigSet::empty(),
-+    );
-+    let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
-+    let _flags = oact.flags();
-+    let oact = unsafe { sigaction(SIGINT, &act) }.unwrap();
-+    let _flags = oact.flags();
-+}
-+
-+#[test]
-+fn test_sigprocmask_noop() {
-+    sigprocmask(SigmaskHow::SIG_BLOCK, None, None)
-+        .expect("this should be an effective noop");
-+}
-+
-+#[test]
-+fn test_sigprocmask() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // This needs to be a signal that rust doesn't use in the test harness.
-+    const SIGNAL: Signal = Signal::SIGCHLD;
-+
-+    let mut old_signal_set = SigSet::empty();
-+    sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
-+        .expect("expect to be able to retrieve old signals");
-+
-+    // Make sure the old set doesn't contain the signal, otherwise the following
-+    // test don't make sense.
-+    assert_eq!(old_signal_set.contains(SIGNAL), false,
-+               "the {:?} signal is already blocked, please change to a \
-+                different one", SIGNAL);
-+
-+    // Now block the signal.
-+    let mut signal_set = SigSet::empty();
-+    signal_set.add(SIGNAL);
-+    sigprocmask(SigmaskHow::SIG_BLOCK, Some(&signal_set), None)
-+        .expect("expect to be able to block signals");
-+
-+    // And test it again, to make sure the change was effective.
-+    old_signal_set.clear();
-+    sigprocmask(SigmaskHow::SIG_BLOCK, None, Some(&mut old_signal_set))
-+        .expect("expect to be able to retrieve old signals");
-+    assert_eq!(old_signal_set.contains(SIGNAL), true,
-+               "expected the {:?} to be blocked", SIGNAL);
-+
-+    // Reset the signal.
-+    sigprocmask(SigmaskHow::SIG_UNBLOCK, Some(&signal_set), None)
-+        .expect("expect to be able to block signals");
-+}
-+
-+lazy_static! {
-+    static ref SIGNALED: AtomicBool = AtomicBool::new(false);
-+}
-+
-+extern fn test_sigaction_handler(signal: libc::c_int) {
-+    let signal = Signal::from_c_int(signal).unwrap();
-+    SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
-+}
-+
-+extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {
-+}
-+
-+#[test]
-+fn test_signal() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
-+    raise(Signal::SIGINT).unwrap();
-+    assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), SigHandler::SigIgn);
-+
-+    let handler = SigHandler::Handler(test_sigaction_handler);
-+    assert_eq!(unsafe { signal(Signal::SIGINT, handler) }.unwrap(), SigHandler::SigDfl);
-+    raise(Signal::SIGINT).unwrap();
-+    assert!(SIGNALED.load(Ordering::Relaxed));
-+    assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
-+
-+    let action_handler = SigHandler::SigAction(test_sigaction_action);
-+    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
-+
-+    // Restore default signal handler
-+    unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs b/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
-new file mode 100644
-index 0000000000000..a3b6098841f1c
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_signalfd.rs
-@@ -0,0 +1,25 @@
-+#[test]
-+fn test_signalfd() {
-+    use nix::sys::signalfd::SignalFd;
-+    use nix::sys::signal::{self, raise, Signal, SigSet};
-+
-+    // Grab the mutex for altering signals so we don't interfere with other tests.
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Block the SIGUSR1 signal from automatic processing for this thread
-+    let mut mask = SigSet::empty();
-+    mask.add(signal::SIGUSR1);
-+    mask.thread_block().unwrap();
-+
-+    let mut fd = SignalFd::new(&mask).unwrap();
-+
-+    // Send a SIGUSR1 signal to the current process. Note that this uses `raise` instead of `kill`
-+    // because `kill` with `getpid` isn't correct during multi-threaded execution like during a
-+    // cargo test session. Instead use `raise` which does the correct thing by default.
-+    raise(signal::SIGUSR1).expect("Error: raise(SIGUSR1) failed");
-+
-+    // And now catch that same signal.
-+    let res = fd.read_signal().unwrap().unwrap();
-+    let signo = Signal::from_c_int(res.ssi_signo as i32).unwrap();
-+    assert_eq!(signo, signal::SIGUSR1);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_socket.rs b/third_party/rust/nix-0.15.0/test/sys/test_socket.rs
-new file mode 100644
-index 0000000000000..7e64d2b77f071
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_socket.rs
-@@ -0,0 +1,1066 @@
-+use nix::ifaddrs::InterfaceAddress;
-+use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
-+use std::collections::hash_map::DefaultHasher;
-+use std::hash::{Hash, Hasher};
-+use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV6};
-+use std::os::unix::io::RawFd;
-+use std::path::Path;
-+use std::slice;
-+use std::str::FromStr;
-+use libc::c_char;
-+use tempfile;
-+
-+#[test]
-+pub fn test_inetv4_addr_to_sock_addr() {
-+    let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
-+    let addr = InetAddr::from_std(&actual);
-+
-+    match addr {
-+        InetAddr::V4(addr) => {
-+            let ip: u32 = 0x7f00_0001;
-+            let port: u16 = 3000;
-+            let saddr = addr.sin_addr.s_addr;
-+
-+            assert_eq!(saddr, ip.to_be());
-+            assert_eq!(addr.sin_port, port.to_be());
-+        }
-+        _ => panic!("nope"),
-+    }
-+
-+    assert_eq!(addr.to_str(), "127.0.0.1:3000");
-+
-+    let inet = addr.to_std();
-+    assert_eq!(actual, inet);
-+}
-+
-+#[test]
-+pub fn test_inetv6_addr_to_sock_addr() {
-+    let port: u16 = 3000;
-+    let flowinfo: u32 = 1;
-+    let scope_id: u32 = 2;
-+    let ip: Ipv6Addr = "fe80::1".parse().unwrap();
-+
-+    let actual = SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
-+    let addr = InetAddr::from_std(&actual);
-+
-+    match addr {
-+        InetAddr::V6(addr) => {
-+            assert_eq!(addr.sin6_port, port.to_be());
-+            assert_eq!(addr.sin6_flowinfo, flowinfo);
-+            assert_eq!(addr.sin6_scope_id, scope_id);
-+        }
-+        _ => panic!("nope"),
-+    }
-+
-+    assert_eq!(actual, addr.to_std());
-+}
-+
-+#[test]
-+pub fn test_path_to_sock_addr() {
-+    let path = "/foo/bar";
-+    let actual = Path::new(path);
-+    let addr = UnixAddr::new(actual).unwrap();
-+
-+    let expect: &[c_char] = unsafe {
-+        slice::from_raw_parts(path.as_bytes().as_ptr() as *const c_char, path.len())
-+    };
-+    assert_eq!(&addr.0.sun_path[..8], expect);
-+
-+    assert_eq!(addr.path(), Some(actual));
-+}
-+
-+fn calculate_hash<T: Hash>(t: &T) -> u64 {
-+    let mut s = DefaultHasher::new();
-+    t.hash(&mut s);
-+    s.finish()
-+}
-+
-+#[test]
-+pub fn test_addr_equality_path() {
-+    let path = "/foo/bar";
-+    let actual = Path::new(path);
-+    let addr1 = UnixAddr::new(actual).unwrap();
-+    let mut addr2 = addr1.clone();
-+
-+    addr2.0.sun_path[10] = 127;
-+
-+    assert_eq!(addr1, addr2);
-+    assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[test]
-+pub fn test_abstract_sun_path_too_long() {
-+    let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough");
-+    let addr = UnixAddr::new_abstract(name.as_bytes());
-+    assert!(addr.is_err());
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[test]
-+pub fn test_addr_equality_abstract() {
-+    let name = String::from("nix\0abstract\0test");
-+    let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-+    let mut addr2 = addr1.clone();
-+
-+    assert_eq!(addr1, addr2);
-+    assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
-+
-+    addr2.0.sun_path[18] = 127;
-+    assert_ne!(addr1, addr2);
-+    assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
-+}
-+
-+// Test getting/setting abstract addresses (without unix socket creation)
-+#[cfg(target_os = "linux")]
-+#[test]
-+pub fn test_abstract_uds_addr() {
-+    let empty = String::new();
-+    let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
-+    let sun_path = [0u8; 107];
-+    assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
-+
-+    let name = String::from("nix\0abstract\0test");
-+    let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-+    let sun_path = [
-+        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0,
-+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+    ];
-+    assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
-+    assert_eq!(addr.path(), None);
-+
-+    // Internally, name is null-prefixed (abstract namespace)
-+    assert_eq!(addr.0.sun_path[0], 0);
-+}
-+
-+#[test]
-+pub fn test_getsockname() {
-+    use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};
-+    use nix::sys::socket::{bind, SockAddr};
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let sockname = tempdir.path().join("sock");
-+    let sock = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
-+               .expect("socket failed");
-+    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
-+    bind(sock, &sockaddr).expect("bind failed");
-+    assert_eq!(sockaddr.to_str(),
-+               getsockname(sock).expect("getsockname failed").to_str());
-+}
-+
-+#[test]
-+pub fn test_socketpair() {
-+    use nix::unistd::{read, write};
-+    use nix::sys::socket::{socketpair, AddressFamily, SockType, SockFlag};
-+
-+    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-+                     .unwrap();
-+    write(fd1, b"hello").unwrap();
-+    let mut buf = [0;5];
-+    read(fd2, &mut buf).unwrap();
-+
-+    assert_eq!(&buf[..], b"hello");
-+}
-+
-+// Test error handling of our recvmsg wrapper
-+#[test]
-+pub fn test_recvmsg_ebadf() {
-+    use nix::Error;
-+    use nix::errno::Errno;
-+    use nix::sys::socket::{MsgFlags, recvmsg};
-+    use nix::sys::uio::IoVec;
-+
-+    let mut buf = [0u8; 5];
-+    let iov = [IoVec::from_mut_slice(&mut buf[..])];
-+    let fd = -1;    // Bad file descriptor
-+    let r = recvmsg(fd, &iov, None, MsgFlags::empty());
-+    assert_eq!(r.err().unwrap(), Error::Sys(Errno::EBADF));
-+}
-+
-+// Disable the test on emulated platforms due to a bug in QEMU versions <
-+// 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-+#[test]
-+pub fn test_scm_rights() {
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::{pipe, read, write, close};
-+    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
-+                           AddressFamily, SockType, SockFlag,
-+                           ControlMessage, ControlMessageOwned, MsgFlags};
-+
-+    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-+                     .unwrap();
-+    let (r, w) = pipe().unwrap();
-+    let mut received_r: Option<RawFd> = None;
-+
-+    {
-+        let iov = [IoVec::from_slice(b"hello")];
-+        let fds = [r];
-+        let cmsg = ControlMessage::ScmRights(&fds);
-+        assert_eq!(sendmsg(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
-+        close(r).unwrap();
-+        close(fd1).unwrap();
-+    }
-+
-+    {
-+        let mut buf = [0u8; 5];
-+        let iov = [IoVec::from_mut_slice(&mut buf[..])];
-+        let mut cmsgspace = cmsg_space!([RawFd; 1]);
-+        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-+
-+        for cmsg in msg.cmsgs() {
-+            if let ControlMessageOwned::ScmRights(fd) = cmsg {
-+                assert_eq!(received_r, None);
-+                assert_eq!(fd.len(), 1);
-+                received_r = Some(fd[0]);
-+            } else {
-+                panic!("unexpected cmsg");
-+            }
-+        }
-+        assert_eq!(msg.bytes, 5);
-+        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-+        close(fd2).unwrap();
-+    }
-+
-+    let received_r = received_r.expect("Did not receive passed fd");
-+    // Ensure that the received file descriptor works
-+    write(w, b"world").unwrap();
-+    let mut buf = [0u8; 5];
-+    read(received_r, &mut buf).unwrap();
-+    assert_eq!(&buf[..], b"world");
-+    close(received_r).unwrap();
-+    close(w).unwrap();
-+}
-+
-+// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
-+#[cfg(any(target_os = "linux", target_os= "android"))]
-+#[test]
-+pub fn test_af_alg_cipher() {
-+    use libc;
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::read;
-+    use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
-+                           AddressFamily, SockType, SockFlag, SockAddr,
-+                           ControlMessage, MsgFlags};
-+    use nix::sys::socket::sockopt::AlgSetKey;
-+
-+    let alg_type = "skcipher";
-+    let alg_name = "ctr(aes)";
-+    // 256-bits secret key
-+    let key = vec![0u8; 32];
-+    // 16-bytes IV
-+    let iv_len = 16;
-+    let iv = vec![1u8; iv_len];
-+    // 256-bytes plain payload
-+    let payload_len = 256;
-+    let payload = vec![2u8; payload_len];
-+
-+    let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
-+        .expect("socket failed");
-+
-+    let sockaddr = SockAddr::new_alg(alg_type, alg_name);
-+    bind(sock, &sockaddr).expect("bind failed");
-+
-+    if let SockAddr::Alg(alg) = sockaddr {
-+        assert_eq!(alg.alg_name().to_string_lossy(), alg_name);
-+        assert_eq!(alg.alg_type().to_string_lossy(), alg_type);
-+    } else {
-+        panic!("unexpected SockAddr");
-+    }
-+
-+    setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt");
-+    let session_socket = accept(sock).expect("accept failed");
-+
-+    let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
-+    let iov = IoVec::from_slice(&payload);
-+    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
-+
-+    // allocate buffer for encrypted data
-+    let mut encrypted = vec![0u8; payload_len];
-+    let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
-+    assert_eq!(num_bytes, payload_len);
-+
-+    let iov = IoVec::from_slice(&encrypted);
-+
-+    let iv = vec![1u8; iv_len];
-+
-+    let msgs = [ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT), ControlMessage::AlgSetIv(iv.as_slice())];
-+    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
-+
-+    // allocate buffer for decrypted data
-+    let mut decrypted = vec![0u8; payload_len];
-+    let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
-+
-+    assert_eq!(num_bytes, payload_len);
-+    assert_eq!(decrypted, payload);
-+}
-+
-+// Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "i686")), ignore)]
-+#[cfg(any(target_os = "linux", target_os= "android"))]
-+#[test]
-+pub fn test_af_alg_aead() {
-+    use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::{read, close};
-+    use nix::sys::socket::{socket, sendmsg, bind, accept, setsockopt,
-+                           AddressFamily, SockType, SockFlag, SockAddr,
-+                           ControlMessage, MsgFlags};
-+    use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
-+
-+    let auth_size = 4usize;
-+    let assoc_size = 16u32;
-+
-+    let alg_type = "aead";
-+    let alg_name = "gcm(aes)";
-+    // 256-bits secret key
-+    let key = vec![0u8; 32];
-+    // 12-bytes IV
-+    let iv_len = 12;
-+    let iv = vec![1u8; iv_len];
-+    // 256-bytes plain payload
-+    let payload_len = 256;
-+    let mut payload = vec![2u8; payload_len + (assoc_size as usize) + auth_size];
-+
-+    for i in 0..assoc_size {
-+        payload[i as usize] = 10;
-+    }
-+
-+    let len = payload.len();
-+
-+    for i in 0..auth_size {
-+        payload[len - 1 - i] = 0;
-+    }
-+
-+    let sock = socket(AddressFamily::Alg, SockType::SeqPacket, SockFlag::empty(), None)
-+        .expect("socket failed");
-+
-+    let sockaddr = SockAddr::new_alg(alg_type, alg_name);
-+    bind(sock, &sockaddr).expect("bind failed");
-+
-+    setsockopt(sock, AlgSetAeadAuthSize, &auth_size).expect("setsockopt AlgSetAeadAuthSize");
-+    setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey");
-+    let session_socket = accept(sock).expect("accept failed");
-+
-+    let msgs = [
-+        ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT),
-+        ControlMessage::AlgSetIv(iv.as_slice()),
-+        ControlMessage::AlgSetAeadAssoclen(&assoc_size)];
-+    let iov = IoVec::from_slice(&payload);
-+    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg encrypt");
-+
-+    // allocate buffer for encrypted data
-+    let mut encrypted = vec![0u8; (assoc_size as usize) + payload_len + auth_size];
-+    let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
-+    assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize));
-+    close(session_socket).expect("close");
-+
-+    for i in 0..assoc_size {
-+        encrypted[i as usize] = 10;
-+    }
-+
-+    let iov = IoVec::from_slice(&encrypted);
-+
-+    let iv = vec![1u8; iv_len];
-+
-+    let session_socket = accept(sock).expect("accept failed");
-+
-+    let msgs = [
-+        ControlMessage::AlgSetOp(&ALG_OP_DECRYPT),
-+        ControlMessage::AlgSetIv(iv.as_slice()),
-+        ControlMessage::AlgSetAeadAssoclen(&assoc_size),
-+    ];
-+    sendmsg(session_socket, &[iov], &msgs, MsgFlags::empty(), None).expect("sendmsg decrypt");
-+
-+    // allocate buffer for decrypted data
-+    let mut decrypted = vec![0u8; payload_len + (assoc_size as usize) + auth_size];
-+    let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
-+
-+    assert!(num_bytes >= payload_len + (assoc_size as usize));
-+    assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]);
-+}
-+
-+/// Tests that passing multiple fds using a single `ControlMessage` works.
-+// Disable the test on emulated platforms due to a bug in QEMU versions <
-+// 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-+#[test]
-+fn test_scm_rights_single_cmsg_multiple_fds() {
-+    use std::os::unix::net::UnixDatagram;
-+    use std::os::unix::io::{RawFd, AsRawFd};
-+    use std::thread;
-+    use nix::sys::socket::{ControlMessage, ControlMessageOwned, MsgFlags,
-+        sendmsg, recvmsg};
-+    use nix::sys::uio::IoVec;
-+    use libc;
-+
-+    let (send, receive) = UnixDatagram::pair().unwrap();
-+    let thread = thread::spawn(move || {
-+        let mut buf = [0u8; 8];
-+        let iovec = [IoVec::from_mut_slice(&mut buf)];
-+        let mut space = cmsg_space!([RawFd; 2]);
-+        let msg = recvmsg(
-+            receive.as_raw_fd(),
-+            &iovec,
-+            Some(&mut space),
-+            MsgFlags::empty()
-+        ).unwrap();
-+        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-+
-+        let mut cmsgs = msg.cmsgs();
-+        match cmsgs.next() {
-+            Some(ControlMessageOwned::ScmRights(fds)) => {
-+                assert_eq!(fds.len(), 2,
-+                           "unexpected fd count (expected 2 fds, got {})",
-+                           fds.len());
-+            },
-+            _ => panic!(),
-+        }
-+        assert!(cmsgs.next().is_none(), "unexpected control msg");
-+
-+        assert_eq!(msg.bytes, 8);
-+        assert_eq!(iovec[0].as_slice(), [1u8, 2, 3, 4, 5, 6, 7, 8]);
-+    });
-+
-+    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+    let iov = [IoVec::from_slice(&slice)];
-+    let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO];    // pass stdin and stdout
-+    let cmsg = [ControlMessage::ScmRights(&fds)];
-+    sendmsg(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None).unwrap();
-+    thread.join().unwrap();
-+}
-+
-+// Verify `sendmsg` builds a valid `msghdr` when passing an empty
-+// `cmsgs` argument.  This should result in a msghdr with a nullptr
-+// msg_control field and a msg_controllen of 0 when calling into the
-+// raw `sendmsg`.
-+#[test]
-+pub fn test_sendmsg_empty_cmsgs() {
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::close;
-+    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
-+                           AddressFamily, SockType, SockFlag, MsgFlags};
-+
-+    let (fd1, fd2) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-+                     .unwrap();
-+
-+    {
-+        let iov = [IoVec::from_slice(b"hello")];
-+        assert_eq!(sendmsg(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(), 5);
-+        close(fd1).unwrap();
-+    }
-+
-+    {
-+        let mut buf = [0u8; 5];
-+        let iov = [IoVec::from_mut_slice(&mut buf[..])];
-+        let mut cmsgspace = cmsg_space!([RawFd; 1]);
-+        let msg = recvmsg(fd2, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-+
-+        for _ in msg.cmsgs() {
-+            panic!("unexpected cmsg");
-+        }
-+        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-+        assert_eq!(msg.bytes, 5);
-+        close(fd2).unwrap();
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[test]
-+fn test_scm_credentials() {
-+    use libc;
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::{close, getpid, getuid, getgid};
-+    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
-+                           AddressFamily, SockType, SockFlag,
-+                           ControlMessage, ControlMessageOwned, MsgFlags};
-+    use nix::sys::socket::sockopt::PassCred;
-+
-+    let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-+        .unwrap();
-+    setsockopt(recv, PassCred, &true).unwrap();
-+
-+    {
-+        let iov = [IoVec::from_slice(b"hello")];
-+        let cred = libc::ucred {
-+            pid: getpid().as_raw(),
-+            uid: getuid().as_raw(),
-+            gid: getgid().as_raw(),
-+        };
-+        let cmsg = ControlMessage::ScmCredentials(&cred);
-+        assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
-+        close(send).unwrap();
-+    }
-+
-+    {
-+        let mut buf = [0u8; 5];
-+        let iov = [IoVec::from_mut_slice(&mut buf[..])];
-+        let mut cmsgspace = cmsg_space!(libc::ucred);
-+        let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-+        let mut received_cred = None;
-+
-+        for cmsg in msg.cmsgs() {
-+            if let ControlMessageOwned::ScmCredentials(cred) = cmsg {
-+                assert!(received_cred.is_none());
-+                assert_eq!(cred.pid, getpid().as_raw());
-+                assert_eq!(cred.uid, getuid().as_raw());
-+                assert_eq!(cred.gid, getgid().as_raw());
-+                received_cred = Some(cred);
-+            } else {
-+                panic!("unexpected cmsg");
-+            }
-+        }
-+        received_cred.expect("no creds received");
-+        assert_eq!(msg.bytes, 5);
-+        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-+        close(recv).unwrap();
-+    }
-+}
-+
-+/// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
-+/// `sendmsg` call.
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
-+// see https://bugs.launchpad.net/qemu/+bug/1781280
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
-+#[test]
-+fn test_scm_credentials_and_rights() {
-+    use libc;
-+
-+    let space = cmsg_space!(libc::ucred, RawFd);
-+    test_impl_scm_credentials_and_rights(space);
-+}
-+
-+/// Ensure that passing a an oversized control message buffer to recvmsg
-+/// still works.
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+// qemu's handling of multiple cmsgs is bugged, ignore tests on non-x86
-+// see https://bugs.launchpad.net/qemu/+bug/1781280
-+#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "x86")), ignore)]
-+#[test]
-+fn test_too_large_cmsgspace() {
-+    let space = vec![0u8; 1024];
-+    test_impl_scm_credentials_and_rights(space);
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
-+    use libc::ucred;
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::{pipe, read, write, close, getpid, getuid, getgid};
-+    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
-+                           SockType, SockFlag,
-+                           ControlMessage, ControlMessageOwned, MsgFlags};
-+    use nix::sys::socket::sockopt::PassCred;
-+
-+    let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-+        .unwrap();
-+    setsockopt(recv, PassCred, &true).unwrap();
-+
-+    let (r, w) = pipe().unwrap();
-+    let mut received_r: Option<RawFd> = None;
-+
-+    {
-+        let iov = [IoVec::from_slice(b"hello")];
-+        let cred = ucred {
-+            pid: getpid().as_raw(),
-+            uid: getuid().as_raw(),
-+            gid: getgid().as_raw(),
-+        };
-+        let fds = [r];
-+        let cmsgs = [
-+            ControlMessage::ScmCredentials(&cred),
-+            ControlMessage::ScmRights(&fds),
-+        ];
-+        assert_eq!(sendmsg(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(), 5);
-+        close(r).unwrap();
-+        close(send).unwrap();
-+    }
-+
-+    {
-+        let mut buf = [0u8; 5];
-+        let iov = [IoVec::from_mut_slice(&mut buf[..])];
-+        let msg = recvmsg(recv, &iov, Some(&mut space), MsgFlags::empty()).unwrap();
-+        let mut received_cred = None;
-+
-+        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
-+
-+        for cmsg in msg.cmsgs() {
-+            match cmsg {
-+                ControlMessageOwned::ScmRights(fds) => {
-+                    assert_eq!(received_r, None, "already received fd");
-+                    assert_eq!(fds.len(), 1);
-+                    received_r = Some(fds[0]);
-+                }
-+                ControlMessageOwned::ScmCredentials(cred) => {
-+                    assert!(received_cred.is_none());
-+                    assert_eq!(cred.pid, getpid().as_raw());
-+                    assert_eq!(cred.uid, getuid().as_raw());
-+                    assert_eq!(cred.gid, getgid().as_raw());
-+                    received_cred = Some(cred);
-+                }
-+                _ => panic!("unexpected cmsg"),
-+            }
-+        }
-+        received_cred.expect("no creds received");
-+        assert_eq!(msg.bytes, 5);
-+        assert!(!msg.flags.intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-+        close(recv).unwrap();
-+    }
-+
-+    let received_r = received_r.expect("Did not receive passed fd");
-+    // Ensure that the received file descriptor works
-+    write(w, b"world").unwrap();
-+    let mut buf = [0u8; 5];
-+    read(received_r, &mut buf).unwrap();
-+    assert_eq!(&buf[..], b"world");
-+    close(received_r).unwrap();
-+    close(w).unwrap();
-+}
-+
-+// Test creating and using named unix domain sockets
-+#[test]
-+pub fn test_unixdomain() {
-+    use nix::sys::socket::{SockType, SockFlag};
-+    use nix::sys::socket::{bind, socket, connect, listen, accept, SockAddr};
-+    use nix::unistd::{read, write, close};
-+    use std::thread;
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let sockname = tempdir.path().join("sock");
-+    let s1 = socket(AddressFamily::Unix, SockType::Stream,
-+                    SockFlag::empty(), None).expect("socket failed");
-+    let sockaddr = SockAddr::new_unix(&sockname).unwrap();
-+    bind(s1, &sockaddr).expect("bind failed");
-+    listen(s1, 10).expect("listen failed");
-+
-+    let thr = thread::spawn(move || {
-+        let s2 = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None)
-+                 .expect("socket failed");
-+        connect(s2, &sockaddr).expect("connect failed");
-+        write(s2, b"hello").expect("write failed");
-+        close(s2).unwrap();
-+    });
-+
-+    let s3 = accept(s1).expect("accept failed");
-+
-+    let mut buf = [0;5];
-+    read(s3, &mut buf).unwrap();
-+    close(s3).unwrap();
-+    close(s1).unwrap();
-+    thr.join().unwrap();
-+
-+    assert_eq!(&buf[..], b"hello");
-+}
-+
-+// Test creating and using named system control sockets
-+#[cfg(any(target_os = "macos", target_os = "ios"))]
-+#[test]
-+pub fn test_syscontrol() {
-+    use nix::Error;
-+    use nix::errno::Errno;
-+    use nix::sys::socket::{socket, SockAddr, SockType, SockFlag, SockProtocol};
-+
-+    let fd = socket(AddressFamily::System, SockType::Datagram,
-+                    SockFlag::empty(), SockProtocol::KextControl)
-+             .expect("socket failed");
-+    let _sockaddr = SockAddr::new_sys_control(fd, "com.apple.net.utun_control", 0).expect("resolving sys_control name failed");
-+    assert_eq!(SockAddr::new_sys_control(fd, "foo.bar.lol", 0).err(), Some(Error::Sys(Errno::ENOENT)));
-+
-+    // requires root privileges
-+    // connect(fd, &sockaddr).expect("connect failed");
-+}
-+
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "linux",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+fn loopback_address(family: AddressFamily) -> Option<InterfaceAddress> {
-+    use std::io;
-+    use std::io::Write;
-+    use nix::ifaddrs::getifaddrs;
-+    use nix::sys::socket::SockAddr;
-+    use nix::net::if_::*;
-+
-+    let addrs = match getifaddrs() {
-+        Ok(iter) => iter,
-+        Err(e) => {
-+            let stdioerr = io::stderr();
-+            let mut handle = stdioerr.lock();
-+            writeln!(handle, "getifaddrs: {:?}", e).unwrap();
-+            return None;
-+        },
-+    };
-+    // return first address matching family
-+    for ifaddr in addrs {
-+        if ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK) {
-+            match ifaddr.address {
-+                Some(SockAddr::Inet(InetAddr::V4(..))) => {
-+                    match family {
-+                        AddressFamily::Inet => return Some(ifaddr),
-+                        _ => continue
-+                    }
-+                },
-+                Some(SockAddr::Inet(InetAddr::V6(..))) => {
-+                    match family {
-+                        AddressFamily::Inet6 => return Some(ifaddr),
-+                        _ => continue
-+                    }
-+                },
-+                _ => continue,
-+            }
-+        }
-+    }
-+    None
-+}
-+
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "ios",
-+    target_os = "linux",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+))]
-+// qemu doesn't seem to be emulating this correctly in these architectures
-+#[cfg_attr(any(
-+    target_arch = "mips",
-+    target_arch = "mips64",
-+    target_arch = "powerpc64",
-+), ignore)]
-+#[test]
-+pub fn test_recv_ipv4pktinfo() {
-+    use libc;
-+    use nix::sys::socket::sockopt::Ipv4PacketInfo;
-+    use nix::sys::socket::{bind, SockFlag, SockType};
-+    use nix::sys::socket::{getsockname, setsockopt, socket};
-+    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
-+    use nix::sys::uio::IoVec;
-+    use nix::net::if_::*;
-+
-+    let lo_ifaddr = loopback_address(AddressFamily::Inet);
-+    let (lo_name, lo) = match lo_ifaddr {
-+        Some(ifaddr) => (ifaddr.interface_name,
-+                         ifaddr.address.expect("Expect IPv4 address on interface")),
-+        None => return,
-+    };
-+    let receive = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("receive socket failed");
-+    bind(receive, &lo).expect("bind failed");
-+    let sa = getsockname(receive).expect("getsockname failed");
-+    setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
-+
-+    {
-+        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+        let iov = [IoVec::from_slice(&slice)];
-+
-+        let send = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
-+    }
-+
-+    {
-+        let mut buf = [0u8; 8];
-+        let iovec = [IoVec::from_mut_slice(&mut buf)];
-+        let mut space = cmsg_space!(libc::in_pktinfo);
-+        let msg = recvmsg(
-+            receive,
-+            &iovec,
-+            Some(&mut space),
-+            MsgFlags::empty(),
-+        ).expect("recvmsg failed");
-+        assert!(
-+            !msg.flags
-+                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
-+        );
-+
-+        let mut cmsgs = msg.cmsgs();
-+        match cmsgs.next() {
-+            Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) => {
-+                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
-+                assert_eq!(
-+                    pktinfo.ipi_ifindex as libc::c_uint,
-+                    i,
-+                    "unexpected ifindex (expected {}, got {})",
-+                    i,
-+                    pktinfo.ipi_ifindex
-+                );
-+            }
-+            _ => (),
-+        }
-+        assert!(cmsgs.next().is_none(), "unexpected additional control msg");
-+        assert_eq!(msg.bytes, 8);
-+        assert_eq!(
-+            iovec[0].as_slice(),
-+            [1u8, 2, 3, 4, 5, 6, 7, 8]
-+        );
-+    }
-+}
-+
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+// qemu doesn't seem to be emulating this correctly in these architectures
-+#[cfg_attr(any(
-+    target_arch = "mips",
-+    target_arch = "mips64",
-+    target_arch = "powerpc64",
-+), ignore)]
-+#[test]
-+pub fn test_recvif() {
-+    use libc;
-+    use nix::net::if_::*;
-+    use nix::sys::socket::sockopt::{Ipv4RecvIf, Ipv4RecvDstAddr};
-+    use nix::sys::socket::{bind, SockFlag, SockType};
-+    use nix::sys::socket::{getsockname, setsockopt, socket, SockAddr};
-+    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
-+    use nix::sys::uio::IoVec;
-+
-+    let lo_ifaddr = loopback_address(AddressFamily::Inet);
-+    let (lo_name, lo) = match lo_ifaddr {
-+        Some(ifaddr) => (ifaddr.interface_name,
-+                         ifaddr.address.expect("Expect IPv4 address on interface")),
-+        None => return,
-+    };
-+    let receive = socket(
-+        AddressFamily::Inet,
-+        SockType::Datagram,
-+        SockFlag::empty(),
-+        None,
-+    ).expect("receive socket failed");
-+    bind(receive, &lo).expect("bind failed");
-+    let sa = getsockname(receive).expect("getsockname failed");
-+    setsockopt(receive, Ipv4RecvIf, &true).expect("setsockopt IP_RECVIF failed");
-+    setsockopt(receive, Ipv4RecvDstAddr, &true).expect("setsockopt IP_RECVDSTADDR failed");
-+
-+    {
-+        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+        let iov = [IoVec::from_slice(&slice)];
-+
-+        let send = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
-+    }
-+
-+    {
-+        let mut buf = [0u8; 8];
-+        let iovec = [IoVec::from_mut_slice(&mut buf)];
-+        let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
-+        let msg = recvmsg(
-+            receive,
-+            &iovec,
-+            Some(&mut space),
-+            MsgFlags::empty(),
-+        ).expect("recvmsg failed");
-+        assert!(
-+            !msg.flags
-+                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
-+        );
-+        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
-+
-+        let mut rx_recvif = false;
-+        let mut rx_recvdstaddr = false;
-+        for cmsg in msg.cmsgs() {
-+            match cmsg {
-+                ControlMessageOwned::Ipv4RecvIf(dl) => {
-+                    rx_recvif = true;
-+                    let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
-+                    assert_eq!(
-+                        dl.sdl_index as libc::c_uint,
-+                        i,
-+                        "unexpected ifindex (expected {}, got {})",
-+                        i,
-+                        dl.sdl_index
-+                    );
-+                },
-+                ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
-+                    rx_recvdstaddr = true;
-+                    if let SockAddr::Inet(InetAddr::V4(a)) = lo {
-+                        assert_eq!(a.sin_addr.s_addr,
-+                                   addr.s_addr,
-+                                   "unexpected destination address (expected {}, got {})",
-+                                   a.sin_addr.s_addr,
-+                                   addr.s_addr);
-+                    } else {
-+                        panic!("unexpected Sockaddr");
-+                    }
-+                },
-+                _ => panic!("unexpected additional control msg"),
-+            }
-+        }
-+        assert_eq!(rx_recvif, true);
-+        assert_eq!(rx_recvdstaddr, true);
-+        assert_eq!(msg.bytes, 8);
-+        assert_eq!(
-+            iovec[0].as_slice(),
-+            [1u8, 2, 3, 4, 5, 6, 7, 8]
-+        );
-+    }
-+}
-+
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "ios",
-+    target_os = "linux",
-+    target_os = "macos",
-+    target_os = "netbsd",
-+    target_os = "openbsd",
-+))]
-+// qemu doesn't seem to be emulating this correctly in these architectures
-+#[cfg_attr(any(
-+    target_arch = "mips",
-+    target_arch = "mips64",
-+    target_arch = "powerpc64",
-+), ignore)]
-+#[test]
-+pub fn test_recv_ipv6pktinfo() {
-+    use libc;
-+    use nix::net::if_::*;
-+    use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
-+    use nix::sys::socket::{bind, SockFlag, SockType};
-+    use nix::sys::socket::{getsockname, setsockopt, socket};
-+    use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
-+    use nix::sys::uio::IoVec;
-+
-+    let lo_ifaddr = loopback_address(AddressFamily::Inet6);
-+    let (lo_name, lo) = match lo_ifaddr {
-+        Some(ifaddr) => (ifaddr.interface_name,
-+                         ifaddr.address.expect("Expect IPv4 address on interface")),
-+        None => return,
-+    };
-+    let receive = socket(
-+        AddressFamily::Inet6,
-+        SockType::Datagram,
-+        SockFlag::empty(),
-+        None,
-+    ).expect("receive socket failed");
-+    bind(receive, &lo).expect("bind failed");
-+    let sa = getsockname(receive).expect("getsockname failed");
-+    setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
-+
-+    {
-+        let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+        let iov = [IoVec::from_slice(&slice)];
-+
-+        let send = socket(
-+            AddressFamily::Inet6,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+        sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa)).expect("sendmsg failed");
-+    }
-+
-+    {
-+        let mut buf = [0u8; 8];
-+        let iovec = [IoVec::from_mut_slice(&mut buf)];
-+        let mut space = cmsg_space!(libc::in6_pktinfo);
-+        let msg = recvmsg(
-+            receive,
-+            &iovec,
-+            Some(&mut space),
-+            MsgFlags::empty(),
-+        ).expect("recvmsg failed");
-+        assert!(
-+            !msg.flags
-+                .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC)
-+        );
-+
-+        let mut cmsgs = msg.cmsgs();
-+        match cmsgs.next() {
-+            Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) => {
-+                let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
-+                assert_eq!(
-+                    pktinfo.ipi6_ifindex,
-+                    i,
-+                    "unexpected ifindex (expected {}, got {})",
-+                    i,
-+                    pktinfo.ipi6_ifindex
-+                );
-+            }
-+            _ => (),
-+        }
-+        assert!(cmsgs.next().is_none(), "unexpected additional control msg");
-+        assert_eq!(msg.bytes, 8);
-+        assert_eq!(
-+            iovec[0].as_slice(),
-+            [1u8, 2, 3, 4, 5, 6, 7, 8]
-+        );
-+    }
-+}
-+
-+#[cfg(target_os = "linux")]
-+#[test]
-+pub fn test_vsock() {
-+    use libc;
-+    use nix::Error;
-+    use nix::errno::Errno;
-+    use nix::sys::socket::{AddressFamily, socket, bind, connect, listen,
-+                           SockAddr, SockType, SockFlag};
-+    use nix::unistd::{close};
-+    use std::thread;
-+
-+    let port: u32 = 3000;
-+
-+    let s1 = socket(AddressFamily::Vsock,  SockType::Stream,
-+                    SockFlag::empty(), None)
-+             .expect("socket failed");
-+
-+    // VMADDR_CID_HYPERVISOR and VMADDR_CID_RESERVED are reserved, so we expect
-+    // an EADDRNOTAVAIL error.
-+    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
-+    assert_eq!(bind(s1, &sockaddr).err(),
-+               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
-+
-+    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_RESERVED, port);
-+    assert_eq!(bind(s1, &sockaddr).err(),
-+               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
-+
-+
-+    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
-+    assert_eq!(bind(s1, &sockaddr), Ok(()));
-+    listen(s1, 10).expect("listen failed");
-+
-+    let thr = thread::spawn(move || {
-+        let cid: u32 = libc::VMADDR_CID_HOST;
-+
-+        let s2 = socket(AddressFamily::Vsock, SockType::Stream,
-+                        SockFlag::empty(), None)
-+                 .expect("socket failed");
-+
-+        let sockaddr = SockAddr::new_vsock(cid, port);
-+
-+        // The current implementation does not support loopback devices, so,
-+        // for now, we expect a failure on the connect.
-+        assert_ne!(connect(s2, &sockaddr), Ok(()));
-+
-+        close(s2).unwrap();
-+    });
-+
-+    close(s1).unwrap();
-+    thr.join().unwrap();
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs b/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
-new file mode 100644
-index 0000000000000..c4860c0d61d3d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_sockopt.rs
-@@ -0,0 +1,53 @@
-+use rand::{thread_rng, Rng};
-+use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
-+
-+#[cfg(target_os = "linux")]
-+#[test]
-+fn is_so_mark_functional() {
-+    use nix::sys::socket::sockopt;
-+
-+    require_capability!(CAP_NET_ADMIN);
-+
-+    let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-+    setsockopt(s, sockopt::Mark, &1337).unwrap();
-+    let mark = getsockopt(s, sockopt::Mark).unwrap();
-+    assert_eq!(mark, 1337);
-+}
-+
-+#[test]
-+fn test_so_buf() {
-+    let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
-+             .unwrap();
-+    let bufsize: usize = thread_rng().gen_range(4096, 131_072);
-+    setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
-+    let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
-+    assert!(actual >= bufsize);
-+    setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
-+    let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
-+    assert!(actual >= bufsize);
-+}
-+
-+// The CI doesn't supported getsockopt and setsockopt on emulated processors.
-+// It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
-+// Current CI just run the binary with QEMU but the Kernel remains the same as the host.
-+// So the syscall doesn't work properly unless the kernel is also emulated.
-+#[test]
-+#[cfg(all(
-+    any(target_arch = "x86", target_arch = "x86_64"),
-+    any(target_os = "freebsd", target_os = "linux")
-+))]
-+fn test_tcp_congestion() {
-+    use std::ffi::OsString;
-+
-+    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-+
-+    let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
-+    setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
-+
-+    setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();
-+
-+    assert_eq!(
-+        getsockopt(fd, sockopt::TcpCongestion).unwrap(),
-+        val
-+    );
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs b/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
-new file mode 100644
-index 0000000000000..73e6586f6223e
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_sysinfo.rs
-@@ -0,0 +1,18 @@
-+use nix::sys::sysinfo::*;
-+
-+#[test]
-+fn sysinfo_works() {
-+    let info = sysinfo().unwrap();
-+
-+    let (l1, l5, l15) = info.load_average();
-+    assert!(l1 >= 0.0);
-+    assert!(l5 >= 0.0);
-+    assert!(l15 >= 0.0);
-+
-+    info.uptime();  // just test Duration construction
-+
-+    assert!(info.swap_free() <= info.swap_total(),
-+            "more swap available than installed (free: {}, total: {})",
-+            info.swap_free(),
-+            info.swap_total());
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_termios.rs b/third_party/rust/nix-0.15.0/test/sys/test_termios.rs
-new file mode 100644
-index 0000000000000..a14b8ce1a23cb
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_termios.rs
-@@ -0,0 +1,136 @@
-+use std::os::unix::prelude::*;
-+use tempfile::tempfile;
-+
-+use nix::{Error, fcntl};
-+use nix::errno::Errno;
-+use nix::pty::openpty;
-+use nix::sys::termios::{self, LocalFlags, OutputFlags, Termios, tcgetattr};
-+use nix::unistd::{read, write, close};
-+
-+/// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
-+fn write_all(f: RawFd, buf: &[u8]) {
-+    let mut len = 0;
-+    while len < buf.len() {
-+        len += write(f, &buf[len..]).unwrap();
-+    }
-+}
-+
-+// Test tcgetattr on a terminal
-+#[test]
-+fn test_tcgetattr_pty() {
-+    // openpty uses ptname(3) internally
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    let pty = openpty(None, None).expect("openpty failed");
-+    assert!(termios::tcgetattr(pty.master).is_ok());
-+    close(pty.master).expect("closing the master failed");
-+    close(pty.slave).expect("closing the slave failed");
-+}
-+
-+// Test tcgetattr on something that isn't a terminal
-+#[test]
-+fn test_tcgetattr_enotty() {
-+    let file = tempfile().unwrap();
-+    assert_eq!(termios::tcgetattr(file.as_raw_fd()).err(),
-+               Some(Error::Sys(Errno::ENOTTY)));
-+}
-+
-+// Test tcgetattr on an invalid file descriptor
-+#[test]
-+fn test_tcgetattr_ebadf() {
-+    assert_eq!(termios::tcgetattr(-1).err(),
-+               Some(Error::Sys(Errno::EBADF)));
-+}
-+
-+// Test modifying output flags
-+#[test]
-+fn test_output_flags() {
-+    // openpty uses ptname(3) internally
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open one pty to get attributes for the second one
-+    let mut termios = {
-+        let pty = openpty(None, None).expect("openpty failed");
-+        assert!(pty.master > 0);
-+        assert!(pty.slave > 0);
-+        let termios = tcgetattr(pty.master).expect("tcgetattr failed");
-+        close(pty.master).unwrap();
-+        close(pty.slave).unwrap();
-+        termios
-+    };
-+
-+    // Make sure postprocessing '\r' isn't specified by default or this test is useless.
-+    assert!(!termios.output_flags.contains(OutputFlags::OPOST | OutputFlags::OCRNL));
-+
-+    // Specify that '\r' characters should be transformed to '\n'
-+    // OPOST is specified to enable post-processing
-+    termios.output_flags.insert(OutputFlags::OPOST | OutputFlags::OCRNL);
-+
-+    // Open a pty
-+    let pty = openpty(None, &termios).unwrap();
-+    assert!(pty.master > 0);
-+    assert!(pty.slave > 0);
-+
-+    // Write into the master
-+    let string = "foofoofoo\r";
-+    write_all(pty.master, string.as_bytes());
-+
-+    // Read from the slave verifying that the output has been properly transformed
-+    let mut buf = [0u8; 10];
-+    ::read_exact(pty.slave, &mut buf);
-+    let transformed_string = "foofoofoo\n";
-+    close(pty.master).unwrap();
-+    close(pty.slave).unwrap();
-+    assert_eq!(&buf, transformed_string.as_bytes());
-+}
-+
-+// Test modifying local flags
-+#[test]
-+fn test_local_flags() {
-+    // openpty uses ptname(3) internally
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open one pty to get attributes for the second one
-+    let mut termios = {
-+        let pty = openpty(None, None).unwrap();
-+        assert!(pty.master > 0);
-+        assert!(pty.slave > 0);
-+        let termios = tcgetattr(pty.master).unwrap();
-+        close(pty.master).unwrap();
-+        close(pty.slave).unwrap();
-+        termios
-+    };
-+
-+    // Make sure echo is specified by default or this test is useless.
-+    assert!(termios.local_flags.contains(LocalFlags::ECHO));
-+
-+    // Disable local echo
-+    termios.local_flags.remove(LocalFlags::ECHO);
-+
-+    // Open a new pty with our modified termios settings
-+    let pty = openpty(None, &termios).unwrap();
-+    assert!(pty.master > 0);
-+    assert!(pty.slave > 0);
-+
-+    // Set the master is in nonblocking mode or reading will never return.
-+    let flags = fcntl::fcntl(pty.master, fcntl::F_GETFL).unwrap();
-+    let new_flags = fcntl::OFlag::from_bits_truncate(flags) | fcntl::OFlag::O_NONBLOCK;
-+    fcntl::fcntl(pty.master, fcntl::F_SETFL(new_flags)).unwrap();
-+
-+    // Write into the master
-+    let string = "foofoofoo\r";
-+    write_all(pty.master, string.as_bytes());
-+
-+    // Try to read from the master, which should not have anything as echoing was disabled.
-+    let mut buf = [0u8; 10];
-+    let read = read(pty.master, &mut buf).unwrap_err();
-+    close(pty.master).unwrap();
-+    close(pty.slave).unwrap();
-+    assert_eq!(read, Error::Sys(Errno::EAGAIN));
-+}
-+
-+#[test]
-+fn test_cfmakeraw() {
-+    let mut termios = unsafe { Termios::default_uninit() };
-+    termios::cfmakeraw(&mut termios);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_uio.rs b/third_party/rust/nix-0.15.0/test/sys/test_uio.rs
-new file mode 100644
-index 0000000000000..3e4fc28ceb0e4
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_uio.rs
-@@ -0,0 +1,241 @@
-+use nix::sys::uio::*;
-+use nix::unistd::*;
-+use rand::{thread_rng, Rng};
-+use rand::distributions::Alphanumeric;
-+use std::{cmp, iter};
-+use std::fs::{OpenOptions};
-+use std::os::unix::io::AsRawFd;
-+
-+use tempfile::{tempfile, tempdir};
-+
-+#[test]
-+fn test_writev() {
-+    let mut to_write = Vec::with_capacity(16 * 128);
-+    for _ in 0..16 {
-+        let s: String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
-+        let b = s.as_bytes();
-+        to_write.extend(b.iter().cloned());
-+    }
-+    // Allocate and fill iovecs
-+    let mut iovecs = Vec::new();
-+    let mut consumed = 0;
-+    while consumed < to_write.len() {
-+        let left = to_write.len() - consumed;
-+        let slice_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
-+        let b = &to_write[consumed..consumed+slice_len];
-+        iovecs.push(IoVec::from_slice(b));
-+        consumed += slice_len;
-+    }
-+    let pipe_res = pipe();
-+    assert!(pipe_res.is_ok());
-+    let (reader, writer) = pipe_res.ok().unwrap();
-+    // FileDesc will close its filedesc (reader).
-+    let mut read_buf: Vec<u8> = iter::repeat(0u8).take(128 * 16).collect();
-+    // Blocking io, should write all data.
-+    let write_res = writev(writer, &iovecs);
-+    // Successful write
-+    assert!(write_res.is_ok());
-+    let written = write_res.ok().unwrap();
-+    // Check whether we written all data
-+    assert_eq!(to_write.len(), written);
-+    let read_res = read(reader, &mut read_buf[..]);
-+    // Successful read
-+    assert!(read_res.is_ok());
-+    let read = read_res.ok().unwrap() as usize;
-+    // Check we have read as much as we written
-+    assert_eq!(read, written);
-+    // Check equality of written and read data
-+    assert_eq!(&to_write, &read_buf);
-+    let close_res = close(writer);
-+    assert!(close_res.is_ok());
-+    let close_res = close(reader);
-+    assert!(close_res.is_ok());
-+}
-+
-+#[test]
-+fn test_readv() {
-+    let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
-+    let to_write = s.as_bytes().to_vec();
-+    let mut storage = Vec::new();
-+    let mut allocated = 0;
-+    while allocated < to_write.len() {
-+        let left = to_write.len() - allocated;
-+        let vec_len = if left <= 64 { left } else { thread_rng().gen_range(64, cmp::min(256, left)) };
-+        let v: Vec<u8> = iter::repeat(0u8).take(vec_len).collect();
-+        storage.push(v);
-+        allocated += vec_len;
-+    }
-+    let mut iovecs = Vec::with_capacity(storage.len());
-+    for v in &mut storage {
-+        iovecs.push(IoVec::from_mut_slice(&mut v[..]));
-+    }
-+    let pipe_res = pipe();
-+    assert!(pipe_res.is_ok());
-+    let (reader, writer) = pipe_res.ok().unwrap();
-+    // Blocking io, should write all data.
-+    let write_res = write(writer, &to_write);
-+    // Successful write
-+    assert!(write_res.is_ok());
-+    let read_res = readv(reader, &mut iovecs[..]);
-+    assert!(read_res.is_ok());
-+    let read = read_res.ok().unwrap();
-+    // Check whether we've read all data
-+    assert_eq!(to_write.len(), read);
-+    // Cccumulate data from iovecs
-+    let mut read_buf = Vec::with_capacity(to_write.len());
-+    for iovec in &iovecs {
-+        read_buf.extend(iovec.as_slice().iter().cloned());
-+    }
-+    // Check whether iovecs contain all written data
-+    assert_eq!(read_buf.len(), to_write.len());
-+    // Check equality of written and read data
-+    assert_eq!(&read_buf, &to_write);
-+    let close_res = close(reader);
-+    assert!(close_res.is_ok());
-+    let close_res = close(writer);
-+    assert!(close_res.is_ok());
-+}
-+
-+#[test]
-+fn test_pwrite() {
-+    use std::io::Read;
-+
-+    let mut file = tempfile().unwrap();
-+    let buf = [1u8;8];
-+    assert_eq!(Ok(8), pwrite(file.as_raw_fd(), &buf, 8));
-+    let mut file_content = Vec::new();
-+    file.read_to_end(&mut file_content).unwrap();
-+    let mut expected = vec![0u8;8];
-+    expected.extend(vec![1;8]);
-+    assert_eq!(file_content, expected);
-+}
-+
-+#[test]
-+fn test_pread() {
-+    use std::io::Write;
-+
-+    let tempdir = tempdir().unwrap();
-+
-+    let path = tempdir.path().join("pread_test_file");
-+    let mut file = OpenOptions::new().write(true).read(true).create(true)
-+                                    .truncate(true).open(path).unwrap();
-+    let file_content: Vec<u8> = (0..64).collect();
-+    file.write_all(&file_content).unwrap();
-+
-+    let mut buf = [0u8;16];
-+    assert_eq!(Ok(16), pread(file.as_raw_fd(), &mut buf, 16));
-+    let expected: Vec<_> = (16..32).collect();
-+    assert_eq!(&buf[..], &expected[..]);
-+}
-+
-+#[test]
-+#[cfg(target_os = "linux")]
-+fn test_pwritev() {
-+    use std::io::Read;
-+
-+    let to_write: Vec<u8> = (0..128).collect();
-+    let expected: Vec<u8> = [vec![0;100], to_write.clone()].concat();
-+
-+    let iovecs = [
-+        IoVec::from_slice(&to_write[0..17]),
-+        IoVec::from_slice(&to_write[17..64]),
-+        IoVec::from_slice(&to_write[64..128]),
-+    ];
-+
-+    let tempdir = tempdir().unwrap();
-+
-+    // pwritev them into a temporary file
-+    let path = tempdir.path().join("pwritev_test_file");
-+    let mut file = OpenOptions::new().write(true).read(true).create(true)
-+                                    .truncate(true).open(path).unwrap();
-+
-+    let written = pwritev(file.as_raw_fd(), &iovecs, 100).ok().unwrap();
-+    assert_eq!(written, to_write.len());
-+
-+    // Read the data back and make sure it matches
-+    let mut contents = Vec::new();
-+    file.read_to_end(&mut contents).unwrap();
-+    assert_eq!(contents, expected);
-+}
-+
-+#[test]
-+#[cfg(target_os = "linux")]
-+fn test_preadv() {
-+    use std::io::Write;
-+
-+    let to_write: Vec<u8> = (0..200).collect();
-+    let expected: Vec<u8> = (100..200).collect();
-+
-+    let tempdir = tempdir().unwrap();
-+
-+    let path = tempdir.path().join("preadv_test_file");
-+
-+    let mut file = OpenOptions::new().read(true).write(true).create(true)
-+                                    .truncate(true).open(path).unwrap();
-+    file.write_all(&to_write).unwrap();
-+
-+    let mut buffers: Vec<Vec<u8>> = vec![
-+        vec![0; 24],
-+        vec![0; 1],
-+        vec![0; 75],
-+    ];
-+
-+    {
-+        // Borrow the buffers into IoVecs and preadv into them
-+        let iovecs: Vec<_> = buffers.iter_mut().map(
-+            |buf| IoVec::from_mut_slice(&mut buf[..])).collect();
-+        assert_eq!(Ok(100), preadv(file.as_raw_fd(), &iovecs, 100));
-+    }
-+
-+    let all = buffers.concat();
-+    assert_eq!(all, expected);
-+}
-+
-+#[test]
-+#[cfg(target_os = "linux")]
-+// FIXME: qemu-user doesn't implement process_vm_readv/writev on most arches
-+#[cfg_attr(not(any(target_arch = "x86", target_arch = "x86_64")), ignore)]
-+fn test_process_vm_readv() {
-+    use nix::unistd::ForkResult::*;
-+    use nix::sys::signal::*;
-+    use nix::sys::wait::*;
-+
-+    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Pre-allocate memory in the child, since allocation isn't safe
-+    // post-fork (~= async-signal-safe)
-+    let mut vector = vec![1u8, 2, 3, 4, 5];
-+
-+    let (r, w) = pipe().unwrap();
-+    match fork().expect("Error: Fork Failed") {
-+        Parent { child } => {
-+            close(w).unwrap();
-+            // wait for child
-+            read(r, &mut [0u8]).unwrap();
-+            close(r).unwrap();
-+
-+            let ptr = vector.as_ptr() as usize;
-+            let remote_iov = RemoteIoVec { base: ptr, len: 5 };
-+            let mut buf = vec![0u8; 5];
-+
-+            let ret = process_vm_readv(child,
-+                                       &[IoVec::from_mut_slice(&mut buf)],
-+                                       &[remote_iov]);
-+
-+            kill(child, SIGTERM).unwrap();
-+            waitpid(child, None).unwrap();
-+
-+            assert_eq!(Ok(5), ret);
-+            assert_eq!(20u8, buf.iter().sum());
-+        },
-+        Child => {
-+            let _ = close(r);
-+            for i in &mut vector {
-+                *i += 1;
-+            }
-+            let _ = write(w, b"\0");
-+            let _ = close(w);
-+            loop { let _ = pause(); }
-+        },
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/sys/test_wait.rs b/third_party/rust/nix-0.15.0/test/sys/test_wait.rs
-new file mode 100644
-index 0000000000000..d07d82f0d9075
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/sys/test_wait.rs
-@@ -0,0 +1,104 @@
-+use nix::Error;
-+use nix::unistd::*;
-+use nix::unistd::ForkResult::*;
-+use nix::sys::signal::*;
-+use nix::sys::wait::*;
-+use libc::_exit;
-+
-+#[test]
-+fn test_wait_signal() {
-+    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
-+    match fork().expect("Error: Fork Failed") {
-+      Child => {
-+          pause();
-+          unsafe { _exit(123) }
-+      },
-+      Parent { child } => {
-+          kill(child, Some(SIGKILL)).expect("Error: Kill Failed");
-+          assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, SIGKILL, false)));
-+      },
-+    }
-+}
-+
-+#[test]
-+fn test_wait_exit() {
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Safe: Child only calls `_exit`, which is async-signal-safe.
-+    match fork().expect("Error: Fork Failed") {
-+      Child => unsafe { _exit(12); },
-+      Parent { child } => {
-+          assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
-+      },
-+    }
-+}
-+
-+#[test]
-+fn test_waitstatus_from_raw() {
-+    let pid = Pid::from_raw(1);
-+    assert_eq!(WaitStatus::from_raw(pid, 0x0002), Ok(WaitStatus::Signaled(pid, Signal::SIGINT, false)));
-+    assert_eq!(WaitStatus::from_raw(pid, 0x0200), Ok(WaitStatus::Exited(pid, 2)));
-+    assert_eq!(WaitStatus::from_raw(pid, 0x7f7f), Err(Error::invalid_argument()));
-+}
-+
-+#[test]
-+fn test_waitstatus_pid() {
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    match fork().unwrap() {
-+        Child => unsafe { _exit(0) },
-+        Parent { child } => {
-+            let status = waitpid(child, None).unwrap();
-+            assert_eq!(status.pid(), Some(child));
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+// FIXME: qemu-user doesn't implement ptrace on most arches
-+#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
-+mod ptrace {
-+    use nix::sys::ptrace::{self, Options, Event};
-+    use nix::sys::signal::*;
-+    use nix::sys::wait::*;
-+    use nix::unistd::*;
-+    use nix::unistd::ForkResult::*;
-+    use libc::_exit;
-+
-+    fn ptrace_child() -> ! {
-+        ptrace::traceme().unwrap();
-+        // As recommended by ptrace(2), raise SIGTRAP to pause the child
-+        // until the parent is ready to continue
-+        raise(SIGTRAP).unwrap();
-+        unsafe { _exit(0) }
-+    }
-+
-+    fn ptrace_parent(child: Pid) {
-+        // Wait for the raised SIGTRAP
-+        assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, SIGTRAP)));
-+        // We want to test a syscall stop and a PTRACE_EVENT stop
-+        assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
-+
-+        // First, stop on the next system call, which will be exit()
-+        assert!(ptrace::syscall(child).is_ok());
-+        assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
-+        // Then get the ptrace event for the process exiting
-+        assert!(ptrace::cont(child, None).is_ok());
-+        assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceEvent(child, SIGTRAP, Event::PTRACE_EVENT_EXIT as i32)));
-+        // Finally get the normal wait() result, now that the process has exited
-+        assert!(ptrace::cont(child, None).is_ok());
-+        assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 0)));
-+    }
-+
-+    #[test]
-+    fn test_wait_ptrace() {
-+        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+        match fork().expect("Error: Fork Failed") {
-+            Child => ptrace_child(),
-+            Parent { child } => ptrace_parent(child),
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test.rs b/third_party/rust/nix-0.15.0/test/test.rs
-new file mode 100644
-index 0000000000000..6a71d261b5712
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test.rs
-@@ -0,0 +1,149 @@
-+// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
-+#![allow(deprecated)]
-+extern crate bytes;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+extern crate caps;
-+#[macro_use]
-+extern crate cfg_if;
-+#[macro_use]
-+extern crate nix;
-+#[macro_use]
-+extern crate lazy_static;
-+extern crate libc;
-+extern crate rand;
-+#[cfg(target_os = "freebsd")]
-+extern crate sysctl;
-+extern crate tempfile;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+macro_rules! require_capability {
-+    ($capname:ident) => {
-+        use ::caps::{Capability, CapSet, has_cap};
-+        use ::std::io::{self, Write};
-+
-+        if !has_cap(None, CapSet::Effective, Capability::$capname).unwrap() {
-+            let stderr = io::stderr();
-+            let mut handle = stderr.lock();
-+            writeln!(handle, "Insufficient capabilities. Skipping test.")
-+                .unwrap();
-+            return;
-+        }
-+    }
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+macro_rules! skip_if_jailed {
-+    ($name:expr) => {
-+        use ::sysctl::CtlValue;
-+
-+        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
-+            .unwrap()
-+        {
-+            use ::std::io::Write;
-+            let stderr = ::std::io::stderr();
-+            let mut handle = stderr.lock();
-+            writeln!(handle, "{} cannot run in a jail. Skipping test.", $name)
-+                .unwrap();
-+            return;
-+        }
-+    }
-+}
-+
-+macro_rules! skip_if_not_root {
-+    ($name:expr) => {
-+        use nix::unistd::Uid;
-+
-+        if !Uid::current().is_root() {
-+            use ::std::io::Write;
-+            let stderr = ::std::io::stderr();
-+            let mut handle = stderr.lock();
-+            writeln!(handle, "{} requires root privileges. Skipping test.", $name).unwrap();
-+            return;
-+        }
-+    };
-+}
-+
-+mod sys;
-+mod test_dir;
-+mod test_fcntl;
-+#[cfg(any(target_os = "android",
-+          target_os = "linux"))]
-+mod test_kmod;
-+#[cfg(any(target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "fushsia",
-+          target_os = "linux",
-+          target_os = "netbsd"))]
-+mod test_mq;
-+mod test_net;
-+mod test_nix_path;
-+mod test_poll;
-+mod test_pty;
-+#[cfg(any(target_os = "android",
-+          target_os = "freebsd",
-+          target_os = "ios",
-+          target_os = "linux",
-+          target_os = "macos"))]
-+mod test_sendfile;
-+mod test_stat;
-+mod test_unistd;
-+
-+use std::os::unix::io::RawFd;
-+use std::path::PathBuf;
-+use std::sync::{Mutex, RwLock, RwLockWriteGuard};
-+use nix::unistd::{chdir, getcwd, read};
-+
-+/// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
-+fn read_exact(f: RawFd, buf: &mut  [u8]) {
-+    let mut len = 0;
-+    while len < buf.len() {
-+        // get_mut would be better than split_at_mut, but it requires nightly
-+        let (_, remaining) = buf.split_at_mut(len);
-+        len += read(f, remaining).unwrap();
-+    }
-+}
-+
-+lazy_static! {
-+    /// Any test that changes the process's current working directory must grab
-+    /// the RwLock exclusively.  Any process that cares about the current
-+    /// working directory must grab it shared.
-+    pub static ref CWD_LOCK: RwLock<()> = RwLock::new(());
-+    /// Any test that creates child processes must grab this mutex, regardless
-+    /// of what it does with those children.
-+    pub static ref FORK_MTX: Mutex<()> = Mutex::new(());
-+    /// Any test that changes the process's supplementary groups must grab this
-+    /// mutex
-+    pub static ref GROUPS_MTX: Mutex<()> = Mutex::new(());
-+    /// Any tests that loads or unloads kernel modules must grab this mutex
-+    pub static ref KMOD_MTX: Mutex<()> = Mutex::new(());
-+    /// Any test that calls ptsname(3) must grab this mutex.
-+    pub static ref PTSNAME_MTX: Mutex<()> = Mutex::new(());
-+    /// Any test that alters signal handling must grab this mutex.
-+    pub static ref SIGNAL_MTX: Mutex<()> = Mutex::new(());
-+}
-+
-+/// RAII object that restores a test's original directory on drop
-+struct DirRestore<'a> {
-+    d: PathBuf,
-+    _g: RwLockWriteGuard<'a, ()>
-+}
-+
-+impl<'a> DirRestore<'a> {
-+    fn new() -> Self {
-+        let guard = ::CWD_LOCK.write()
-+            .expect("Lock got poisoned by another test");
-+        DirRestore{
-+            _g: guard,
-+            d: getcwd().unwrap(),
-+        }
-+    }
-+}
-+
-+impl<'a> Drop for DirRestore<'a> {
-+    fn drop(&mut self) {
-+        let r = chdir(&self.d);
-+        if std::thread::panicking() {
-+            r.unwrap();
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_dir.rs b/third_party/rust/nix-0.15.0/test/test_dir.rs
-new file mode 100644
-index 0000000000000..c42fbcd18a29d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_dir.rs
-@@ -0,0 +1,46 @@
-+extern crate nix;
-+extern crate tempfile;
-+
-+use nix::dir::{Dir, Type};
-+use nix::fcntl::OFlag;
-+use nix::sys::stat::Mode;
-+use std::fs::File;
-+use self::tempfile::tempdir;
-+
-+#[test]
-+fn read() {
-+    let tmp = tempdir().unwrap();
-+    File::create(&tmp.path().join("foo")).unwrap();
-+    ::std::os::unix::fs::symlink("foo", tmp.path().join("bar")).unwrap();
-+    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
-+                            Mode::empty()).unwrap();
-+    let mut entries: Vec<_> = dir.iter().map(|e| e.unwrap()).collect();
-+    entries.sort_by(|a, b| a.file_name().cmp(b.file_name()));
-+    let entry_names: Vec<_> = entries
-+        .iter()
-+        .map(|e| e.file_name().to_str().unwrap().to_owned())
-+        .collect();
-+    assert_eq!(&entry_names[..], &[".", "..", "bar", "foo"]);
-+
-+    // Check file types. The system is allowed to return DT_UNKNOWN (aka None here) but if it does
-+    // return a type, ensure it's correct.
-+    assert!(&[Some(Type::Directory), None].contains(&entries[0].file_type())); // .: dir
-+    assert!(&[Some(Type::Directory), None].contains(&entries[1].file_type())); // ..: dir
-+    assert!(&[Some(Type::Symlink), None].contains(&entries[2].file_type())); // bar: symlink
-+    assert!(&[Some(Type::File), None].contains(&entries[3].file_type())); // foo: regular file
-+}
-+
-+#[test]
-+fn rewind() {
-+    let tmp = tempdir().unwrap();
-+    let mut dir = Dir::open(tmp.path(), OFlag::O_DIRECTORY | OFlag::O_RDONLY | OFlag::O_CLOEXEC,
-+                            Mode::empty()).unwrap();
-+    let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
-+    let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
-+    assert_eq!(entries1, entries2);
-+}
-+
-+#[test]
-+fn ebadf() {
-+    assert_eq!(Dir::from_fd(-1).unwrap_err(), nix::Error::Sys(nix::errno::Errno::EBADF));
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_fcntl.rs b/third_party/rust/nix-0.15.0/test/test_fcntl.rs
-new file mode 100644
-index 0000000000000..6b2bbd679fc31
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_fcntl.rs
-@@ -0,0 +1,234 @@
-+use nix::Error;
-+use nix::errno::*;
-+use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
-+use nix::sys::stat::Mode;
-+use nix::unistd::{close, read};
-+use tempfile::{self, NamedTempFile};
-+use std::fs::File;
-+use std::io::prelude::*;
-+use std::os::unix::fs;
-+
-+#[test]
-+fn test_openat() {
-+    const CONTENTS: &[u8] = b"abcd";
-+    let mut tmp = NamedTempFile::new().unwrap();
-+    tmp.write_all(CONTENTS).unwrap();
-+
-+    let dirfd = open(tmp.path().parent().unwrap(),
-+                     OFlag::empty(),
-+                     Mode::empty()).unwrap();
-+    let fd = openat(dirfd,
-+                    tmp.path().file_name().unwrap(),
-+                    OFlag::O_RDONLY,
-+                    Mode::empty()).unwrap();
-+
-+    let mut buf = [0u8; 1024];
-+    assert_eq!(4, read(fd, &mut buf).unwrap());
-+    assert_eq!(CONTENTS, &buf[0..4]);
-+
-+    close(fd).unwrap();
-+    close(dirfd).unwrap();
-+}
-+
-+#[test]
-+fn test_renameat() {
-+    let old_dir = tempfile::tempdir().unwrap();
-+    let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+    let old_path = old_dir.path().join("old");
-+    File::create(&old_path).unwrap();
-+    let new_dir = tempfile::tempdir().unwrap();
-+    let new_dirfd = open(new_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+    renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap();
-+    assert_eq!(renameat(Some(old_dirfd), "old", Some(new_dirfd), "new").unwrap_err(),
-+               Error::Sys(Errno::ENOENT));
-+    close(old_dirfd).unwrap();
-+    close(new_dirfd).unwrap();
-+    assert!(new_dir.path().join("new").exists());
-+}
-+
-+#[test]
-+fn test_readlink() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let src = tempdir.path().join("a");
-+    let dst = tempdir.path().join("b");
-+    println!("a: {:?}, b: {:?}", &src, &dst);
-+    fs::symlink(&src.as_path(), &dst.as_path()).unwrap();
-+    let dirfd = open(tempdir.path(),
-+                     OFlag::empty(),
-+                     Mode::empty()).unwrap();
-+
-+    let mut buf = vec![0; src.to_str().unwrap().len() + 1];
-+    assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
-+               src.to_str().unwrap());
-+    assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
-+               src.to_str().unwrap());
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+mod linux_android {
-+    use std::io::prelude::*;
-+    use std::io::SeekFrom;
-+    use std::os::unix::prelude::*;
-+
-+    use libc::loff_t;
-+
-+    use nix::fcntl::*;
-+    use nix::sys::uio::IoVec;
-+    use nix::unistd::{close, pipe, read, write};
-+
-+    use tempfile::{tempfile, NamedTempFile};
-+
-+    /// This test creates a temporary file containing the contents
-+    /// 'foobarbaz' and uses the `copy_file_range` call to transfer
-+    /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
-+    /// resulting file is read and should contain the contents `bar`.
-+    /// The from_offset should be updated by the call to reflect
-+    /// the 3 bytes read (6).
-+    ///
-+    /// FIXME: This test is disabled for linux based builds, because Travis
-+    /// Linux version is too old for `copy_file_range`.
-+    #[test]
-+    #[ignore]
-+    fn test_copy_file_range() {
-+        const CONTENTS: &[u8] = b"foobarbaz";
-+
-+        let mut tmp1 = tempfile().unwrap();
-+        let mut tmp2 = tempfile().unwrap();
-+
-+        tmp1.write_all(CONTENTS).unwrap();
-+        tmp1.flush().unwrap();
-+
-+        let mut from_offset: i64 = 3;
-+        copy_file_range(
-+            tmp1.as_raw_fd(),
-+            Some(&mut from_offset),
-+            tmp2.as_raw_fd(),
-+            None,
-+            3,
-+        )
-+        .unwrap();
-+
-+        let mut res: String = String::new();
-+        tmp2.seek(SeekFrom::Start(0)).unwrap();
-+        tmp2.read_to_string(&mut res).unwrap();
-+
-+        assert_eq!(res, String::from("bar"));
-+        assert_eq!(from_offset, 6);
-+    }
-+
-+    #[test]
-+    fn test_splice() {
-+        const CONTENTS: &[u8] = b"abcdef123456";
-+        let mut tmp = tempfile().unwrap();
-+        tmp.write_all(CONTENTS).unwrap();
-+
-+        let (rd, wr) = pipe().unwrap();
-+        let mut offset: loff_t = 5;
-+        let res = splice(tmp.as_raw_fd(), Some(&mut offset),
-+            wr, None, 2, SpliceFFlags::empty()).unwrap();
-+
-+        assert_eq!(2, res);
-+
-+        let mut buf = [0u8; 1024];
-+        assert_eq!(2, read(rd, &mut buf).unwrap());
-+        assert_eq!(b"f1", &buf[0..2]);
-+        assert_eq!(7, offset);
-+
-+        close(rd).unwrap();
-+        close(wr).unwrap();
-+    }
-+
-+    #[test]
-+    fn test_tee() {
-+        let (rd1, wr1) = pipe().unwrap();
-+        let (rd2, wr2) = pipe().unwrap();
-+
-+        write(wr1, b"abc").unwrap();
-+        let res = tee(rd1, wr2, 2, SpliceFFlags::empty()).unwrap();
-+
-+        assert_eq!(2, res);
-+
-+        let mut buf = [0u8; 1024];
-+
-+        // Check the tee'd bytes are at rd2.
-+        assert_eq!(2, read(rd2, &mut buf).unwrap());
-+        assert_eq!(b"ab", &buf[0..2]);
-+
-+        // Check all the bytes are still at rd1.
-+        assert_eq!(3, read(rd1, &mut buf).unwrap());
-+        assert_eq!(b"abc", &buf[0..3]);
-+
-+        close(rd1).unwrap();
-+        close(wr1).unwrap();
-+        close(rd2).unwrap();
-+        close(wr2).unwrap();
-+    }
-+
-+    #[test]
-+    fn test_vmsplice() {
-+        let (rd, wr) = pipe().unwrap();
-+
-+        let buf1 = b"abcdef";
-+        let buf2 = b"defghi";
-+        let mut iovecs = Vec::with_capacity(2);
-+        iovecs.push(IoVec::from_slice(&buf1[0..3]));
-+        iovecs.push(IoVec::from_slice(&buf2[0..3]));
-+
-+        let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
-+
-+        assert_eq!(6, res);
-+
-+        // Check the bytes can be read at rd.
-+        let mut buf = [0u8; 32];
-+        assert_eq!(6, read(rd, &mut buf).unwrap());
-+        assert_eq!(b"abcdef", &buf[0..6]);
-+
-+        close(rd).unwrap();
-+        close(wr).unwrap();
-+    }
-+
-+    #[test]
-+    fn test_fallocate() {
-+        let tmp = NamedTempFile::new().unwrap();
-+
-+        let fd = tmp.as_raw_fd();
-+        fallocate(fd, FallocateFlags::empty(), 0, 100).unwrap();
-+
-+        // Check if we read exactly 100 bytes
-+        let mut buf = [0u8; 200];
-+        assert_eq!(100, read(fd, &mut buf).unwrap());
-+    }
-+}
-+
-+#[cfg(any(target_os = "linux",
-+          target_os = "android",
-+          target_os = "emscripten",
-+          target_os = "fuchsia",
-+          any(target_os = "wasi", target_env = "wasi"),
-+          target_env = "uclibc",
-+          target_env = "freebsd"))]
-+mod test_posix_fadvise {
-+
-+    use tempfile::NamedTempFile;
-+    use std::os::unix::io::{RawFd, AsRawFd};
-+    use nix::errno::Errno;
-+    use nix::fcntl::*;
-+    use nix::unistd::pipe;
-+
-+    #[test]
-+    fn test_success() {
-+        let tmp = NamedTempFile::new().unwrap();
-+        let fd = tmp.as_raw_fd();
-+        let res = posix_fadvise(fd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED).unwrap();
-+
-+        assert_eq!(res, 0);
-+    }
-+
-+    #[test]
-+    fn test_errno() {
-+        let (rd, _wr) = pipe().unwrap();
-+        let errno = posix_fadvise(rd as RawFd, 0, 100, PosixFadviseAdvice::POSIX_FADV_WILLNEED)
-+                                 .unwrap();
-+        assert_eq!(errno, Errno::ESPIPE as i32);
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
-new file mode 100644
-index 0000000000000..74c99b77e96e1
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/Makefile
-@@ -0,0 +1,7 @@
-+obj-m += hello.o
-+
-+all:
-+	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
-+
-+clean:
-+	make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean
-diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
-new file mode 100644
-index 0000000000000..1c34987d2ac39
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_kmod/hello_mod/hello.c
-@@ -0,0 +1,26 @@
-+/*
-+ *  SPDX-License-Identifier: GPL-2.0+ or MIT
-+ */
-+#include <linux/module.h>
-+#include <linux/kernel.h>
-+
-+static int number= 1;
-+static char *who = "World";
-+
-+module_param(number, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-+MODULE_PARM_DESC(myint, "Just some number");
-+module_param(who, charp, 0000);
-+MODULE_PARM_DESC(who, "Whot to greet");
-+
-+int init_module(void)
-+{
-+	printk(KERN_INFO "Hello %s (%d)!\n", who, number);
-+	return 0;
-+}
-+
-+void cleanup_module(void)
-+{
-+	printk(KERN_INFO "Goodbye %s (%d)!\n", who, number);
-+}
-+
-+MODULE_LICENSE("Dual MIT/GPL");
-diff --git a/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs b/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
-new file mode 100644
-index 0000000000000..ad406357b06d2
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_kmod/mod.rs
-@@ -0,0 +1,166 @@
-+use std::fs::copy;
-+use std::path::PathBuf;
-+use std::process::Command;
-+use tempfile::{tempdir, TempDir};
-+
-+fn compile_kernel_module() -> (PathBuf, String, TempDir) {
-+    let _m = ::FORK_MTX
-+        .lock()
-+        .expect("Mutex got poisoned by another test");
-+
-+    let tmp_dir = tempdir().expect("unable to create temporary build directory");
-+
-+    copy(
-+        "test/test_kmod/hello_mod/hello.c",
-+        &tmp_dir.path().join("hello.c"),
-+    ).expect("unable to copy hello.c to temporary build directory");
-+    copy(
-+        "test/test_kmod/hello_mod/Makefile",
-+        &tmp_dir.path().join("Makefile"),
-+    ).expect("unable to copy Makefile to temporary build directory");
-+
-+    let status = Command::new("make")
-+        .current_dir(tmp_dir.path())
-+        .status()
-+        .expect("failed to run make");
-+
-+    assert!(status.success());
-+
-+    // Return the relative path of the build kernel module
-+    (tmp_dir.path().join("hello.ko"), "hello".to_owned(), tmp_dir)
-+}
-+
-+use nix::errno::Errno;
-+use nix::kmod::{delete_module, DeleteModuleFlags};
-+use nix::kmod::{finit_module, init_module, ModuleInitFlags};
-+use nix::Error;
-+use std::ffi::CString;
-+use std::fs::File;
-+use std::io::Read;
-+
-+#[test]
-+fn test_finit_and_delete_module() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-+
-+    let f = File::open(kmod_path).expect("unable to open kernel module");
-+    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
-+        .expect("unable to load kernel module");
-+
-+    delete_module(
-+        &CString::new(kmod_name).unwrap(),
-+        DeleteModuleFlags::empty(),
-+    ).expect("unable to unload kernel module");
-+}
-+
-+#[test]
-+fn test_finit_and_delete_modul_with_params() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-+
-+    let f = File::open(kmod_path).expect("unable to open kernel module");
-+    finit_module(
-+        &f,
-+        &CString::new("who=Rust number=2018").unwrap(),
-+        ModuleInitFlags::empty(),
-+    ).expect("unable to load kernel module");
-+
-+    delete_module(
-+        &CString::new(kmod_name).unwrap(),
-+        DeleteModuleFlags::empty(),
-+    ).expect("unable to unload kernel module");
-+}
-+
-+#[test]
-+fn test_init_and_delete_module() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-+
-+    let mut f = File::open(kmod_path).expect("unable to open kernel module");
-+    let mut contents: Vec<u8> = Vec::new();
-+    f.read_to_end(&mut contents)
-+        .expect("unable to read kernel module content to buffer");
-+    init_module(&mut contents, &CString::new("").unwrap()).expect("unable to load kernel module");
-+
-+    delete_module(
-+        &CString::new(kmod_name).unwrap(),
-+        DeleteModuleFlags::empty(),
-+    ).expect("unable to unload kernel module");
-+}
-+
-+#[test]
-+fn test_init_and_delete_module_with_params() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-+
-+    let mut f = File::open(kmod_path).expect("unable to open kernel module");
-+    let mut contents: Vec<u8> = Vec::new();
-+    f.read_to_end(&mut contents)
-+        .expect("unable to read kernel module content to buffer");
-+    init_module(&mut contents, &CString::new("who=Nix number=2015").unwrap())
-+        .expect("unable to load kernel module");
-+
-+    delete_module(
-+        &CString::new(kmod_name).unwrap(),
-+        DeleteModuleFlags::empty(),
-+    ).expect("unable to unload kernel module");
-+}
-+
-+#[test]
-+fn test_finit_module_invalid() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let kmod_path = "/dev/zero";
-+
-+    let f = File::open(kmod_path).expect("unable to open kernel module");
-+    let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
-+
-+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EINVAL));
-+}
-+
-+#[test]
-+fn test_finit_module_twice_and_delete_module() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
-+
-+    let f = File::open(kmod_path).expect("unable to open kernel module");
-+    finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty())
-+        .expect("unable to load kernel module");
-+
-+    let result = finit_module(&f, &CString::new("").unwrap(), ModuleInitFlags::empty());
-+
-+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::EEXIST));
-+
-+    delete_module(
-+        &CString::new(kmod_name).unwrap(),
-+        DeleteModuleFlags::empty(),
-+    ).expect("unable to unload kernel module");
-+}
-+
-+#[test]
-+fn test_delete_module_not_loaded() {
-+    require_capability!(CAP_SYS_MODULE);
-+    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
-+
-+    assert_eq!(result.unwrap_err(), Error::Sys(Errno::ENOENT));
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_mount.rs b/third_party/rust/nix-0.15.0/test/test_mount.rs
-new file mode 100644
-index 0000000000000..d2e08bc42855d
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_mount.rs
-@@ -0,0 +1,238 @@
-+// Impelmentation note: to allow unprivileged users to run it, this test makes
-+// use of user and mount namespaces. On systems that allow unprivileged user
-+// namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
-+// without root.
-+
-+extern crate libc;
-+extern crate nix;
-+extern crate tempfile;
-+
-+#[cfg(target_os = "linux")]
-+mod test_mount {
-+    use std::fs::{self, File};
-+    use std::io::{self, Read, Write};
-+    use std::os::unix::fs::OpenOptionsExt;
-+    use std::os::unix::fs::PermissionsExt;
-+    use std::process::{self, Command};
-+
-+    use libc::{EACCES, EROFS};
-+
-+    use nix::errno::Errno;
-+    use nix::mount::{mount, umount, MsFlags};
-+    use nix::sched::{unshare, CloneFlags};
-+    use nix::sys::stat::{self, Mode};
-+    use nix::unistd::getuid;
-+
-+    use tempfile;
-+
-+    static SCRIPT_CONTENTS: &'static [u8] = b"#!/bin/sh
-+exit 23";
-+
-+    const EXPECTED_STATUS: i32 = 23;
-+
-+    const NONE: Option<&'static [u8]> = None;
-+    pub fn test_mount_tmpfs_without_flags_allows_rwx() {
-+        let tempdir = tempfile::tempdir().unwrap();
-+
-+        mount(NONE,
-+              tempdir.path(),
-+              Some(b"tmpfs".as_ref()),
-+              MsFlags::empty(),
-+              NONE)
-+            .unwrap_or_else(|e| panic!("mount failed: {}", e));
-+
-+        let test_path = tempdir.path().join("test");
-+
-+        // Verify write.
-+        fs::OpenOptions::new()
-+            .create(true)
-+            .write(true)
-+            .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
-+            .open(&test_path)
-+            .or_else(|e|
-+                if Errno::from_i32(e.raw_os_error().unwrap()) == Errno::EOVERFLOW {
-+                    // Skip tests on certain Linux kernels which have a bug
-+                    // regarding tmpfs in namespaces.
-+                    // Ubuntu 14.04 and 16.04 are known to be affected; 16.10 is
-+                    // not.  There is no legitimate reason for open(2) to return
-+                    // EOVERFLOW here.
-+                    // https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1659087
-+                    let stderr = io::stderr();
-+                    let mut handle = stderr.lock();
-+                    writeln!(handle, "Buggy Linux kernel detected.  Skipping test.")
-+                    .unwrap();
-+                    process::exit(0);
-+               } else {
-+                   panic!("open failed: {}", e);
-+               }
-+            )
-+            .and_then(|mut f| f.write(SCRIPT_CONTENTS))
-+            .unwrap_or_else(|e| panic!("write failed: {}", e));
-+
-+        // Verify read.
-+        let mut buf = Vec::new();
-+        File::open(&test_path)
-+            .and_then(|mut f| f.read_to_end(&mut buf))
-+            .unwrap_or_else(|e| panic!("read failed: {}", e));
-+        assert_eq!(buf, SCRIPT_CONTENTS);
-+
-+        // Verify execute.
-+        assert_eq!(EXPECTED_STATUS,
-+                   Command::new(&test_path)
-+                       .status()
-+                       .unwrap_or_else(|e| panic!("exec failed: {}", e))
-+                       .code()
-+                       .unwrap_or_else(|| panic!("child killed by signal")));
-+
-+        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
-+    }
-+
-+    pub fn test_mount_rdonly_disallows_write() {
-+        let tempdir = tempfile::tempdir().unwrap();
-+
-+        mount(NONE,
-+              tempdir.path(),
-+              Some(b"tmpfs".as_ref()),
-+              MsFlags::MS_RDONLY,
-+              NONE)
-+            .unwrap_or_else(|e| panic!("mount failed: {}", e));
-+
-+        // EROFS: Read-only file system
-+        assert_eq!(EROFS as i32,
-+                   File::create(tempdir.path().join("test")).unwrap_err().raw_os_error().unwrap());
-+
-+        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
-+    }
-+
-+    pub fn test_mount_noexec_disallows_exec() {
-+        let tempdir = tempfile::tempdir().unwrap();
-+
-+        mount(NONE,
-+              tempdir.path(),
-+              Some(b"tmpfs".as_ref()),
-+              MsFlags::MS_NOEXEC,
-+              NONE)
-+            .unwrap_or_else(|e| panic!("mount failed: {}", e));
-+
-+        let test_path = tempdir.path().join("test");
-+
-+        fs::OpenOptions::new()
-+            .create(true)
-+            .write(true)
-+            .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
-+            .open(&test_path)
-+            .and_then(|mut f| f.write(SCRIPT_CONTENTS))
-+            .unwrap_or_else(|e| panic!("write failed: {}", e));
-+
-+        // Verify that we cannot execute despite a+x permissions being set.
-+        let mode = stat::Mode::from_bits_truncate(fs::metadata(&test_path)
-+                                                      .map(|md| md.permissions().mode())
-+                                                      .unwrap_or_else(|e| {
-+                                                          panic!("metadata failed: {}", e)
-+                                                      }));
-+
-+        assert!(mode.contains(Mode::S_IXUSR | Mode::S_IXGRP | Mode::S_IXOTH),
-+                "{:?} did not have execute permissions",
-+                &test_path);
-+
-+        // EACCES: Permission denied
-+        assert_eq!(EACCES as i32,
-+                   Command::new(&test_path).status().unwrap_err().raw_os_error().unwrap());
-+
-+        umount(tempdir.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
-+    }
-+
-+    pub fn test_mount_bind() {
-+        let tempdir = tempfile::tempdir().unwrap();
-+        let file_name = "test";
-+
-+        {
-+            let mount_point = tempfile::tempdir().unwrap();
-+
-+            mount(Some(tempdir.path()),
-+                  mount_point.path(),
-+                  NONE,
-+                  MsFlags::MS_BIND,
-+                  NONE)
-+                .unwrap_or_else(|e| panic!("mount failed: {}", e));
-+
-+            fs::OpenOptions::new()
-+                .create(true)
-+                .write(true)
-+                .mode((Mode::S_IRWXU | Mode::S_IRWXG | Mode::S_IRWXO).bits())
-+                .open(mount_point.path().join(file_name))
-+                .and_then(|mut f| f.write(SCRIPT_CONTENTS))
-+                .unwrap_or_else(|e| panic!("write failed: {}", e));
-+
-+            umount(mount_point.path()).unwrap_or_else(|e| panic!("umount failed: {}", e));
-+        }
-+
-+        // Verify the file written in the mount shows up in source directory, even
-+        // after unmounting.
-+
-+        let mut buf = Vec::new();
-+        File::open(tempdir.path().join(file_name))
-+            .and_then(|mut f| f.read_to_end(&mut buf))
-+            .unwrap_or_else(|e| panic!("read failed: {}", e));
-+        assert_eq!(buf, SCRIPT_CONTENTS);
-+    }
-+
-+    pub fn setup_namespaces() {
-+        // Hold on to the uid in the parent namespace.
-+        let uid = getuid();
-+
-+        unshare(CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWUSER).unwrap_or_else(|e| {
-+            let stderr = io::stderr();
-+            let mut handle = stderr.lock();
-+            writeln!(handle,
-+                     "unshare failed: {}. Are unprivileged user namespaces available?",
-+                     e).unwrap();
-+            writeln!(handle, "mount is not being tested").unwrap();
-+            // Exit with success because not all systems support unprivileged user namespaces, and
-+            // that's not what we're testing for.
-+            process::exit(0);
-+        });
-+
-+        // Map user as uid 1000.
-+        fs::OpenOptions::new()
-+            .write(true)
-+            .open("/proc/self/uid_map")
-+            .and_then(|mut f| f.write(format!("1000 {} 1\n", uid).as_bytes()))
-+            .unwrap_or_else(|e| panic!("could not write uid map: {}", e));
-+    }
-+}
-+
-+
-+// Test runner
-+
-+/// Mimic normal test output (hackishly).
-+#[cfg(target_os = "linux")]
-+macro_rules! run_tests {
-+    ( $($test_fn:ident),* ) => {{
-+        println!();
-+
-+        $(
-+            print!("test test_mount::{} ... ", stringify!($test_fn));
-+            $test_fn();
-+            println!("ok");
-+        )*
-+
-+        println!();
-+    }}
-+}
-+
-+#[cfg(target_os = "linux")]
-+fn main() {
-+    use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx,
-+                     test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec,
-+                     test_mount_bind};
-+    setup_namespaces();
-+
-+    run_tests!(test_mount_tmpfs_without_flags_allows_rwx,
-+               test_mount_rdonly_disallows_write,
-+               test_mount_noexec_disallows_exec,
-+               test_mount_bind);
-+}
-+
-+#[cfg(not(target_os = "linux"))]
-+fn main() {}
-diff --git a/third_party/rust/nix-0.15.0/test/test_mq.rs b/third_party/rust/nix-0.15.0/test/test_mq.rs
-new file mode 100644
-index 0000000000000..caac4fc261cd6
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_mq.rs
-@@ -0,0 +1,152 @@
-+use libc::c_long;
-+
-+use std::ffi::CString;
-+use std::str;
-+
-+use nix::errno::Errno::*;
-+use nix::Error::Sys;
-+use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive};
-+use nix::mqueue::{MqAttr, MQ_OFlag};
-+use nix::sys::stat::Mode;
-+
-+#[test]
-+fn test_mq_send_and_receive() {
-+    const MSG_SIZE: c_long =  32;
-+    let attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-+    let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
-+
-+    let oflag0 = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-+    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
-+    let r0 = mq_open(mq_name, oflag0, mode, Some(&attr));
-+    if let Err(Sys(ENOSYS)) = r0 {
-+        println!("message queues not supported or module not loaded?");
-+        return;
-+    };
-+    let mqd0 = r0.unwrap();
-+    let msg_to_send = "msg_1";
-+    mq_send(mqd0, msg_to_send.as_bytes(), 1).unwrap();
-+
-+    let oflag1 = MQ_OFlag::O_CREAT | MQ_OFlag::O_RDONLY;
-+    let mqd1 = mq_open(mq_name, oflag1, mode, Some(&attr)).unwrap();
-+    let mut buf = [0u8; 32];
-+    let mut prio = 0u32;
-+    let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
-+    assert!(prio == 1);
-+
-+    mq_close(mqd1).unwrap();
-+    mq_close(mqd0).unwrap();
-+    assert_eq!(msg_to_send, str::from_utf8(&buf[0..len]).unwrap());
-+}
-+
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_mq_getattr() {
-+    use nix::mqueue::mq_getattr;
-+    const MSG_SIZE: c_long =  32;
-+    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-+    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-+    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-+    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
-+    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-+    if let Err(Sys(ENOSYS)) = r {
-+        println!("message queues not supported or module not loaded?");
-+        return;
-+    };
-+    let mqd = r.unwrap();
-+
-+    let read_attr = mq_getattr(mqd).unwrap();
-+    assert_eq!(read_attr, initial_attr);
-+    mq_close(mqd).unwrap();
-+}
-+
-+// FIXME: Fix failures for mips in QEMU
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
-+fn test_mq_setattr() {
-+    use nix::mqueue::{mq_getattr, mq_setattr};
-+    const MSG_SIZE: c_long =  32;
-+    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-+    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-+    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-+    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
-+    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-+    if let Err(Sys(ENOSYS)) = r {
-+        println!("message queues not supported or module not loaded?");
-+        return;
-+    };
-+    let mqd = r.unwrap();
-+
-+    let new_attr =  MqAttr::new(0, 20, MSG_SIZE * 2, 100);
-+    let old_attr = mq_setattr(mqd, &new_attr).unwrap();
-+    assert_eq!(old_attr, initial_attr);
-+
-+    let new_attr_get = mq_getattr(mqd).unwrap();
-+    // The following tests make sense. No changes here because according to the Linux man page only
-+    // O_NONBLOCK can be set (see tests below)
-+    assert_ne!(new_attr_get, new_attr);
-+
-+    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0);
-+    mq_setattr(mqd, &new_attr_non_blocking).unwrap();
-+    let new_attr_get = mq_getattr(mqd).unwrap();
-+
-+    // now the O_NONBLOCK flag has been set
-+    assert_ne!(new_attr_get, initial_attr);
-+    assert_eq!(new_attr_get, new_attr_non_blocking);
-+    mq_close(mqd).unwrap();
-+}
-+
-+// FIXME: Fix failures for mips in QEMU
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
-+fn test_mq_set_nonblocking() {
-+    use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
-+    const MSG_SIZE: c_long =  32;
-+    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-+    let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-+    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-+    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
-+    let r = mq_open(mq_name, oflag, mode, Some(&initial_attr));
-+    if let Err(Sys(ENOSYS)) = r {
-+        println!("message queues not supported or module not loaded?");
-+        return;
-+    };
-+    let mqd = r.unwrap();
-+    mq_set_nonblock(mqd).unwrap();
-+    let new_attr = mq_getattr(mqd);
-+    assert!(new_attr.unwrap().flags() == MQ_OFlag::O_NONBLOCK.bits() as c_long);
-+    mq_remove_nonblock(mqd).unwrap();
-+    let new_attr = mq_getattr(mqd);
-+    assert!(new_attr.unwrap().flags() == 0);
-+    mq_close(mqd).unwrap();
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_mq_unlink() {
-+    use nix::mqueue::mq_unlink;
-+    const MSG_SIZE: c_long =  32;
-+    let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-+    let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
-+    let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
-+    let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-+    let mode = Mode::S_IWUSR | Mode::S_IRUSR | Mode::S_IRGRP | Mode::S_IROTH;
-+    let r = mq_open(mq_name_opened, oflag, mode, Some(&initial_attr));
-+    if let Err(Sys(ENOSYS)) = r {
-+        println!("message queues not supported or module not loaded?");
-+        return;
-+    };
-+    let mqd = r.unwrap();
-+
-+    let res_unlink = mq_unlink(mq_name_opened);
-+    assert!(res_unlink == Ok(()) );
-+
-+    let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
-+    assert!(res_unlink_not_opened == Err(Sys(ENOENT)) );
-+
-+    mq_close(mqd).unwrap();
-+    let res_unlink_after_close = mq_unlink(mq_name_opened);
-+    assert!(res_unlink_after_close == Err(Sys(ENOENT)) );
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_net.rs b/third_party/rust/nix-0.15.0/test/test_net.rs
-new file mode 100644
-index 0000000000000..b8940e718bdf3
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_net.rs
-@@ -0,0 +1,12 @@
-+use nix::net::if_::*;
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+const LOOPBACK: &[u8] = b"lo";
-+
-+#[cfg(not(any(target_os = "android", target_os = "linux")))]
-+const LOOPBACK: &[u8] = b"lo0";
-+
-+#[test]
-+fn test_if_nametoindex() {
-+    assert!(if_nametoindex(&LOOPBACK[..]).is_ok());
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_nix_path.rs b/third_party/rust/nix-0.15.0/test/test_nix_path.rs
-new file mode 100644
-index 0000000000000..e69de29bb2d1d
-diff --git a/third_party/rust/nix-0.15.0/test/test_poll.rs b/third_party/rust/nix-0.15.0/test/test_poll.rs
-new file mode 100644
-index 0000000000000..aef40e4792b5a
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_poll.rs
-@@ -0,0 +1,50 @@
-+use nix::poll::{PollFlags, poll, PollFd};
-+use nix::unistd::{write, pipe};
-+
-+#[test]
-+fn test_poll() {
-+    let (r, w) = pipe().unwrap();
-+    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
-+
-+    // Poll an idle pipe.  Should timeout
-+    let nfds = poll(&mut fds, 100).unwrap();
-+    assert_eq!(nfds, 0);
-+    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-+
-+    write(w, b".").unwrap();
-+
-+    // Poll a readable pipe.  Should return an event.
-+    let nfds = poll(&mut fds, 100).unwrap();
-+    assert_eq!(nfds, 1);
-+    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-+}
-+
-+// ppoll(2) is the same as poll except for how it handles timeouts and signals.
-+// Repeating the test for poll(2) should be sufficient to check that our
-+// bindings are correct.
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux"))]
-+#[test]
-+fn test_ppoll() {
-+    use nix::poll::ppoll;
-+    use nix::sys::signal::SigSet;
-+    use nix::sys::time::{TimeSpec, TimeValLike};
-+
-+    let timeout = TimeSpec::milliseconds(1);
-+    let (r, w) = pipe().unwrap();
-+    let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
-+
-+    // Poll an idle pipe.  Should timeout
-+    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
-+    assert_eq!(nfds, 0);
-+    assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-+
-+    write(w, b".").unwrap();
-+
-+    // Poll a readable pipe.  Should return an event.
-+    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
-+    assert_eq!(nfds, 1);
-+    assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_pty.rs b/third_party/rust/nix-0.15.0/test/test_pty.rs
-new file mode 100644
-index 0000000000000..476b15c10128c
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_pty.rs
-@@ -0,0 +1,235 @@
-+use std::io::Write;
-+use std::path::Path;
-+use std::os::unix::prelude::*;
-+use tempfile::tempfile;
-+
-+use libc::{_exit, STDOUT_FILENO};
-+use nix::fcntl::{OFlag, open};
-+use nix::pty::*;
-+use nix::sys::stat;
-+use nix::sys::termios::*;
-+use nix::unistd::{write, close, pause};
-+
-+/// Regression test for Issue #659
-+/// This is the correct way to explicitly close a `PtyMaster`
-+#[test]
-+fn test_explicit_close() {
-+    let mut f = {
-+        let m = posix_openpt(OFlag::O_RDWR).unwrap();
-+        close(m.into_raw_fd()).unwrap();
-+        tempfile().unwrap()
-+    };
-+    // This should work.  But if there's been a double close, then it will
-+    // return EBADF
-+    f.write_all(b"whatever").unwrap();
-+}
-+
-+/// Test equivalence of `ptsname` and `ptsname_r`
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptsname_equivalence() {
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open a new PTTY master
-+    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-+    assert!(master_fd.as_raw_fd() > 0);
-+
-+    // Get the name of the slave
-+    let slave_name = unsafe { ptsname(&master_fd) }.unwrap() ;
-+    let slave_name_r = ptsname_r(&master_fd).unwrap();
-+    assert_eq!(slave_name, slave_name_r);
-+}
-+
-+/// Test data copying of `ptsname`
-+// TODO need to run in a subprocess, since ptsname is non-reentrant
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptsname_copy() {
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open a new PTTY master
-+    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-+    assert!(master_fd.as_raw_fd() > 0);
-+
-+    // Get the name of the slave
-+    let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
-+    let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
-+    assert!(slave_name1 == slave_name2);
-+    // Also make sure that the string was actually copied and they point to different parts of
-+    // memory.
-+    assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
-+}
-+
-+/// Test data copying of `ptsname_r`
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptsname_r_copy() {
-+    // Open a new PTTY master
-+    let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-+    assert!(master_fd.as_raw_fd() > 0);
-+
-+    // Get the name of the slave
-+    let slave_name1 = ptsname_r(&master_fd).unwrap();
-+    let slave_name2 = ptsname_r(&master_fd).unwrap();
-+    assert!(slave_name1 == slave_name2);
-+    assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
-+}
-+
-+/// Test that `ptsname` returns different names for different devices
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_ptsname_unique() {
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open a new PTTY master
-+    let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-+    assert!(master1_fd.as_raw_fd() > 0);
-+
-+    // Open a second PTTY master
-+    let master2_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-+    assert!(master2_fd.as_raw_fd() > 0);
-+
-+    // Get the name of the slave
-+    let slave_name1 = unsafe { ptsname(&master1_fd) }.unwrap();
-+    let slave_name2 = unsafe { ptsname(&master2_fd) }.unwrap();
-+    assert!(slave_name1 != slave_name2);
-+}
-+
-+/// Test opening a master/slave PTTY pair
-+///
-+/// This is a single larger test because much of these functions aren't useful by themselves. So for
-+/// this test we perform the basic act of getting a file handle for a connect master/slave PTTY
-+/// pair.
-+#[test]
-+fn test_open_ptty_pair() {
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open a new PTTY master
-+    let master_fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
-+    assert!(master_fd.as_raw_fd() > 0);
-+
-+    // Allow a slave to be generated for it
-+    grantpt(&master_fd).expect("grantpt failed");
-+    unlockpt(&master_fd).expect("unlockpt failed");
-+
-+    // Get the name of the slave
-+    let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed");
-+
-+    // Open the slave device
-+    let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
-+    assert!(slave_fd > 0);
-+}
-+
-+#[test]
-+fn test_openpty() {
-+    // openpty uses ptname(3) internally
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    let pty = openpty(None, None).unwrap();
-+    assert!(pty.master > 0);
-+    assert!(pty.slave > 0);
-+
-+    // Writing to one should be readable on the other one
-+    let string = "foofoofoo\n";
-+    let mut buf = [0u8; 10];
-+    write(pty.master, string.as_bytes()).unwrap();
-+    ::read_exact(pty.slave, &mut buf);
-+
-+    assert_eq!(&buf, string.as_bytes());
-+
-+    // Read the echo as well
-+    let echoed_string = "foofoofoo\r\n";
-+    let mut buf = [0u8; 11];
-+    ::read_exact(pty.master, &mut buf);
-+    assert_eq!(&buf, echoed_string.as_bytes());
-+
-+    let string2 = "barbarbarbar\n";
-+    let echoed_string2 = "barbarbarbar\r\n";
-+    let mut buf = [0u8; 14];
-+    write(pty.slave, string2.as_bytes()).unwrap();
-+    ::read_exact(pty.master, &mut buf);
-+
-+    assert_eq!(&buf, echoed_string2.as_bytes());
-+
-+    close(pty.master).unwrap();
-+    close(pty.slave).unwrap();
-+}
-+
-+#[test]
-+fn test_openpty_with_termios() {
-+    // openpty uses ptname(3) internally
-+    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Open one pty to get attributes for the second one
-+    let mut termios = {
-+        let pty = openpty(None, None).unwrap();
-+        assert!(pty.master > 0);
-+        assert!(pty.slave > 0);
-+        let termios = tcgetattr(pty.master).unwrap();
-+        close(pty.master).unwrap();
-+        close(pty.slave).unwrap();
-+        termios
-+    };
-+    // Make sure newlines are not transformed so the data is preserved when sent.
-+    termios.output_flags.remove(OutputFlags::ONLCR);
-+
-+    let pty = openpty(None, &termios).unwrap();
-+    // Must be valid file descriptors
-+    assert!(pty.master > 0);
-+    assert!(pty.slave > 0);
-+
-+    // Writing to one should be readable on the other one
-+    let string = "foofoofoo\n";
-+    let mut buf = [0u8; 10];
-+    write(pty.master, string.as_bytes()).unwrap();
-+    ::read_exact(pty.slave, &mut buf);
-+
-+    assert_eq!(&buf, string.as_bytes());
-+
-+    // read the echo as well
-+    let echoed_string = "foofoofoo\n";
-+    ::read_exact(pty.master, &mut buf);
-+    assert_eq!(&buf, echoed_string.as_bytes());
-+
-+    let string2 = "barbarbarbar\n";
-+    let echoed_string2 = "barbarbarbar\n";
-+    let mut buf = [0u8; 13];
-+    write(pty.slave, string2.as_bytes()).unwrap();
-+    ::read_exact(pty.master, &mut buf);
-+
-+    assert_eq!(&buf, echoed_string2.as_bytes());
-+
-+    close(pty.master).unwrap();
-+    close(pty.slave).unwrap();
-+}
-+
-+#[test]
-+fn test_forkpty() {
-+    use nix::unistd::ForkResult::*;
-+    use nix::sys::signal::*;
-+    use nix::sys::wait::wait;
-+    // forkpty calls openpty which uses ptname(3) internally.
-+    let _m0 = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    // forkpty spawns a child process
-+    let _m1 = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    let string = "naninani\n";
-+    let echoed_string = "naninani\r\n";
-+    let pty = forkpty(None, None).unwrap();
-+    match pty.fork_result {
-+        Child => {
-+            write(STDOUT_FILENO, string.as_bytes()).unwrap();
-+            pause();  // we need the child to stay alive until the parent calls read
-+            unsafe { _exit(0); }
-+        },
-+        Parent { child } => {
-+            let mut buf = [0u8; 10];
-+            assert!(child.as_raw() > 0);
-+            ::read_exact(pty.master, &mut buf);
-+            kill(child, SIGTERM).unwrap();
-+            wait().unwrap(); // keep other tests using generic wait from getting our child
-+            assert_eq!(&buf, echoed_string.as_bytes());
-+            close(pty.master).unwrap();
-+        },
-+    }
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs b/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
-new file mode 100644
-index 0000000000000..9b59d66435ed0
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_ptymaster_drop.rs
-@@ -0,0 +1,21 @@
-+extern crate nix;
-+
-+use nix::fcntl::OFlag;
-+use nix::pty::*;
-+use nix::unistd::close;
-+use std::os::unix::io::AsRawFd;
-+
-+/// Regression test for Issue #659
-+/// `PtyMaster` should panic rather than double close the file descriptor
-+/// This must run in its own test process because it deliberately creates a race
-+/// condition.
-+#[test]
-+#[should_panic(expected = "Closing an invalid file descriptor!")]
-+// In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't know
-+// why.  It doesn't happen on any other target, and it doesn't happen on my PC.
-+#[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
-+fn test_double_close() {
-+    let m = posix_openpt(OFlag::O_RDWR).unwrap();
-+    close(m.as_raw_fd()).unwrap();
-+    drop(m);            // should panic here
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_sendfile.rs b/third_party/rust/nix-0.15.0/test/test_sendfile.rs
-new file mode 100644
-index 0000000000000..3bc7932f4c84f
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_sendfile.rs
-@@ -0,0 +1,129 @@
-+use std::io::prelude::*;
-+use std::os::unix::prelude::*;
-+
-+use libc::off_t;
-+use nix::sys::sendfile::*;
-+use tempfile::tempfile;
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        use nix::unistd::{close, pipe, read};
-+    } else if #[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))] {
-+        use std::net::Shutdown;
-+        use std::os::unix::net::UnixStream;
-+    }
-+}
-+
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[test]
-+fn test_sendfile_linux() {
-+    const CONTENTS: &[u8] = b"abcdef123456";
-+    let mut tmp = tempfile().unwrap();
-+    tmp.write_all(CONTENTS).unwrap();
-+
-+    let (rd, wr) = pipe().unwrap();
-+    let mut offset: off_t = 5;
-+    let res = sendfile(wr, tmp.as_raw_fd(), Some(&mut offset), 2).unwrap();
-+
-+    assert_eq!(2, res);
-+
-+    let mut buf = [0u8; 1024];
-+    assert_eq!(2, read(rd, &mut buf).unwrap());
-+    assert_eq!(b"f1", &buf[0..2]);
-+    assert_eq!(7, offset);
-+
-+    close(rd).unwrap();
-+    close(wr).unwrap();
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+#[test]
-+fn test_sendfile_freebsd() {
-+    // Declare the content
-+    let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
-+    let body = "Xabcdef123456";
-+    let body_offset = 1;
-+    let trailer_strings = vec!["\n", "Served by Make Believe\n"];
-+
-+    // Write the body to a file
-+    let mut tmp = tempfile().unwrap();
-+    tmp.write_all(body.as_bytes()).unwrap();
-+
-+    // Prepare headers and trailers for sendfile
-+    let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
-+    let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
-+
-+    // Prepare socket pair
-+    let (mut rd, wr) = UnixStream::pair().unwrap();
-+
-+    // Call the test method
-+    let (res, bytes_written) = sendfile(
-+        tmp.as_raw_fd(),
-+        wr.as_raw_fd(),
-+        body_offset as off_t,
-+        None,
-+        Some(headers.as_slice()),
-+        Some(trailers.as_slice()),
-+        SfFlags::empty(),
-+        0,
-+    );
-+    assert!(res.is_ok());
-+    wr.shutdown(Shutdown::Both).unwrap();
-+
-+    // Prepare the expected result
-+    let expected_string =
-+        header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
-+
-+    // Verify the message that was sent
-+    assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
-+
-+    let mut read_string = String::new();
-+    let bytes_read = rd.read_to_string(&mut read_string).unwrap();
-+    assert_eq!(bytes_written as usize, bytes_read);
-+    assert_eq!(expected_string, read_string);
-+}
-+
-+#[cfg(any(target_os = "ios", target_os = "macos"))]
-+#[test]
-+fn test_sendfile_darwin() {
-+    // Declare the content
-+    let header_strings = vec!["HTTP/1.1 200 OK\n", "Content-Type: text/plain\n", "\n"];
-+    let body = "Xabcdef123456";
-+    let body_offset = 1;
-+    let trailer_strings = vec!["\n", "Served by Make Believe\n"];
-+
-+    // Write the body to a file
-+    let mut tmp = tempfile().unwrap();
-+    tmp.write_all(body.as_bytes()).unwrap();
-+
-+    // Prepare headers and trailers for sendfile
-+    let headers: Vec<&[u8]> = header_strings.iter().map(|s| s.as_bytes()).collect();
-+    let trailers: Vec<&[u8]> = trailer_strings.iter().map(|s| s.as_bytes()).collect();
-+
-+    // Prepare socket pair
-+    let (mut rd, wr) = UnixStream::pair().unwrap();
-+
-+    // Call the test method
-+    let (res, bytes_written) = sendfile(
-+        tmp.as_raw_fd(),
-+        wr.as_raw_fd(),
-+        body_offset as off_t,
-+        None,
-+        Some(headers.as_slice()),
-+        Some(trailers.as_slice()),
-+    );
-+    assert!(res.is_ok());
-+    wr.shutdown(Shutdown::Both).unwrap();
-+
-+    // Prepare the expected result
-+    let expected_string =
-+        header_strings.concat() + &body[body_offset..] + &trailer_strings.concat();
-+
-+    // Verify the message that was sent
-+    assert_eq!(bytes_written as usize, expected_string.as_bytes().len());
-+
-+    let mut read_string = String::new();
-+    let bytes_read = rd.read_to_string(&mut read_string).unwrap();
-+    assert_eq!(bytes_written as usize, bytes_read);
-+    assert_eq!(expected_string, read_string);
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_stat.rs b/third_party/rust/nix-0.15.0/test/test_stat.rs
-new file mode 100644
-index 0000000000000..1173455fae8db
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_stat.rs
-@@ -0,0 +1,296 @@
-+use std::fs::{self, File};
-+use std::os::unix::fs::{symlink, PermissionsExt};
-+use std::os::unix::prelude::AsRawFd;
-+use std::time::{Duration, UNIX_EPOCH};
-+use std::path::Path;
-+
-+#[cfg(not(any(target_os = "netbsd")))]
-+use libc::{S_IFMT, S_IFLNK, mode_t};
-+
-+use nix::{fcntl, Error};
-+use nix::errno::{Errno};
-+use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
-+#[cfg(any(target_os = "linux",
-+          target_os = "haiku",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "freebsd",
-+          target_os = "netbsd"))]
-+use nix::sys::stat::lutimes;
-+use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags};
-+
-+#[cfg(not(any(target_os = "netbsd")))]
-+use nix::sys::stat::FileStat;
-+
-+use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
-+use nix::unistd::chdir;
-+
-+#[cfg(not(any(target_os = "netbsd")))]
-+use nix::Result;
-+use tempfile;
-+
-+#[allow(unused_comparisons)]
-+// uid and gid are signed on Windows, but not on other platforms. This function
-+// allows warning free compiles on all platforms, and can be removed when
-+// expression-level #[allow] is available.
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn valid_uid_gid(stat: FileStat) -> bool {
-+    // uid could be 0 for the `root` user. This quite possible when
-+    // the tests are being run on a rooted Android device.
-+    stat.st_uid >= 0 && stat.st_gid >= 0
-+}
-+
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn assert_stat_results(stat_result: Result<FileStat>) {
-+    let stats = stat_result.expect("stat call failed");
-+    assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
-+    assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
-+    assert!(stats.st_mode > 0);     // must be positive integer
-+    assert!(stats.st_nlink == 1);   // there links created, must be 1
-+    assert!(valid_uid_gid(stats));  // must be positive integers
-+    assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
-+    assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
-+    assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
-+}
-+
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn assert_lstat_results(stat_result: Result<FileStat>) {
-+    let stats = stat_result.expect("stat call failed");
-+    assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
-+    assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
-+    assert!(stats.st_mode > 0);     // must be positive integer
-+
-+    // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
-+    // (u16 on Android), and that will be a compile error.
-+    // On other platforms they are the same (either both are u16 or u32).
-+    assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
-+    assert!(stats.st_nlink == 1);   // there links created, must be 1
-+    assert!(valid_uid_gid(stats));  // must be positive integers
-+    assert!(stats.st_size > 0);    // size is > 0 because it points to another file
-+    assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
-+
-+    // st_blocks depends on whether the machine's file system uses fast
-+    // or slow symlinks, so just make sure it's not negative
-+    // (Android's st_blocks is ulonglong which is always non-negative.)
-+    assert!(stats.st_blocks >= 0);
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_stat_and_fstat() {
-+    use nix::sys::stat::fstat;
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = tempdir.path().join("foo.txt");
-+    let file = File::create(&filename).unwrap();
-+
-+    let stat_result = stat(&filename);
-+    assert_stat_results(stat_result);
-+
-+    let fstat_result = fstat(file.as_raw_fd());
-+    assert_stat_results(fstat_result);
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_fstatat() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = tempdir.path().join("foo.txt");
-+    File::create(&filename).unwrap();
-+    let dirfd = fcntl::open(tempdir.path(),
-+                            fcntl::OFlag::empty(),
-+                            stat::Mode::empty());
-+
-+    let result = stat::fstatat(dirfd.unwrap(),
-+                               &filename,
-+                               fcntl::AtFlags::empty());
-+    assert_stat_results(result);
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_stat_fstat_lstat() {
-+    use nix::sys::stat::{fstat, lstat};
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = tempdir.path().join("bar.txt");
-+    let linkname = tempdir.path().join("barlink");
-+
-+    File::create(&filename).unwrap();
-+    symlink("bar.txt", &linkname).unwrap();
-+    let link = File::open(&linkname).unwrap();
-+
-+    // should be the same result as calling stat,
-+    // since it's a regular file
-+    let stat_result = stat(&filename);
-+    assert_stat_results(stat_result);
-+
-+    let lstat_result = lstat(&linkname);
-+    assert_lstat_results(lstat_result);
-+
-+    let fstat_result = fstat(link.as_raw_fd());
-+    assert_stat_results(fstat_result);
-+}
-+
-+#[test]
-+fn test_fchmod() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = tempdir.path().join("foo.txt");
-+    let file = File::create(&filename).unwrap();
-+
-+    let mut mode1 = Mode::empty();
-+    mode1.insert(Mode::S_IRUSR);
-+    mode1.insert(Mode::S_IWUSR);
-+    fchmod(file.as_raw_fd(), mode1).unwrap();
-+
-+    let file_stat1 = stat(&filename).unwrap();
-+    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
-+
-+    let mut mode2 = Mode::empty();
-+    mode2.insert(Mode::S_IROTH);
-+    fchmod(file.as_raw_fd(), mode2).unwrap();
-+
-+    let file_stat2 = stat(&filename).unwrap();
-+    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
-+}
-+
-+#[test]
-+fn test_fchmodat() {
-+    let _dr = ::DirRestore::new();
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = "foo.txt";
-+    let fullpath = tempdir.path().join(filename);
-+    File::create(&fullpath).unwrap();
-+
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    let mut mode1 = Mode::empty();
-+    mode1.insert(Mode::S_IRUSR);
-+    mode1.insert(Mode::S_IWUSR);
-+    fchmodat(Some(dirfd), filename, mode1, FchmodatFlags::FollowSymlink).unwrap();
-+
-+    let file_stat1 = stat(&fullpath).unwrap();
-+    assert_eq!(file_stat1.st_mode & 0o7777, mode1.bits());
-+
-+    chdir(tempdir.path()).unwrap();
-+
-+    let mut mode2 = Mode::empty();
-+    mode2.insert(Mode::S_IROTH);
-+    fchmodat(None, filename, mode2, FchmodatFlags::FollowSymlink).unwrap();
-+
-+    let file_stat2 = stat(&fullpath).unwrap();
-+    assert_eq!(file_stat2.st_mode & 0o7777, mode2.bits());
-+}
-+
-+/// Asserts that the atime and mtime in a file's metadata match expected values.
-+///
-+/// The atime and mtime are expressed with a resolution of seconds because some file systems
-+/// (like macOS's HFS+) do not have higher granularity.
-+fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
-+    assert_eq!(
-+        Duration::new(exp_atime_sec, 0),
-+        attr.accessed().unwrap().duration_since(UNIX_EPOCH).unwrap());
-+    assert_eq!(
-+        Duration::new(exp_mtime_sec, 0),
-+        attr.modified().unwrap().duration_since(UNIX_EPOCH).unwrap());
-+}
-+
-+#[test]
-+fn test_utimes() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let fullpath = tempdir.path().join("file");
-+    drop(File::create(&fullpath).unwrap());
-+
-+    utimes(&fullpath, &TimeVal::seconds(9990), &TimeVal::seconds(5550)).unwrap();
-+    assert_times_eq(9990, 5550, &fs::metadata(&fullpath).unwrap());
-+}
-+
-+#[test]
-+#[cfg(any(target_os = "linux",
-+          target_os = "haiku",
-+          target_os = "ios",
-+          target_os = "macos",
-+          target_os = "freebsd",
-+          target_os = "netbsd"))]
-+fn test_lutimes() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let target = tempdir.path().join("target");
-+    let fullpath = tempdir.path().join("symlink");
-+    drop(File::create(&target).unwrap());
-+    symlink(&target, &fullpath).unwrap();
-+
-+    let exp_target_metadata = fs::symlink_metadata(&target).unwrap();
-+    lutimes(&fullpath, &TimeVal::seconds(4560), &TimeVal::seconds(1230)).unwrap();
-+    assert_times_eq(4560, 1230, &fs::symlink_metadata(&fullpath).unwrap());
-+
-+    let target_metadata = fs::symlink_metadata(&target).unwrap();
-+    assert_eq!(exp_target_metadata.accessed().unwrap(), target_metadata.accessed().unwrap(),
-+               "atime of symlink target was unexpectedly modified");
-+    assert_eq!(exp_target_metadata.modified().unwrap(), target_metadata.modified().unwrap(),
-+               "mtime of symlink target was unexpectedly modified");
-+}
-+
-+#[test]
-+fn test_futimens() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let fullpath = tempdir.path().join("file");
-+    drop(File::create(&fullpath).unwrap());
-+
-+    let fd = fcntl::open(&fullpath, fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    futimens(fd, &TimeSpec::seconds(10), &TimeSpec::seconds(20)).unwrap();
-+    assert_times_eq(10, 20, &fs::metadata(&fullpath).unwrap());
-+}
-+
-+#[test]
-+fn test_utimensat() {
-+    let _dr = ::DirRestore::new();
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = "foo.txt";
-+    let fullpath = tempdir.path().join(filename);
-+    drop(File::create(&fullpath).unwrap());
-+
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    utimensat(Some(dirfd), filename, &TimeSpec::seconds(12345), &TimeSpec::seconds(678),
-+              UtimensatFlags::FollowSymlink).unwrap();
-+    assert_times_eq(12345, 678, &fs::metadata(&fullpath).unwrap());
-+
-+    chdir(tempdir.path()).unwrap();
-+
-+    utimensat(None, filename, &TimeSpec::seconds(500), &TimeSpec::seconds(800),
-+              UtimensatFlags::FollowSymlink).unwrap();
-+    assert_times_eq(500, 800, &fs::metadata(&fullpath).unwrap());
-+}
-+
-+#[test]
-+fn test_mkdirat_success_path() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = "example_subdir";
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+    assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
-+    assert!(Path::exists(&tempdir.path().join(filename)));
-+}
-+
-+#[test]
-+fn test_mkdirat_success_mode() {
-+    let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = "example_subdir";
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+    assert!((mkdirat(dirfd, filename, Mode::S_IRWXU)).is_ok());
-+    let permissions = fs::metadata(tempdir.path().join(filename)).unwrap().permissions();
-+    let mode = permissions.mode();
-+    assert_eq!(mode as mode_t, expected_bits)
-+}
-+
-+#[test]
-+fn test_mkdirat_fail() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let not_dir_filename= "example_not_dir";
-+    let filename = "example_subdir_dir";
-+    let dirfd = fcntl::open(&tempdir.path().join(not_dir_filename), fcntl::OFlag::O_CREAT,
-+                            stat::Mode::empty()).unwrap();
-+    let result = mkdirat(dirfd, filename, Mode::S_IRWXU).unwrap_err();
-+    assert_eq!(result, Error::Sys(Errno::ENOTDIR));
-+}
-diff --git a/third_party/rust/nix-0.15.0/test/test_unistd.rs b/third_party/rust/nix-0.15.0/test/test_unistd.rs
-new file mode 100644
-index 0000000000000..46196dec7ccce
---- /dev/null
-+++ b/third_party/rust/nix-0.15.0/test/test_unistd.rs
-@@ -0,0 +1,669 @@
-+use nix::fcntl::{self, fcntl, FcntlArg, FdFlag, open, OFlag, readlink};
-+use nix::unistd::*;
-+use nix::unistd::ForkResult::*;
-+use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
-+use nix::sys::wait::*;
-+use nix::sys::stat::{self, Mode, SFlag};
-+use nix::errno::Errno;
-+use nix::Error;
-+use std::{env, iter};
-+use std::ffi::CString;
-+use std::fs::{self, DirBuilder, File};
-+use std::io::Write;
-+use std::os::unix::prelude::*;
-+use tempfile::{self, tempfile};
-+use libc::{self, _exit, off_t};
-+
-+#[test]
-+#[cfg(not(any(target_os = "netbsd")))]
-+fn test_fork_and_waitpid() {
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Safe: Child only calls `_exit`, which is signal-safe
-+    match fork().expect("Error: Fork Failed") {
-+        Child => unsafe { _exit(0) },
-+        Parent { child } => {
-+            // assert that child was created and pid > 0
-+            let child_raw: ::libc::pid_t = child.into();
-+            assert!(child_raw > 0);
-+            let wait_status = waitpid(child, None);
-+            match wait_status {
-+                // assert that waitpid returned correct status and the pid is the one of the child
-+                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),
-+
-+                // panic, must never happen
-+                s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
-+
-+                // panic, waitpid should never fail
-+                Err(s) => panic!("Error: waitpid returned Err({:?}", s)
-+            }
-+
-+        },
-+    }
-+}
-+
-+#[test]
-+fn test_wait() {
-+    // Grab FORK_MTX so wait doesn't reap a different test's child process
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Safe: Child only calls `_exit`, which is signal-safe
-+    match fork().expect("Error: Fork Failed") {
-+        Child => unsafe { _exit(0) },
-+        Parent { child } => {
-+            let wait_status = wait();
-+
-+            // just assert that (any) one child returns with WaitStatus::Exited
-+            assert_eq!(wait_status, Ok(WaitStatus::Exited(child, 0)));
-+        },
-+    }
-+}
-+
-+#[test]
-+fn test_mkstemp() {
-+    let mut path = env::temp_dir();
-+    path.push("nix_tempfile.XXXXXX");
-+
-+    let result = mkstemp(&path);
-+    match result {
-+        Ok((fd, path)) => {
-+            close(fd).unwrap();
-+            unlink(path.as_path()).unwrap();
-+        },
-+        Err(e) => panic!("mkstemp failed: {}", e)
-+    }
-+}
-+
-+#[test]
-+fn test_mkstemp_directory() {
-+    // mkstemp should fail if a directory is given
-+    assert!(mkstemp(&env::temp_dir()).is_err());
-+}
-+
-+#[test]
-+fn test_mkfifo() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let mkfifo_fifo = tempdir.path().join("mkfifo_fifo");
-+
-+    mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
-+
-+    let stats = stat::stat(&mkfifo_fifo).unwrap();
-+    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
-+    assert!(typ == SFlag::S_IFIFO);
-+}
-+
-+#[test]
-+fn test_mkfifo_directory() {
-+    // mkfifo should fail if a directory is given
-+    assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err());
-+}
-+
-+#[test]
-+fn test_getpid() {
-+    let pid: ::libc::pid_t = getpid().into();
-+    let ppid: ::libc::pid_t = getppid().into();
-+    assert!(pid > 0);
-+    assert!(ppid > 0);
-+}
-+
-+#[test]
-+fn test_getsid() {
-+    let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
-+    let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
-+    assert!(none_sid > 0);
-+    assert!(none_sid == pid_sid);
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+mod linux_android {
-+    use nix::unistd::gettid;
-+
-+    #[test]
-+    fn test_gettid() {
-+        let tid: ::libc::pid_t = gettid().into();
-+        assert!(tid > 0);
-+    }
-+}
-+
-+#[test]
-+// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+fn test_setgroups() {
-+    // Skip this test when not run as root as `setgroups()` requires root.
-+    skip_if_not_root!("test_setgroups");
-+
-+    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Save the existing groups
-+    let old_groups = getgroups().unwrap();
-+
-+    // Set some new made up groups
-+    let groups = [Gid::from_raw(123), Gid::from_raw(456)];
-+    setgroups(&groups).unwrap();
-+
-+    let new_groups = getgroups().unwrap();
-+    assert_eq!(new_groups, groups);
-+
-+    // Revert back to the old groups
-+    setgroups(&old_groups).unwrap();
-+}
-+
-+#[test]
-+// `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
-+#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+fn test_initgroups() {
-+    // Skip this test when not run as root as `initgroups()` and `setgroups()`
-+    // require root.
-+    skip_if_not_root!("test_initgroups");
-+
-+    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    // Save the existing groups
-+    let old_groups = getgroups().unwrap();
-+
-+    // It doesn't matter if the root user is not called "root" or if a user
-+    // called "root" doesn't exist. We are just checking that the extra,
-+    // made-up group, `123`, is set.
-+    // FIXME: Test the other half of initgroups' functionality: whether the
-+    // groups that the user belongs to are also set.
-+    let user = CString::new("root").unwrap();
-+    let group = Gid::from_raw(123);
-+    let group_list = getgrouplist(&user, group).unwrap();
-+    assert!(group_list.contains(&group));
-+
-+    initgroups(&user, group).unwrap();
-+
-+    let new_groups = getgroups().unwrap();
-+    assert_eq!(new_groups, group_list);
-+
-+    // Revert back to the old groups
-+    setgroups(&old_groups).unwrap();
-+}
-+
-+macro_rules! execve_test_factory(
-+    ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
-+    #[test]
-+    fn $test_name() {
-+        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+        // The `exec`d process will write to `writer`, and we'll read that
-+        // data from `reader`.
-+        let (reader, writer) = pipe().unwrap();
-+
-+        // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
-+        // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
-+        //       The tests make sure not to do that, though.
-+        match fork().unwrap() {
-+            Child => {
-+                // Close stdout.
-+                close(1).unwrap();
-+                // Make `writer` be the stdout of the new process.
-+                dup(writer).unwrap();
-+                // exec!
-+                $syscall(
-+                    $exe,
-+                    $(&CString::new($pathname).unwrap(), )*
-+                    &[CString::new(b"".as_ref()).unwrap(),
-+                      CString::new(b"-c".as_ref()).unwrap(),
-+                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
-+                                   .as_ref()).unwrap()],
-+                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
-+                      CString::new(b"baz=quux".as_ref()).unwrap()]
-+                    $(, $flags)*).unwrap();
-+            },
-+            Parent { child } => {
-+                // Wait for the child to exit.
-+                waitpid(child, None).unwrap();
-+                // Read 1024 bytes.
-+                let mut buf = [0u8; 1024];
-+                read(reader, &mut buf).unwrap();
-+                // It should contain the things we printed using `/bin/sh`.
-+                let string = String::from_utf8_lossy(&buf);
-+                assert!(string.contains("nix!!!"));
-+                assert!(string.contains("foo=bar"));
-+                assert!(string.contains("baz=quux"));
-+            }
-+        }
-+    }
-+    )
-+);
-+
-+cfg_if!{
-+    if #[cfg(target_os = "android")] {
-+        execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
-+        execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
-+    } else if #[cfg(any(target_os = "freebsd",
-+                        target_os = "linux"))] {
-+        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
-+        execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
-+    } else if #[cfg(any(target_os = "dragonfly",
-+                        target_os = "ios",
-+                        target_os = "macos",
-+                        target_os = "netbsd",
-+                        target_os = "openbsd"))] {
-+        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
-+        // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
-+        //
-+        // Note for NetBSD and OpenBSD: although rust-lang/libc includes it
-+        // (under unix/bsd/netbsdlike/) fexecve is not currently implemented on
-+        // NetBSD nor on OpenBSD.
-+    }
-+}
-+
-+#[cfg(any(target_os = "haiku", target_os = "linux", target_os = "openbsd"))]
-+execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
-+
-+cfg_if!{
-+    if #[cfg(target_os = "android")] {
-+        use nix::fcntl::AtFlags;
-+        execve_test_factory!(test_execveat_empty, execveat, File::open("/system/bin/sh").unwrap().into_raw_fd(),
-+                             "", AtFlags::AT_EMPTY_PATH);
-+        execve_test_factory!(test_execveat_relative, execveat, File::open("/system/bin/").unwrap().into_raw_fd(),
-+                             "./sh", AtFlags::empty());
-+        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
-+                             "/system/bin/sh", AtFlags::empty());
-+    } else if #[cfg(all(target_os = "linux"), any(target_arch ="x86_64", target_arch ="x86"))] {
-+        use nix::fcntl::AtFlags;
-+        execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
-+                             "", AtFlags::AT_EMPTY_PATH);
-+        execve_test_factory!(test_execveat_relative, execveat, File::open("/bin/").unwrap().into_raw_fd(),
-+                             "./sh", AtFlags::empty());
-+        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
-+                             "/bin/sh", AtFlags::empty());
-+    }
-+}
-+
-+#[test]
-+fn test_fchdir() {
-+    // fchdir changes the process's cwd
-+    let _dr = ::DirRestore::new();
-+
-+    let tmpdir = tempfile::tempdir().unwrap();
-+    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
-+    let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
-+
-+    assert!(fchdir(tmpdir_fd).is_ok());
-+    assert_eq!(getcwd().unwrap(), tmpdir_path);
-+
-+    assert!(close(tmpdir_fd).is_ok());
-+}
-+
-+#[test]
-+fn test_getcwd() {
-+    // chdir changes the process's cwd
-+    let _dr = ::DirRestore::new();
-+
-+    let tmpdir = tempfile::tempdir().unwrap();
-+    let tmpdir_path = tmpdir.path().canonicalize().unwrap();
-+    assert!(chdir(&tmpdir_path).is_ok());
-+    assert_eq!(getcwd().unwrap(), tmpdir_path);
-+
-+    // make path 500 chars longer so that buffer doubling in getcwd
-+    // kicks in.  Note: One path cannot be longer than 255 bytes
-+    // (NAME_MAX) whole path cannot be longer than PATH_MAX (usually
-+    // 4096 on linux, 1024 on macos)
-+    let mut inner_tmp_dir = tmpdir_path.to_path_buf();
-+    for _ in 0..5 {
-+        let newdir = iter::repeat("a").take(100).collect::<String>();
-+        inner_tmp_dir.push(newdir);
-+        assert!(mkdir(inner_tmp_dir.as_path(), Mode::S_IRWXU).is_ok());
-+    }
-+    assert!(chdir(inner_tmp_dir.as_path()).is_ok());
-+    assert_eq!(getcwd().unwrap(), inner_tmp_dir.as_path());
-+}
-+
-+#[test]
-+fn test_chown() {
-+    // Testing for anything other than our own UID/GID is hard.
-+    let uid = Some(getuid());
-+    let gid = Some(getgid());
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let path = tempdir.path().join("file");
-+    {
-+        File::create(&path).unwrap();
-+    }
-+
-+    chown(&path, uid, gid).unwrap();
-+    chown(&path, uid, None).unwrap();
-+    chown(&path, None, gid).unwrap();
-+
-+    fs::remove_file(&path).unwrap();
-+    chown(&path, uid, gid).unwrap_err();
-+}
-+
-+#[test]
-+fn test_fchownat() {
-+    let _dr = ::DirRestore::new();
-+    // Testing for anything other than our own UID/GID is hard.
-+    let uid = Some(getuid());
-+    let gid = Some(getgid());
-+
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let path = tempdir.path().join("file");
-+    {
-+        File::create(&path).unwrap();
-+    }
-+
-+    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+
-+    fchownat(Some(dirfd), "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
-+
-+    chdir(tempdir.path()).unwrap();
-+    fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap();
-+
-+    fs::remove_file(&path).unwrap();
-+    fchownat(None, "file", uid, gid, FchownatFlags::FollowSymlink).unwrap_err();
-+}
-+
-+#[test]
-+fn test_lseek() {
-+    const CONTENTS: &[u8] = b"abcdef123456";
-+    let mut tmp = tempfile().unwrap();
-+    tmp.write_all(CONTENTS).unwrap();
-+    let tmpfd = tmp.into_raw_fd();
-+
-+    let offset: off_t = 5;
-+    lseek(tmpfd, offset, Whence::SeekSet).unwrap();
-+
-+    let mut buf = [0u8; 7];
-+    ::read_exact(tmpfd, &mut buf);
-+    assert_eq!(b"f123456", &buf);
-+
-+    close(tmpfd).unwrap();
-+}
-+
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+#[test]
-+fn test_lseek64() {
-+    const CONTENTS: &[u8] = b"abcdef123456";
-+    let mut tmp = tempfile().unwrap();
-+    tmp.write_all(CONTENTS).unwrap();
-+    let tmpfd = tmp.into_raw_fd();
-+
-+    lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
-+
-+    let mut buf = [0u8; 7];
-+    ::read_exact(tmpfd, &mut buf);
-+    assert_eq!(b"f123456", &buf);
-+
-+    close(tmpfd).unwrap();
-+}
-+
-+cfg_if!{
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        macro_rules! require_acct{
-+            () => {
-+                require_capability!(CAP_SYS_PACCT);
-+            }
-+        }
-+    } else if #[cfg(target_os = "freebsd")] {
-+        macro_rules! require_acct{
-+            () => {
-+                skip_if_not_root!("test_acct");
-+                skip_if_jailed!("test_acct");
-+            }
-+        }
-+    } else {
-+        macro_rules! require_acct{
-+            () => {
-+                skip_if_not_root!("test_acct");
-+            }
-+        }
-+    }
-+}
-+
-+#[test]
-+fn test_acct() {
-+    use tempfile::NamedTempFile;
-+    use std::process::Command;
-+    use std::{thread, time};
-+
-+    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    require_acct!();
-+
-+    let file = NamedTempFile::new().unwrap();
-+    let path = file.path().to_str().unwrap();
-+
-+    acct::enable(path).unwrap();
-+
-+    loop {
-+        Command::new("echo").arg("Hello world");
-+        let len = fs::metadata(path).unwrap().len();
-+        if len > 0 { break; }
-+        thread::sleep(time::Duration::from_millis(10));
-+    }
-+    acct::disable().unwrap();
-+}
-+
-+#[test]
-+fn test_fpathconf_limited() {
-+    let f = tempfile().unwrap();
-+    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
-+    let path_max = fpathconf(f.as_raw_fd(), PathconfVar::PATH_MAX);
-+    assert!(path_max.expect("fpathconf failed").expect("PATH_MAX is unlimited") > 0);
-+}
-+
-+#[test]
-+fn test_pathconf_limited() {
-+    // AFAIK, PATH_MAX is limited on all platforms, so it makes a good test
-+    let path_max = pathconf("/", PathconfVar::PATH_MAX);
-+    assert!(path_max.expect("pathconf failed").expect("PATH_MAX is unlimited") > 0);
-+}
-+
-+#[test]
-+fn test_sysconf_limited() {
-+    // AFAIK, OPEN_MAX is limited on all platforms, so it makes a good test
-+    let open_max = sysconf(SysconfVar::OPEN_MAX);
-+    assert!(open_max.expect("sysconf failed").expect("OPEN_MAX is unlimited") > 0);
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+#[test]
-+fn test_sysconf_unsupported() {
-+    // I know of no sysconf variables that are unsupported everywhere, but
-+    // _XOPEN_CRYPT is unsupported on FreeBSD 11.0, which is one of the platforms
-+    // we test.
-+    let open_max = sysconf(SysconfVar::_XOPEN_CRYPT);
-+    assert!(open_max.expect("sysconf failed").is_none())
-+}
-+
-+// Test that we can create a pair of pipes.  No need to verify that they pass
-+// data; that's the domain of the OS, not nix.
-+#[test]
-+fn test_pipe() {
-+    let (fd0, fd1) = pipe().unwrap();
-+    let m0 = stat::SFlag::from_bits_truncate(stat::fstat(fd0).unwrap().st_mode);
-+    // S_IFIFO means it's a pipe
-+    assert_eq!(m0, SFlag::S_IFIFO);
-+    let m1 = stat::SFlag::from_bits_truncate(stat::fstat(fd1).unwrap().st_mode);
-+    assert_eq!(m1, SFlag::S_IFIFO);
-+}
-+
-+// pipe2(2) is the same as pipe(2), except it allows setting some flags.  Check
-+// that we can set a flag.
-+#[test]
-+fn test_pipe2() {
-+    let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
-+    let f0 = FdFlag::from_bits_truncate(fcntl(fd0, FcntlArg::F_GETFD).unwrap());
-+    assert!(f0.contains(FdFlag::FD_CLOEXEC));
-+    let f1 = FdFlag::from_bits_truncate(fcntl(fd1, FcntlArg::F_GETFD).unwrap());
-+    assert!(f1.contains(FdFlag::FD_CLOEXEC));
-+}
-+
-+#[test]
-+fn test_truncate() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let path = tempdir.path().join("file");
-+
-+    {
-+        let mut tmp = File::create(&path).unwrap();
-+        const CONTENTS: &[u8] = b"12345678";
-+        tmp.write_all(CONTENTS).unwrap();
-+    }
-+
-+    truncate(&path, 4).unwrap();
-+
-+    let metadata = fs::metadata(&path).unwrap();
-+    assert_eq!(4, metadata.len());
-+}
-+
-+#[test]
-+fn test_ftruncate() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let path = tempdir.path().join("file");
-+
-+    let tmpfd = {
-+        let mut tmp = File::create(&path).unwrap();
-+        const CONTENTS: &[u8] = b"12345678";
-+        tmp.write_all(CONTENTS).unwrap();
-+        tmp.into_raw_fd()
-+    };
-+
-+    ftruncate(tmpfd, 2).unwrap();
-+    close(tmpfd).unwrap();
-+
-+    let metadata = fs::metadata(&path).unwrap();
-+    assert_eq!(2, metadata.len());
-+}
-+
-+// Used in `test_alarm`.
-+static mut ALARM_CALLED: bool = false;
-+
-+// Used in `test_alarm`.
-+pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
-+    assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
-+    unsafe { ALARM_CALLED = true };
-+}
-+
-+#[test]
-+fn test_alarm() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    let handler = SigHandler::Handler(alarm_signal_handler);
-+    let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
-+    let old_handler = unsafe {
-+        sigaction(Signal::SIGALRM, &signal_action)
-+            .expect("unable to set signal handler for alarm")
-+    };
-+
-+    // Set an alarm.
-+    assert_eq!(alarm::set(60), None);
-+
-+    // Overwriting an alarm should return the old alarm.
-+    assert_eq!(alarm::set(1), Some(60));
-+
-+    // We should be woken up after 1 second by the alarm, so we'll sleep for 2
-+    // seconds to be sure.
-+    sleep(2);
-+    assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");
-+
-+    // Reset the signal.
-+    unsafe {
-+        sigaction(Signal::SIGALRM, &old_handler)
-+            .expect("unable to set signal handler for alarm");
-+    }
-+}
-+
-+#[test]
-+fn test_canceling_alarm() {
-+    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    assert_eq!(alarm::cancel(), None);
-+
-+    assert_eq!(alarm::set(60), None);
-+    assert_eq!(alarm::cancel(), Some(60));
-+}
-+
-+#[test]
-+fn test_symlinkat() {
-+    let mut buf = [0; 1024];
-+    let tempdir = tempfile::tempdir().unwrap();
-+
-+    let target = tempdir.path().join("a");
-+    let linkpath = tempdir.path().join("b");
-+    symlinkat(&target, None, &linkpath).unwrap();
-+    assert_eq!(
-+        readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
-+        target.to_str().unwrap()
-+    );
-+
-+    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+    let target = "c";
-+    let linkpath = "d";
-+    symlinkat(target, Some(dirfd), linkpath).unwrap();
-+    assert_eq!(
-+        readlink(&tempdir.path().join(linkpath), &mut buf)
-+            .unwrap()
-+            .to_str()
-+            .unwrap(),
-+        target
-+    );
-+}
-+
-+
-+#[test]
-+fn test_unlinkat_dir_noremovedir() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let dirname = "foo_dir";
-+    let dirpath = tempdir.path().join(dirname);
-+
-+    // Create dir
-+    DirBuilder::new().recursive(true).create(&dirpath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt unlink dir at relative path without proper flag
-+    let err_result = unlinkat(Some(dirfd), dirname, UnlinkatFlags::NoRemoveDir).unwrap_err();
-+    assert!(err_result == Error::Sys(Errno::EISDIR) || err_result == Error::Sys(Errno::EPERM));
-+ }
-+
-+#[test]
-+fn test_unlinkat_dir_removedir() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let dirname = "foo_dir";
-+    let dirpath = tempdir.path().join(dirname);
-+
-+    // Create dir
-+    DirBuilder::new().recursive(true).create(&dirpath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt unlink dir at relative path with proper flag
-+    unlinkat(Some(dirfd), dirname, UnlinkatFlags::RemoveDir).unwrap();
-+    assert!(!dirpath.exists());
-+ }
-+
-+#[test]
-+fn test_unlinkat_file() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let filename = "foo.txt";
-+    let filepath = tempdir.path().join(filename);
-+
-+    // Create file
-+    File::create(&filepath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt unlink file at relative path
-+    unlinkat(Some(dirfd), filename, UnlinkatFlags::NoRemoveDir).unwrap();
-+    assert!(!filepath.exists());
-+ }
-+
-+#[test]
-+fn test_access_not_existing() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let dir = tempdir.path().join("does_not_exist.txt");
-+    assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
-+               Errno::ENOENT);
-+}
-+
-+#[test]
-+fn test_access_file_exists() {
-+    let tempdir = tempfile::tempdir().unwrap();
-+    let path  = tempdir.path().join("does_exist.txt");
-+    let _file = File::create(path.clone()).unwrap();
-+    assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
-+}
-diff --git a/third_party/rust/nix/.cargo-checksum.json b/third_party/rust/nix/.cargo-checksum.json
-index e5f2bc789185a..85adbc1eae931 100644
---- a/third_party/rust/nix/.cargo-checksum.json
-+++ b/third_party/rust/nix/.cargo-checksum.json
-@@ -1 +1 @@
--{"files":{"CHANGELOG.md":"91af9fd5f2d9cdb9c8bb750e24b625742e95a6c74bcff419f3de70eb26578281","CONTRIBUTING.md":"a9101e3d1487170d691d5f062ff49a433c167582ac8984dd41a744be92652f74","CONVENTIONS.md":"e150ce43c1d188c392c1a3bf7f2e08e3cf84906705c7bef43f319037d29ea385","Cargo.toml":"af0cc0ae7ff4bf6c2e5b35fe062f54fe2d619f70ba67795f4f43a981420b5de0","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"80d71b9eaac7bf7f0d307372592ed1467f994291e6fad816a44f3c70e2887d0f","build.rs":"14c9c678c33f5894509da47f77d6a326b14aecb4190ce87a24cce98687ca63b2","src/dir.rs":"21e330cbe6594274335b94d9e9b6059f1fa8e53d2e5b5c697058c52ec6b3c5ff","src/errno.rs":"a009ccf18b45c0a4c9319c65b0dc5bc322d9ad43cfe462ec4661559f44162451","src/errno_dragonfly.c":"a857e47b114acb85fddcb252a610ab5734d225c26b7bedd7c35d7789d46c8526","src/fcntl.rs":"6ae2f7f01dd2568b82a4e57f86e02b1d63eec6c26111c5adb2ca5d78a2a99fe7","src/features.rs":"22ff626ff8287a07dd55bcfc63c9f518c19c56144e15f9b6f9e3bbdcda51c2a8","
 src/ifaddrs.rs":"9a93de176edcca4613e668b8ccc2c3e3b6b711aa2d8d94ccb0ba08694d1ef35f","src/kmod.rs":"4d8a695d3d761f351a39d654303a1bd168e74295b7d142b918737e355b24f34d","src/lib.rs":"fdd8049a79ffb92384c72f0a6b0bab717001ddfa9b01f2b33413c83f424f2ac8","src/macros.rs":"aec27fa0fd98900913fada926c9a4581cd28f2640e3a7b5480707f923c9200f8","src/mount.rs":"cdf5db8409017483132db9d7493b5d6cc96df5560d0fa5ad8f385aff72db10ca","src/mqueue.rs":"82af42b31381af73e7966f845d1ed93957f0b9976bf2da524b178fad15b2b08d","src/net/if_.rs":"f7e02076fcf3cadf3fdf141884c9bd2c468a7047ba60bc490f0057df802b53ce","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"7305e250066cd1a7318cd239ed3db787937ee98426fe9289cf00fa874d76b6c7","src/pty.rs":"6b965b586579933af47d4efef4c82c391b927037eaa08d8c83fc974ef17fc7c8","src/sched.rs":"f9b214fa60006b5450ffb3589a55ec59c3694bd49597c65c38ac813fcd96c7dd","src/sys/aio.rs":"a1ba629258b3ce1268e5fe8e5b41dce3581f77d415dc5e2455c1f82f26dd3085","src/sys/e
 poll.rs":"f0b539e0645569657f2142db91a38c94ebe1925f44852d64c61c818758dbbf0b","src/sys/event.rs":"ef8bc02a08d9ce7924c87f8f891fa051587b195a36913712fe85237a2fe0685b","src/sys/eventfd.rs":"08008cf3dc64c2216847c02c0dd8d7189cf08edbaafe35ba2c57c053fde09ef4","src/sys/inotify.rs":"687c8417d737939aa93f805d6003afc4f84f50828b1bd9429ef5d00bef0e0955","src/sys/ioctl/bsd.rs":"56ca6ecf5f7cfb566f4f3ba589fcc778f747a517dd45e13780981922e6215344","src/sys/ioctl/linux.rs":"6cfbdff4dbfa1a3782acdedebe89ffa9f000fdfc4ab68cb46f52890ebc1c6f2d","src/sys/ioctl/mod.rs":"20bc3cf1fcbbc7c31e4d507baa4e576a793ea42fb33618d2e7afeda730c4324f","src/sys/memfd.rs":"11cd93c867fdbdbc9588cecb94268691de42b2ef2a38fe33525be7c7f60c85d5","src/sys/mman.rs":"f77d28611a7ff3bf62784a3c4f26d7d79969395b1d9bbc6ff15e734f52dc404f","src/sys/mod.rs":"f39a08c72e37638c7cecfb9c087e0a41e2b69409aa545b0ef7bbd59c0a063ee2","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"8a7eacfc172b55763ae
 32109bf9b252669ba68b72cd5122f7504eb35c0c08345","src/sys/ptrace/linux.rs":"f09b45148004f4b28d8503c397a8d112d31046c98e68335bf4e89425d5b33f07","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"7eb8e797466b506f6ed882f18eda92c4639cf43d9384a19bc39cd1bf982989c9","src/sys/reboot.rs":"fde9da27c2928f7026231430fa14fec2058df4e49a0aeda2a237a60524f11241","src/sys/select.rs":"57d6c4403d1bf788bd52ab6f03cfc16a189d31b6bfb338b135cb775fe369121f","src/sys/sendfile.rs":"ea386e83baf9b5b23488aca26635aacdc92f2bfe238e4399a7380bd0331e0ef7","src/sys/signal.rs":"9216cdd609b4dfb9c2e559c411be6b7c722f7ddd8024682c0895a32126b488aa","src/sys/signalfd.rs":"bfcfce619bf199e50f9cc80a3eb778d48474a015cfdafc64a0c3517373a225a9","src/sys/socket/addr.rs":"8b297ce13cd8ad200b3e764888c26ceb582ee505385d1e172440de94ade99644","src/sys/socket/mod.rs":"e0353f04f3d098a8bf5e2aae431645897b96e0889fb76537dc0330159c6f233d","src/sys/socket/sockopt.rs":"c663505d6a7a7ae9d76e03fbc17e5
 3d308ea6b1eae92212812e1d76b2bf2916f","src/sys/stat.rs":"c4807048f86be67026756737cf81f448ec23c2a4745776cb40f40b533a88e0c8","src/sys/statfs.rs":"d2b72069f20aa7782ce5de4ec2d00c76a82a92376c2066bbb270cdac2167719e","src/sys/statvfs.rs":"2d328cf525ba04ab1e1351128624a7df7d0c55ea91fda6c8d620d13710d61606","src/sys/sysinfo.rs":"0c05244655aa9e6dff5138392c5c1ae97630d35bae0e5510d7f51a75c31fd425","src/sys/termios.rs":"a2e99afdfc3526641a2cb82b57bfd0a25a362fb9be5ad37ff9f11acaeb0b9439","src/sys/time.rs":"8a1224b9262026086af698630aedbed21b45d661fbd045fc6c6af41a16a23374","src/sys/uio.rs":"60a974275ff8c485ea183bdd6f7e25894e6f2360a5bfb25442391a825a3b9b8c","src/sys/utsname.rs":"c977a1aec6e051c72b27506395e942abab9cbd9523e6d345ea66dc10875ee87d","src/sys/wait.rs":"30b14a8f518d031805cae6c6ff644116f162d8c8a75fddcfce4479d8d55fd1c0","src/ucontext.rs":"075560ec08a362881534211f8c6b78844886d6b767c2f7067174600e38ed3f63","src/unistd.rs":"82308ec31b6293b55f86fafd04e976a41127fedebb8f158abd1399c7399af947","test/sys/mod.
 rs":"e0821cbc289ad952f17229609c7de4282cca1e44cd13e1a7494a6378ecbc12f8","test/sys/test_aio.rs":"b2544bfb321ca7fbed276ee637c769fb438156d14666cdc1e1d547b3514a44e3","test/sys/test_aio_drop.rs":"30dd1d238269d00381fa50f6d3cb2b13794b7cceb9f6455f3878fcbffa9aa62d","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"eea690ed386da0a666df5eb23a417421fddb99dc8e39556f63b30969bb6cf779","test/sys/test_lio_listio_resubmit.rs":"203a583313542593148f375b087ae30620222a745680173fa98fc448d1e5ae7f","test/sys/test_pthread.rs":"3890e5ecbf2082e0d05d102cc9cec6e76ede3c15f250d104e3483b1c1c3400b1","test/sys/test_ptrace.rs":"4e8d5dff5fe6bc56e4ae53bdfd10f5e8ea567d8099576d1c690cf7a6b2bc955f","test/sys/test_select.rs":"bdb20211fc6ec1e3f186337eac51e08757acb6901d307d67c71bf9011f0d54bd","test/sys/test_signal.rs":"84ae63c2baa49eebeabe5bbd347b9c5417e14ba97f342719d7
 53dc1c1c768d60","test/sys/test_signalfd.rs":"71b5d6d782283f6db64ca90f7fb06617faec71091d59d2587e41bbc9d8c43d5c","test/sys/test_socket.rs":"09a7ef0322e07b4579893e0307a7c4f81fbbc653d005b827a519c33a33e185ce","test/sys/test_sockopt.rs":"b3d386c8279f86bf9439c772317bafcdba5630fa806c8319e87ddac0ccfa3a03","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"fa4be3ade859b527bf33408f85a6f57b127917cf5f2afb662d09f6019d07913a","test/sys/test_uio.rs":"9da234e3bd5003fd200cc37c4a5be147ecda1a7670feb1d505f23d646d3e1c57","test/sys/test_wait.rs":"e6c5147e213daa93892cd828f53214995d2e019ff2372cc48d85ce9b93d26ec9","test/test.rs":"e6307f82a39426a949b8e925a2df4a62e31c0e43081d7a33d23759bdfeeece1f","test/test_dir.rs":"5d137a62f11d1a4993b4bb35dccc38a4c4416b7da374887f2335a9895b4fdee4","test/test_fcntl.rs":"730e64e99dc867ba5af7cc4ca83a4489c8b96b1a52f8937bcc666d673af27002","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c903
 33ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"f4754f028402a8ba788c87686288424cd3784e77c7eb5d96682ef491b1dd5262","test/test_mount.rs":"78ddc657f5098360c764fffa3a7d844503e4b6b65b44bfd42d9aa9045b415cb6","test/test_mq.rs":"5806f8825e91edc79dd0e2bc81d8be3ba094c2de6c0b2ac0268221ae2ad22701","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"46c71ee988fe1b85561ea0530d099750be8c1b8f95ab6e845c8a9f46f16f060c","test/test_pty.rs":"be04f99904fa47b60400c2bd156a388b73df4b9aec2eebf13df7dcdfc9aacf45","test/test_ptymaster_drop.rs":"5cfbbb79551c205ab510c2d4ef497bf937ceac9151fbe2f2e543d6515e406990","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"1dc420d3119bf4d863a7ae0ba63efa7f1416f6e46e4
 100ea161003fe1c3f66ba","test/test_unistd.rs":"0325c998acca1e826e9e2b3d351d55ab9723a6cb2ca2072245978e7f5a9acee8"},"package":"3b2e0b4f3320ed72aaedb9a5ac838690a8047c7b275da22711fddff4f8a14229"}
-\ No newline at end of file
-+{"files":{"CHANGELOG.md":"9294216482039acf0dd5911548feaaf04d410298fc5cd3df450d8d36c914756e","CONTRIBUTING.md":"7da4f8c2ff8e06850bdd9ebc0a3552419fd21d2c6bb0c6f0719566e263b0a1b9","CONVENTIONS.md":"df0d4fe9fe65af0bfa4723dc7b641d5130087259799e6b404ad63884f79031cb","Cargo.toml":"03e8c7ae8afb88e9d698712e2428d19a367c19079e994a170cb16dca985cc48d","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"d7a8568ffb72d76acc2812d8f545ad71b24a7c1301d2a258f49057fcaded0b9f","src/dir.rs":"52170e8bfc8c4bc1996db2f5cd5a2aace71beac59e4a0e7c1817fdecbf8bd6a7","src/env.rs":"bc52e80d3fa6c5388e3e23767d214a72f88d2927c5604246016c4cf978bbbeb7","src/errno.rs":"1aab33e5dcab9c6f83e48e452f361840645ce6a434bc13bd8ab9abb0e0ef25c3","src/fcntl.rs":"7f3f95baad70ceb1231b8a647988a8e54292d84176820eb6a9f89d40f309c3a6","src/features.rs":"2cb080da3f26eca2d2e18282a41afec921426423a6354a50b840cf20f3f153f6","src/ifaddrs.rs":"4f19ed3b15f5059c2859958c6aa313d6fa75703e68f8608359ef8e0089508ed3","src/k
 mod.rs":"873bec7f32e30a552a4fd86d5f884c2b3a0cd73012121dfe1587b508475beb0a","src/lib.rs":"ae1a16e142c47afc3f52a07a2afb2fc013cfd427df955aa42e4bd372c77c49d5","src/macros.rs":"7c6c81441c967d73a75a975bb660ae48efde22c6f5ae2705c62a8db446ce0d39","src/mount.rs":"cde7c59b79a8e535c4d8c57c53d7825384b110be244803b1f895d5a3b97bc72f","src/mqueue.rs":"3520495f6a881a7239fba19e90234f7fc9df6729b6bc150bd2e6664b7c98d6a1","src/net/if_.rs":"928066a6ec473ce565e2323858ff64e179e4b81b80768d830dd29008f2fafb7f","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"ba635fbed688a165279a9851269310220befd211c8fcf5761d1a62dab39ba52b","src/pty.rs":"7a73ba21b2ec8910f7932e456d2fb097a0553c5fe07717238c58455e3de7b275","src/sched.rs":"2bdb5ce449bc093a8eecdd8964e5d05feee3e7b804e4271e40d674178295df79","src/sys/aio.rs":"bbcc1d8639a9c89c66c00357353dde94d0f48b516b4354ab3d3dcfc16a2e0b56","src/sys/epoll.rs":"a3ace2282e77989e9b927dcdca8ad2070d4fb7710398af0763ea6eb26d431968","src/sys/even
 t.rs":"075e84e5a5d1fd922fbcac8c01c8e7cd7f1a1c1f8f60ede8f7ebc5fe6d5e76ac","src/sys/eventfd.rs":"b5301029e95f77f280cc169bb8aa247352efbb600c749f26e2fffa0474c872bb","src/sys/inotify.rs":"114be3860c9daaee1c781df90b63abb87cd82d677c4470b359bbf0787a25d302","src/sys/ioctl/bsd.rs":"853b50c3539dc4a1284c847f2689fde3dbed5dca7a8599db36193048e030296a","src/sys/ioctl/linux.rs":"642b25d3997518815dea454fa976e9067ad5fe4ed75622e7540e3f0d0c7d320a","src/sys/ioctl/mod.rs":"dd3435e44c42f55a600e40599038bebc7417934dade00113ef0f3b6318bf54de","src/sys/memfd.rs":"35dba6c3eeb4f74edbf86530ba1696d9251495b82b814a36b76e6d2b26490e3c","src/sys/mman.rs":"bdca4a151dc31d27c7435e30a5030ad2edef9dd3ac69a33363454cada8466ca3","src/sys/mod.rs":"b8d7d9e3cb331f1d972699cfbaa54fff34a9f26eaba38b8ee49e84bfeee22bd3","src/sys/personality.rs":"2019e58aa69c5ad68ae060e1b9a399138a2e4742f37a868e2681588963ca8acf","src/sys/pthread.rs":"cfa9ccd6f3b86c0c3fe012773c9c82a7813b298c2f20f8ab629781db627ce56b","src/sys/ptrace/bsd.rs":"feced79575c5dbea
 f0a0877ba888761675310b277f477acee820c785e132dbe9","src/sys/ptrace/linux.rs":"34524ad4911d2ef7ec0e21a49e479d6fd91d4ef5c660e0b7e2afa4878b27367a","src/sys/ptrace/mod.rs":"671a6ccac955e75d5998f7e53ffc45ed4c7b6522a0f24a0937d60141f692dd39","src/sys/quota.rs":"4ceb895896bbd0bb67ce98e91dec3bd40c9a7d5936abbe13b74691c6afa07f9f","src/sys/reboot.rs":"1fd26955bc095bd4f8804c850183f527560803cbceaf345c3760c8f32fe1224f","src/sys/select.rs":"02226a733d160701f07d27384f87bf21032f3cc4d5a6214dc61e398dd1606b60","src/sys/sendfile.rs":"110955788e3f5f36a7e563c334c6fe400edfb93d6cb2fdce6b8a79d2e892f8ce","src/sys/signal.rs":"53232ef1165272d109173fbba769cde77f3446050dbdaf36e56c4c0fde084348","src/sys/signalfd.rs":"37704804eb75571d03bbc1c99bd90846ae50ce361cc9998777744f8265d51074","src/sys/socket/addr.rs":"0513e0fbe57c19f8f9538e31074a4ed50c443fd45dd66ce1fa56db2dee46b371","src/sys/socket/mod.rs":"7d0d0b2da45d45493c494ad8669f53577439510914777b03febb6d2f18dcc787","src/sys/socket/sockopt.rs":"42b335e7a2e2b8cf1605065244
 90bb685bd2488ebff65921aa10f60363ffda7b","src/sys/stat.rs":"a969ae88221a50c89d54f97987d108d3c017339d7eedd66ac7218463d2bb07db","src/sys/statfs.rs":"6bd23f941107dc79ec34dc50516ff5eb18d9fad108ad976796669505692c1582","src/sys/statvfs.rs":"09a7268f3f6f321961e4f25943236fe103fe8c7661ea841f4e71014fda0d8952","src/sys/sysinfo.rs":"1aa6f402bc10689c5dd7ad454ecb60834e2b065dddbd3d87d1daecf88cb2b3ee","src/sys/termios.rs":"c3c310cdec9c7c80e7b11ada25d3dc87c0d0fc6c30fcda8f94edab1d27132300","src/sys/time.rs":"cc955b6b6647ca1db33ac076780ca6c984200e3cc47df5d836b1528489cdef70","src/sys/timerfd.rs":"51443f37b1dd4b03f16e1b569945f0ae715db4028f69e3ddd6c311db00e67ab3","src/sys/uio.rs":"a25dd7a84135ea50a671a7a06a8989dc9d53d3e755d36cef9f37cdc79a123d9d","src/sys/utsname.rs":"9509a092c837d1700f9f4ac30e4568e5b9b63ad8925a56cd8ad7add05d0ac452","src/sys/wait.rs":"ab18e66acaf161750394d802409ee8c95707dbd68d2fb59c88f7d4ed8936a1be","src/time.rs":"957845f8c689aec3c5dcf1af8bbc274a28ed5a214e4ee31ec8a89ed5eea0d3f1","src/ucont
 ext.rs":"10fdfebcecafa8d1c6cf573a5768adc07b87e9ff52a0bdc2527e77f73608f264","src/unistd.rs":"9c2b170f2b217393e571fb8021e000dfec4a5d99e170e11532a665163ecf3d54","test/common/mod.rs":"a26ecf30fc06008bab21d96eabf711bb0c41e8b50fe4c1f35cb2797ef405296c","test/sys/mod.rs":"c6f6a376fca73025bd76043a1739f54d24e856d4d0af9c58cc2b9d730ab87144","test/sys/test_aio.rs":"f21c157a07a29d60b0d68baa78ce24b352a19a35eaced0a792f62fa16d38617f","test/sys/test_aio_drop.rs":"eb086fcebd53ec82359ed7323f039b16ef7abced66b111f4876486fb058476e5","test/sys/test_epoll.rs":"35093d0cb1096a934dfc4f6efc737eadc4bdc2e2134d2a879061374a51b10c97","test/sys/test_inotify.rs":"a4f804bcf414b6635d9863c8534769a609009c451c3476cc839cdc30c439b3b1","test/sys/test_ioctl.rs":"39ddd52b27d942ab1b4018d213a378fb221598febc8fc7759ae5e6f746364396","test/sys/test_lio_listio_resubmit.rs":"29718e5fd04ef041125db4963f518f6f518b50436ea2df91e44c9c6b9418b704","test/sys/test_mman.rs":"b129b1d40d7a6e23cfc10956f9aa689d578a745f82fa267d24c40475063b592c","test/
 sys/test_pthread.rs":"891726053083bf488655eca1518630b08fa7c5937433fb5e446a9eed181ff7c5","test/sys/test_ptrace.rs":"46e51267cc93e45894a1e5a194563af5fb65a170dca95ad7cf9110520d764703","test/sys/test_select.rs":"7ece285a78cb66852ba8e89cac82c2d4fcff7d17a5f35e282cc52a09f5820daf","test/sys/test_signal.rs":"753f2ccbfcf2c5353a75b1e48d746a07c1949defba515c0ceee589ad1ed0aff6","test/sys/test_signalfd.rs":"2068a028c88395ff51c09e43b18c03d16e2d851f1d26ca1d121cdb5cb050f5c5","test/sys/test_socket.rs":"0f5fe9637f196cef459aadee27e449e5f9f968c10bf8dd017763c607cb6261d3","test/sys/test_sockopt.rs":"3334e12322e8b4e7c095ddc4a40a2d0e73a0d3a6e1820a6e0970eb8e1136c6de","test/sys/test_sysinfo.rs":"1e1bea9130fe38ccb07cd0ad7334c7be1e45efc33f7656a5973f8cad7126f225","test/sys/test_termios.rs":"93cd5cc181f1d8cef5c69aa23ddfabbf0480369cffab523e677c81e208998328","test/sys/test_timerfd.rs":"fcada956abd981e4d846da58e5640c5705b16026d47bccd1d603fae765ad10db","test/sys/test_uio.rs":"ae915c03e4f64ce370ae46f5dbe37834dae2849bb9
 fa7961872cec50f45de1f4","test/sys/test_wait.rs":"1fefed60ea3f9c5d8d4518e1d7a122d50aad44c2bd87873ac9ddc31ecdcc5a39","test/test.rs":"be9c29b8a8c9669b6674746ac8065c828a5d1d40ba41226846fe964310a18188","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e0dc7c317871eda3873a5d9df801c2ebb34cd958210c42a15f8dff623f05cae0","test/test_fcntl.rs":"e60c1dde6d0a6fde7a52cf98332e5b96fef5749868f0313cb7082bda7a66adb9","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"07f5445812593c994d1c25d5c8669aa3c4b1750f3b8ed2c1ddb1c661809983dc","test/test_mount.rs":"55503e8b28f77b45d755d549375cab34fa3a3cc9b94cbb23cfbd4426c5d9cb9c","test/test_mq.rs":"1020a4eb2f88cc29c59c44ad965d0573fba2beeb4c8986060aac56de99eea63c","test/test_net.rs":"ec6d580b87292519d514b0236bdd5abdd576fcf4835cfe
 49ed1ddb47c5f1aea3","test/test_nix_path.rs":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","test/test_poll.rs":"fbcf1780447f75a0177b4f47ba3d99b68f4324059ff66d993034ae5035c6d3ef","test/test_pty.rs":"56198cb9537ec3409717acecb133a49eb48bfc180c135ff0296974ec466d1171","test/test_ptymaster_drop.rs":"d162510cc96b8b7389d8bc34e097db1c80b84b5070c1d16f15b053ffd20cfa17","test/test_sched.rs":"f8ad92eb554164b0f92428f716db99040186d741cc6e1976f7930f099652f70c","test/test_sendfile.rs":"e0cbabbd34052ccaa03d6555d5631686aa076728f6378ee90f7ecec68f891144","test/test_stat.rs":"9668fc1f894b7f8a60dfddbdaef4bc833463e4e0cf04c1cff7f8c0569a226ad2","test/test_time.rs":"199b1c89d373e9398cca97f83ecd6459c6bd5ba7adca28013d9109d5cbad03f3","test/test_unistd.rs":"9bf047d877fd7c0826a2241737574923c3fd102a6b143b6d9710f52af5655588"},"package":"f5e06129fb611568ef4e868c14b326274959aa70ff7776e9d55323531c374945"}
-\ No newline at end of file
-diff --git a/third_party/rust/nix/CHANGELOG.md b/third_party/rust/nix/CHANGELOG.md
-index d93a5ce6bbfc9..234f2307c6d36 100644
---- a/third_party/rust/nix/CHANGELOG.md
-+++ b/third_party/rust/nix/CHANGELOG.md
-@@ -2,12 +2,316 @@
- 
- All notable changes to this project will be documented in this file.
- This project adheres to [Semantic Versioning](http://semver.org/).
-+This project adheres to [Semantic Versioning](https://semver.org/).
- 
--## [Unreleased] - ReleaseDate
-+## [0.20.2] - 28 September 2021
- ### Added
- ### Changed
- ### Fixed
-+
-+- Fixed buffer overflow in `unistd::getgrouplist`.
-+  (#[1545](https://github.com/nix-rust/nix/pull/1545))
-+
-+## [0.20.1] - 13 August 2021
-+### Added
-+### Changed
-+### Fixed
-+
-+- Locked bitflags to < 1.3.0 to fix the build with rust < 1.46.0.
-+
-+### Removed
-+
-+- Removed a couple of termios constants on redox that were never actually
-+  supported.
-+  (#[1483](https://github.com/nix-rust/nix/pull/1483))
-+
-+## [0.20.0] - 20 February 2021
-+### Added
-+
-+- Added a `passwd` field to `Group` (#[1338](https://github.com/nix-rust/nix/pull/1338))
-+- Added `mremap` (#[1306](https://github.com/nix-rust/nix/pull/1306))
-+- Added `personality` (#[1331](https://github.com/nix-rust/nix/pull/1331))
-+- Added limited Fuchsia support (#[1285](https://github.com/nix-rust/nix/pull/1285))
-+- Added `getpeereid` (#[1342](https://github.com/nix-rust/nix/pull/1342))
-+- Implemented `IntoIterator` for `Dir`
-+  (#[1333](https://github.com/nix-rust/nix/pull/1333)).
-+
-+### Changed
-+
-+- Minimum supported Rust version is now 1.40.0.
-+  ([#1356](https://github.com/nix-rust/nix/pull/1356))
-+- i686-apple-darwin has been demoted to Tier 2 support, because it's deprecated
-+  by Xcode.
-+  (#[1350](https://github.com/nix-rust/nix/pull/1350))
-+- Fixed calling `recvfrom` on an `AddrFamily::Packet` socket
-+  (#[1344](https://github.com/nix-rust/nix/pull/1344))
-+
-+### Fixed
-+- `TimerFd` now closes the underlying fd on drop.
-+  ([#1381](https://github.com/nix-rust/nix/pull/1381))
-+- Define `*_MAGIC` filesystem constants on Linux s390x
-+  (#[1372](https://github.com/nix-rust/nix/pull/1372))
-+- mqueue, sysinfo, timespec, statfs, test_ptrace_syscall() on x32
-+  (#[1366](https://github.com/nix-rust/nix/pull/1366))
-+
-+### Removed
-+
-+- `Dir`, `SignalFd`, and `PtyMaster` are no longer `Clone`.
-+  (#[1382](https://github.com/nix-rust/nix/pull/1382))
-+- Removed `SockLevel`, which hasn't been used for a few years
-+  (#[1362](https://github.com/nix-rust/nix/pull/1362))
-+- Removed both `Copy` and `Clone` from `TimerFd`.
-+  ([#1381](https://github.com/nix-rust/nix/pull/1381))
-+
-+## [0.19.1] - 28 November 2020
-+### Fixed
-+- Fixed bugs in `recvmmsg`.
-+  (#[1341](https://github.com/nix-rust/nix/pull/1341))
-+
-+## [0.19.0] - 6 October 2020
-+### Added
-+- Added Netlink protocol families to the `SockProtocol` enum
-+  (#[1289](https://github.com/nix-rust/nix/pull/1289))
-+- Added `clock_gettime`, `clock_settime`, `clock_getres`,
-+  `clock_getcpuclockid` functions and `ClockId` struct.
-+  (#[1281](https://github.com/nix-rust/nix/pull/1281))
-+- Added wrapper functions for `PTRACE_SYSEMU` and `PTRACE_SYSEMU_SINGLESTEP`.
-+  (#[1300](https://github.com/nix-rust/nix/pull/1300))
-+- Add support for Vsock on Android rather than just Linux.
-+  (#[1301](https://github.com/nix-rust/nix/pull/1301))
-+- Added `TCP_KEEPCNT` and `TCP_KEEPINTVL` TCP keepalive options.
-+  (#[1283](https://github.com/nix-rust/nix/pull/1283))
-+### Changed
-+- Expose `SeekData` and `SeekHole` on all Linux targets
-+  (#[1284](https://github.com/nix-rust/nix/pull/1284))
-+- Changed unistd::{execv,execve,execvp,execvpe,fexecve,execveat} to take both `&[&CStr]` and `&[CString]` as its list argument(s).
-+  (#[1278](https://github.com/nix-rust/nix/pull/1278))
-+- Made `unistd::fork` an unsafe funtion, bringing it in line with [libstd's decision](https://github.com/rust-lang/rust/pull/58059).
-+  (#[1293](https://github.com/nix-rust/nix/pull/1293))
-+### Fixed
-+### Removed
-+
-+## [0.18.0] - 26 July 2020
-+### Added
-+- Added `fchown(2)` wrapper.
-+  (#[1257](https://github.com/nix-rust/nix/pull/1257))
-+- Added support on linux systems for `MAP_HUGE_`_`SIZE`_ family of flags.
-+  (#[1211](https://github.com/nix-rust/nix/pull/1211))
-+- Added support for `F_OFD_*` `fcntl` commands on Linux and Android.
-+  (#[1195](https://github.com/nix-rust/nix/pull/1195))
-+- Added `env::clearenv()`: calls `libc::clearenv` on platforms
-+  where it's available, and clears the environment of all variables
-+  via `std::env::vars` and `std::env::remove_var` on others.
-+  (#[1185](https://github.com/nix-rust/nix/pull/1185))
-+- `FsType` inner value made public.
-+  (#[1187](https://github.com/nix-rust/nix/pull/1187))
-+- Added `unistd::setfsuid` and `unistd::setfsgid` to set the user or group
-+  identity for filesystem checks per-thread.
-+  (#[1163](https://github.com/nix-rust/nix/pull/1163))
-+- Derived `Ord`, `PartialOrd` for `unistd::Pid` (#[1189](https://github.com/nix-rust/nix/pull/1189))
-+- Added `select::FdSet::fds` method to iterate over file descriptors in a set.
-+  ([#1207](https://github.com/nix-rust/nix/pull/1207))
-+- Added support for UDP generic segmentation offload (GSO) and generic
-+  receive offload (GRO) ([#1209](https://github.com/nix-rust/nix/pull/1209))
-+- Added support for `sendmmsg` and `recvmmsg` calls
-+  (#[1208](https://github.com/nix-rust/nix/pull/1208))
-+- Added support for `SCM_CREDS` messages (`UnixCredentials`) on FreeBSD/DragonFly
-+  (#[1216](https://github.com/nix-rust/nix/pull/1216))
-+- Added `BindToDevice` socket option (sockopt) on Linux
-+  (#[1233](https://github.com/nix-rust/nix/pull/1233))
-+- Added `EventFilter` bitflags for `EV_DISPATCH` and `EV_RECEIPT` on OpenBSD.
-+  (#[1252](https://github.com/nix-rust/nix/pull/1252))
-+- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage`.
-+  (#[1222](https://github.com/nix-rust/nix/pull/1222))
-+- `CpuSet` and `UnixCredentials` now implement `Default`.
-+  (#[1244](https://github.com/nix-rust/nix/pull/1244))
-+- Added `unistd::ttyname`
-+  (#[1259](https://github.com/nix-rust/nix/pull/1259))
-+- Added support for `Ipv4PacketInfo` and `Ipv6PacketInfo` to `ControlMessage` for iOS and Android.
-+  (#[1265](https://github.com/nix-rust/nix/pull/1265))
-+- Added support for `TimerFd`.
-+  (#[1261](https://github.com/nix-rust/nix/pull/1261))
-+
-+### Changed
-+- Changed `fallocate` return type from `c_int` to `()` (#[1201](https://github.com/nix-rust/nix/pull/1201))
-+- Enabled `sys::ptrace::setregs` and `sys::ptrace::getregs` on x86_64-unknown-linux-musl target
-+  (#[1198](https://github.com/nix-rust/nix/pull/1198))
-+- On Linux, `ptrace::write` is now an `unsafe` function. Caveat programmer.
-+  (#[1245](https://github.com/nix-rust/nix/pull/1245))
-+- `execv`, `execve`, `execvp` and `execveat` in `::nix::unistd` and `reboot` in
-+  `::nix::sys::reboot` now return `Result<Infallible>` instead of `Result<Void>` (#[1239](https://github.com/nix-rust/nix/pull/1239))
-+- `sys::socket::sockaddr_storage_to_addr` is no longer `unsafe`.  So is
-+  `offset_of!`.
-+- `sys::socket::sockaddr_storage_to_addr`, `offset_of!`, and `Errno::clear` are
-+  no longer `unsafe`.
-+- `SockAddr::as_ffi_pair`,`sys::socket::sockaddr_storage_to_addr`, `offset_of!`,
-+  and `Errno::clear` are no longer `unsafe`.
-+  (#[1244](https://github.com/nix-rust/nix/pull/1244))
-+- Several `Inotify` methods now take `self` by value instead of by reference
-+  (#[1244](https://github.com/nix-rust/nix/pull/1244))
-+- `nix::poll::ppoll`: `timeout` parameter is now optional, None is equivalent for infinite timeout.
-+
-+### Fixed
-+
-+- Fixed `getsockopt`.  The old code produced UB which triggers a panic with
-+  Rust 1.44.0.
-+  (#[1214](https://github.com/nix-rust/nix/pull/1214))
-+
-+- Fixed a bug in nix::unistd that would result in an infinite loop
-+  when a group or user lookup required a buffer larger than
-+  16KB. (#[1198](https://github.com/nix-rust/nix/pull/1198))
-+- Fixed unaligned casting of `cmsg_data` to `af_alg_iv` (#[1206](https://github.com/nix-rust/nix/pull/1206))
-+- Fixed `readlink`/`readlinkat` when reading symlinks longer than `PATH_MAX` (#[1231](https://github.com/nix-rust/nix/pull/1231))
-+- `PollFd`, `EpollEvent`, `IpMembershipRequest`, `Ipv6MembershipRequest`,
-+  `TimeVal`, and `IoVec` are now `repr(transparent)`.  This is required for
-+  correctness's sake across all architectures and compilers, though now bugs
-+  have been reported so far.
-+  (#[1243](https://github.com/nix-rust/nix/pull/1243))
-+- Fixed unaligned pointer read in `Inotify::read_events`.
-+  (#[1244](https://github.com/nix-rust/nix/pull/1244))
-+
-+### Removed
-+
-+- Removed `sys::socket::addr::from_libc_sockaddr` from the public API.
-+  (#[1215](https://github.com/nix-rust/nix/pull/1215))
-+- Removed `sys::termios::{get_libc_termios, get_libc_termios_mut, update_wrapper`
-+  from the public API. These were previously hidden in the docs but still usable
-+  by downstream.
-+  (#[1235](https://github.com/nix-rust/nix/pull/1235))
-+
-+- Nix no longer implements `NixPath` for `Option<P> where P: NixPath`.  Most
-+  Nix functions that accept `NixPath` arguments can't do anything useful with
-+  `None`.  The exceptions (`mount` and `quotactl_sync`) already take explicitly
-+  optional arguments.
-+  (#[1242](https://github.com/nix-rust/nix/pull/1242))
-+
-+- Removed `unistd::daemon` and `unistd::pipe2` on OSX and ios
-+  (#[1255](https://github.com/nix-rust/nix/pull/1255))
-+
-+- Removed `sys::event::FilterFlag::NOTE_EXIT_REPARENTED` and
-+  `sys::event::FilterFlag::NOTE_REAP` on OSX and ios.
-+  (#[1255](https://github.com/nix-rust/nix/pull/1255))
-+
-+- Removed `sys::ptrace::ptrace` on Android and Linux.
-+  (#[1255](https://github.com/nix-rust/nix/pull/1255))
-+
-+- Dropped support for powerpc64-unknown-linux-gnu
-+  (#[1266](https://github.com/nix-rust/nix/pull/1268))
-+
-+## [0.17.0] - 3 February 2020
-+### Added
-+- Add `CLK_TCK` to `SysconfVar`
-+  (#[1177](https://github.com/nix-rust/nix/pull/1177))
-+### Changed
-+### Fixed
-+### Removed
-+- Removed deprecated Error::description from error types
-+  (#[1175](https://github.com/nix-rust/nix/pull/1175))
-+
-+## [0.16.1] - 23 December 2019
-+### Added
-+### Changed
-+### Fixed
-+
-+- Fixed the build for OpenBSD
-+  (#[1168](https://github.com/nix-rust/nix/pull/1168))
-+
-+### Removed
-+
-+## [0.16.0] - 1 December 2019
-+### Added
-+- Added `ptrace::seize()`: similar to `attach()` on Linux
-+  but with better-defined semantics.
-+  (#[1154](https://github.com/nix-rust/nix/pull/1154))
-+
-+- Added `Signal::as_str()`: returns signal name as `&'static str`
-+  (#[1138](https://github.com/nix-rust/nix/pull/1138))
-+
-+- Added `posix_fallocate`.
-+  ([#1105](https://github.com/nix-rust/nix/pull/1105))
-+
-+- Implemented `Default` for `FdSet`
-+  ([#1107](https://github.com/nix-rust/nix/pull/1107))
-+
-+- Added `NixPath::is_empty`.
-+  ([#1107](https://github.com/nix-rust/nix/pull/1107))
-+
-+- Added `mkfifoat`
-+  ([#1133](https://github.com/nix-rust/nix/pull/1133))
-+
-+- Added `User::from_uid`, `User::from_name`, `User::from_gid` and
-+  `Group::from_name`,
-+  ([#1139](https://github.com/nix-rust/nix/pull/1139))
-+
-+- Added `linkat`
-+  ([#1101](https://github.com/nix-rust/nix/pull/1101))
-+
-+- Added `sched_getaffinity`.
-+  ([#1148](https://github.com/nix-rust/nix/pull/1148))
-+
-+- Added optional `Signal` argument to `ptrace::{detach, syscall}` for signal
-+  injection. ([#1083](https://github.com/nix-rust/nix/pull/1083))
-+
-+### Changed
-+- `sys::termios::BaudRate` now implements `TryFrom<speed_t>` instead of
-+  `From<speed_t>`.  The old `From` implementation would panic on failure.
-+  ([#1159](https://github.com/nix-rust/nix/pull/1159))
-+
-+- `sys::socket::ControlMessage::ScmCredentials` and
-+  `sys::socket::ControlMessageOwned::ScmCredentials` now wrap `UnixCredentials`
-+  rather than `libc::ucred`.
-+  ([#1160](https://github.com/nix-rust/nix/pull/1160))
-+
-+- `sys::socket::recvmsg` now takes a plain `Vec` instead of a `CmsgBuffer`
-+  implementor.  If you were already using `cmsg_space!`, then you needn't worry.
-+  ([#1156](https://github.com/nix-rust/nix/pull/1156))
-+
-+- `sys::socket::recvfrom` now returns
-+  `Result<(usize, Option<SockAddr>)>` instead of `Result<(usize, SockAddr)>`.
-+  ([#1145](https://github.com/nix-rust/nix/pull/1145))
-+
-+- `Signal::from_c_int` has been replaced by `Signal::try_from`
-+  ([#1113](https://github.com/nix-rust/nix/pull/1113))
-+
-+- Changed `readlink` and `readlinkat` to return `OsString`
-+  ([#1109](https://github.com/nix-rust/nix/pull/1109))
-+
-+  ```rust
-+  # use nix::fcntl::{readlink, readlinkat};
-+  // the buffer argument of `readlink` and `readlinkat` has been removed,
-+  // and the return value is now an owned type (`OsString`).
-+  // Existing code can be updated by removing the buffer argument
-+  // and removing any clone or similar operation on the output
-+
-+  // old code `readlink(&path, &mut buf)` can be replaced with the following
-+  let _: OsString = readlink(&path);
-+
-+  // old code `readlinkat(dirfd, &path, &mut buf)` can be replaced with the following
-+  let _: OsString = readlinkat(dirfd, &path);
-+  ```
-+
-+- Minimum supported Rust version is now 1.36.0.
-+  ([#1108](https://github.com/nix-rust/nix/pull/1108))
-+
-+- `Ipv4Addr::octets`, `Ipv4Addr::to_std`, `Error::as_errno`,
-+  `ForkResult::is_child`, `ForkResult::is_parent`, `Gid::as_raw`,
-+  `Uid::is_root`, `Uid::as_raw`, `Pid::as_raw`, and `PollFd::revents` now take
-+  `self` by value.
-+  ([#1107](https://github.com/nix-rust/nix/pull/1107))
-+
-+- Type `&CString` for parameters of `exec(v|ve|vp|vpe|veat)` are changed to `&CStr`.
-+  ([#1121](https://github.com/nix-rust/nix/pull/1121))
-+
-+### Fixed
-+- Fix length of abstract socket addresses
-+  ([#1120](https://github.com/nix-rust/nix/pull/1120))
-+
-+- Fix initialization of msghdr in recvmsg/sendmsg when built with musl
-+  ([#1136](https://github.com/nix-rust/nix/pull/1136))
-+
- ### Removed
-+- Remove the deprecated `CmsgSpace`.
-+  ([#1156](https://github.com/nix-rust/nix/pull/1156))
- 
- ## [0.15.0] - 10 August 2019
- ### Added
-diff --git a/third_party/rust/nix/CONTRIBUTING.md b/third_party/rust/nix/CONTRIBUTING.md
-index 03a1f630dbb06..55990c4f1a24f 100644
---- a/third_party/rust/nix/CONTRIBUTING.md
-+++ b/third_party/rust/nix/CONTRIBUTING.md
-@@ -76,21 +76,21 @@ add a test that would have failed without the fix.
- 
- After you've made your change, make sure the tests pass in your development
- environment. We also have [continuous integration set up on
--Travis-CI][travis-ci], which might find some issues on other platforms. The CI
-+Cirrus-CI][cirrus-ci], which might find some issues on other platforms. The CI
- will run once you open a pull request.
- 
- There is also infrastructure for running tests for other targets
- locally.  More information is available in the [CI Readme][ci-readme].
- 
--[travis-ci]: https://travis-ci.org/nix-rust/nix
-+[cirrus-ci]: https://cirrus-ci.com/github/nix-rust/nix
- [ci-readme]: ci/README.md
- 
- ### Disabling a test in the CI environment
- 
- Sometimes there are features that cannot be tested in the CI environment.
--To stop a test from running under CI, add `#[cfg_attr(travis, ignore)]`
--to it. Please include a comment describing the reason it shouldn't run
--under CI, and a link to an upstream issue if possible!
-+To stop a test from running under CI, add `skip_if_cirrus!()` to it. Please
-+describe the reason it shouldn't run under CI, and a link to an issue if
-+possible!
- 
- ## bors, the bot who merges all the PRs
- 
-diff --git a/third_party/rust/nix/CONVENTIONS.md b/third_party/rust/nix/CONVENTIONS.md
-index 48daa937345d2..2461085eb664a 100644
---- a/third_party/rust/nix/CONVENTIONS.md
-+++ b/third_party/rust/nix/CONVENTIONS.md
-@@ -76,12 +76,11 @@ to parameters of functions by [enumerations][enum].
- 
- Whenever we need to use a [libc][libc] function to properly initialize a
- variable and said function allows us to use uninitialized memory, we use
--[`std::mem::uninitialized`][std_uninitialized] (or [`core::mem::uninitialized`][core_uninitialized])
--when defining the variable. This allows us to avoid the overhead incurred by
--zeroing or otherwise initializing the variable.
-+[`std::mem::MaybeUninit`][std_MaybeUninit] when defining the variable. This
-+allows us to avoid the overhead incurred by zeroing or otherwise initializing
-+the variable.
- 
- [bitflags]: https://crates.io/crates/bitflags/
--[core_uninitialized]: https://doc.rust-lang.org/core/mem/fn.uninitialized.html
- [enum]: https://doc.rust-lang.org/reference.html#enumerations
- [libc]: https://crates.io/crates/libc/
--[std_uninitialized]: https://doc.rust-lang.org/std/mem/fn.uninitialized.html
-+[std_MaybeUninit]: https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html
-diff --git a/third_party/rust/nix/Cargo.toml b/third_party/rust/nix/Cargo.toml
-index 555b99020d68f..456bdca9c2599 100644
---- a/third_party/rust/nix/Cargo.toml
-+++ b/third_party/rust/nix/Cargo.toml
-@@ -3,22 +3,24 @@
- # When uploading crates to the registry Cargo will automatically
- # "normalize" Cargo.toml files for maximal compatibility
- # with all versions of Cargo and also rewrite `path` dependencies
--# to registry (e.g., crates.io) dependencies
-+# to registry (e.g., crates.io) dependencies.
- #
--# If you believe there's an error in this file please file an
--# issue against the rust-lang/cargo repository. If you're
--# editing this file be aware that the upstream Cargo.toml
--# will likely look very different (and much more reasonable)
-+# If you are reading this file be aware that the original Cargo.toml
-+# will likely look very different (and much more reasonable).
-+# See Cargo.toml.orig for the original contents.
- 
- [package]
-+edition = "2018"
- name = "nix"
--version = "0.15.0"
-+version = "0.20.2"
- authors = ["The nix-rust Project Developers"]
--exclude = ["/.gitignore", "/.travis.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
-+exclude = ["/.gitignore", "/.cirrus.yml", "/ci/*", "/Cross.toml", "/RELEASE_PROCEDURE.md", "/bors.toml"]
- description = "Rust friendly bindings to *nix APIs"
- categories = ["os::unix-apis"]
- license = "MIT"
- repository = "https://github.com/nix-rust/nix"
-+[package.metadata.docs.rs]
-+targets = ["x86_64-unknown-linux-gnu", "aarch64-linux-android", "x86_64-apple-darwin", "aarch64-apple-ios", "x86_64-unknown-freebsd", "x86_64-unknown-openbsd", "x86_64-unknown-netbsd", "x86_64-unknown-dragonfly", "x86_64-fuchsia", "x86_64-unknown-redox"]
- 
- [[test]]
- name = "test"
-@@ -28,6 +30,10 @@ path = "test/test.rs"
- name = "test-aio-drop"
- path = "test/sys/test_aio_drop.rs"
- 
-+[[test]]
-+name = "test-clearenv"
-+path = "test/test_clearenv.rs"
-+
- [[test]]
- name = "test-lio-listio-resubmit"
- path = "test/sys/test_lio_listio_resubmit.rs"
-@@ -41,17 +47,14 @@ harness = false
- name = "test-ptymaster-drop"
- path = "test/test_ptymaster_drop.rs"
- [dependencies.bitflags]
--version = "1.0"
-+version = ">= 1.1.0, < 1.3.0"
- 
- [dependencies.cfg-if]
--version = "0.1.2"
-+version = "1.0"
- 
- [dependencies.libc]
--version = "0.2.60"
-+version = "0.2.99"
- features = ["extra_traits"]
--
--[dependencies.void]
--version = "1.0.2"
- [dev-dependencies.bytes]
- version = "0.4.8"
- 
-@@ -59,12 +62,17 @@ version = "0.4.8"
- version = "1.2"
- 
- [dev-dependencies.rand]
--version = ">= 0.6, < 0.7"
-+version = "0.6"
-+
-+[dev-dependencies.semver]
-+version = "0.9.0"
- 
- [dev-dependencies.tempfile]
--version = ">= 3.0.5, < 3.0.9"
-+version = "3.0.5"
- [target."cfg(any(target_os = \"android\", target_os = \"linux\"))".dev-dependencies.caps]
--version = "0.3.1"
-+version = "0.5.1"
-+[target."cfg(not(target_os = \"redox\"))".dependencies.memoffset]
-+version = "0.6.3"
- [target."cfg(target_os = \"dragonfly\")".build-dependencies.cc]
- version = "1"
- [target."cfg(target_os = \"freebsd\")".dev-dependencies.sysctl]
-diff --git a/third_party/rust/nix/README.md b/third_party/rust/nix/README.md
-index 0e540ba5b968e..b4909ea4345cc 100644
---- a/third_party/rust/nix/README.md
-+++ b/third_party/rust/nix/README.md
-@@ -1,6 +1,6 @@
- # Rust bindings to *nix APIs
- 
--[![Build Status](https://travis-ci.org/nix-rust/nix.svg?branch=master)](https://travis-ci.org/nix-rust/nix)
-+[![Cirrus Build Status](https://api.cirrus-ci.com/github/nix-rust/nix.svg)](https://cirrus-ci.com/github/nix-rust/nix)
- [![crates.io](http://meritbadge.herokuapp.com/nix)](https://crates.io/crates/nix)
- 
- [Documentation (Releases)](https://docs.rs/nix/)
-@@ -50,7 +50,6 @@ Tier 1:
-   * aarch64-unknown-linux-gnu
-   * arm-unknown-linux-gnueabi
-   * armv7-unknown-linux-gnueabihf
--  * i686-apple-darwin
-   * i686-unknown-freebsd
-   * i686-unknown-linux-gnu
-   * i686-unknown-linux-musl
-@@ -58,7 +57,6 @@ Tier 1:
-   * mips64-unknown-linux-gnuabi64
-   * mips64el-unknown-linux-gnuabi64
-   * mipsel-unknown-linux-gnu
--  * powerpc64-unknown-linux-gnu
-   * powerpc64le-unknown-linux-gnu
-   * x86_64-apple-darwin
-   * x86_64-unknown-freebsd
-@@ -74,6 +72,7 @@ Tier 2:
-   * armv7-linux-androideabi
-   * armv7s-apple-ios
-   * i386-apple-ios
-+  * i686-apple-darwin
-   * i686-linux-android
-   * powerpc-unknown-linux-gnu
-   * s390x-unknown-linux-gnu
-@@ -81,21 +80,20 @@ Tier 2:
-   * x86_64-linux-android
-   * x86_64-unknown-netbsd
- 
-+Tier 3:
-+  * x86_64-fuchsia
-+  * x86_64-unknown-redox
-+  * x86_64-unknown-linux-gnux32
-+
- ## Usage
- 
--`nix` requires Rust 1.31.0 or newer.
-+`nix` requires Rust 1.40.0 or newer.
- 
--To use `nix`, first add this to your `Cargo.toml`:
-+To use `nix`, add this to your `Cargo.toml`:
- 
- ```toml
- [dependencies]
--nix = "0.15.0"
--```
--
--Then, add this to your crate root:
--
--```rust,ignore
--extern crate nix;
-+nix = "0.20.2"
- ```
- 
- ## Contributing
-diff --git a/third_party/rust/nix/src/dir.rs b/third_party/rust/nix/src/dir.rs
-index 1820b5330ff60..7d4ab82f79e0d 100644
---- a/third_party/rust/nix/src/dir.rs
-+++ b/third_party/rust/nix/src/dir.rs
-@@ -1,10 +1,10 @@
--use {Error, NixPath, Result};
--use errno::Errno;
--use fcntl::{self, OFlag};
--use libc;
-+use crate::{Error, NixPath, Result};
-+use crate::errno::Errno;
-+use crate::fcntl::{self, OFlag};
- use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
--use std::{ffi, ptr};
--use sys;
-+use std::ptr;
-+use std::ffi;
-+use crate::sys;
- 
- #[cfg(target_os = "linux")]
- use libc::{dirent64 as dirent, readdir64_r as readdir_r};
-@@ -25,7 +25,7 @@ use libc::{dirent, readdir_r};
- ///    * returns entries for `.` (current directory) and `..` (parent directory).
- ///    * returns entries' names as a `CStr` (no allocation or conversion beyond whatever libc
- ///      does).
--#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+#[derive(Debug, Eq, Hash, PartialEq)]
- pub struct Dir(
-     ptr::NonNull<libc::DIR>
- );
-@@ -85,7 +85,32 @@ impl AsRawFd for Dir {
- 
- impl Drop for Dir {
-     fn drop(&mut self) {
--        unsafe { libc::closedir(self.0.as_ptr()) };
-+        let e = Errno::result(unsafe { libc::closedir(self.0.as_ptr()) });
-+        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
-+            panic!("Closing an invalid file descriptor!");
-+        };
-+    }
-+}
-+
-+fn next(dir: &mut Dir) -> Option<Result<Entry>> {
-+    unsafe {
-+        // Note: POSIX specifies that portable applications should dynamically allocate a
-+        // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
-+        // for the NUL byte. It doesn't look like the std library does this; it just uses
-+        // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
-+        // Probably fine here too then.
-+        let mut ent = std::mem::MaybeUninit::<dirent>::uninit();
-+        let mut result = ptr::null_mut();
-+        if let Err(e) = Errno::result(
-+            readdir_r(dir.0.as_ptr(), ent.as_mut_ptr(), &mut result))
-+        {
-+            return Some(Err(e));
-+        }
-+        if result.is_null() {
-+            return None;
-+        }
-+        assert_eq!(result, ent.as_mut_ptr());
-+        Some(Ok(Entry(ent.assume_init())))
-     }
- }
- 
-@@ -96,23 +121,7 @@ impl<'d> Iterator for Iter<'d> {
-     type Item = Result<Entry>;
- 
-     fn next(&mut self) -> Option<Self::Item> {
--        unsafe {
--            // Note: POSIX specifies that portable applications should dynamically allocate a
--            // buffer with room for a `d_name` field of size `pathconf(..., _PC_NAME_MAX)` plus 1
--            // for the NUL byte. It doesn't look like the std library does this; it just uses
--            // fixed-sized buffers (and libc's dirent seems to be sized so this is appropriate).
--            // Probably fine here too then.
--            let mut ent: Entry = Entry(::std::mem::uninitialized());
--            let mut result = ptr::null_mut();
--            if let Err(e) = Errno::result(readdir_r((self.0).0.as_ptr(), &mut ent.0, &mut result)) {
--                return Some(Err(e));
--            }
--            if result == ptr::null_mut() {
--                return None;
--            }
--            assert_eq!(result, &mut ent.0 as *mut dirent);
--            return Some(Ok(ent));
--        }
-+        next(self.0)
-     }
- }
- 
-@@ -122,10 +131,48 @@ impl<'d> Drop for Iter<'d> {
-     }
- }
- 
-+/// The return type of [Dir::into_iter]
-+#[derive(Debug, Eq, Hash, PartialEq)]
-+pub struct OwningIter(Dir);
-+
-+impl Iterator for OwningIter {
-+    type Item = Result<Entry>;
-+
-+    fn next(&mut self) -> Option<Self::Item> {
-+        next(&mut self.0)
-+    }
-+}
-+
-+impl IntoIterator for Dir {
-+    type Item = Result<Entry>;
-+    type IntoIter = OwningIter;
-+
-+    /// Creates a owning iterator, that is, one that takes ownership of the
-+    /// `Dir`. The `Dir` cannot be used after calling this.  This can be useful
-+    /// when you have a function that both creates a `Dir` instance and returns
-+    /// an `Iterator`.
-+    ///
-+    /// Example:
-+    ///
-+    /// ```
-+    /// use nix::{dir::Dir, fcntl::OFlag, sys::stat::Mode};
-+    /// use std::{iter::Iterator, string::String};
-+    ///
-+    /// fn ls_upper(dirname: &str) -> impl Iterator<Item=String> {
-+    ///     let d = Dir::open(dirname, OFlag::O_DIRECTORY, Mode::S_IXUSR).unwrap();
-+    ///     d.into_iter().map(|x| x.unwrap().file_name().as_ref().to_string_lossy().to_ascii_uppercase())
-+    /// }
-+    /// ```
-+    fn into_iter(self) -> Self::IntoIter {
-+        OwningIter(self)
-+    }
-+}
-+
- /// A directory entry, similar to `std::fs::DirEntry`.
- ///
- /// Note that unlike the std version, this may represent the `.` or `..` entries.
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+#[repr(transparent)]
- pub struct Entry(dirent);
- 
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-@@ -165,7 +212,7 @@ impl Entry {
-                   target_os = "macos",
-                   target_os = "solaris")))]
-     pub fn ino(&self) -> u64 {
--        self.0.d_fileno as u64
-+        u64::from(self.0.d_fileno)
-     }
- 
-     /// Returns the bare file name of this directory entry without any other leading path component.
-diff --git a/third_party/rust/nix/src/env.rs b/third_party/rust/nix/src/env.rs
-new file mode 100644
-index 0000000000000..f144dfedd0c1a
---- /dev/null
-+++ b/third_party/rust/nix/src/env.rs
-@@ -0,0 +1,53 @@
-+use cfg_if::cfg_if;
-+use crate::{Error, Result};
-+
-+/// Clear the environment of all name-value pairs.
-+///
-+/// On platforms where libc provides `clearenv()`, it will be used. libc's
-+/// `clearenv()` is documented to return an error code but not set errno; if the
-+/// return value indicates a failure, this function will return
-+/// `Error::UnsupportedOperation`.
-+///
-+/// On platforms where libc does not provide `clearenv()`, a fallback
-+/// implementation will be used that iterates over all environment variables and
-+/// removes them one-by-one.
-+///
-+/// # Safety
-+///
-+/// This function is not threadsafe and can cause undefined behavior in
-+/// combination with `std::env` or other program components that access the
-+/// environment. See, for example, the discussion on `std::env::remove_var`; this
-+/// function is a case of an "inherently unsafe non-threadsafe API" dealing with
-+/// the environment.
-+///
-+///  The caller must ensure no other threads access the process environment while
-+///  this function executes and that no raw pointers to an element of libc's
-+///  `environ` is currently held. The latter is not an issue if the only other
-+///  environment access in the program is via `std::env`, but the requirement on
-+///  thread safety must still be upheld.
-+pub unsafe fn clearenv() -> Result<()> {
-+    let ret;
-+    cfg_if! {
-+        if #[cfg(any(target_os = "fuchsia",
-+                     target_os = "wasi",
-+                     target_env = "wasi",
-+                     target_env = "uclibc",
-+                     target_os = "linux",
-+                     target_os = "android",
-+                     target_os = "emscripten"))] {
-+            ret = libc::clearenv();
-+        } else {
-+            use std::env;
-+            for (name, _) in env::vars_os() {
-+                env::remove_var(name);
-+            }
-+            ret = 0;
-+        }
-+    }
-+
-+    if ret == 0 {
-+        Ok(())
-+    } else {
-+        Err(Error::UnsupportedOperation)
-+    }
-+}
-diff --git a/third_party/rust/nix/src/errno.rs b/third_party/rust/nix/src/errno.rs
-index 6a2447bc52675..e5c709252025c 100644
---- a/third_party/rust/nix/src/errno.rs
-+++ b/third_party/rust/nix/src/errno.rs
-@@ -1,8 +1,7 @@
--#[cfg(not(target_os = "dragonfly"))]
--use libc;
-+use cfg_if::cfg_if;
- use libc::{c_int, c_void};
- use std::{fmt, io, error};
--use {Error, Result};
-+use crate::{Error, Result};
- 
- pub use self::consts::*;
- 
-@@ -13,32 +12,16 @@ cfg_if! {
-         unsafe fn errno_location() -> *mut c_int {
-             libc::__error()
-         }
--    } else if #[cfg(target_os = "dragonfly")] {
--        // DragonFly uses a thread-local errno variable, but #[thread_local] is
--        // feature-gated and not available in stable Rust as of this writing
--        // (Rust 1.21.0). We have to use a C extension to access it
--        // (src/errno_dragonfly.c).
--        //
--        // Tracking issue for `thread_local` stabilization:
--        //
--        //     https://github.com/rust-lang/rust/issues/29594
--        //
--        // Once this becomes stable, we can remove build.rs,
--        // src/errno_dragonfly.c, and use:
--        //
--        //     extern { #[thread_local] static errno: c_int; }
--        //
--        #[link(name="errno_dragonfly", kind="static")]
--        extern {
--            pub fn errno_location() -> *mut c_int;
--        }
-     } else if #[cfg(any(target_os = "android",
-                         target_os = "netbsd",
-                         target_os = "openbsd"))] {
-         unsafe fn errno_location() -> *mut c_int {
-             libc::__errno()
-         }
--    } else if #[cfg(target_os = "linux")] {
-+    } else if #[cfg(any(target_os = "linux",
-+                        target_os = "redox",
-+                        target_os = "dragonfly",
-+                        target_os = "fuchsia"))] {
-         unsafe fn errno_location() -> *mut c_int {
-             libc::__errno_location()
-         }
-@@ -46,8 +29,11 @@ cfg_if! {
- }
- 
- /// Sets the platform-specific errno to no-error
--unsafe fn clear() -> () {
--    *errno_location() = 0;
-+fn clear() {
-+    // Safe because errno is a thread-local variable
-+    unsafe {
-+        *errno_location() = 0;
-+    }
- }
- 
- /// Returns the platform-specific value of errno
-@@ -70,7 +56,7 @@ impl Errno {
-         from_i32(err)
-     }
- 
--    pub unsafe fn clear() -> () {
-+    pub fn clear() {
-         clear()
-     }
- 
-@@ -111,11 +97,7 @@ impl ErrnoSentinel for libc::sighandler_t {
-     fn sentinel() -> Self { libc::SIG_ERR }
- }
- 
--impl error::Error for Errno {
--    fn description(&self) -> &str {
--        self.desc()
--    }
--}
-+impl error::Error for Errno {}
- 
- impl fmt::Display for Errno {
-     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-@@ -207,200 +189,263 @@ fn desc(errno: Errno) -> &'static str {
-         EHOSTDOWN       => "Host is down",
-         EHOSTUNREACH    => "No route to host",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ECHRNG          => "Channel number out of range",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EL2NSYNC        => "Level 2 not synchronized",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EL3HLT          => "Level 3 halted",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EL3RST          => "Level 3 reset",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELNRNG          => "Link number out of range",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EUNATCH         => "Protocol driver not attached",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOCSI          => "No CSI structure available",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EL2HLT          => "Level 2 halted",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADE           => "Invalid exchange",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADR           => "Invalid request descriptor",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EXFULL          => "Exchange full",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOANO          => "No anode",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADRQC         => "Invalid request code",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADSLT         => "Invalid slot",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBFONT          => "Bad font file format",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOSTR          => "Device not a stream",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENODATA         => "No data available",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ETIME           => "Timer expired",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOSR           => "Out of streams resources",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENONET          => "Machine is not on the network",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOPKG          => "Package not installed",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EREMOTE         => "Object is remote",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOLINK         => "Link has been severed",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EADV            => "Advertise error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ESRMNT          => "Srmount error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ECOMM           => "Communication error on send",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EPROTO          => "Protocol error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EMULTIHOP       => "Multihop attempted",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EDOTDOT         => "RFS specific error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADMSG         => "Not a data message",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[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"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOTUNIQ        => "Name not unique on network",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EBADFD          => "File descriptor in bad state",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EREMCHG         => "Remote address changed",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELIBACC         => "Can not access a needed shared library",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELIBBAD         => "Accessing a corrupted shared library",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELIBSCN         => ".lib section in a.out corrupted",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELIBMAX         => "Attempting to link in too many shared libraries",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ELIBEXEC        => "Cannot exec a shared library directly",
- 
--        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia", target_os = "openbsd"))]
-         EILSEQ          => "Illegal byte sequence",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ERESTART        => "Interrupted system call should be restarted",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ESTRPIPE        => "Streams pipe error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EUSERS          => "Too many users",
- 
--        #[cfg(any(target_os = "linux", target_os = "android", target_os = "netbsd"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia", target_os = "netbsd",
-+                  target_os = "redox"))]
-         EOPNOTSUPP      => "Operation not supported on transport endpoint",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ESTALE          => "Stale file handle",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EUCLEAN         => "Structure needs cleaning",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOTNAM         => "Not a XENIX named type file",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENAVAIL         => "No XENIX semaphores available",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EISNAM          => "Is a named type file",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EREMOTEIO       => "Remote I/O error",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EDQUOT          => "Quota exceeded",
- 
-         #[cfg(any(target_os = "linux", target_os = "android",
--                  target_os = "openbsd", target_os = "dragonfly"))]
-+                  target_os = "fuchsia", target_os = "openbsd",
-+                  target_os = "dragonfly"))]
-         ENOMEDIUM       => "No medium found",
- 
--        #[cfg(any(target_os = "linux", target_os = "android", target_os = "openbsd"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia", target_os = "openbsd"))]
-         EMEDIUMTYPE     => "Wrong medium type",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ECANCELED       => "Operation canceled",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOKEY          => "Required key not available",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EKEYEXPIRED     => "Key has expired",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EKEYREVOKED     => "Key has been revoked",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EKEYREJECTED    => "Key was rejected by service",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         EOWNERDEAD      => "Owner died",
- 
--        #[cfg(any(target_os = "linux", target_os = "android"))]
-+        #[cfg(any(target_os = "linux", target_os = "android",
-+                  target_os = "fuchsia"))]
-         ENOTRECOVERABLE => "State not recoverable",
- 
--        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
-+        #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
-+                  target_os = "fuchsia"))]
-         ERFKILL         => "Operation not possible due to RF-kill",
- 
--        #[cfg(all(target_os = "linux", not(target_arch="mips")))]
-+        #[cfg(any(all(target_os = "linux", not(target_arch="mips")),
-+                  target_os = "fuchsia"))]
-         EHWPOISON       => "Memory page has hardware error",
- 
-         #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-         EDOOFUS         => "Programming error",
- 
--        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
-         EMULTIHOP       => "Multihop attempted",
- 
--        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly", target_os = "redox"))]
-         ENOLINK         => "Link has been severed",
- 
-         #[cfg(target_os = "freebsd")]
-@@ -416,12 +461,13 @@ fn desc(errno: Errno) -> &'static str {
- 
-         #[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 = "redox"))]
-         EOVERFLOW       => "Value too large to be stored in data type",
- 
-         #[cfg(any(target_os = "macos", target_os = "freebsd",
-                   target_os = "dragonfly", target_os = "ios",
--                  target_os = "netbsd"))]
-+                  target_os = "netbsd", target_os = "redox"))]
-         EILSEQ          => "Illegal byte sequence",
- 
-         #[cfg(any(target_os = "macos", target_os = "freebsd",
-@@ -431,12 +477,14 @@ fn desc(errno: Errno) -> &'static str {
- 
-         #[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 = "redox"))]
-         EBADMSG         => "Bad message",
- 
-         #[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 = "redox"))]
-         EPROTO          => "Protocol error",
- 
-         #[cfg(any(target_os = "macos", target_os = "freebsd",
-@@ -459,22 +507,26 @@ fn desc(errno: Errno) -> &'static str {
- 
-         #[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 = "redox"))]
-         EUSERS          => "Too many users",
- 
-         #[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 = "redox"))]
-         EDQUOT          => "Disc quota exceeded",
- 
-         #[cfg(any(target_os = "macos", target_os = "freebsd",
-                   target_os = "dragonfly", target_os = "ios",
--                  target_os = "openbsd", target_os = "netbsd"))]
-+                  target_os = "openbsd", target_os = "netbsd",
-+                  target_os = "redox"))]
-         ESTALE          => "Stale NFS file handle",
- 
-         #[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 = "redox"))]
-         EREMOTE         => "Too many levels of remote in path",
- 
-         #[cfg(any(target_os = "macos", target_os = "freebsd",
-@@ -514,7 +566,8 @@ fn desc(errno: Errno) -> &'static str {
- 
-         #[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 = "redox"))]
-         ECANCELED       => "Operation canceled",
- 
-         #[cfg(any(target_os = "macos", target_os = "ios"))]
-@@ -538,19 +591,23 @@ fn desc(errno: Errno) -> &'static str {
-         #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-         EMULTIHOP       => "Reserved",
- 
--        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        #[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"))]
-         ENOLINK         => "Reserved",
- 
--        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        #[cfg(any(target_os = "macos", target_os = "ios",
-+                  target_os = "netbsd", target_os = "redox"))]
-         ENOSR           => "No STREAM resources",
- 
--        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        #[cfg(any(target_os = "macos", target_os = "ios",
-+                  target_os = "netbsd", target_os = "redox"))]
-         ENOSTR          => "Not a STREAM",
- 
--        #[cfg(any(target_os = "macos", target_os = "ios", target_os = "netbsd"))]
-+        #[cfg(any(target_os = "macos", target_os = "ios",
-+                  target_os = "netbsd", target_os = "redox"))]
-         ETIME           => "STREAM ioctl timeout",
- 
-         #[cfg(any(target_os = "macos", target_os = "ios"))]
-@@ -573,10 +630,9 @@ fn desc(errno: Errno) -> &'static str {
-     }
- }
- 
--#[cfg(any(target_os = "linux", target_os = "android"))]
-+#[cfg(any(target_os = "linux", target_os = "android",
-+          target_os = "fuchsia"))]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -864,8 +920,6 @@ mod consts {
- 
- #[cfg(any(target_os = "macos", target_os = "ios"))]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -1101,8 +1155,6 @@ mod consts {
- 
- #[cfg(target_os = "freebsd")]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -1319,8 +1371,6 @@ mod consts {
- 
- #[cfg(target_os = "dragonfly")]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -1534,8 +1584,6 @@ mod consts {
- 
- #[cfg(target_os = "openbsd")]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -1748,8 +1796,6 @@ mod consts {
- 
- #[cfg(target_os = "netbsd")]
- mod consts {
--    use libc;
--
-     #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-     #[repr(i32)]
-     pub enum Errno {
-@@ -1961,3 +2007,195 @@ mod consts {
-         }
-     }
- }
-+
-+#[cfg(target_os = "redox")]
-+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,
-+        EDEADLK = libc::EDEADLK,
-+        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,
-+        EAGAIN = libc::EAGAIN,
-+        EINPROGRESS = libc::EINPROGRESS,
-+        EALREADY = libc::EALREADY,
-+        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,
-+        ELOOP = libc::ELOOP,
-+        ENAMETOOLONG = libc::ENAMETOOLONG,
-+        EHOSTDOWN = libc::EHOSTDOWN,
-+        EHOSTUNREACH = libc::EHOSTUNREACH,
-+        ENOTEMPTY = libc::ENOTEMPTY,
-+        EUSERS = libc::EUSERS,
-+        EDQUOT = libc::EDQUOT,
-+        ESTALE = libc::ESTALE,
-+        EREMOTE = libc::EREMOTE,
-+        ENOLCK = libc::ENOLCK,
-+        ENOSYS = libc::ENOSYS,
-+        EIDRM = libc::EIDRM,
-+        ENOMSG = libc::ENOMSG,
-+        EOVERFLOW = libc::EOVERFLOW,
-+        EILSEQ = libc::EILSEQ,
-+        ECANCELED = libc::ECANCELED,
-+        EBADMSG = libc::EBADMSG,
-+        ENODATA = libc::ENODATA,
-+        ENOSR = libc::ENOSR,
-+        ENOSTR = libc::ENOSTR,
-+        ETIME = libc::ETIME,
-+        EMULTIHOP = libc::EMULTIHOP,
-+        ENOLINK = libc::ENOLINK,
-+        EPROTO = libc::EPROTO,
-+    }
-+
-+    pub const ELAST: Errno = Errno::UnknownErrno;
-+    pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
-+
-+    pub const EL2NSYNC: Errno = Errno::UnknownErrno;
-+
-+    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::EDEADLK => EDEADLK,
-+            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::EAGAIN => EAGAIN,
-+            libc::EINPROGRESS => EINPROGRESS,
-+            libc::EALREADY => EALREADY,
-+            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::ELOOP => ELOOP,
-+            libc::ENAMETOOLONG => ENAMETOOLONG,
-+            libc::EHOSTDOWN => EHOSTDOWN,
-+            libc::EHOSTUNREACH => EHOSTUNREACH,
-+            libc::ENOTEMPTY => ENOTEMPTY,
-+            libc::EUSERS => EUSERS,
-+            libc::EDQUOT => EDQUOT,
-+            libc::ESTALE => ESTALE,
-+            libc::EREMOTE => EREMOTE,
-+            libc::ENOLCK => ENOLCK,
-+            libc::ENOSYS => ENOSYS,
-+            libc::EIDRM => EIDRM,
-+            libc::ENOMSG => ENOMSG,
-+            libc::EOVERFLOW => EOVERFLOW,
-+            libc::EILSEQ => EILSEQ,
-+            libc::ECANCELED => ECANCELED,
-+            libc::EBADMSG => EBADMSG,
-+            libc::ENODATA => ENODATA,
-+            libc::ENOSR => ENOSR,
-+            libc::ENOSTR => ENOSTR,
-+            libc::ETIME => ETIME,
-+            libc::EMULTIHOP => EMULTIHOP,
-+            libc::ENOLINK => ENOLINK,
-+            libc::EPROTO => EPROTO,
-+            _ => UnknownErrno,
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix/src/fcntl.rs b/third_party/rust/nix/src/fcntl.rs
-index be6ee0f73a8be..d2242dacd61b0 100644
---- a/third_party/rust/nix/src/fcntl.rs
-+++ b/third_party/rust/nix/src/fcntl.rs
-@@ -1,29 +1,34 @@
--use {Error, Result, NixPath};
--use errno::Errno;
--use libc::{self, c_int, c_uint, c_char, size_t, ssize_t};
--use sys::stat::Mode;
-+use crate::errno::Errno;
-+use libc::{self, c_char, c_int, c_uint, size_t, ssize_t};
-+use std::ffi::OsString;
-+#[cfg(not(target_os = "redox"))]
- use std::os::raw;
-+use std::os::unix::ffi::OsStringExt;
- use std::os::unix::io::RawFd;
--use std::ffi::OsStr;
--use std::os::unix::ffi::OsStrExt;
-+use crate::sys::stat::Mode;
-+use crate::{NixPath, Result};
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use std::ptr; // For splice and copy_file_range
- #[cfg(any(target_os = "android", target_os = "linux"))]
--use sys::uio::IoVec;  // For vmsplice
--
--#[cfg(any(target_os = "linux",
--          target_os = "android",
--          target_os = "emscripten",
--          target_os = "fuchsia",
--          any(target_os = "wasi", target_env = "wasi"),
--          target_env = "uclibc",
--          target_env = "freebsd"))]
-+use crate::sys::uio::IoVec; // For vmsplice
-+
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+    target_os = "fuchsia",
-+    any(target_os = "wasi", target_env = "wasi"),
-+    target_env = "uclibc",
-+    target_os = "freebsd"
-+))]
- pub use self::posix_fadvise::*;
- 
--libc_bitflags!{
-+#[cfg(not(target_os = "redox"))]
-+libc_bitflags! {
-     pub struct AtFlags: c_int {
-         AT_REMOVEDIR;
-+        AT_SYMLINK_FOLLOW;
-         AT_SYMLINK_NOFOLLOW;
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-         AT_NO_AUTOMOUNT;
-@@ -78,7 +83,8 @@ libc_bitflags!(
-                   target_os = "ios",
-                   target_os = "macos",
-                   target_os = "netbsd",
--                  target_os = "openbsd"))]
-+                  target_os = "openbsd",
-+                  target_os = "redox"))]
-         O_EXLOCK;
-         /// Same as `O_SYNC`.
-         #[cfg(any(target_os = "dragonfly",
-@@ -87,7 +93,8 @@ libc_bitflags!(
-                   all(target_os = "linux", not(target_env = "musl")),
-                   target_os = "macos",
-                   target_os = "netbsd",
--                  target_os = "openbsd"))]
-+                  target_os = "openbsd",
-+                  target_os = "redox"))]
-         O_FSYNC;
-         /// Allow files whose sizes can't be represented in an `off_t` to be opened.
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -96,8 +103,10 @@ libc_bitflags!(
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-         O_NOATIME;
-         /// Don't attach the device as the process' controlling terminal.
-+        #[cfg(not(target_os = "redox"))]
-         O_NOCTTY;
-         /// Same as `O_NONBLOCK`.
-+        #[cfg(not(target_os = "redox"))]
-         O_NDELAY;
-         /// `open()` will fail if the given path is a symbolic link.
-         O_NOFOLLOW;
-@@ -109,7 +118,7 @@ libc_bitflags!(
-         /// Obtain a file descriptor for low-level access.
-         ///
-         /// The file itself is not opened and other file operations will fail.
--        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-         O_PATH;
-         /// Only allow reading.
-         ///
-@@ -131,9 +140,11 @@ libc_bitflags!(
-                   target_os = "ios",
-                   target_os = "macos",
-                   target_os = "netbsd",
--                  target_os = "openbsd"))]
-+                  target_os = "openbsd",
-+                  target_os = "redox"))]
-         O_SHLOCK;
-         /// Implicitly follow each `write()` with an `fsync()`.
-+        #[cfg(not(target_os = "redox"))]
-         O_SYNC;
-         /// Create an unnamed temporary file.
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -150,6 +161,8 @@ libc_bitflags!(
-     }
- );
- 
-+// The conversion is not identical on all operating systems.
-+#[allow(clippy::identity_conversion)]
- pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
-     let fd = path.with_nix_path(|cstr| {
-         unsafe { libc::open(cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
-@@ -158,56 +171,125 @@ pub fn open<P: ?Sized + NixPath>(path: &P, oflag: OFlag, mode: Mode) -> Result<R
-     Errno::result(fd)
- }
- 
--pub fn openat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P, oflag: OFlag, mode: Mode) -> Result<RawFd> {
-+// The conversion is not identical on all operating systems.
-+#[allow(clippy::identity_conversion)]
-+#[cfg(not(target_os = "redox"))]
-+pub fn openat<P: ?Sized + NixPath>(
-+    dirfd: RawFd,
-+    path: &P,
-+    oflag: OFlag,
-+    mode: Mode,
-+) -> Result<RawFd> {
-     let fd = path.with_nix_path(|cstr| {
-         unsafe { libc::openat(dirfd, cstr.as_ptr(), oflag.bits(), mode.bits() as c_uint) }
-     })?;
-     Errno::result(fd)
- }
- 
--pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(old_dirfd: Option<RawFd>, old_path: &P1,
--                                                            new_dirfd: Option<RawFd>, new_path: &P2)
--                                                            -> Result<()> {
-+#[cfg(not(target_os = "redox"))]
-+pub fn renameat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-+    old_dirfd: Option<RawFd>,
-+    old_path: &P1,
-+    new_dirfd: Option<RawFd>,
-+    new_path: &P2,
-+) -> Result<()> {
-     let res = old_path.with_nix_path(|old_cstr| {
-         new_path.with_nix_path(|new_cstr| unsafe {
--            libc::renameat(at_rawfd(old_dirfd), old_cstr.as_ptr(),
--                           at_rawfd(new_dirfd), new_cstr.as_ptr())
-+            libc::renameat(
-+                at_rawfd(old_dirfd),
-+                old_cstr.as_ptr(),
-+                at_rawfd(new_dirfd),
-+                new_cstr.as_ptr(),
-+            )
-         })
-     })??;
-     Errno::result(res).map(drop)
- }
- 
--fn wrap_readlink_result(buffer: &mut[u8], res: ssize_t) -> Result<&OsStr> {
--    match Errno::result(res) {
--        Err(err) => Err(err),
--        Ok(len) => {
--            if (len as usize) >= buffer.len() {
--                Err(Error::Sys(Errno::ENAMETOOLONG))
--            } else {
--                Ok(OsStr::from_bytes(&buffer[..(len as usize)]))
-+fn wrap_readlink_result(mut v: Vec<u8>, len: ssize_t) -> Result<OsString> {
-+    unsafe { v.set_len(len as usize) }
-+    v.shrink_to_fit();
-+    Ok(OsString::from_vec(v.to_vec()))
-+}
-+
-+fn readlink_maybe_at<P: ?Sized + NixPath>(
-+    dirfd: Option<RawFd>,
-+    path: &P,
-+    v: &mut Vec<u8>,
-+) -> Result<libc::ssize_t> {
-+    path.with_nix_path(|cstr| unsafe {
-+        match dirfd {
-+            #[cfg(target_os = "redox")]
-+            Some(_) => unreachable!(),
-+            #[cfg(not(target_os = "redox"))]
-+            Some(dirfd) => libc::readlinkat(
-+                dirfd,
-+                cstr.as_ptr(),
-+                v.as_mut_ptr() as *mut c_char,
-+                v.capacity() as size_t,
-+            ),
-+            None => libc::readlink(
-+                cstr.as_ptr(),
-+                v.as_mut_ptr() as *mut c_char,
-+                v.capacity() as size_t,
-+            ),
-+        }
-+    })
-+}
-+
-+fn inner_readlink<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P) -> Result<OsString> {
-+    let mut v = Vec::with_capacity(libc::PATH_MAX as usize);
-+    // simple case: result is strictly less than `PATH_MAX`
-+    let res = readlink_maybe_at(dirfd, path, &mut v)?;
-+    let len = Errno::result(res)?;
-+    debug_assert!(len >= 0);
-+    if (len as usize) < v.capacity() {
-+        return wrap_readlink_result(v, res);
-+    }
-+    // 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))
-+        .unwrap_or(0);
-+    let mut try_size = if reported_size > 0 {
-+        // Note: even if `lstat`'s apparently valid answer turns out to be
-+        // wrong, we will still read the full symlink no matter what.
-+        reported_size as usize + 1
-+    } else {
-+        // If lstat doesn't cooperate, or reports an error, be a little less
-+        // precise.
-+        (libc::PATH_MAX as usize).max(128) << 1
-+    };
-+    loop {
-+        v.reserve_exact(try_size);
-+        let res = readlink_maybe_at(dirfd, path, &mut v)?;
-+        let len = Errno::result(res)?;
-+        debug_assert!(len >= 0);
-+        if (len as usize) < v.capacity() {
-+            break wrap_readlink_result(v, res);
-+        } else {
-+            // Ugh! Still not big enough!
-+            match try_size.checked_shl(1) {
-+                Some(next_size) => try_size = next_size,
-+                // It's absurd that this would happen, but handle it sanely
-+                // anyway.
-+                None => break Err(super::Error::Sys(Errno::ENAMETOOLONG)),
-             }
-         }
-     }
- }
- 
--pub fn readlink<'a, P: ?Sized + NixPath>(path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
--    let res = path.with_nix_path(|cstr| {
--        unsafe { libc::readlink(cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
--    })?;
--
--    wrap_readlink_result(buffer, res)
-+pub fn readlink<P: ?Sized + NixPath>(path: &P) -> Result<OsString> {
-+    inner_readlink(None, path)
- }
- 
--
--pub fn readlinkat<'a, P: ?Sized + NixPath>(dirfd: RawFd, path: &P, buffer: &'a mut [u8]) -> Result<&'a OsStr> {
--    let res = path.with_nix_path(|cstr| {
--        unsafe { libc::readlinkat(dirfd, cstr.as_ptr(), buffer.as_mut_ptr() as *mut c_char, buffer.len() as size_t) }
--    })?;
--
--    wrap_readlink_result(buffer, res)
-+#[cfg(not(target_os = "redox"))]
-+pub fn readlinkat<P: ?Sized + NixPath>(dirfd: RawFd, path: &P) -> Result<OsString> {
-+    inner_readlink(Some(dirfd), path)
- }
- 
- /// Computes the raw fd consumed by a function of the form `*at`.
-+#[cfg(not(target_os = "redox"))]
- pub(crate) fn at_rawfd(fd: Option<RawFd>) -> raw::c_int {
-     match fd {
-         None => libc::AT_FDCWD,
-@@ -238,6 +320,7 @@ libc_bitflags!(
-     }
- );
- 
-+#[cfg(not(target_os = "redox"))]
- #[derive(Debug, Eq, Hash, PartialEq)]
- pub enum FcntlArg<'a> {
-     F_DUPFD(RawFd),
-@@ -265,9 +348,19 @@ pub enum FcntlArg<'a> {
-     F_GETPIPE_SZ,
-     #[cfg(any(target_os = "linux", target_os = "android"))]
-     F_SETPIPE_SZ(c_int),
--
-     // TODO: Rest of flags
- }
-+
-+#[cfg(target_os = "redox")]
-+#[derive(Debug, Clone, Copy, Eq, Hash, PartialEq)]
-+pub enum FcntlArg {
-+    F_DUPFD(RawFd),
-+    F_DUPFD_CLOEXEC(RawFd),
-+    F_GETFD,
-+    F_SETFD(FdFlag), // FD_FLAGS
-+    F_GETFL,
-+    F_SETFL(OFlag), // O_NONBLOCK
-+}
- pub use self::FcntlArg::*;
- 
- // TODO: Figure out how to handle value fcntl returns
-@@ -280,10 +373,19 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
-             F_SETFD(flag) => libc::fcntl(fd, libc::F_SETFD, flag.bits()),
-             F_GETFL => libc::fcntl(fd, libc::F_GETFL),
-             F_SETFL(flag) => libc::fcntl(fd, libc::F_SETFL, flag.bits()),
-+            #[cfg(not(target_os = "redox"))]
-             F_SETLK(flock) => libc::fcntl(fd, libc::F_SETLK, flock),
-+            #[cfg(not(target_os = "redox"))]
-             F_SETLKW(flock) => libc::fcntl(fd, libc::F_SETLKW, flock),
-+            #[cfg(not(target_os = "redox"))]
-             F_GETLK(flock) => libc::fcntl(fd, libc::F_GETLK, flock),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
-+            F_OFD_SETLK(flock) => libc::fcntl(fd, libc::F_OFD_SETLK, flock),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            F_OFD_SETLKW(flock) => libc::fcntl(fd, libc::F_OFD_SETLKW, flock),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            F_OFD_GETLK(flock) => libc::fcntl(fd, libc::F_OFD_GETLK, flock),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-             F_ADD_SEALS(flag) => libc::fcntl(fd, libc::F_ADD_SEALS, flag.bits()),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
-             F_GET_SEALS => libc::fcntl(fd, libc::F_GET_SEALS),
-@@ -293,8 +395,6 @@ pub fn fcntl(fd: RawFd, arg: FcntlArg) -> Result<c_int> {
-             F_GETPIPE_SZ => libc::fcntl(fd, libc::F_GETPIPE_SZ),
-             #[cfg(any(target_os = "linux", target_os = "android"))]
-             F_SETPIPE_SZ(size) => libc::fcntl(fd, libc::F_SETPIPE_SZ, size),
--            #[cfg(any(target_os = "linux", target_os = "android"))]
--            _ => unimplemented!()
-         }
-     };
- 
-@@ -311,6 +411,7 @@ pub enum FlockArg {
-     UnlockNonblock,
- }
- 
-+#[cfg(not(target_os = "redox"))]
- pub fn flock(fd: RawFd, arg: FlockArg) -> Result<()> {
-     use self::FlockArg::*;
- 
-@@ -410,9 +511,7 @@ pub fn splice(
-         .map(|offset| offset as *mut libc::loff_t)
-         .unwrap_or(ptr::null_mut());
- 
--    let ret = unsafe {
--        libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
--    };
-+    let ret = unsafe { libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits()) };
-     Errno::result(ret).map(|r| r as usize)
- }
- 
-@@ -425,7 +524,12 @@ pub fn tee(fd_in: RawFd, fd_out: RawFd, len: usize, flags: SpliceFFlags) -> Resu
- #[cfg(any(target_os = "linux", target_os = "android"))]
- pub fn vmsplice(fd: RawFd, iov: &[IoVec<&[u8]>], flags: SpliceFFlags) -> Result<usize> {
-     let ret = unsafe {
--        libc::vmsplice(fd, iov.as_ptr() as *const libc::iovec, iov.len(), flags.bits())
-+        libc::vmsplice(
-+            fd,
-+            iov.as_ptr() as *const libc::iovec,
-+            iov.len(),
-+            flags.bits(),
-+        )
-     };
-     Errno::result(ret).map(|r| r as usize)
- }
-@@ -466,23 +570,30 @@ libc_bitflags!(
- /// Allows the caller to directly manipulate the allocated disk space for the
- /// file referred to by fd.
- #[cfg(any(target_os = "linux"))]
--pub fn fallocate(fd: RawFd, mode: FallocateFlags, offset: libc::off_t, len: libc::off_t) -> Result<c_int> {
-+pub fn fallocate(
-+    fd: RawFd,
-+    mode: FallocateFlags,
-+    offset: libc::off_t,
-+    len: libc::off_t,
-+) -> Result<()> {
-     let res = unsafe { libc::fallocate(fd, mode.bits(), offset, len) };
--    Errno::result(res)
-+    Errno::result(res).map(drop)
- }
- 
--#[cfg(any(target_os = "linux",
--          target_os = "android",
--          target_os = "emscripten",
--          target_os = "fuchsia",
--          any(target_os = "wasi", target_env = "wasi"),
--          target_env = "uclibc",
--          target_env = "freebsd"))]
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+    target_os = "fuchsia",
-+    any(target_os = "wasi", target_env = "wasi"),
-+    target_env = "uclibc",
-+    target_os = "freebsd"
-+))]
- mod posix_fadvise {
--    use Result;
-+    use crate::errno::Errno;
-     use libc;
--    use errno::Errno;
-     use std::os::unix::io::RawFd;
-+    use crate::Result;
- 
-     libc_enum! {
-         #[repr(i32)]
-@@ -496,11 +607,30 @@ mod posix_fadvise {
-         }
-     }
- 
--    pub fn posix_fadvise(fd: RawFd,
--                         offset: libc::off_t,
--                         len: libc::off_t,
--                         advice: PosixFadviseAdvice) -> Result<libc::c_int> {
-+    pub fn posix_fadvise(
-+        fd: RawFd,
-+        offset: libc::off_t,
-+        len: libc::off_t,
-+        advice: PosixFadviseAdvice,
-+    ) -> Result<libc::c_int> {
-         let res = unsafe { libc::posix_fadvise(fd, offset, len, advice as libc::c_int) };
-         Errno::result(res)
-     }
- }
-+
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+    target_os = "fuchsia",
-+    any(target_os = "wasi", target_env = "wasi"),
-+    target_os = "freebsd"
-+))]
-+pub fn posix_fallocate(fd: RawFd, offset: libc::off_t, len: libc::off_t) -> Result<()> {
-+    let res = unsafe { libc::posix_fallocate(fd, offset, len) };
-+    match Errno::result(res) {
-+        Err(err) => Err(err),
-+        Ok(0) => Ok(()),
-+        Ok(errno) => Err(crate::Error::Sys(Errno::from_i32(errno))),
-+    }
-+}
-diff --git a/third_party/rust/nix/src/features.rs b/third_party/rust/nix/src/features.rs
-index 76cdfd3a1a6f1..6b1cff5deed1d 100644
---- a/third_party/rust/nix/src/features.rs
-+++ b/third_party/rust/nix/src/features.rs
-@@ -3,7 +3,7 @@ pub use self::os::*;
- 
- #[cfg(any(target_os = "linux", target_os = "android"))]
- mod os {
--    use sys::utsname::uname;
-+    use crate::sys::utsname::uname;
- 
-     // Features:
-     // * atomic cloexec on socket: 2.6.27
-@@ -94,7 +94,10 @@ mod os {
-     }
- }
- 
--#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "dragonfly", target_os = "ios", target_os = "openbsd", target_os = "netbsd"))]
-+#[cfg(any(target_os = "macos", target_os = "freebsd",
-+          target_os = "dragonfly", target_os = "ios",
-+          target_os = "openbsd", target_os = "netbsd",
-+          target_os = "redox", target_os = "fuchsia"))]
- mod os {
-     /// Check if the OS supports atomic close-on-exec for sockets
-     pub fn socket_atomic_cloexec() -> bool {
-diff --git a/third_party/rust/nix/src/ifaddrs.rs b/third_party/rust/nix/src/ifaddrs.rs
-index 12b59bcc92bef..ed6328f3efab2 100644
---- a/third_party/rust/nix/src/ifaddrs.rs
-+++ b/third_party/rust/nix/src/ifaddrs.rs
-@@ -3,16 +3,15 @@
- //! Uses the Linux and/or BSD specific function `getifaddrs` to query the list
- //! of interfaces and their associated addresses.
- 
-+use cfg_if::cfg_if;
- use std::ffi;
- use std::iter::Iterator;
- use std::mem;
- use std::option::Option;
- 
--use libc;
--
--use {Result, Errno};
--use sys::socket::SockAddr;
--use net::if_::*;
-+use crate::{Result, Errno};
-+use crate::sys::socket::SockAddr;
-+use crate::net::if_::*;
- 
- /// Describes a single address for an interface as returned by `getifaddrs`.
- #[derive(Clone, Debug, Eq, Hash, PartialEq)]
-@@ -52,8 +51,8 @@ impl InterfaceAddress {
-         let mut addr = InterfaceAddress {
-             interface_name: ifname.to_string_lossy().to_string(),
-             flags: InterfaceFlags::from_bits_truncate(info.ifa_flags as i32),
--            address: address,
--            netmask: netmask,
-+            address,
-+            netmask,
-             broadcast: None,
-             destination: None,
-         };
-@@ -125,13 +124,15 @@ impl Iterator for InterfaceAddressIterator {
- /// }
- /// ```
- pub fn getifaddrs() -> Result<InterfaceAddressIterator> {
--    let mut addrs: *mut libc::ifaddrs = unsafe { mem::uninitialized() };
--    Errno::result(unsafe { libc::getifaddrs(&mut addrs) }).map(|_| {
--        InterfaceAddressIterator {
--            base: addrs,
--            next: addrs,
--        }
--    })
-+    let mut addrs = mem::MaybeUninit::<*mut libc::ifaddrs>::uninit();
-+    unsafe {
-+        Errno::result(libc::getifaddrs(addrs.as_mut_ptr())).map(|_| {
-+            InterfaceAddressIterator {
-+                base: addrs.assume_init(),
-+                next: addrs.assume_init(),
-+            }
-+        })
-+    }
- }
- 
- #[cfg(test)]
-diff --git a/third_party/rust/nix/src/kmod.rs b/third_party/rust/nix/src/kmod.rs
-index e853261b14f9d..8789cb69f4617 100644
---- a/third_party/rust/nix/src/kmod.rs
-+++ b/third_party/rust/nix/src/kmod.rs
-@@ -6,8 +6,8 @@ use libc;
- use std::ffi::CStr;
- use std::os::unix::io::AsRawFd;
- 
--use errno::Errno;
--use Result;
-+use crate::errno::Errno;
-+use crate::Result;
- 
- /// Loads a kernel module from a buffer.
- ///
-diff --git a/third_party/rust/nix/src/lib.rs b/third_party/rust/nix/src/lib.rs
-index 71485d2af1824..e62c158c8bc9b 100644
---- a/third_party/rust/nix/src/lib.rs
-+++ b/third_party/rust/nix/src/lib.rs
-@@ -14,24 +14,17 @@
- #![deny(unstable_features)]
- #![deny(missing_copy_implementations)]
- #![deny(missing_debug_implementations)]
--// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
--#![allow(deprecated)]
--
--// External crates
--#[macro_use]
--extern crate bitflags;
--#[macro_use]
--extern crate cfg_if;
--extern crate void;
- 
- // Re-exported external crates
--pub extern crate libc;
-+pub use libc;
- 
- // Private internal modules
- #[macro_use] mod macros;
- 
- // Public crates
-+#[cfg(not(target_os = "redox"))]
- pub mod dir;
-+pub mod env;
- pub mod errno;
- #[deny(missing_docs)]
- pub mod features;
-@@ -59,13 +52,16 @@ pub mod mount;
-           target_os = "netbsd"))]
- pub mod mqueue;
- #[deny(missing_docs)]
-+#[cfg(not(target_os = "redox"))]
- pub mod net;
- #[deny(missing_docs)]
- pub mod poll;
- #[deny(missing_docs)]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- pub mod pty;
- pub mod sched;
- pub mod sys;
-+pub mod time;
- // This can be implemented for other platforms as soon as libc
- // provides bindings for them.
- #[cfg(all(target_os = "linux",
-@@ -121,9 +117,9 @@ impl Error {
-     /// let e = Error::from(Errno::EPERM);
-     /// assert_eq!(Some(Errno::EPERM), e.as_errno());
-     /// ```
--    pub fn as_errno(&self) -> Option<Errno> {
--        if let &Error::Sys(ref e) = self {
--            Some(*e)
-+    pub fn as_errno(self) -> Option<Errno> {
-+        if let Error::Sys(e) = self {
-+            Some(e)
-         } else {
-             None
-         }
-@@ -154,16 +150,7 @@ impl From<std::string::FromUtf8Error> for Error {
-     fn from(_: std::string::FromUtf8Error) -> Error { Error::InvalidUtf8 }
- }
- 
--impl error::Error for Error {
--    fn description(&self) -> &str {
--        match *self {
--            Error::InvalidPath => "Invalid path",
--            Error::InvalidUtf8 => "Invalid UTF-8 string",
--            Error::UnsupportedOperation => "Unsupported Operation",
--            Error::Sys(ref errno) => errno.desc(),
--        }
--    }
--}
-+impl error::Error for Error {}
- 
- impl fmt::Display for Error {
-     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-@@ -177,6 +164,8 @@ impl fmt::Display for Error {
- }
- 
- pub trait NixPath {
-+    fn is_empty(&self) -> bool;
-+
-     fn len(&self) -> usize;
- 
-     fn with_nix_path<T, F>(&self, f: F) -> Result<T>
-@@ -184,6 +173,10 @@ pub trait NixPath {
- }
- 
- impl NixPath for str {
-+    fn is_empty(&self) -> bool {
-+        NixPath::is_empty(OsStr::new(self))
-+    }
-+
-     fn len(&self) -> usize {
-         NixPath::len(OsStr::new(self))
-     }
-@@ -195,6 +188,10 @@ impl NixPath for str {
- }
- 
- impl NixPath for OsStr {
-+    fn is_empty(&self) -> bool {
-+        self.as_bytes().is_empty()
-+    }
-+
-     fn len(&self) -> usize {
-         self.as_bytes().len()
-     }
-@@ -206,6 +203,10 @@ impl NixPath for OsStr {
- }
- 
- impl NixPath for CStr {
-+    fn is_empty(&self) -> bool {
-+        self.to_bytes().is_empty()
-+    }
-+
-     fn len(&self) -> usize {
-         self.to_bytes().len()
-     }
-@@ -222,6 +223,10 @@ impl NixPath for CStr {
- }
- 
- impl NixPath for [u8] {
-+    fn is_empty(&self) -> bool {
-+        self.is_empty()
-+    }
-+
-     fn len(&self) -> usize {
-         self.len()
-     }
-@@ -249,6 +254,10 @@ impl NixPath for [u8] {
- }
- 
- impl NixPath for Path {
-+    fn is_empty(&self) -> bool {
-+        NixPath::is_empty(self.as_os_str())
-+    }
-+
-     fn len(&self) -> usize {
-         NixPath::len(self.as_os_str())
-     }
-@@ -259,26 +268,15 @@ impl NixPath for Path {
- }
- 
- impl NixPath for PathBuf {
--    fn len(&self) -> usize {
--        NixPath::len(self.as_os_str())
-+    fn is_empty(&self) -> bool {
-+        NixPath::is_empty(self.as_os_str())
-     }
- 
--    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
--        self.as_os_str().with_nix_path(f)
--    }
--}
--
--/// Treats `None` as an empty string.
--impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
-     fn len(&self) -> usize {
--        self.map_or(0, NixPath::len)
-+        NixPath::len(self.as_os_str())
-     }
- 
-     fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
--        if let Some(nix_path) = *self {
--            nix_path.with_nix_path(f)
--        } else {
--            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
--        }
-+        self.as_os_str().with_nix_path(f)
-     }
- }
-diff --git a/third_party/rust/nix/src/macros.rs b/third_party/rust/nix/src/macros.rs
-index 3d1b0e4b7699c..7d6ac8dfbf5f7 100644
---- a/third_party/rust/nix/src/macros.rs
-+++ b/third_party/rust/nix/src/macros.rs
-@@ -48,7 +48,7 @@ macro_rules! libc_bitflags {
-             )+
-         }
-     ) => {
--        bitflags! {
-+        ::bitflags::bitflags! {
-             $(#[$outer])*
-             pub struct $BitFlags: $T {
-                 $(
-@@ -81,9 +81,10 @@ macro_rules! libc_bitflags {
- /// }
- /// ```
- macro_rules! libc_enum {
--    // (non-pub) Exit rule.
-+    // Exit rule.
-     (@make_enum
-         {
-+            $v:vis
-             name: $BitFlags:ident,
-             attrs: [$($attrs:tt)*],
-             entries: [$($entries:tt)*],
-@@ -91,49 +92,15 @@ macro_rules! libc_enum {
-     ) => {
-         $($attrs)*
-         #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
--        enum $BitFlags {
-+        $v enum $BitFlags {
-             $($entries)*
-         }
-     };
- 
--    // (pub) Exit rule.
--    (@make_enum
--        {
--            pub,
--            name: $BitFlags:ident,
--            attrs: [$($attrs:tt)*],
--            entries: [$($entries:tt)*],
--        }
--    ) => {
--        $($attrs)*
--        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
--        pub enum $BitFlags {
--            $($entries)*
--        }
--    };
--
--    // (non-pub) Done accumulating.
--    (@accumulate_entries
--        {
--            name: $BitFlags:ident,
--            attrs: $attrs:tt,
--        },
--        $entries:tt;
--    ) => {
--        libc_enum! {
--            @make_enum
--            {
--                name: $BitFlags,
--                attrs: $attrs,
--                entries: $entries,
--            }
--        }
--    };
--
--    // (pub) Done accumulating.
-+    // Done accumulating.
-     (@accumulate_entries
-         {
--            pub,
-+            $v:vis
-             name: $BitFlags:ident,
-             attrs: $attrs:tt,
-         },
-@@ -142,7 +109,7 @@ macro_rules! libc_enum {
-         libc_enum! {
-             @make_enum
-             {
--                pub,
-+                $v
-                 name: $BitFlags,
-                 attrs: $attrs,
-                 entries: $entries,
-@@ -217,35 +184,17 @@ macro_rules! libc_enum {
-         }
-     };
- 
--    // (non-pub) Entry rule.
--    (
--        $(#[$attr:meta])*
--        enum $BitFlags:ident {
--            $($vals:tt)*
--        }
--    ) => {
--        libc_enum! {
--            @accumulate_entries
--            {
--                name: $BitFlags,
--                attrs: [$(#[$attr])*],
--            },
--            [];
--            $($vals)*
--        }
--    };
--
--    // (pub) Entry rule.
-+    // Entry rule.
-     (
-         $(#[$attr:meta])*
--        pub enum $BitFlags:ident {
-+        $v:vis enum $BitFlags:ident {
-             $($vals:tt)*
-         }
-     ) => {
-         libc_enum! {
-             @accumulate_entries
-             {
--                pub,
-+                $v
-                 name: $BitFlags,
-                 attrs: [$(#[$attr])*],
-             },
-@@ -254,11 +203,3 @@ macro_rules! libc_enum {
-         }
-     };
- }
--
--/// A Rust version of the familiar C `offset_of` macro.  It returns the byte
--/// offset of `field` within struct `ty`
--macro_rules! offset_of {
--    ($ty:ty, $field:ident) => {
--        &(*(0 as *const $ty)).$field as *const _ as usize
--    }
--}
-diff --git a/third_party/rust/nix/src/mount.rs b/third_party/rust/nix/src/mount.rs
-index a9902b170ace8..2c54761e2bb0c 100644
---- a/third_party/rust/nix/src/mount.rs
-+++ b/third_party/rust/nix/src/mount.rs
-@@ -1,6 +1,6 @@
- use libc::{self, c_ulong, c_int};
--use {Result, NixPath};
--use errno::Errno;
-+use crate::{Result, NixPath};
-+use crate::errno::Errno;
- 
- libc_bitflags!(
-     pub struct MsFlags: c_ulong {
-@@ -61,22 +61,33 @@ pub fn mount<P1: ?Sized + NixPath, P2: ?Sized + NixPath, P3: ?Sized + NixPath, P
-         flags: MsFlags,
-         data: Option<&P4>) -> Result<()> {
- 
--    let res =
--        source.with_nix_path(|source| {
--            target.with_nix_path(|target| {
--                fstype.with_nix_path(|fstype| {
--                    data.with_nix_path(|data| {
--                        unsafe {
--                            libc::mount(source.as_ptr(),
--                                       target.as_ptr(),
--                                       fstype.as_ptr(),
--                                       flags.bits,
--                                       data.as_ptr() as *const libc::c_void)
--                        }
--                    })
-+    fn with_opt_nix_path<P, T, F>(p: Option<&P>, f: F) -> Result<T>
-+        where P: ?Sized + NixPath,
-+              F: FnOnce(*const libc::c_char) -> T
-+    {
-+        match p {
-+            Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
-+            None => Ok(f(std::ptr::null()))
-+        }
-+    }
-+
-+    let res = with_opt_nix_path(source, |s| {
-+        target.with_nix_path(|t| {
-+            with_opt_nix_path(fstype, |ty| {
-+                with_opt_nix_path(data, |d| {
-+                    unsafe {
-+                        libc::mount(
-+                            s,
-+                            t.as_ptr(),
-+                            ty,
-+                            flags.bits,
-+                            d as *const libc::c_void
-+                        )
-+                    }
-                 })
-             })
--        })????;
-+        })
-+    })????;
- 
-     Errno::result(res).map(drop)
- }
-diff --git a/third_party/rust/nix/src/mqueue.rs b/third_party/rust/nix/src/mqueue.rs
-index b958b71cddb46..0215de5af214b 100644
---- a/third_party/rust/nix/src/mqueue.rs
-+++ b/third_party/rust/nix/src/mqueue.rs
-@@ -2,12 +2,12 @@
- //!
- //! [Further reading and details on the C API](http://man7.org/linux/man-pages/man7/mq_overview.7.html)
- 
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- 
--use libc::{self, c_char, c_long, mqd_t, size_t};
-+use libc::{self, c_char, mqd_t, size_t};
- use std::ffi::CString;
--use sys::stat::Mode;
-+use crate::sys::stat::Mode;
- use std::mem;
- 
- libc_bitflags!{
-@@ -34,21 +34,32 @@ pub struct MqAttr {
-     mq_attr: libc::mq_attr,
- }
- 
-+// x32 compatibility
-+// See https://sourceware.org/bugzilla/show_bug.cgi?id=21279
-+#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-+pub type mq_attr_member_t = i64;
-+#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-+pub type mq_attr_member_t = libc::c_long;
-+
- impl MqAttr {
--    pub fn new(mq_flags: c_long,
--               mq_maxmsg: c_long,
--               mq_msgsize: c_long,
--               mq_curmsgs: c_long)
--               -> MqAttr {
--        let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
--        attr.mq_flags = mq_flags;
--        attr.mq_maxmsg = mq_maxmsg;
--        attr.mq_msgsize = mq_msgsize;
--        attr.mq_curmsgs = mq_curmsgs;
--        MqAttr { mq_attr: attr }
-+    pub fn new(mq_flags: mq_attr_member_t,
-+               mq_maxmsg: mq_attr_member_t,
-+               mq_msgsize: mq_attr_member_t,
-+               mq_curmsgs: mq_attr_member_t)
-+               -> MqAttr
-+    {
-+        let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
-+        unsafe {
-+            let p = attr.as_mut_ptr();
-+            (*p).mq_flags = mq_flags;
-+            (*p).mq_maxmsg = mq_maxmsg;
-+            (*p).mq_msgsize = mq_msgsize;
-+            (*p).mq_curmsgs = mq_curmsgs;
-+            MqAttr { mq_attr: attr.assume_init() }
-+        }
-     }
- 
--    pub fn flags(&self) -> c_long {
-+    pub fn flags(&self) -> mq_attr_member_t {
-         self.mq_attr.mq_flags
-     }
- }
-@@ -57,6 +68,8 @@ impl MqAttr {
- /// Open a message queue
- ///
- /// See also [`mq_open(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_open.html)
-+// The mode.bits cast is only lossless on some OSes
-+#[allow(clippy::cast_lossless)]
- pub fn mq_open(name: &CString,
-                oflag: MQ_OFlag,
-                mode: Mode,
-@@ -121,9 +134,9 @@ pub fn mq_send(mqdes: mqd_t, message: &[u8], msq_prio: u32) -> Result<()> {
- ///
- /// See also [`mq_getattr(2)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_getattr.html)
- pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
--    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
--    let res = unsafe { libc::mq_getattr(mqd, &mut attr) };
--    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
-+    let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
-+    let res = unsafe { libc::mq_getattr(mqd, attr.as_mut_ptr()) };
-+    Errno::result(res).map(|_| unsafe{MqAttr { mq_attr: attr.assume_init() }})
- }
- 
- /// Set the attributes of the message queue. Only `O_NONBLOCK` can be set, everything else will be ignored
-@@ -132,17 +145,19 @@ pub fn mq_getattr(mqd: mqd_t) -> Result<MqAttr> {
- ///
- /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mq_setattr.html)
- pub fn mq_setattr(mqd: mqd_t, newattr: &MqAttr) -> Result<MqAttr> {
--    let mut attr = unsafe { mem::uninitialized::<libc::mq_attr>() };
--    let res = unsafe { libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, &mut attr) };
--    Errno::result(res).map(|_| MqAttr { mq_attr: attr })
-+    let mut attr = mem::MaybeUninit::<libc::mq_attr>::uninit();
-+    let res = unsafe {
-+        libc::mq_setattr(mqd, &newattr.mq_attr as *const libc::mq_attr, attr.as_mut_ptr())
-+    };
-+    Errno::result(res).map(|_| unsafe{ MqAttr { mq_attr: attr.assume_init() }})
- }
- 
- /// Convenience function.
- /// Sets the `O_NONBLOCK` attribute for a given message queue descriptor
- /// Returns the old attributes
--pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
-+pub fn mq_set_nonblock(mqd: mqd_t) -> Result<MqAttr> {
-     let oldattr = mq_getattr(mqd)?;
--    let newattr = MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long,
-+    let newattr = MqAttr::new(mq_attr_member_t::from(MQ_OFlag::O_NONBLOCK.bits()),
-                               oldattr.mq_attr.mq_maxmsg,
-                               oldattr.mq_attr.mq_msgsize,
-                               oldattr.mq_attr.mq_curmsgs);
-@@ -152,7 +167,7 @@ pub fn mq_set_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
- /// Convenience function.
- /// Removes `O_NONBLOCK` attribute for a given message queue descriptor
- /// Returns the old attributes
--pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<(MqAttr)> {
-+pub fn mq_remove_nonblock(mqd: mqd_t) -> Result<MqAttr> {
-     let oldattr = mq_getattr(mqd)?;
-     let newattr = MqAttr::new(0,
-                               oldattr.mq_attr.mq_maxmsg,
-diff --git a/third_party/rust/nix/src/net/if_.rs b/third_party/rust/nix/src/net/if_.rs
-index 58d677ae343d1..96364884e39cb 100644
---- a/third_party/rust/nix/src/net/if_.rs
-+++ b/third_party/rust/nix/src/net/if_.rs
-@@ -3,9 +3,8 @@
- //! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
- //! or "socan1" into device numbers.
- 
--use libc;
- use libc::c_uint;
--use {Result, Error, NixPath};
-+use crate::{Result, Error, NixPath};
- 
- /// Resolve an interface into a interface number.
- pub fn if_nametoindex<P: ?Sized + NixPath>(name: &P) -> Result<c_uint> {
-diff --git a/third_party/rust/nix/src/poll.rs b/third_party/rust/nix/src/poll.rs
-index c603611e3176f..be5bf224990f2 100644
---- a/third_party/rust/nix/src/poll.rs
-+++ b/third_party/rust/nix/src/poll.rs
-@@ -1,13 +1,12 @@
- //! Wait for events to trigger on specific file descriptors
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
--use sys::time::TimeSpec;
-+use crate::sys::time::TimeSpec;
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
--use sys::signal::SigSet;
-+use crate::sys::signal::SigSet;
- use std::os::unix::io::RawFd;
- 
--use libc;
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- 
- /// This is a wrapper around `libc::pollfd`.
- ///
-@@ -17,7 +16,7 @@ use errno::Errno;
- ///
- /// After a call to `poll` or `ppoll`, the events that occured can be
- /// retrieved by calling [`revents()`](#method.revents) on the `PollFd`.
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct PollFd {
-     pollfd: libc::pollfd,
-@@ -29,7 +28,7 @@ impl PollFd {
-     pub fn new(fd: RawFd, events: PollFlags) -> PollFd {
-         PollFd {
-             pollfd: libc::pollfd {
--                fd: fd,
-+                fd,
-                 events: events.bits(),
-                 revents: PollFlags::empty().bits(),
-             },
-@@ -37,7 +36,7 @@ impl PollFd {
-     }
- 
-     /// Returns the events that occured in the last call to `poll` or `ppoll`.
--    pub fn revents(&self) -> Option<PollFlags> {
-+    pub fn revents(self) -> Option<PollFlags> {
-         PollFlags::from_bits(self.pollfd.revents)
-     }
- }
-@@ -64,12 +63,16 @@ libc_bitflags! {
-         /// `O_NONBLOCK` is set).
-         POLLOUT;
-         /// Equivalent to [`POLLIN`](constant.POLLIN.html)
-+        #[cfg(not(target_os = "redox"))]
-         POLLRDNORM;
-+        #[cfg(not(target_os = "redox"))]
-         /// Equivalent to [`POLLOUT`](constant.POLLOUT.html)
-         POLLWRNORM;
-         /// Priority band data can be read (generally unused on Linux).
-+        #[cfg(not(target_os = "redox"))]
-         POLLRDBAND;
-         /// Priority data may be written.
-+        #[cfg(not(target_os = "redox"))]
-         POLLWRBAND;
-         /// Error condition (only returned in
-         /// [`PollFd::revents`](struct.PollFd.html#method.revents);
-@@ -127,16 +130,16 @@ pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<libc::c_int> {
- /// ([`poll(2)`](http://man7.org/linux/man-pages/man2/poll.2.html))
- ///
- /// `ppoll` behaves like `poll`, but let you specify what signals may interrupt it
--/// with the `sigmask` argument.
-+/// with the `sigmask` argument. If you want `ppoll` to block indefinitely,
-+/// specify `None` as `timeout` (it is like `timeout = -1` for `poll`).
- ///
- #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
--pub fn ppoll(fds: &mut [PollFd], timeout: TimeSpec, sigmask: SigSet) -> Result<libc::c_int> {
--
--
-+pub fn ppoll(fds: &mut [PollFd], timeout: Option<TimeSpec>, sigmask: SigSet) -> Result<libc::c_int> {
-+    let timeout = timeout.as_ref().map_or(core::ptr::null(), |r| r.as_ref());
-     let res = unsafe {
-         libc::ppoll(fds.as_mut_ptr() as *mut libc::pollfd,
-                     fds.len() as libc::nfds_t,
--                    timeout.as_ref(),
-+                    timeout,
-                     sigmask.as_ref())
-     };
-     Errno::result(res)
-diff --git a/third_party/rust/nix/src/pty.rs b/third_party/rust/nix/src/pty.rs
-index db012d8158c53..d67518f4744f3 100644
---- a/third_party/rust/nix/src/pty.rs
-+++ b/third_party/rust/nix/src/pty.rs
-@@ -1,18 +1,17 @@
- //! Create master and slave virtual pseudo-terminals (PTYs)
- 
--use libc;
--
- pub use libc::pid_t as SessionId;
- pub use libc::winsize as Winsize;
- 
- use std::ffi::CStr;
-+use std::io;
- use std::mem;
- use std::os::unix::prelude::*;
- 
--use sys::termios::Termios;
--use unistd::ForkResult;
--use {Result, Error, fcntl};
--use errno::Errno;
-+use crate::sys::termios::Termios;
-+use crate::unistd::{self, ForkResult, Pid};
-+use crate::{Result, Error, fcntl};
-+use crate::errno::Errno;
- 
- /// Representation of a master/slave pty pair
- ///
-@@ -44,7 +43,7 @@ pub struct ForkptyResult {
- /// While this datatype is a thin wrapper around `RawFd`, it enforces that the available PTY
- /// functions are given the correct file descriptor. Additionally this type implements `Drop`,
- /// so that when it's consumed or goes out of scope, it's automatically cleaned-up.
--#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+#[derive(Debug, Eq, Hash, PartialEq)]
- pub struct PtyMaster(RawFd);
- 
- impl AsRawFd for PtyMaster {
-@@ -70,13 +69,28 @@ impl Drop for PtyMaster {
-         // invalid file descriptor.  That frequently indicates a double-close
-         // condition, which can cause confusing errors for future I/O
-         // operations.
--        let e = ::unistd::close(self.0);
-+        let e = unistd::close(self.0);
-         if e == Err(Error::Sys(Errno::EBADF)) {
-             panic!("Closing an invalid file descriptor!");
-         };
-     }
- }
- 
-+impl io::Read for PtyMaster {
-+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-+        unistd::read(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
-+    }
-+}
-+
-+impl io::Write for PtyMaster {
-+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-+        unistd::write(self.0, buf).map_err(|e| e.as_errno().unwrap().into())
-+    }
-+    fn flush(&mut self) -> io::Result<()> {
-+        Ok(())
-+    }
-+}
-+
- /// Grant access to a slave pseudoterminal (see
- /// [`grantpt(3)`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/grantpt.html))
- ///
-@@ -218,16 +232,16 @@ pub fn unlockpt(fd: &PtyMaster) -> Result<()> {
- pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(winsize: T, termios: U) -> Result<OpenptyResult> {
-     use std::ptr;
- 
--    let mut slave: libc::c_int = unsafe { mem::uninitialized() };
--    let mut master: libc::c_int = unsafe { mem::uninitialized() };
-+    let mut slave = mem::MaybeUninit::<libc::c_int>::uninit();
-+    let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
-     let ret = {
-         match (termios.into(), winsize.into()) {
-             (Some(termios), Some(winsize)) => {
-                 let inner_termios = termios.get_libc_termios();
-                 unsafe {
-                     libc::openpty(
--                        &mut master,
--                        &mut slave,
-+                        master.as_mut_ptr(),
-+                        slave.as_mut_ptr(),
-                         ptr::null_mut(),
-                         &*inner_termios as *const libc::termios as *mut _,
-                         winsize as *const Winsize as *mut _,
-@@ -237,8 +251,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
-             (None, Some(winsize)) => {
-                 unsafe {
-                     libc::openpty(
--                        &mut master,
--                        &mut slave,
-+                        master.as_mut_ptr(),
-+                        slave.as_mut_ptr(),
-                         ptr::null_mut(),
-                         ptr::null_mut(),
-                         winsize as *const Winsize as *mut _,
-@@ -249,8 +263,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
-                 let inner_termios = termios.get_libc_termios();
-                 unsafe {
-                     libc::openpty(
--                        &mut master,
--                        &mut slave,
-+                        master.as_mut_ptr(),
-+                        slave.as_mut_ptr(),
-                         ptr::null_mut(),
-                         &*inner_termios as *const libc::termios as *mut _,
-                         ptr::null_mut(),
-@@ -260,8 +274,8 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
-             (None, None) => {
-                 unsafe {
-                     libc::openpty(
--                        &mut master,
--                        &mut slave,
-+                        master.as_mut_ptr(),
-+                        slave.as_mut_ptr(),
-                         ptr::null_mut(),
-                         ptr::null_mut(),
-                         ptr::null_mut(),
-@@ -273,10 +287,12 @@ pub fn openpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
- 
-     Errno::result(ret)?;
- 
--    Ok(OpenptyResult {
--        master: master,
--        slave: slave,
--    })
-+    unsafe {
-+        Ok(OpenptyResult {
-+            master: master.assume_init(),
-+            slave: slave.assume_init(),
-+        })
-+    }
- }
- 
- /// Create a new pseudoterminal, returning the master file descriptor and forked pid.
-@@ -291,10 +307,8 @@ pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
-     termios: U,
- ) -> Result<ForkptyResult> {
-     use std::ptr;
--    use unistd::Pid;
--    use unistd::ForkResult::*;
- 
--    let mut master: libc::c_int = unsafe { mem::uninitialized() };
-+    let mut master = mem::MaybeUninit::<libc::c_int>::uninit();
- 
-     let term = match termios.into() {
-         Some(termios) => {
-@@ -310,17 +324,19 @@ pub fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>
-         .unwrap_or(ptr::null_mut());
- 
-     let res = unsafe {
--        libc::forkpty(&mut master, ptr::null_mut(), term, win)
-+        libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win)
-     };
- 
-     let fork_result = Errno::result(res).map(|res| match res {
--        0 => Child,
--        res => Parent { child: Pid::from_raw(res) },
-+        0 => ForkResult::Child,
-+        res => ForkResult::Parent { child: Pid::from_raw(res) },
-     })?;
- 
--    Ok(ForkptyResult {
--        master: master,
--        fork_result: fork_result,
--    })
-+    unsafe {
-+        Ok(ForkptyResult {
-+            master: master.assume_init(),
-+            fork_result,
-+        })
-+    }
- }
- 
-diff --git a/third_party/rust/nix/src/sched.rs b/third_party/rust/nix/src/sched.rs
-index 67188c57eef7d..3b48b4adf6d05 100644
---- a/third_party/rust/nix/src/sched.rs
-+++ b/third_party/rust/nix/src/sched.rs
-@@ -1,18 +1,17 @@
--use libc;
--use {Errno, Result};
-+use crate::{Errno, Result};
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub use self::sched_linux_like::*;
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- mod sched_linux_like {
--    use errno::Errno;
-+    use crate::errno::Errno;
-     use libc::{self, c_int, c_void};
-     use std::mem;
-     use std::option::Option;
-     use std::os::unix::io::RawFd;
--    use unistd::Pid;
--    use {Error, Result};
-+    use crate::unistd::Pid;
-+    use crate::{Error, Result};
- 
-     // For some functions taking with a parameter of type CloneFlags,
-     // only a subset of these flags have an effect.
-@@ -46,6 +45,11 @@ mod sched_linux_like {
- 
-     pub type CloneCb<'a> = Box<dyn FnMut() -> isize + 'a>;
- 
-+    /// CpuSet represent a bit-mask of CPUs.
-+    /// CpuSets are used by sched_setaffinity and
-+    /// sched_getaffinity for example.
-+    ///
-+    /// This is a wrapper around `libc::cpu_set_t`.
-     #[repr(C)]
-     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-     pub struct CpuSet {
-@@ -53,37 +57,78 @@ mod sched_linux_like {
-     }
- 
-     impl CpuSet {
-+        /// Create a new and empty CpuSet.
-         pub fn new() -> CpuSet {
-             CpuSet {
-                 cpu_set: unsafe { mem::zeroed() },
-             }
-         }
- 
-+        /// Test to see if a CPU is in the CpuSet.
-+        /// `field` is the CPU id to test
-         pub fn is_set(&self, field: usize) -> Result<bool> {
--            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+            if field >= CpuSet::count() {
-                 Err(Error::Sys(Errno::EINVAL))
-             } else {
-                 Ok(unsafe { libc::CPU_ISSET(field, &self.cpu_set) })
-             }
-         }
- 
-+        /// Add a CPU to CpuSet.
-+        /// `field` is the CPU id to add
-         pub fn set(&mut self, field: usize) -> Result<()> {
--            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+            if field >= CpuSet::count() {
-                 Err(Error::Sys(Errno::EINVAL))
-             } else {
--                Ok(unsafe { libc::CPU_SET(field, &mut self.cpu_set) })
-+                unsafe { libc::CPU_SET(field, &mut self.cpu_set); }
-+                Ok(())
-             }
-         }
- 
-+        /// Remove a CPU from CpuSet.
-+        /// `field` is the CPU id to remove
-         pub fn unset(&mut self, field: usize) -> Result<()> {
--            if field >= 8 * mem::size_of::<libc::cpu_set_t>() {
-+            if field >= CpuSet::count() {
-                 Err(Error::Sys(Errno::EINVAL))
-             } else {
--                Ok(unsafe { libc::CPU_CLR(field, &mut self.cpu_set) })
-+                unsafe { libc::CPU_CLR(field, &mut self.cpu_set);}
-+                Ok(())
-             }
-         }
-+
-+        /// Return the maximum number of CPU in CpuSet
-+        pub fn count() -> usize {
-+            8 * mem::size_of::<libc::cpu_set_t>()
-+        }
-     }
- 
-+    impl Default for CpuSet {
-+        fn default() -> Self {
-+            Self::new()
-+        }
-+    }
-+
-+    /// `sched_setaffinity` set a thread's CPU affinity mask
-+    /// ([`sched_setaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_setaffinity.2.html))
-+    ///
-+    /// `pid` is the thread ID to update.
-+    /// If pid is zero, then the calling thread is updated.
-+    ///
-+    /// The `cpuset` argument specifies the set of CPUs on which the thread
-+    /// will be eligible to run.
-+    ///
-+    /// # Example
-+    ///
-+    /// Binding the current thread to CPU 0 can be done as follows:
-+    ///
-+    /// ```rust,no_run
-+    /// use nix::sched::{CpuSet, sched_setaffinity};
-+    /// use nix::unistd::Pid;
-+    ///
-+    /// let mut cpu_set = CpuSet::new();
-+    /// cpu_set.set(0);
-+    /// sched_setaffinity(Pid::from_raw(0), &cpu_set);
-+    /// ```
-     pub fn sched_setaffinity(pid: Pid, cpuset: &CpuSet) -> Result<()> {
-         let res = unsafe {
-             libc::sched_setaffinity(
-@@ -96,6 +141,41 @@ mod sched_linux_like {
-         Errno::result(res).map(drop)
-     }
- 
-+    /// `sched_getaffinity` get a thread's CPU affinity mask
-+    /// ([`sched_getaffinity(2)`](http://man7.org/linux/man-pages/man2/sched_getaffinity.2.html))
-+    ///
-+    /// `pid` is the thread ID to check.
-+    /// If pid is zero, then the calling thread is checked.
-+    ///
-+    /// Returned `cpuset` is the set of CPUs on which the thread
-+    /// is eligible to run.
-+    ///
-+    /// # Example
-+    ///
-+    /// Checking if the current thread can run on CPU 0 can be done as follows:
-+    ///
-+    /// ```rust,no_run
-+    /// use nix::sched::sched_getaffinity;
-+    /// use nix::unistd::Pid;
-+    ///
-+    /// let cpu_set = sched_getaffinity(Pid::from_raw(0)).unwrap();
-+    /// if cpu_set.is_set(0).unwrap() {
-+    ///     println!("Current thread can run on CPU 0");
-+    /// }
-+    /// ```
-+    pub fn sched_getaffinity(pid: Pid) -> Result<CpuSet> {
-+        let mut cpuset = CpuSet::new();
-+        let res = unsafe {
-+            libc::sched_getaffinity(
-+                pid.into(),
-+                mem::size_of::<CpuSet>() as libc::size_t,
-+                &mut cpuset.cpu_set,
-+            )
-+        };
-+
-+        Errno::result(res).and(Ok(cpuset))
-+    }
-+
-     pub fn clone(
-         mut cb: CloneCb,
-         stack: &mut [u8],
-@@ -109,8 +189,8 @@ mod sched_linux_like {
- 
-         let res = unsafe {
-             let combined = flags.bits() | signal.unwrap_or(0);
--            let ptr = stack.as_mut_ptr().offset(stack.len() as isize);
--            let ptr_aligned = ptr.offset((ptr as usize % 16) as isize * -1);
-+            let ptr = stack.as_mut_ptr().add(stack.len());
-+            let ptr_aligned = ptr.sub(ptr as usize % 16);
-             libc::clone(
-                 mem::transmute(
-                     callback as extern "C" fn(*mut Box<dyn FnMut() -> isize>) -> i32,
-diff --git a/third_party/rust/nix/src/sys/aio.rs b/third_party/rust/nix/src/sys/aio.rs
-index 9258a0657cc8a..1afdb35866c28 100644
---- a/third_party/rust/nix/src/sys/aio.rs
-+++ b/third_party/rust/nix/src/sys/aio.rs
-@@ -21,20 +21,19 @@
- //! [`aio_cancel_all`](fn.aio_cancel_all.html), though the operating system may
- //! not support this for all filesystems and devices.
- 
--use {Error, Result};
--use errno::Errno;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
- use std::os::unix::io::RawFd;
- use libc::{c_void, off_t, size_t};
--use libc;
- use std::borrow::{Borrow, BorrowMut};
- use std::fmt;
- use std::fmt::Debug;
- use std::marker::PhantomData;
- use std::mem;
- use std::ptr::{null, null_mut};
--use sys::signal::*;
-+use crate::sys::signal::*;
- use std::thread;
--use sys::time::TimeSpec;
-+use crate::sys::time::TimeSpec;
- 
- libc_enum! {
-     /// Mode for `AioCb::fsync`.  Controls whether only data or both data and
-@@ -226,8 +225,6 @@ impl<'a> AioCb<'a> {
-     /// [`fsync`](#method.fsync) operation.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -287,8 +284,6 @@ impl<'a> AioCb<'a> {
-     /// Create an `AioCb` from a mutable slice and read into it.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -363,8 +358,6 @@ impl<'a> AioCb<'a> {
-     /// Create an `AioCb` from a Vector and use it for writing
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -394,9 +387,6 @@ impl<'a> AioCb<'a> {
-     /// Create an `AioCb` from a `Bytes` object
-     ///
-     /// ```
--    /// # extern crate bytes;
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use bytes::Bytes;
-     /// # use nix::sys::aio::*;
-     /// # use nix::sys::signal::SigevNotify;
-@@ -419,9 +409,6 @@ impl<'a> AioCb<'a> {
-     /// using an un`Box`ed `Bytes` object.
-     ///
-     /// ```
--    /// # extern crate bytes;
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use bytes::Bytes;
-     /// # use nix::sys::aio::*;
-     /// # use nix::sys::signal::SigevNotify;
-@@ -480,8 +467,6 @@ impl<'a> AioCb<'a> {
-     /// Create an `AioCb` from a Vector and use it for reading
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -642,8 +627,6 @@ impl<'a> AioCb<'a> {
-     /// Construct an `AioCb` from a slice and use it for writing.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -726,8 +709,6 @@ impl<'a> AioCb<'a> {
-     /// result.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -781,8 +762,6 @@ impl<'a> AioCb<'a> {
-     /// is an alternative to `aio_suspend`, used by most of the other examples.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::errno::Errno;
-     /// # use nix::Error;
-     /// # use nix::sys::aio::*;
-@@ -925,8 +904,6 @@ impl<'a> AioCb<'a> {
- /// descriptor.
- ///
- /// ```
--/// # extern crate tempfile;
--/// # extern crate nix;
- /// # use nix::errno::Errno;
- /// # use nix::Error;
- /// # use nix::sys::aio::*;
-@@ -978,13 +955,7 @@ pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
- ///
- /// Use `aio_suspend` to block until an aio operation completes.
- ///
--// Disable doctest due to a known bug in FreeBSD's 32-bit emulation.  The fix
--// will be included in release 11.2.
--// FIXME reenable the doc test when the CI machine gets upgraded to that release.
--// https://svnweb.freebsd.org/base?view=revision&revision=325018
--/// ```no_run
--/// # extern crate tempfile;
--/// # extern crate nix;
-+/// ```
- /// # use nix::sys::aio::*;
- /// # use nix::sys::signal::SigevNotify;
- /// # use std::os::unix::io::AsRawFd;
-@@ -1091,8 +1062,6 @@ impl<'a> LioCb<'a> {
-     /// [`AioCb::error`] to poll.
-     ///
-     /// ```
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::sys::aio::*;
-     /// # use nix::sys::signal::SigevNotify;
-     /// # use std::os::unix::io::AsRawFd;
-@@ -1148,8 +1117,6 @@ impl<'a> LioCb<'a> {
-     ///
-     /// # Examples
-     /// ```no_run
--    /// # extern crate tempfile;
--    /// # extern crate nix;
-     /// # use nix::Error;
-     /// # use nix::errno::Errno;
-     /// # use nix::sys::aio::*;
-@@ -1213,7 +1180,6 @@ impl<'a> LioCb<'a> {
-                 },
-                 Err(Error::Sys(Errno::EINPROGRESS)) => {
-                     // aiocb is was successfully queued; no need to do anything
--                    ()
-                 },
-                 Err(Error::Sys(Errno::EINVAL)) => panic!(
-                     "AioCb was never submitted, or already finalized"),
-diff --git a/third_party/rust/nix/src/sys/epoll.rs b/third_party/rust/nix/src/sys/epoll.rs
-index fef6f4e3ec92c..2437bbe2ddb3b 100644
---- a/third_party/rust/nix/src/sys/epoll.rs
-+++ b/third_party/rust/nix/src/sys/epoll.rs
-@@ -1,10 +1,10 @@
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- use libc::{self, c_int};
- use std::os::unix::io::RawFd;
- use std::ptr;
- use std::mem;
--use ::Error;
-+use crate::Error;
- 
- libc_bitflags!(
-     pub struct EpollFlags: c_int {
-@@ -43,7 +43,7 @@ libc_bitflags!{
- }
- 
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
--#[repr(C)]
-+#[repr(transparent)]
- pub struct EpollEvent {
-     event: libc::epoll_event,
- }
-diff --git a/third_party/rust/nix/src/sys/event.rs b/third_party/rust/nix/src/sys/event.rs
-index 8cd7372f88188..8050af313245d 100644
---- a/third_party/rust/nix/src/sys/event.rs
-+++ b/third_party/rust/nix/src/sys/event.rs
-@@ -1,12 +1,11 @@
- /* TOOD: Implement for other kqueue based systems
-  */
- 
--use {Errno, Result};
-+use crate::{Errno, Result};
- #[cfg(not(target_os = "netbsd"))]
- use libc::{timespec, time_t, c_int, c_long, intptr_t, uintptr_t};
- #[cfg(target_os = "netbsd")]
- use libc::{timespec, time_t, c_long, intptr_t, uintptr_t, size_t};
--use libc;
- use std::os::unix::io::RawFd;
- use std::ptr;
- use std::mem;
-@@ -28,7 +27,7 @@ type type_of_data = intptr_t;
- #[cfg(any(target_os = "netbsd"))]
- type type_of_udata = intptr_t;
- #[cfg(any(target_os = "netbsd", target_os = "openbsd"))]
--type type_of_data = libc::int64_t;
-+type type_of_data = i64;
- 
- #[cfg(target_os = "netbsd")]
- type type_of_event_filter = u32;
-@@ -90,14 +89,9 @@ libc_bitflags!{
-         EV_CLEAR;
-         EV_DELETE;
-         EV_DISABLE;
--        // No released version of OpenBSD supports EV_DISPATCH or EV_RECEIPT.
--        // These have been commited to the -current branch though and are
--        // expected to be part of the OpenBSD 6.2 release in Nov 2017.
--        // See: https://marc.info/?l=openbsd-tech&m=149621427511219&w=2
--        // https://github.com/rust-lang/libc/pull/613
-         #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-                   target_os = "ios", target_os = "macos",
--                  target_os = "netbsd"))]
-+                  target_os = "netbsd", target_os = "openbsd"))]
-         EV_DISPATCH;
-         #[cfg(target_os = "freebsd")]
-         EV_DROP;
-@@ -116,7 +110,7 @@ libc_bitflags!{
-         EV_POLL;
-         #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
-                   target_os = "ios", target_os = "macos",
--                  target_os = "netbsd"))]
-+                  target_os = "netbsd", target_os = "openbsd"))]
-         EV_RECEIPT;
-         EV_SYSFLAGS;
-     }
-@@ -134,10 +128,6 @@ libc_bitflags!(
-         NOTE_EXEC;
-         NOTE_EXIT;
-         #[cfg(any(target_os = "macos", target_os = "ios"))]
--        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
--        #[allow(deprecated)]
--        NOTE_EXIT_REPARENTED;
--        #[cfg(any(target_os = "macos", target_os = "ios"))]
-         NOTE_EXITSTATUS;
-         NOTE_EXTEND;
-         #[cfg(any(target_os = "macos",
-@@ -183,11 +173,6 @@ libc_bitflags!(
-         NOTE_OOB;
-         NOTE_PCTRLMASK;
-         NOTE_PDATAMASK;
--        #[cfg(any(target_os = "macos", target_os = "ios"))]
--        #[cfg(any(target_os = "macos", target_os = "ios"))]
--        #[deprecated( since="0.14.0", note="Deprecated since OSX 10.9")]
--        #[allow(deprecated)]
--        NOTE_REAP;
-         NOTE_RENAME;
-         NOTE_REVOKE;
-         #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
-@@ -234,7 +219,7 @@ impl KEvent {
-     pub fn new(ident: uintptr_t, filter: EventFilter, flags: EventFlag,
-                fflags:FilterFlag, data: intptr_t, udata: intptr_t) -> KEvent {
-         KEvent { kevent: libc::kevent {
--            ident: ident,
-+            ident,
-             filter: filter as type_of_event_filter,
-             flags: flags.bits(),
-             fflags: fflags.bits(),
-@@ -329,23 +314,17 @@ pub fn ev_set(ev: &mut KEvent,
- fn test_struct_kevent() {
-     let udata : intptr_t = 12345;
- 
--    let expected = libc::kevent{ident: 0xdead_beef,
--                                filter: libc::EVFILT_READ,
--                                flags: libc::EV_ONESHOT | libc::EV_ADD,
--                                fflags: libc::NOTE_CHILD | libc::NOTE_EXIT,
--                                data: 0x1337,
--                                udata: udata as type_of_udata};
-     let actual = KEvent::new(0xdead_beef,
-                              EventFilter::EVFILT_READ,
-                              EventFlag::EV_ONESHOT | EventFlag::EV_ADD,
-                              FilterFlag::NOTE_CHILD | FilterFlag::NOTE_EXIT,
-                              0x1337,
-                              udata);
--    assert!(expected.ident == actual.ident());
--    assert!(expected.filter == actual.filter() as type_of_event_filter);
--    assert!(expected.flags == actual.flags().bits());
--    assert!(expected.fflags == actual.fflags().bits());
--    assert!(expected.data == actual.data() as type_of_data);
--    assert!(expected.udata == actual.udata() as type_of_udata);
--    assert!(mem::size_of::<libc::kevent>() == mem::size_of::<KEvent>());
-+    assert_eq!(0xdead_beef, actual.ident());
-+    assert_eq!(libc::EVFILT_READ, actual.filter() as type_of_event_filter);
-+    assert_eq!(libc::EV_ONESHOT | libc::EV_ADD, actual.flags().bits());
-+    assert_eq!(libc::NOTE_CHILD | libc::NOTE_EXIT, actual.fflags().bits());
-+    assert_eq!(0x1337, actual.data() as type_of_data);
-+    assert_eq!(udata as type_of_udata, actual.udata() as type_of_udata);
-+    assert_eq!(mem::size_of::<libc::kevent>(), mem::size_of::<KEvent>());
- }
-diff --git a/third_party/rust/nix/src/sys/eventfd.rs b/third_party/rust/nix/src/sys/eventfd.rs
-index c5a54e46a1735..baaaa89ddd52e 100644
---- a/third_party/rust/nix/src/sys/eventfd.rs
-+++ b/third_party/rust/nix/src/sys/eventfd.rs
-@@ -1,7 +1,7 @@
- use libc;
- use std::os::unix::io::RawFd;
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- 
- libc_bitflags! {
-     pub struct EfdFlags: libc::c_int {
-diff --git a/third_party/rust/nix/src/sys/inotify.rs b/third_party/rust/nix/src/sys/inotify.rs
-index e6c2cf64d29dc..4880a4a514e77 100644
---- a/third_party/rust/nix/src/sys/inotify.rs
-+++ b/third_party/rust/nix/src/sys/inotify.rs
-@@ -23,19 +23,19 @@
- //! }
- //! ```
- 
--use libc;
- use libc::{
-     c_char,
-     c_int,
- };
- use std::ffi::{OsString,OsStr,CStr};
- use std::os::unix::ffi::OsStrExt;
--use std::mem::size_of;
-+use std::mem::{MaybeUninit, size_of};
- use std::os::unix::io::{RawFd,AsRawFd,FromRawFd};
--use unistd::read;
--use Result;
--use NixPath;
--use errno::Errno;
-+use std::ptr;
-+use crate::unistd::read;
-+use crate::Result;
-+use crate::NixPath;
-+use crate::errno::Errno;
- 
- libc_bitflags! {
-     /// Configuration options for [`inotify_add_watch`](fn.inotify_add_watch.html).
-@@ -131,7 +131,7 @@ impl Inotify {
-     /// 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).
--    pub fn add_watch<P: ?Sized + NixPath>(&self,
-+    pub fn add_watch<P: ?Sized + NixPath>(self,
-                                           path: &P,
-                                           mask: AddWatchFlags) 
-                                             -> Result<WatchDescriptor>
-@@ -152,14 +152,14 @@ impl Inotify {
-     ///
-     /// For more information see, [inotify_rm_watch(2)](http://man7.org/linux/man-pages/man2/inotify_rm_watch.2.html).
-     #[cfg(target_os = "linux")]
--    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
-+    pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
-         let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd) };
- 
-         Errno::result(res).map(drop)
-     }
- 
-     #[cfg(target_os = "android")]
--    pub fn rm_watch(&self, wd: WatchDescriptor) -> Result<()> {
-+    pub fn rm_watch(self, wd: WatchDescriptor) -> Result<()> {
-         let res = unsafe { libc::inotify_rm_watch(self.fd, wd.wd as u32) };
- 
-         Errno::result(res).map(drop)
-@@ -171,9 +171,10 @@ impl Inotify {
-     /// 
-     /// 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>> {
-+    pub fn read_events(self) -> Result<Vec<InotifyEvent>> {
-         let header_size = size_of::<libc::inotify_event>();
--        let mut buffer = [0u8; 4096];
-+        const BUFSIZ: usize = 4096;
-+        let mut buffer = [0u8; BUFSIZ];
-         let mut events = Vec::new();
-         let mut offset = 0;
- 
-@@ -181,11 +182,13 @@ impl Inotify {
- 
-         while (nread - offset) >= header_size {
-             let event = unsafe {
--                &*(
--                    buffer
--                        .as_ptr()
--                        .offset(offset as isize) as *const libc::inotify_event
--                )
-+                let mut event = MaybeUninit::<libc::inotify_event>::uninit();
-+                ptr::copy_nonoverlapping(
-+                    buffer.as_ptr().add(offset),
-+                    event.as_mut_ptr() as *mut u8,
-+                    (BUFSIZ - offset).min(header_size)
-+                );
-+                event.assume_init()
-             };
- 
-             let name = match event.len {
-@@ -194,7 +197,7 @@ impl Inotify {
-                     let ptr = unsafe { 
-                         buffer
-                             .as_ptr()
--                            .offset(offset as isize + header_size as isize)
-+                            .add(offset + header_size)
-                             as *const c_char
-                     };
-                     let cstr = unsafe { CStr::from_ptr(ptr) };
-diff --git a/third_party/rust/nix/src/sys/ioctl/bsd.rs b/third_party/rust/nix/src/sys/ioctl/bsd.rs
-index 9b8b0ff1a155f..f39c0eb688f8a 100644
---- a/third_party/rust/nix/src/sys/ioctl/bsd.rs
-+++ b/third_party/rust/nix/src/sys/ioctl/bsd.rs
-@@ -6,7 +6,7 @@ pub type ioctl_num_type = ::libc::c_ulong;
- pub type ioctl_param_type = ::libc::c_int;
- 
- mod consts {
--    use ::sys::ioctl::ioctl_num_type;
-+    use crate::sys::ioctl::ioctl_num_type;
-     #[doc(hidden)]
-     pub const VOID: ioctl_num_type = 0x2000_0000;
-     #[doc(hidden)]
-@@ -14,7 +14,7 @@ mod consts {
-     #[doc(hidden)]
-     pub const IN: ioctl_num_type = 0x8000_0000;
-     #[doc(hidden)]
--    pub const INOUT: ioctl_num_type = (IN|OUT);
-+    pub const INOUT: ioctl_num_type = IN|OUT;
-     #[doc(hidden)]
-     pub const IOCPARM_MASK: ioctl_num_type = 0x1fff;
- }
-diff --git a/third_party/rust/nix/src/sys/ioctl/linux.rs b/third_party/rust/nix/src/sys/ioctl/linux.rs
-index 9cdac72a4b80b..68ebaba9bf496 100644
---- a/third_party/rust/nix/src/sys/ioctl/linux.rs
-+++ b/third_party/rust/nix/src/sys/ioctl/linux.rs
-@@ -33,7 +33,8 @@ mod consts {
-           target_arch = "arm",
-           target_arch = "s390x",
-           target_arch = "x86_64",
--          target_arch = "aarch64"))]
-+          target_arch = "aarch64",
-+          target_arch = "riscv64"))]
- mod consts {
-     #[doc(hidden)]
-     pub const NONE: u8 = 0;
-diff --git a/third_party/rust/nix/src/sys/ioctl/mod.rs b/third_party/rust/nix/src/sys/ioctl/mod.rs
-index 4513bf877434a..8858a9d57779f 100644
---- a/third_party/rust/nix/src/sys/ioctl/mod.rs
-+++ b/third_party/rust/nix/src/sys/ioctl/mod.rs
-@@ -29,7 +29,7 @@
- //! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
- //! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
- //! subcomponents (For linux this is documented in
--//! [`Documentation/ioctl/ioctl-number.txt`](http://elixir.free-electrons.com/linux/latest/source/Documentation/ioctl/ioctl-number.txt)):
-+//! [`Documentation/ioctl/ioctl-number.rst`](https://elixir.bootlin.com/linux/latest/source/Documentation/userspace-api/ioctl/ioctl-number.rst)):
- //!
- //!   * Number: The actual ioctl ID
- //!   * Type: A grouping of ioctls for a common purpose or driver
-@@ -221,11 +221,13 @@
- //!
- //! # fn main() {}
- //! ```
--#[cfg(any(target_os = "android", target_os = "linux"))]
-+use cfg_if::cfg_if;
-+
-+#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- #[macro_use]
- mod linux;
- 
--#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
- pub use self::linux::*;
- 
- #[cfg(any(target_os = "dragonfly",
-@@ -317,7 +319,6 @@ macro_rules! ioctl_none {
- ///
- /// ```no_run
- /// # #[macro_use] extern crate nix;
--/// # extern crate libc;
- /// # use libc::TIOCNXCL;
- /// # use std::fs::File;
- /// # use std::os::unix::io::AsRawFd;
-@@ -396,7 +397,6 @@ macro_rules! ioctl_read {
- /// # Example
- ///
- /// ```
--/// # extern crate libc;
- /// # #[macro_use] extern crate nix;
- /// # #[cfg(any(target_os = "android", target_os = "linux"))]
- /// ioctl_read_bad!(tcgets, libc::TCGETS, libc::termios);
-@@ -470,7 +470,6 @@ macro_rules! ioctl_write_ptr {
- /// # Example
- ///
- /// ```
--/// # extern crate libc;
- /// # #[macro_use] extern crate nix;
- /// # #[cfg(any(target_os = "android", target_os = "linux"))]
- /// ioctl_write_ptr_bad!(tcsets, libc::TCSETS, libc::termios);
-@@ -590,7 +589,6 @@ cfg_if!{
- /// # Examples
- ///
- /// ```
--/// # extern crate libc;
- /// # #[macro_use] extern crate nix;
- /// # #[cfg(any(target_os = "android", target_os = "linux"))]
- /// ioctl_write_int_bad!(tcsbrk, libc::TCSBRK);
-diff --git a/third_party/rust/nix/src/sys/memfd.rs b/third_party/rust/nix/src/sys/memfd.rs
-index 9672429b31e7f..51b7e6b18849b 100644
---- a/third_party/rust/nix/src/sys/memfd.rs
-+++ b/third_party/rust/nix/src/sys/memfd.rs
-@@ -1,7 +1,7 @@
- use libc;
- use std::os::unix::io::RawFd;
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- use std::ffi::CStr;
- 
- libc_bitflags!(
-diff --git a/third_party/rust/nix/src/sys/mman.rs b/third_party/rust/nix/src/sys/mman.rs
-index 4e250501dd0f0..63a0779c19382 100644
---- a/third_party/rust/nix/src/sys/mman.rs
-+++ b/third_party/rust/nix/src/sys/mman.rs
-@@ -1,12 +1,12 @@
--use {Error, Result};
-+use crate::{Error, Result};
- #[cfg(not(target_os = "android"))]
--use NixPath;
--use errno::Errno;
-+use crate::NixPath;
-+use crate::errno::Errno;
- #[cfg(not(target_os = "android"))]
--use fcntl::OFlag;
-+use crate::fcntl::OFlag;
- use libc::{self, c_int, c_void, size_t, off_t};
- #[cfg(not(target_os = "android"))]
--use sys::stat::Mode;
-+use crate::sys::stat::Mode;
- use std::os::unix::io::RawFd;
- 
- libc_bitflags!{
-@@ -77,6 +77,43 @@ libc_bitflags!{
-         /// Allocate the mapping using "huge pages."
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-         MAP_HUGETLB;
-+        /// Make use of 64KB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_64KB;
-+        /// Make use of 512KB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_512KB;
-+        /// Make use of 1MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_1MB;
-+        /// Make use of 2MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_2MB;
-+        /// Make use of 8MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_8MB;
-+        /// Make use of 16MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_16MB;
-+        /// Make use of 32MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_32MB;
-+        /// Make use of 256MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_256MB;
-+        /// Make use of 512MB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_512MB;
-+        /// Make use of 1GB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_1GB;
-+        /// Make use of 2GB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_2GB;
-+        /// Make use of 16GB huge page (must be supported by the system)
-+        #[cfg(target_os = "linux")]
-+        MAP_HUGE_16GB;
-+
-         /// Lock the mapped region into memory as with `mlock(2)`.
-         #[cfg(target_os = "netbsd")]
-         MAP_WIRED;
-@@ -102,6 +139,17 @@ libc_bitflags!{
-     }
- }
- 
-+#[cfg(target_os = "linux")]
-+libc_bitflags!{
-+    /// Options for `mremap()`.
-+    pub struct MRemapFlags: c_int {
-+        /// Permit the kernel to relocate the mapping to a new virtual address, if necessary.
-+        MREMAP_MAYMOVE;
-+        /// Place the mapping at exactly the address specified in `new_address`.
-+        MREMAP_FIXED;
-+    }
-+}
-+
- libc_enum!{
-     /// Usage information for a range of memory to allow for performance optimizations by the kernel.
-     ///
-@@ -223,20 +271,37 @@ libc_bitflags!{
-     }
- }
- 
--/// Locks all memory pages that contain part of the address range with `length` bytes starting at
--/// `addr`. Locked pages never move to the swap area.
-+/// Locks all memory pages that contain part of the address range with `length`
-+/// bytes starting at `addr`.
-+///
-+/// Locked pages never move to the swap area.
-+///
-+/// # Safety
-+///
-+/// `addr` must meet all the requirements described in the `mlock(2)` man page.
- pub unsafe fn mlock(addr: *const c_void, length: size_t) -> Result<()> {
-     Errno::result(libc::mlock(addr, length)).map(drop)
- }
- 
--/// Unlocks all memory pages that contain part of the address range with `length` bytes starting at
--/// `addr`.
-+/// Unlocks all memory pages that contain part of the address range with
-+/// `length` bytes starting at `addr`.
-+///
-+/// # Safety
-+///
-+/// `addr` must meet all the requirements described in the `munlock(2)` man
-+/// page.
- pub unsafe fn munlock(addr: *const c_void, length: size_t) -> Result<()> {
-     Errno::result(libc::munlock(addr, length)).map(drop)
- }
- 
--/// Locks all memory pages mapped into this process' address space. Locked pages never move to the
--/// swap area.
-+/// Locks all memory pages mapped into this process' address space.
-+///
-+/// Locked pages never move to the swap area.
-+///
-+/// # Safety
-+///
-+/// `addr` must meet all the requirements described in the `mlockall(2)` man
-+/// page.
- pub fn mlockall(flags: MlockAllFlags) -> Result<()> {
-     unsafe { Errno::result(libc::mlockall(flags.bits())) }.map(drop)
- }
-@@ -246,8 +311,11 @@ pub fn munlockall() -> Result<()> {
-     unsafe { Errno::result(libc::munlockall()) }.map(drop)
- }
- 
--/// Calls to mmap are inherently unsafe, so they must be made in an unsafe block. Typically
--/// a higher-level abstraction will hide the unsafe interactions with the mmap'd region.
-+/// allocate memory, or map files or devices into memory
-+///
-+/// # Safety
-+///
-+/// See the `mmap(2)` man page for detailed requirements.
- pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: MapFlags, fd: RawFd, offset: off_t) -> Result<*mut c_void> {
-     let ret = libc::mmap(addr, length, prot.bits(), flags.bits(), fd, offset);
- 
-@@ -258,10 +326,46 @@ pub unsafe fn mmap(addr: *mut c_void, length: size_t, prot: ProtFlags, flags: Ma
-     }
- }
- 
-+/// Expands (or shrinks) an existing memory mapping, potentially moving it at
-+/// the same time.
-+///
-+/// # Safety
-+///
-+/// See the `mremap(2)` [man page](https://man7.org/linux/man-pages/man2/mremap.2.html) for
-+/// detailed requirements.
-+#[cfg(target_os = "linux")]
-+pub unsafe fn mremap(
-+    addr: *mut c_void,
-+    old_size: size_t,
-+    new_size: size_t,
-+    flags: MRemapFlags,
-+    new_address: Option<* mut c_void>,
-+) -> Result<*mut c_void> {
-+    let ret = libc::mremap(addr, old_size, new_size, flags.bits(), new_address.unwrap_or(std::ptr::null_mut()));
-+
-+    if ret == libc::MAP_FAILED {
-+        Err(Error::Sys(Errno::last()))
-+    } else {
-+        Ok(ret)
-+    }
-+}
-+
-+/// remove a mapping
-+///
-+/// # Safety
-+///
-+/// `addr` must meet all the requirements described in the `munmap(2)` man
-+/// page.
- pub unsafe fn munmap(addr: *mut c_void, len: size_t) -> Result<()> {
-     Errno::result(libc::munmap(addr, len)).map(drop)
- }
- 
-+/// give advice about use of memory
-+///
-+/// # Safety
-+///
-+/// See the `madvise(2)` man page.  Take special care when using
-+/// `MmapAdvise::MADV_FREE`.
- pub unsafe fn madvise(addr: *mut c_void, length: size_t, advise: MmapAdvise) -> Result<()> {
-     Errno::result(libc::madvise(addr, length, advise as i32)).map(drop)
- }
-@@ -295,6 +399,12 @@ pub unsafe fn mprotect(addr: *mut c_void, length: size_t, prot: ProtFlags) -> Re
-     Errno::result(libc::mprotect(addr, length, prot.bits())).map(drop)
- }
- 
-+/// synchronize a mapped region
-+///
-+/// # Safety
-+///
-+/// `addr` must meet all the requirements described in the `msync(2)` man
-+/// page.
- pub unsafe fn msync(addr: *mut c_void, length: size_t, flags: MsFlags) -> Result<()> {
-     Errno::result(libc::msync(addr, length, flags.bits())).map(drop)
- }
-diff --git a/third_party/rust/nix/src/sys/mod.rs b/third_party/rust/nix/src/sys/mod.rs
-index d3c2f92bbaaea..438fb4fdcb438 100644
---- a/third_party/rust/nix/src/sys/mod.rs
-+++ b/third_party/rust/nix/src/sys/mod.rs
-@@ -25,6 +25,7 @@ pub mod eventfd;
-           target_os = "freebsd",
-           target_os = "ios",
-           target_os = "linux",
-+          target_os = "redox",
-           target_os = "macos",
-           target_os = "netbsd",
-           target_os = "openbsd"))]
-@@ -34,8 +35,12 @@ pub mod ioctl;
- #[cfg(target_os = "linux")]
- pub mod memfd;
- 
-+#[cfg(not(target_os = "redox"))]
- pub mod mman;
- 
-+#[cfg(target_os = "linux")]
-+pub mod personality;
-+
- pub mod pthread;
- 
- #[cfg(any(target_os = "android",
-@@ -53,6 +58,7 @@ pub mod quota;
- #[cfg(any(target_os = "linux"))]
- pub mod reboot;
- 
-+#[cfg(not(target_os = "redox"))]
- pub mod select;
- 
- #[cfg(any(target_os = "android",
-@@ -67,6 +73,7 @@ pub mod signal;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub mod signalfd;
- 
-+#[cfg(not(target_os = "redox"))]
- pub mod socket;
- 
- pub mod stat;
-@@ -98,3 +105,6 @@ pub mod wait;
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub mod inotify;
-+
-+#[cfg(target_os = "linux")]
-+pub mod timerfd;
-diff --git a/third_party/rust/nix/src/sys/personality.rs b/third_party/rust/nix/src/sys/personality.rs
-new file mode 100644
-index 0000000000000..6548b654aa1f4
---- /dev/null
-+++ b/third_party/rust/nix/src/sys/personality.rs
-@@ -0,0 +1,70 @@
-+use crate::Result;
-+use crate::errno::Errno;
-+
-+use libc::{self, c_int, c_ulong};
-+
-+libc_bitflags! {
-+    /// Flags used and returned by [`get()`](fn.get.html) and
-+    /// [`set()`](fn.set.html).
-+    pub struct Persona: c_int {
-+        ADDR_COMPAT_LAYOUT;
-+        ADDR_NO_RANDOMIZE;
-+        ADDR_LIMIT_32BIT;
-+        ADDR_LIMIT_3GB;
-+        #[cfg(not(target_env = "musl"))]
-+        FDPIC_FUNCPTRS;
-+        MMAP_PAGE_ZERO;
-+        READ_IMPLIES_EXEC;
-+        SHORT_INODE;
-+        STICKY_TIMEOUTS;
-+        #[cfg(not(target_env = "musl"))]
-+        UNAME26;
-+        WHOLE_SECONDS;
-+    }
-+}
-+
-+/// Retrieve the current process personality.
-+///
-+/// Returns a Result containing a Persona instance.
-+///
-+/// Example:
-+///
-+/// ```
-+/// # use nix::sys::personality::{self, Persona};
-+/// let pers = personality::get().unwrap();
-+/// assert!(!pers.contains(Persona::WHOLE_SECONDS));
-+/// ```
-+pub fn get() -> Result<Persona> {
-+    let res = unsafe {
-+        libc::personality(0xFFFFFFFF)
-+    };
-+
-+    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
-+}
-+
-+/// Set the current process personality.
-+///
-+/// Returns a Result containing the *previous* personality for the
-+/// process, as a Persona.
-+///
-+/// For more information, see [personality(2)](https://man7.org/linux/man-pages/man2/personality.2.html)
-+///
-+/// **NOTE**: This call **replaces** the current personality entirely.
-+/// To **update** the personality, first call `get()` and then `set()`
-+/// with the modified persona.
-+///
-+/// Example:
-+///
-+/// ```
-+/// # use nix::sys::personality::{self, Persona};
-+/// let mut pers = personality::get().unwrap();
-+/// assert!(!pers.contains(Persona::ADDR_NO_RANDOMIZE));
-+/// personality::set(pers | Persona::ADDR_NO_RANDOMIZE);
-+/// ```
-+pub fn set(persona: Persona) -> Result<Persona> {
-+    let res = unsafe {
-+        libc::personality(persona.bits() as c_ulong)
-+    };
-+
-+    Errno::result(res).map(|r| Persona::from_bits_truncate(r))
-+}
-diff --git a/third_party/rust/nix/src/sys/ptrace/bsd.rs b/third_party/rust/nix/src/sys/ptrace/bsd.rs
-index 7797d10647ef4..e85afc761198b 100644
---- a/third_party/rust/nix/src/sys/ptrace/bsd.rs
-+++ b/third_party/rust/nix/src/sys/ptrace/bsd.rs
-@@ -1,9 +1,10 @@
--use errno::Errno;
-+use cfg_if::cfg_if;
-+use crate::errno::Errno;
- use libc::{self, c_int};
- use std::ptr;
--use sys::signal::Signal;
--use unistd::Pid;
--use Result;
-+use crate::sys::signal::Signal;
-+use crate::unistd::Pid;
-+use crate::Result;
- 
- pub type RequestType = c_int;
- 
-@@ -77,16 +78,23 @@ pub fn traceme() -> Result<()> {
- 
- /// Attach to a running process, as with `ptrace(PT_ATTACH, ...)`
- ///
--/// Attaches to the process specified in pid, making it a tracee of the calling process.
-+/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
- pub fn attach(pid: Pid) -> Result<()> {
-     unsafe { ptrace_other(Request::PT_ATTACH, pid, ptr::null_mut(), 0).map(drop) }
- }
- 
- /// Detaches the current running process, as with `ptrace(PT_DETACH, ...)`
- ///
--/// Detaches from the process specified in pid allowing it to run freely
--pub fn detach(pid: Pid) -> Result<()> {
--    unsafe { ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), 0).map(drop) }
-+/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-+/// signal specified by `sig`.
-+pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as c_int,
-+        None => 0,
-+    };
-+    unsafe {
-+        ptrace_other(Request::PT_DETACH, pid, ptr::null_mut(), data).map(drop)
-+    }
- }
- 
- /// Restart the stopped tracee process, as with `ptrace(PTRACE_CONT, ...)`
-@@ -121,7 +129,6 @@ pub fn kill(pid: Pid) -> Result<()> {
- ///
- /// # Example
- /// ```rust
--/// extern crate nix;
- /// use nix::sys::ptrace::step;
- /// use nix::unistd::Pid;
- /// use nix::sys::signal::Signal;
-diff --git a/third_party/rust/nix/src/sys/ptrace/linux.rs b/third_party/rust/nix/src/sys/ptrace/linux.rs
-index df15e66527562..8d1dd16e5dd76 100644
---- a/third_party/rust/nix/src/sys/ptrace/linux.rs
-+++ b/third_party/rust/nix/src/sys/ptrace/linux.rs
-@@ -1,18 +1,21 @@
- //! For detailed description of the ptrace requests, consult `man ptrace`.
- 
-+use cfg_if::cfg_if;
- use std::{mem, ptr};
--use {Error, Result};
--use errno::Errno;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
- use libc::{self, c_void, c_long, siginfo_t};
--use ::unistd::Pid;
--use sys::signal::Signal;
-+use crate::unistd::Pid;
-+use crate::sys::signal::Signal;
- 
- pub type AddressType = *mut ::libc::c_void;
- 
--#[cfg(all(target_os = "linux",
--          any(target_arch = "x86_64",
--              target_arch = "x86"),
--          target_env = "gnu"))]
-+#[cfg(all(
-+    target_os = "linux",
-+    any(all(target_arch = "x86_64",
-+            any(target_env = "gnu", target_env = "musl")),
-+        all(target_arch = "x86", target_env = "gnu"))
-+))]
- use libc::user_regs_struct;
- 
- cfg_if! {
-@@ -106,6 +109,12 @@ libc_enum!{
-         #[cfg(all(target_os = "linux", not(any(target_arch = "mips",
-                                                target_arch = "mips64"))))]
-         PTRACE_PEEKSIGINFO,
-+        #[cfg(all(target_os = "linux", target_env = "gnu",
-+                  any(target_arch = "x86", target_arch = "x86_64")))]
-+        PTRACE_SYSEMU,
-+        #[cfg(all(target_os = "linux", target_env = "gnu",
-+                  any(target_arch = "x86", target_arch = "x86_64")))]
-+        PTRACE_SYSEMU_SINGLESTEP,
-     }
- }
- 
-@@ -165,22 +174,6 @@ libc_bitflags! {
-     }
- }
- 
--/// Performs a ptrace request. If the request in question is provided by a specialised function
--/// this function will return an unsupported operation error.
--#[deprecated(
--    since="0.10.0",
--    note="usages of `ptrace()` should be replaced with the specialized helper functions instead"
--)]
--pub unsafe fn ptrace(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
--    use self::Request::*;
--    match request {
--        PTRACE_PEEKTEXT | PTRACE_PEEKDATA | PTRACE_GETSIGINFO | 
--            PTRACE_GETEVENTMSG | PTRACE_SETSIGINFO | PTRACE_SETOPTIONS | 
--            PTRACE_POKETEXT | PTRACE_POKEDATA | PTRACE_KILL => Err(Error::UnsupportedOperation),
--        _ => ptrace_other(request, pid, addr, data)
--    }
--}
--
- fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
-     let ret = unsafe {
-         Errno::clear();
-@@ -193,19 +186,23 @@ fn ptrace_peek(request: Request, pid: Pid, addr: AddressType, data: *mut c_void)
- }
- 
- /// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
--#[cfg(all(target_os = "linux",
--          any(target_arch = "x86_64",
--              target_arch = "x86"),
--          target_env = "gnu"))]
-+#[cfg(all(
-+    target_os = "linux",
-+    any(all(target_arch = "x86_64",
-+            any(target_env = "gnu", target_env = "musl")),
-+        all(target_arch = "x86", target_env = "gnu"))
-+))]
- pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
-     ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
- }
- 
- /// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
--#[cfg(all(target_os = "linux",
--          any(target_arch = "x86_64",
--              target_arch = "x86"),
--          target_env = "gnu"))]
-+#[cfg(all(
-+    target_os = "linux",
-+    any(all(target_arch = "x86_64",
-+            any(target_env = "gnu", target_env = "musl")),
-+        all(target_arch = "x86", target_env = "gnu"))
-+))]
- pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
-     let res = unsafe {
-         libc::ptrace(Request::PTRACE_SETREGS as RequestType,
-@@ -221,16 +218,15 @@ pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
- /// and therefore use the data field to return values. This function handles these
- /// requests.
- fn ptrace_get_data<T>(request: Request, pid: Pid) -> Result<T> {
--    // Creates an uninitialized pointer to store result in
--    let data: T = unsafe { mem::uninitialized() };
-+    let mut data = mem::MaybeUninit::uninit();
-     let res = unsafe {
-         libc::ptrace(request as RequestType,
-                      libc::pid_t::from(pid),
-                      ptr::null_mut::<T>(),
--                     &data as *const _ as *const c_void)
-+                     data.as_mut_ptr() as *const _ as *const c_void)
-     };
-     Errno::result(res)?;
--    Ok(data)
-+    Ok(unsafe{ data.assume_init() })
- }
- 
- unsafe fn ptrace_other(request: Request, pid: Pid, addr: AddressType, data: *mut c_void) -> Result<c_long> {
-@@ -288,23 +284,45 @@ pub fn traceme() -> Result<()> {
-     }
- }
- 
--/// Ask for next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
-+/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSCALL, ...)`
- ///
--/// Arranges for the tracee to be stopped at the next entry to or exit from a system call.
--pub fn syscall(pid: Pid) -> Result<()> {
-+/// Arranges for the tracee to be stopped at the next entry to or exit from a system call,
-+/// optionally delivering a signal specified by `sig`.
-+pub fn syscall<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-     unsafe {
-         ptrace_other(
-             Request::PTRACE_SYSCALL,
-             pid,
-             ptr::null_mut(),
--            ptr::null_mut(),
-+            data,
-         ).map(drop) // ignore the useless return value
-     }
- }
- 
-+/// Continue execution until the next syscall, as with `ptrace(PTRACE_SYSEMU, ...)`
-+///
-+/// In contrast to the `syscall` function, the syscall stopped at will not be executed.
-+/// Thus the the tracee will only be stopped once per syscall,
-+/// optionally delivering a signal specified by `sig`.
-+#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
-+pub fn sysemu<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-+    unsafe {
-+        ptrace_other(Request::PTRACE_SYSEMU, pid, ptr::null_mut(), data).map(drop)
-+        // ignore the useless return value
-+    }
-+}
-+
- /// Attach to a running process, as with `ptrace(PTRACE_ATTACH, ...)`
- ///
--/// Attaches to the process specified in pid, making it a tracee of the calling process.
-+/// Attaches to the process specified by `pid`, making it a tracee of the calling process.
- pub fn attach(pid: Pid) -> Result<()> {
-     unsafe {
-         ptrace_other(
-@@ -316,16 +334,36 @@ pub fn attach(pid: Pid) -> Result<()> {
-     }
- }
- 
-+/// Attach to a running process, as with `ptrace(PTRACE_SEIZE, ...)`
-+///
-+/// Attaches to the process specified in pid, making it a tracee of the calling process.
-+#[cfg(all(target_os = "linux", not(any(target_arch = "mips", target_arch = "mips64"))))]
-+pub fn seize(pid: Pid, options: Options) -> Result<()> {
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_SEIZE,
-+            pid,
-+            ptr::null_mut(),
-+            options.bits() as *mut c_void,
-+        ).map(drop) // ignore the useless return value
-+    }
-+}
-+
- /// Detaches the current running process, as with `ptrace(PTRACE_DETACH, ...)`
- ///
--/// Detaches from the process specified in pid allowing it to run freely
--pub fn detach(pid: Pid) -> Result<()> {
-+/// Detaches from the process specified by `pid` allowing it to run freely, optionally delivering a
-+/// signal specified by `sig`.
-+pub fn detach<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-     unsafe {
-         ptrace_other(
-             Request::PTRACE_DETACH,
-             pid,
-             ptr::null_mut(),
--            ptr::null_mut()
-+            data
-         ).map(drop)
-     }
- }
-@@ -361,7 +399,6 @@ pub fn kill(pid: Pid) -> Result<()> {
- ///
- /// # Example
- /// ```rust
--/// extern crate nix;
- /// use nix::sys::ptrace::step;
- /// use nix::unistd::Pid;
- /// use nix::sys::signal::Signal; 
-@@ -388,6 +425,28 @@ pub fn step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-     }
- }
- 
-+/// Move the stopped tracee process forward by a single step or stop at the next syscall
-+/// as with `ptrace(PTRACE_SYSEMU_SINGLESTEP, ...)`
-+///
-+/// Advances the execution by a single step or until the next syscall.
-+/// In case the tracee is stopped at a syscall, the syscall will not be executed.
-+/// Optionally, the signal specified by `sig` is delivered to the tracee upon continuation.
-+#[cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86", target_arch = "x86_64")))]
-+pub fn sysemu_step<T: Into<Option<Signal>>>(pid: Pid, sig: T) -> Result<()> {
-+    let data = match sig.into() {
-+        Some(s) => s as i32 as *mut c_void,
-+        None => ptr::null_mut(),
-+    };
-+    unsafe {
-+        ptrace_other(
-+            Request::PTRACE_SYSEMU_SINGLESTEP,
-+            pid,
-+            ptr::null_mut(),
-+            data,
-+        )
-+        .map(drop) // ignore the useless return value
-+    }
-+}
- 
- /// Reads a word from a processes memory at the given address
- pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
-@@ -395,8 +454,15 @@ pub fn read(pid: Pid, addr: AddressType) -> Result<c_long> {
- }
- 
- /// Writes a word into the processes memory at the given address
--pub fn write(pid: Pid, addr: AddressType, data: *mut c_void) -> Result<()> {
--    unsafe {
--        ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
--    }
-+///
-+/// # Safety
-+///
-+/// The `data` argument is passed directly to `ptrace(2)`.  Read that man page
-+/// for guidance.
-+pub unsafe fn write(
-+    pid: Pid,
-+    addr: AddressType,
-+    data: *mut c_void) -> Result<()>
-+{
-+    ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop)
- }
-diff --git a/third_party/rust/nix/src/sys/quota.rs b/third_party/rust/nix/src/sys/quota.rs
-index 8946fca2213c8..1933013219102 100644
---- a/third_party/rust/nix/src/sys/quota.rs
-+++ b/third_party/rust/nix/src/sys/quota.rs
-@@ -15,12 +15,13 @@
- use std::default::Default;
- use std::{mem, ptr};
- use libc::{self, c_int, c_char};
--use {Result, NixPath};
--use errno::Errno;
-+use crate::{Result, NixPath};
-+use crate::errno::Errno;
- 
- struct QuotaCmd(QuotaSubCmd, QuotaType);
- 
- impl QuotaCmd {
-+    #[allow(unused_unsafe)]
-     fn as_int(&self) -> c_int {
-         unsafe { libc::QCMD(self.0 as i32, self.1 as i32) }
-     }
-@@ -94,8 +95,7 @@ libc_bitflags!(
- );
- 
- /// Wrapper type for `if_dqblk`
--// FIXME: Change to repr(transparent)
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct Dqblk(libc::dqblk);
- 
-@@ -254,15 +254,17 @@ pub fn quotactl_off<P: ?Sized + NixPath>(which: QuotaType, special: &P) -> Resul
- }
- 
- /// Update the on-disk copy of quota usages for a filesystem.
-+///
-+/// If `special` is `None`, then all file systems with active quotas are sync'd.
- pub fn quotactl_sync<P: ?Sized + NixPath>(which: QuotaType, special: Option<&P>) -> Result<()> {
-     quotactl(QuotaCmd(QuotaSubCmd::Q_SYNC, which), special, 0, ptr::null_mut())
- }
- 
- /// Get disk quota limits and current usage for the given user/group id.
- pub fn quotactl_get<P: ?Sized + NixPath>(which: QuotaType, special: &P, id: c_int) -> Result<Dqblk> {
--    let mut dqblk = unsafe { mem::uninitialized() };
--    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, &mut dqblk as *mut _ as *mut c_char)?;
--    dqblk
-+    let mut dqblk = mem::MaybeUninit::uninit();
-+    quotactl(QuotaCmd(QuotaSubCmd::Q_GETQUOTA, which), Some(special), id, dqblk.as_mut_ptr() as *mut c_char)?;
-+    Ok(unsafe{ Dqblk(dqblk.assume_init())})
- }
- 
- /// Configure quota values for the specified fields for a given user/group id.
-diff --git a/third_party/rust/nix/src/sys/reboot.rs b/third_party/rust/nix/src/sys/reboot.rs
-index bafa8fc11996d..e319130698e82 100644
---- a/third_party/rust/nix/src/sys/reboot.rs
-+++ b/third_party/rust/nix/src/sys/reboot.rs
-@@ -1,9 +1,9 @@
- //! Reboot/shutdown or enable/disable Ctrl-Alt-Delete.
- 
--use {Error, Result};
--use errno::Errno;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
- use libc;
--use void::Void;
-+use std::convert::Infallible;
- use std::mem::drop;
- 
- libc_enum! {
-@@ -22,7 +22,7 @@ libc_enum! {
-     }
- }
- 
--pub fn reboot(how: RebootMode) -> Result<Void> {
-+pub fn reboot(how: RebootMode) -> Result<Infallible> {
-     unsafe {
-         libc::reboot(how as libc::c_int)
-     };
-diff --git a/third_party/rust/nix/src/sys/select.rs b/third_party/rust/nix/src/sys/select.rs
-index 1b518e29f67a6..a576c7e4929c4 100644
---- a/third_party/rust/nix/src/sys/select.rs
-+++ b/third_party/rust/nix/src/sys/select.rs
-@@ -1,24 +1,27 @@
-+use std::iter::FusedIterator;
- use std::mem;
-+use std::ops::Range;
- use std::os::unix::io::RawFd;
- use std::ptr::{null, null_mut};
- use libc::{self, c_int};
--use Result;
--use errno::Errno;
--use sys::signal::SigSet;
--use sys::time::{TimeSpec, TimeVal};
-+use crate::Result;
-+use crate::errno::Errno;
-+use crate::sys::signal::SigSet;
-+use crate::sys::time::{TimeSpec, TimeVal};
- 
- pub use libc::FD_SETSIZE;
- 
--// FIXME: Change to repr(transparent) once it's stable
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct FdSet(libc::fd_set);
- 
- impl FdSet {
-     pub fn new() -> FdSet {
--        let mut fdset = unsafe { mem::uninitialized() };
--        unsafe { libc::FD_ZERO(&mut fdset) };
--        FdSet(fdset)
-+        let mut fdset = mem::MaybeUninit::uninit();
-+        unsafe {
-+            libc::FD_ZERO(fdset.as_mut_ptr());
-+            FdSet(fdset.assume_init())
-+        }
-     }
- 
-     pub fn insert(&mut self, fd: RawFd) {
-@@ -46,7 +49,6 @@ impl FdSet {
-     /// # Example
-     ///
-     /// ```
--    /// # extern crate nix;
-     /// # use nix::sys::select::FdSet;
-     /// # fn main() {
-     /// let mut set = FdSet::new();
-@@ -58,17 +60,81 @@ impl FdSet {
-     ///
-     /// [`select`]: fn.select.html
-     pub fn highest(&mut self) -> Option<RawFd> {
--        for i in (0..FD_SETSIZE).rev() {
--            let i = i as RawFd;
--            if unsafe { libc::FD_ISSET(i, self as *mut _ as *mut libc::fd_set) } {
--                return Some(i)
-+        self.fds(None).next_back()
-+    }
-+
-+    /// Returns an iterator over the file descriptors in the set.
-+    /// 
-+    /// For performance, it takes an optional higher bound: the iterator will
-+    /// not return any elements of the set greater than the given file
-+    /// descriptor.
-+    ///
-+    /// # Examples
-+    ///
-+    /// ```
-+    /// # use nix::sys::select::FdSet;
-+    /// # use std::os::unix::io::RawFd;
-+    /// let mut set = FdSet::new();
-+    /// set.insert(4);
-+    /// set.insert(9);
-+    /// let fds: Vec<RawFd> = set.fds(None).collect();
-+    /// assert_eq!(fds, vec![4, 9]);
-+    /// ```
-+    #[inline]
-+    pub fn fds(&mut self, highest: Option<RawFd>) -> Fds {
-+        Fds {
-+            set: self,
-+            range: 0..highest.map(|h| h as usize + 1).unwrap_or(FD_SETSIZE),
-+        }
-+    }
-+}
-+
-+impl Default for FdSet {
-+    fn default() -> Self {
-+        Self::new()
-+    }
-+}
-+
-+/// Iterator over `FdSet`.
-+#[derive(Debug)]
-+pub struct Fds<'a> {
-+    set: &'a mut FdSet,
-+    range: Range<usize>,
-+}
-+
-+impl<'a> Iterator for Fds<'a> {
-+    type Item = RawFd;
-+
-+    fn next(&mut self) -> Option<RawFd> {
-+        while let Some(i) = self.range.next() {
-+            if self.set.contains(i as RawFd) {
-+                return Some(i as RawFd);
-             }
-         }
-+        None
-+    }
-+
-+    #[inline]
-+    fn size_hint(&self) -> (usize, Option<usize>) {
-+        let (_, upper) = self.range.size_hint();
-+        (0, upper)
-+    }
-+}
- 
-+impl<'a> DoubleEndedIterator for Fds<'a> {
-+    #[inline]
-+    fn next_back(&mut self) -> Option<RawFd> {
-+        while let Some(i) = self.range.next_back() {
-+            if self.set.contains(i as RawFd) {
-+                return Some(i as RawFd);
-+            }
-+        }
-         None
-     }
- }
- 
-+impl<'a> FusedIterator for Fds<'a> {}
-+
- /// Monitors file descriptors for readiness
- ///
- /// Returns the total number of ready file descriptors in all sets. The sets are changed so that all
-@@ -93,9 +159,9 @@ impl FdSet {
- ///
- /// [`FdSet::highest`]: struct.FdSet.html#method.highest
- pub fn select<'a, N, R, W, E, T>(nfds: N,
--                                 readfds: R,
--                                 writefds: W,
--                                 errorfds: E,
-+    readfds: R,
-+    writefds: W,
-+    errorfds: E,
-                                  timeout: T) -> Result<c_int>
- where
-     N: Into<Option<c_int>>,
-@@ -122,7 +188,7 @@ where
-     let writefds = writefds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-     let errorfds = errorfds.map(|set| set as *mut _ as *mut libc::fd_set).unwrap_or(null_mut());
-     let timeout = timeout.map(|tv| tv as *mut _ as *mut libc::timeval)
--                         .unwrap_or(null_mut());
-+        .unwrap_or(null_mut());
- 
-     let res = unsafe {
-         libc::select(nfds, readfds, writefds, errorfds, timeout)
-@@ -161,10 +227,10 @@ where
- ///
- /// [`FdSet::highest`]: struct.FdSet.html#method.highest
- pub fn pselect<'a, N, R, W, E, T, S>(nfds: N,
--                                     readfds: R,
--                                     writefds: W,
--                                     errorfds: E,
--                                     timeout: T,
-+    readfds: R,
-+    writefds: W,
-+    errorfds: E,
-+    timeout: T,
-                                      sigmask: S) -> Result<c_int>
- where
-     N: Into<Option<c_int>>,
-@@ -207,8 +273,8 @@ where
- mod tests {
-     use super::*;
-     use std::os::unix::io::RawFd;
--    use sys::time::{TimeVal, TimeValLike};
--    use unistd::{write, pipe};
-+    use crate::sys::time::{TimeVal, TimeValLike};
-+    use crate::unistd::{write, pipe};
- 
-     #[test]
-     fn fdset_insert() {
-@@ -272,6 +338,20 @@ mod tests {
-         assert_eq!(set.highest(), Some(7));
-     }
- 
-+    #[test]
-+    fn fdset_fds() {
-+        let mut set = FdSet::new();
-+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![]);
-+        set.insert(0);
-+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0]);
-+        set.insert(90);
-+        assert_eq!(set.fds(None).collect::<Vec<_>>(), vec![0, 90]);
-+
-+        // highest limit
-+        assert_eq!(set.fds(Some(89)).collect::<Vec<_>>(), vec![0]);
-+        assert_eq!(set.fds(Some(90)).collect::<Vec<_>>(), vec![0, 90]);
-+    }
-+
-     #[test]
-     fn test_select() {
-         let (r1, w1) = pipe().unwrap();
-@@ -304,9 +384,9 @@ mod tests {
- 
-         let mut timeout = TimeVal::seconds(10);
-         assert_eq!(1, select(Some(fd_set.highest().unwrap() + 1),
--                             &mut fd_set,
--                             None,
--                             None,
-+                &mut fd_set,
-+                None,
-+                None,
-                              &mut timeout).unwrap());
-         assert!(fd_set.contains(r1));
-         assert!(!fd_set.contains(r2));
-@@ -324,9 +404,9 @@ mod tests {
- 
-         let mut timeout = TimeVal::seconds(10);
-         assert_eq!(1, select(::std::cmp::max(r1, r2) + 1,
--                             &mut fd_set,
--                             None,
--                             None,
-+                &mut fd_set,
-+                None,
-+                None,
-                              &mut timeout).unwrap());
-         assert!(fd_set.contains(r1));
-         assert!(!fd_set.contains(r2));
-diff --git a/third_party/rust/nix/src/sys/sendfile.rs b/third_party/rust/nix/src/sys/sendfile.rs
-index a47d8962f73fb..84fe2a919e8b4 100644
---- a/third_party/rust/nix/src/sys/sendfile.rs
-+++ b/third_party/rust/nix/src/sys/sendfile.rs
-@@ -1,10 +1,11 @@
-+use cfg_if::cfg_if;
- use std::os::unix::io::RawFd;
- use std::ptr;
- 
- use libc::{self, off_t};
- 
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- 
- /// Copy up to `count` bytes to `out_fd` from `in_fd` starting at `offset`.
- ///
-@@ -36,7 +37,7 @@ cfg_if! {
-     if #[cfg(any(target_os = "freebsd",
-                  target_os = "ios",
-                  target_os = "macos"))] {
--        use sys::uio::IoVec;
-+        use crate::sys::uio::IoVec;
- 
-         #[derive(Clone, Debug, Eq, Hash, PartialEq)]
-         struct SendfileHeaderTrailer<'a>(
-@@ -123,6 +124,7 @@ cfg_if! {
-         ///
-         /// For more information, see
-         /// [the sendfile(2) man page.](https://www.freebsd.org/cgi/man.cgi?query=sendfile&sektion=2)
-+        #[allow(clippy::too_many_arguments)]
-         pub fn sendfile(
-             in_fd: RawFd,
-             out_sock: RawFd,
-@@ -136,7 +138,8 @@ cfg_if! {
-             // Readahead goes in upper 16 bits
-             // Flags goes in lower 16 bits
-             // see `man 2 sendfile`
--            let flags: u32 = ((readahead as u32) << 16) | (flags.bits() as u32);
-+            let ra32 = u32::from(readahead);
-+            let flags: u32 = (ra32 << 16) | (flags.bits() as u32);
-             let mut bytes_sent: off_t = 0;
-             let hdtr = headers.or(trailers).map(|_| SendfileHeaderTrailer::new(headers, trailers));
-             let hdtr_ptr = hdtr.as_ref().map_or(ptr::null(), |s| &s.0 as *const libc::sf_hdtr);
-diff --git a/third_party/rust/nix/src/sys/signal.rs b/third_party/rust/nix/src/sys/signal.rs
-index 1013a77fd4b40..2f8b5fa88823d 100644
---- a/third_party/rust/nix/src/sys/signal.rs
-+++ b/third_party/rust/nix/src/sys/signal.rs
-@@ -3,9 +3,10 @@
- 
- ///! Operating system signals.
- 
--use libc;
--use {Error, Result};
--use errno::Errno;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
-+use crate::unistd::Pid;
-+use std::convert::TryFrom;
- use std::mem;
- use std::fmt;
- use std::str::FromStr;
-@@ -13,7 +14,7 @@ use std::str::FromStr;
- use std::os::unix::io::RawFd;
- use std::ptr;
- 
--#[cfg(not(target_os = "openbsd"))]
-+#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
- pub use self::sigevent::*;
- 
- libc_enum!{
-@@ -38,8 +39,10 @@ libc_enum!{
-         SIGPIPE,
-         SIGALRM,
-         SIGTERM,
--        #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
--                  not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+        #[cfg(all(any(target_os = "android", target_os = "emscripten",
-+                      target_os = "fuchsia", target_os = "linux"),
-+                  not(any(target_arch = "mips", target_arch = "mips64",
-+                          target_arch = "sparc64"))))]
-         SIGSTKFLT,
-         SIGCHLD,
-         SIGCONT,
-@@ -54,12 +57,17 @@ libc_enum!{
-         SIGPROF,
-         SIGWINCH,
-         SIGIO,
--        #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+        #[cfg(any(target_os = "android", target_os = "emscripten",
-+                  target_os = "fuchsia", target_os = "linux"))]
-         SIGPWR,
-         SIGSYS,
--        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+        #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                      target_os = "fuchsia", target_os = "linux",
-+                      target_os = "redox")))]
-         SIGEMT,
--        #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+        #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                      target_os = "fuchsia", target_os = "linux",
-+                      target_os = "redox")))]
-         SIGINFO,
-     }
- }
-@@ -83,8 +91,10 @@ impl FromStr for Signal {
-             "SIGPIPE" => Signal::SIGPIPE,
-             "SIGALRM" => Signal::SIGALRM,
-             "SIGTERM" => Signal::SIGTERM,
--            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
--                      not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+            #[cfg(all(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux"),
-+                      not(any(target_arch = "mips", target_arch = "mips64",
-+                              target_arch = "sparc64"))))]
-             "SIGSTKFLT" => Signal::SIGSTKFLT,
-             "SIGCHLD" => Signal::SIGCHLD,
-             "SIGCONT" => Signal::SIGCONT,
-@@ -99,21 +109,31 @@ impl FromStr for Signal {
-             "SIGPROF" => Signal::SIGPROF,
-             "SIGWINCH" => Signal::SIGWINCH,
-             "SIGIO" => Signal::SIGIO,
--            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+            #[cfg(any(target_os = "android", target_os = "emscripten",
-+                      target_os = "fuchsia", target_os = "linux"))]
-             "SIGPWR" => Signal::SIGPWR,
-             "SIGSYS" => Signal::SIGSYS,
--            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux",
-+                          target_os = "redox")))]
-             "SIGEMT" => Signal::SIGEMT,
--            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux",
-+                          target_os = "redox")))]
-             "SIGINFO" => Signal::SIGINFO,
-             _ => return Err(Error::invalid_argument()),
-         })
-     }
- }
- 
--impl AsRef<str> for Signal {
--    fn as_ref(&self) -> &str {
--        match *self {
-+impl Signal {
-+    /// Returns name of signal.
-+    ///
-+    /// This function is equivalent to `<Signal as AsRef<str>>::as_ref()`,
-+    /// with difference that returned string is `'static`
-+    /// and not bound to `self`'s lifetime.
-+    pub fn as_str(self) -> &'static str {
-+        match self {
-             Signal::SIGHUP => "SIGHUP",
-             Signal::SIGINT => "SIGINT",
-             Signal::SIGQUIT => "SIGQUIT",
-@@ -129,7 +149,8 @@ impl AsRef<str> for Signal {
-             Signal::SIGPIPE => "SIGPIPE",
-             Signal::SIGALRM => "SIGALRM",
-             Signal::SIGTERM => "SIGTERM",
--            #[cfg(all(any(target_os = "android", target_os = "emscripten", target_os = "linux"),
-+            #[cfg(all(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux"),
-                       not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-             Signal::SIGSTKFLT => "SIGSTKFLT",
-             Signal::SIGCHLD => "SIGCHLD",
-@@ -145,17 +166,28 @@ impl AsRef<str> for Signal {
-             Signal::SIGPROF => "SIGPROF",
-             Signal::SIGWINCH => "SIGWINCH",
-             Signal::SIGIO => "SIGIO",
--            #[cfg(any(target_os = "android", target_os = "emscripten", target_os = "linux"))]
-+            #[cfg(any(target_os = "android", target_os = "emscripten",
-+                      target_os = "fuchsia", target_os = "linux"))]
-             Signal::SIGPWR => "SIGPWR",
-             Signal::SIGSYS => "SIGSYS",
--            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux",
-+                          target_os = "redox")))]
-             Signal::SIGEMT => "SIGEMT",
--            #[cfg(not(any(target_os = "android", target_os = "emscripten", target_os = "linux")))]
-+            #[cfg(not(any(target_os = "android", target_os = "emscripten",
-+                          target_os = "fuchsia", target_os = "linux",
-+                          target_os = "redox")))]
-             Signal::SIGINFO => "SIGINFO",
-         }
-     }
- }
- 
-+impl AsRef<str> for Signal {
-+    fn as_ref(&self) -> &str {
-+        self.as_str()
-+    }
-+}
-+
- impl fmt::Display for Signal {
-     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-         f.write_str(self.as_ref())
-@@ -164,7 +196,41 @@ impl fmt::Display for Signal {
- 
- pub use self::Signal::*;
- 
--#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), not(any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64"))))]
-+#[cfg(target_os = "redox")]
-+const SIGNALS: [Signal; 29] = [
-+    SIGHUP,
-+    SIGINT,
-+    SIGQUIT,
-+    SIGILL,
-+    SIGTRAP,
-+    SIGABRT,
-+    SIGBUS,
-+    SIGFPE,
-+    SIGKILL,
-+    SIGUSR1,
-+    SIGSEGV,
-+    SIGUSR2,
-+    SIGPIPE,
-+    SIGALRM,
-+    SIGTERM,
-+    SIGCHLD,
-+    SIGCONT,
-+    SIGSTOP,
-+    SIGTSTP,
-+    SIGTTIN,
-+    SIGTTOU,
-+    SIGURG,
-+    SIGXCPU,
-+    SIGXFSZ,
-+    SIGVTALRM,
-+    SIGPROF,
-+    SIGWINCH,
-+    SIGIO,
-+    SIGSYS];
-+#[cfg(all(any(target_os = "linux", target_os = "android",
-+              target_os = "emscripten", target_os = "fuchsia"),
-+          not(any(target_arch = "mips", target_arch = "mips64",
-+                  target_arch = "sparc64"))))]
- const SIGNALS: [Signal; 31] = [
-     SIGHUP,
-     SIGINT,
-@@ -197,7 +263,10 @@ const SIGNALS: [Signal; 31] = [
-     SIGIO,
-     SIGPWR,
-     SIGSYS];
--#[cfg(all(any(target_os = "linux", target_os = "android", target_os = "emscripten"), any(target_arch = "mips", target_arch = "mips64", target_arch = "sparc64")))]
-+#[cfg(all(any(target_os = "linux", target_os = "android",
-+              target_os = "emscripten", target_os = "fuchsia"),
-+          any(target_arch = "mips", target_arch = "mips64",
-+              target_arch = "sparc64")))]
- const SIGNALS: [Signal; 30] = [
-     SIGHUP,
-     SIGINT,
-@@ -229,7 +298,9 @@ const SIGNALS: [Signal; 30] = [
-     SIGIO,
-     SIGPWR,
-     SIGSYS];
--#[cfg(not(any(target_os = "linux", target_os = "android", target_os = "emscripten")))]
-+#[cfg(not(any(target_os = "linux", target_os = "android",
-+              target_os = "fuchsia", target_os = "emscripten",
-+              target_os = "redox")))]
- const SIGNALS: [Signal; 31] = [
-     SIGHUP,
-     SIGINT,
-@@ -288,12 +359,12 @@ impl Signal {
-     pub fn iterator() -> SignalIterator {
-         SignalIterator{next: 0}
-     }
-+}
-+
-+impl TryFrom<libc::c_int> for Signal {
-+    type Error = Error;
- 
--    // We do not implement the From trait, because it is supposed to be infallible.
--    // With Rust RFC 1542 comes the appropriate trait TryFrom. Once it is
--    // implemented, we'll replace this function.
--    #[inline]
--    pub fn from_c_int(signum: libc::c_int) -> Result<Signal> {
-+    fn try_from(signum: libc::c_int) -> Result<Signal> {
-         if 0 < signum && signum < NSIG {
-             Ok(unsafe { mem::transmute(signum) })
-         } else {
-@@ -306,8 +377,13 @@ pub const SIGIOT : Signal = SIGABRT;
- pub const SIGPOLL : Signal = SIGIO;
- pub const SIGUNUSED : Signal = SIGSYS;
- 
-+#[cfg(not(target_os = "redox"))]
-+type SaFlags_t = libc::c_int;
-+#[cfg(target_os = "redox")]
-+type SaFlags_t = libc::c_ulong;
-+
- libc_bitflags!{
--    pub struct SaFlags: libc::c_int {
-+    pub struct SaFlags: SaFlags_t {
-         SA_NOCLDSTOP;
-         SA_NOCLDWAIT;
-         SA_NODEFER;
-@@ -335,17 +411,17 @@ pub struct SigSet {
- 
- impl SigSet {
-     pub fn all() -> SigSet {
--        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
--        let _ = unsafe { libc::sigfillset(&mut sigset as *mut libc::sigset_t) };
-+        let mut sigset = mem::MaybeUninit::uninit();
-+        let _ = unsafe { libc::sigfillset(sigset.as_mut_ptr()) };
- 
--        SigSet { sigset: sigset }
-+        unsafe{ SigSet { sigset: sigset.assume_init() } }
-     }
- 
-     pub fn empty() -> SigSet {
--        let mut sigset: libc::sigset_t = unsafe { mem::uninitialized() };
--        let _ = unsafe { libc::sigemptyset(&mut sigset as *mut libc::sigset_t) };
-+        let mut sigset = mem::MaybeUninit::uninit();
-+        let _ = unsafe { libc::sigemptyset(sigset.as_mut_ptr()) };
- 
--        SigSet { sigset: sigset }
-+        unsafe{ SigSet { sigset: sigset.assume_init() } }
-     }
- 
-     pub fn add(&mut self, signal: Signal) {
-@@ -380,9 +456,9 @@ impl SigSet {
- 
-     /// Gets the currently blocked (masked) set of signals for the calling thread.
-     pub fn thread_get_mask() -> Result<SigSet> {
--        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
--        pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(&mut oldmask))?;
--        Ok(oldmask)
-+        let mut oldmask = mem::MaybeUninit::uninit();
-+        do_pthread_sigmask(SigmaskHow::SIG_SETMASK, None, Some(oldmask.as_mut_ptr()))?;
-+        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
-     }
- 
-     /// Sets the set of signals as the signal mask for the calling thread.
-@@ -402,18 +478,21 @@ impl SigSet {
- 
-     /// Sets the set of signals as the signal mask, and returns the old mask.
-     pub fn thread_swap_mask(&self, how: SigmaskHow) -> Result<SigSet> {
--        let mut oldmask: SigSet = unsafe { mem::uninitialized() };
--        pthread_sigmask(how, Some(self), Some(&mut oldmask))?;
--        Ok(oldmask)
-+        let mut oldmask = mem::MaybeUninit::uninit();
-+        do_pthread_sigmask(how, Some(self), Some(oldmask.as_mut_ptr()))?;
-+        Ok(unsafe{ SigSet{sigset: oldmask.assume_init()}})
-     }
- 
-     /// Suspends execution of the calling thread until one of the signals in the
-     /// signal mask becomes pending, and returns the accepted signal.
-+    #[cfg(not(target_os = "redox"))] // RedoxFS does not yet support sigwait
-     pub fn wait(&self) -> Result<Signal> {
--        let mut signum: libc::c_int = unsafe { mem::uninitialized() };
--        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, &mut signum) };
-+        let mut signum = mem::MaybeUninit::uninit();
-+        let res = unsafe { libc::sigwait(&self.sigset as *const libc::sigset_t, signum.as_mut_ptr()) };
- 
--        Errno::result(res).map(|_| Signal::from_c_int(signum).unwrap())
-+        Errno::result(res).map(|_| unsafe {
-+            Signal::try_from(signum.assume_init()).unwrap()
-+        })
-     }
- }
- 
-@@ -435,6 +514,7 @@ pub enum SigHandler {
-     Handler(extern fn(libc::c_int)),
-     /// Use the given signal-catching function, which takes in the signal, information about how
-     /// the signal was generated, and a pointer to the threads `ucontext_t`.
-+    #[cfg(not(target_os = "redox"))]
-     SigAction(extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void))
- }
- 
-@@ -451,20 +531,38 @@ impl SigAction {
-     /// is the `SigAction` variant). `mask` specifies other signals to block during execution of
-     /// the signal-catching function.
-     pub fn new(handler: SigHandler, flags: SaFlags, mask: SigSet) -> SigAction {
--        let mut s = unsafe { mem::uninitialized::<libc::sigaction>() };
--        s.sa_sigaction = match handler {
--            SigHandler::SigDfl => libc::SIG_DFL,
--            SigHandler::SigIgn => libc::SIG_IGN,
--            SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
--            SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
--        };
--        s.sa_flags = match handler {
--            SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
--            _ => (flags - SaFlags::SA_SIGINFO).bits(),
--        };
--        s.sa_mask = mask.sigset;
--
--        SigAction { sigaction: s }
-+        #[cfg(target_os = "redox")]
-+        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
-+            (*p).sa_handler = match handler {
-+                SigHandler::SigDfl => libc::SIG_DFL,
-+                SigHandler::SigIgn => libc::SIG_IGN,
-+                SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
-+            };
-+        }
-+
-+        #[cfg(not(target_os = "redox"))]
-+        unsafe fn install_sig(p: *mut libc::sigaction, handler: SigHandler) {
-+            (*p).sa_sigaction = match handler {
-+                SigHandler::SigDfl => libc::SIG_DFL,
-+                SigHandler::SigIgn => libc::SIG_IGN,
-+                SigHandler::Handler(f) => f as *const extern fn(libc::c_int) as usize,
-+                SigHandler::SigAction(f) => f as *const extern fn(libc::c_int, *mut libc::siginfo_t, *mut libc::c_void) as usize,
-+            };
-+        }
-+
-+        let mut s = mem::MaybeUninit::<libc::sigaction>::uninit();
-+        unsafe {
-+            let p = s.as_mut_ptr();
-+            install_sig(p, handler);
-+            (*p).sa_flags = match handler {
-+                #[cfg(not(target_os = "redox"))]
-+                SigHandler::SigAction(_) => (flags | SaFlags::SA_SIGINFO).bits(),
-+                _ => (flags - SaFlags::SA_SIGINFO).bits(),
-+            };
-+            (*p).sa_mask = mask.sigset;
-+
-+            SigAction { sigaction: s.assume_init() }
-+        }
-     }
- 
-     /// Returns the flags set on the action.
-@@ -479,6 +577,7 @@ impl SigAction {
-     }
- 
-     /// Returns the action's handler.
-+    #[cfg(not(target_os = "redox"))]
-     pub fn handler(&self) -> SigHandler {
-         match self.sigaction.sa_sigaction {
-             libc::SIG_DFL => SigHandler::SigDfl,
-@@ -488,6 +587,16 @@ impl SigAction {
-             f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
-         }
-     }
-+
-+    /// Returns the action's handler.
-+    #[cfg(target_os = "redox")]
-+    pub fn handler(&self) -> SigHandler {
-+        match self.sigaction.sa_handler {
-+            libc::SIG_DFL => SigHandler::SigDfl,
-+            libc::SIG_IGN => SigHandler::SigIgn,
-+            f => SigHandler::Handler( unsafe { mem::transmute(f) } ),
-+        }
-+    }
- }
- 
- /// Changes the action taken by a process on receipt of a specific signal.
-@@ -501,12 +610,13 @@ impl SigAction {
- /// the body of the signal-catching function. Be certain to only make syscalls that are explicitly
- /// marked safe for signal handlers and only share global data using atomics.
- pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigAction> {
--    let mut oldact = mem::uninitialized::<libc::sigaction>();
-+    let mut oldact = mem::MaybeUninit::<libc::sigaction>::uninit();
- 
--    let res =
--        libc::sigaction(signal as libc::c_int, &sigaction.sigaction as *const libc::sigaction, &mut oldact as *mut libc::sigaction);
-+    let res = libc::sigaction(signal as libc::c_int,
-+                              &sigaction.sigaction as *const libc::sigaction,
-+                              oldact.as_mut_ptr());
- 
--    Errno::result(res).map(|_| SigAction { sigaction: oldact })
-+    Errno::result(res).map(|_| SigAction { sigaction: oldact.assume_init() })
- }
- 
- /// Signal management (see [signal(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/signal.html))
-@@ -534,8 +644,7 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
- ///
- /// ```no_run
- /// # #[macro_use] extern crate lazy_static;
--/// # extern crate libc;
--/// # extern crate nix;
-+/// # use std::convert::TryFrom;
- /// # use std::sync::atomic::{AtomicBool, Ordering};
- /// # use nix::sys::signal::{self, Signal, SigHandler};
- /// lazy_static! {
-@@ -543,7 +652,7 @@ pub unsafe fn sigaction(signal: Signal, sigaction: &SigAction) -> Result<SigActi
- /// }
- ///
- /// extern fn handle_sigint(signal: libc::c_int) {
--///     let signal = Signal::from_c_int(signal).unwrap();
-+///     let signal = Signal::try_from(signal).unwrap();
- ///     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
- /// }
- ///
-@@ -571,6 +680,7 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
-         SigHandler::SigDfl => libc::signal(signal, libc::SIG_DFL),
-         SigHandler::SigIgn => libc::signal(signal, libc::SIG_IGN),
-         SigHandler::Handler(handler) => libc::signal(signal, handler as libc::sighandler_t),
-+        #[cfg(not(target_os = "redox"))]
-         SigHandler::SigAction(_) => return Err(Error::UnsupportedOperation),
-     };
-     Errno::result(res).map(|oldhandler| {
-@@ -582,6 +692,25 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
-     })
- }
- 
-+fn do_pthread_sigmask(how: SigmaskHow,
-+                       set: Option<&SigSet>,
-+                       oldset: Option<*mut libc::sigset_t>) -> Result<()> {
-+    if set.is_none() && oldset.is_none() {
-+        return Ok(())
-+    }
-+
-+    let res = unsafe {
-+        // if set or oldset is None, pass in null pointers instead
-+        libc::pthread_sigmask(how as libc::c_int,
-+                             set.map_or_else(ptr::null::<libc::sigset_t>,
-+                                             |s| &s.sigset as *const libc::sigset_t),
-+                             oldset.unwrap_or(ptr::null_mut())
-+                             )
-+    };
-+
-+    Errno::result(res).map(drop)
-+}
-+
- /// Manages the signal mask (set of blocked signals) for the calling thread.
- ///
- /// If the `set` parameter is `Some(..)`, then the signal mask will be updated with the signal set.
-@@ -599,21 +728,9 @@ pub unsafe fn signal(signal: Signal, handler: SigHandler) -> Result<SigHandler>
- /// or [`sigprocmask`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigprocmask.html) man pages.
- pub fn pthread_sigmask(how: SigmaskHow,
-                        set: Option<&SigSet>,
--                       oldset: Option<&mut SigSet>) -> Result<()> {
--    if set.is_none() && oldset.is_none() {
--        return Ok(())
--    }
--
--    let res = unsafe {
--        // if set or oldset is None, pass in null pointers instead
--        libc::pthread_sigmask(how as libc::c_int,
--                             set.map_or_else(ptr::null::<libc::sigset_t>,
--                                             |s| &s.sigset as *const libc::sigset_t),
--                             oldset.map_or_else(ptr::null_mut::<libc::sigset_t>,
--                                                |os| &mut os.sigset as *mut libc::sigset_t))
--    };
--
--    Errno::result(res).map(drop)
-+                       oldset: Option<&mut SigSet>) -> Result<()>
-+{
-+    do_pthread_sigmask(how, set, oldset.map(|os| &mut os.sigset as *mut _ ))
- }
- 
- /// Examine and change blocked signals.
-@@ -637,7 +754,7 @@ pub fn sigprocmask(how: SigmaskHow, set: Option<&SigSet>, oldset: Option<&mut Si
-     Errno::result(res).map(drop)
- }
- 
--pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()> {
-+pub fn kill<T: Into<Option<Signal>>>(pid: Pid, signal: T) -> Result<()> {
-     let res = unsafe { libc::kill(pid.into(),
-                                   match signal.into() {
-                                       Some(s) => s as libc::c_int,
-@@ -653,7 +770,8 @@ pub fn kill<T: Into<Option<Signal>>>(pid: ::unistd::Pid, signal: T) -> Result<()
- /// If `pgrp` less then or equal 1, the behavior is platform-specific.
- /// If `signal` is `None`, `killpg` will only preform error checking and won't
- /// send any signal.
--pub fn killpg<T: Into<Option<Signal>>>(pgrp: ::unistd::Pid, signal: T) -> Result<()> {
-+#[cfg(not(target_os = "fuchsia"))]
-+pub fn killpg<T: Into<Option<Signal>>>(pgrp: Pid, signal: T) -> Result<()> {
-     let res = unsafe { libc::killpg(pgrp.into(),
-                                   match signal.into() {
-                                       Some(s) => s as libc::c_int,
-@@ -702,9 +820,8 @@ pub enum SigevNotify {
-                     si_value: libc::intptr_t },
- }
- 
--#[cfg(not(target_os = "openbsd"))]
-+#[cfg(not(any(target_os = "openbsd", target_os = "redox")))]
- mod sigevent {
--    use libc;
-     use std::mem;
-     use std::ptr;
-     use super::SigevNotify;
-@@ -734,7 +851,10 @@ mod sigevent {
-         /// `SIGEV_SIGNAL`.  That field is part of a union that shares space with the
-         /// more genuinely useful `sigev_notify_thread_id`
-         pub fn new(sigev_notify: SigevNotify) -> SigEvent {
--            let mut sev = unsafe { mem::zeroed::<libc::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,
-                 SigevNotify::SigevSignal{..} => libc::SIGEV_SIGNAL,
-@@ -793,6 +913,7 @@ mod sigevent {
- 
- #[cfg(test)]
- mod tests {
-+    #[cfg(not(target_os = "redox"))]
-     use std::thread;
-     use super::*;
- 
-@@ -848,6 +969,7 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_thread_signal_set_mask() {
-         thread::spawn(|| {
-             let prev_mask = SigSet::thread_get_mask()
-@@ -868,6 +990,7 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_thread_signal_block() {
-         thread::spawn(|| {
-             let mut mask = SigSet::empty();
-@@ -880,6 +1003,7 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_thread_signal_unblock() {
-         thread::spawn(|| {
-             let mut mask = SigSet::empty();
-@@ -892,6 +1016,7 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_thread_signal_swap() {
-         thread::spawn(|| {
-             let mut mask = SigSet::empty();
-@@ -914,8 +1039,8 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_sigaction() {
--        use libc;
-         thread::spawn(|| {
-             extern fn test_sigaction_handler(_: libc::c_int) {}
-             extern fn test_sigaction_action(_: libc::c_int,
-@@ -952,6 +1077,7 @@ mod tests {
-     }
- 
-     #[test]
-+    #[cfg(not(target_os = "redox"))]
-     fn test_sigwait() {
-         thread::spawn(|| {
-             let mut mask = SigSet::empty();
-diff --git a/third_party/rust/nix/src/sys/signalfd.rs b/third_party/rust/nix/src/sys/signalfd.rs
-index 5425a27be9e52..c43b45046f719 100644
---- a/third_party/rust/nix/src/sys/signalfd.rs
-+++ b/third_party/rust/nix/src/sys/signalfd.rs
-@@ -16,10 +16,10 @@
- //! Please note that signal discarding is not specific to `signalfd`, but also happens with regular
- //! signal handlers.
- use libc;
--use unistd;
--use {Error, Result};
--use errno::Errno;
--pub use sys::signal::{self, SigSet};
-+use crate::unistd;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
-+pub use crate::sys::signal::{self, SigSet};
- pub use libc::signalfd_siginfo as siginfo;
- 
- use std::os::unix::io::{RawFd, AsRawFd};
-@@ -79,7 +79,7 @@ pub fn signalfd(fd: RawFd, mask: &SigSet, flags: SfdFlags) -> Result<RawFd> {
- ///     Err(err) => (), // some error happend
- /// }
- /// ```
--#[derive(Clone, Debug, Eq, Hash, PartialEq)]
-+#[derive(Debug, Eq, Hash, PartialEq)]
- pub struct SignalFd(RawFd);
- 
- impl SignalFd {
-@@ -98,10 +98,15 @@ impl SignalFd {
-     }
- 
-     pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
--        let mut buffer: [u8; SIGNALFD_SIGINFO_SIZE] = unsafe { mem::uninitialized() };
--
--        match unistd::read(self.0, &mut buffer) {
--            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer) })),
-+        let mut buffer = mem::MaybeUninit::<[u8; SIGNALFD_SIGINFO_SIZE]>::uninit();
-+
-+        let res = Errno::result(unsafe {
-+            libc::read(self.0,
-+                       buffer.as_mut_ptr() as *mut libc::c_void,
-+                       SIGNALFD_SIGINFO_SIZE as libc::size_t)
-+        }).map(|r| r as usize);
-+        match res {
-+            Ok(SIGNALFD_SIGINFO_SIZE) => Ok(Some(unsafe { mem::transmute(buffer.assume_init()) })),
-             Ok(_) => unreachable!("partial read on signalfd"),
-             Err(Error::Sys(Errno::EAGAIN)) => Ok(None),
-             Err(error) => Err(error)
-@@ -111,7 +116,10 @@ impl SignalFd {
- 
- impl Drop for SignalFd {
-     fn drop(&mut self) {
--        let _ = unistd::close(self.0);
-+        let e = unistd::close(self.0);
-+        if !std::thread::panicking() && e == Err(Error::Sys(Errno::EBADF)) {
-+            panic!("Closing an invalid file descriptor!");
-+        };
-     }
- }
- 
-diff --git a/third_party/rust/nix/src/sys/socket/addr.rs b/third_party/rust/nix/src/sys/socket/addr.rs
-index ed41441155361..5a2739bd10194 100644
---- a/third_party/rust/nix/src/sys/socket/addr.rs
-+++ b/third_party/rust/nix/src/sys/socket/addr.rs
-@@ -1,20 +1,20 @@
- use super::sa_family_t;
--use {Error, Result, NixPath};
--use errno::Errno;
--use libc;
-+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};
- use std::path::Path;
- use std::os::unix::ffi::OsStrExt;
- #[cfg(any(target_os = "android", target_os = "linux"))]
--use ::sys::socket::addr::netlink::NetlinkAddr;
-+use crate::sys::socket::addr::netlink::NetlinkAddr;
- #[cfg(any(target_os = "android", target_os = "linux"))]
--use ::sys::socket::addr::alg::AlgAddr;
-+use crate::sys::socket::addr::alg::AlgAddr;
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- use std::os::unix::io::RawFd;
- #[cfg(any(target_os = "ios", target_os = "macos"))]
--use ::sys::socket::addr::sys_control::SysControlAddr;
-+use crate::sys::socket::addr::sys_control::SysControlAddr;
- #[cfg(any(target_os = "android",
-           target_os = "dragonfly",
-           target_os = "freebsd",
-@@ -22,9 +22,10 @@ use ::sys::socket::addr::sys_control::SysControlAddr;
-           target_os = "linux",
-           target_os = "macos",
-           target_os = "netbsd",
--          target_os = "openbsd"))]
-+          target_os = "openbsd",
-+          target_os = "fuchsia"))]
- pub use self::datalink::LinkAddr;
--#[cfg(target_os = "linux")]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
- pub use self::vsock::VsockAddr;
- 
- /// These constants specify the protocol family to be used
-@@ -42,7 +43,7 @@ pub enum AddressFamily {
-     #[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"))]
-+    #[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
-     Packet = libc::AF_PACKET,
-     /// KEXT Controls and Notifications
-     #[cfg(any(target_os = "ios", target_os = "macos"))]
-@@ -116,7 +117,7 @@ pub enum AddressFamily {
-     Alg = libc::AF_ALG,
-     #[cfg(target_os = "linux")]
-     Nfc = libc::AF_NFC,
--    #[cfg(target_os = "linux")]
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-     Vsock = libc::AF_VSOCK,
-     #[cfg(any(target_os = "dragonfly",
-               target_os = "freebsd",
-@@ -243,7 +244,7 @@ impl AddressFamily {
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
-             libc::AF_LINK => Some(AddressFamily::Link),
--            #[cfg(target_os = "linux")]
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-             libc::AF_VSOCK => Some(AddressFamily::Vsock),
-             _ => None
-         }
-@@ -367,6 +368,8 @@ impl IpAddr {
-     /// Create a new IpAddr that contains an IPv6 address.
-     ///
-     /// The result will represent the IP address a:b:c:d:e:f
-+    #[allow(clippy::many_single_char_names)]
-+    #[allow(clippy::too_many_arguments)]
-     pub fn new_v6(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddr {
-         IpAddr::V6(Ipv6Addr::new(a, b, c, d, e, f, g, h))
-     }
-@@ -405,15 +408,18 @@ impl fmt::Display for IpAddr {
- pub struct Ipv4Addr(pub libc::in_addr);
- 
- impl Ipv4Addr {
-+    #[allow(clippy::identity_op)]   // More readable this way
-     pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
--        let ip = (((a as u32) << 24) |
--                  ((b as u32) << 16) |
--                  ((c as u32) <<  8) |
--                  ((d as u32) <<  0)).to_be();
-+        let ip = ((u32::from(a) << 24) |
-+                  (u32::from(b) << 16) |
-+                  (u32::from(c) <<  8) |
-+                  (u32::from(d) <<  0)).to_be();
- 
-         Ipv4Addr(libc::in_addr { s_addr: ip })
-     }
- 
-+    // Use pass by reference for symmetry with Ipv6Addr::from_std
-+    #[allow(clippy::trivially_copy_pass_by_ref)]
-     pub fn from_std(std: &net::Ipv4Addr) -> Ipv4Addr {
-         let bits = std.octets();
-         Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
-@@ -423,12 +429,12 @@ impl Ipv4Addr {
-         Ipv4Addr(libc::in_addr { s_addr: libc::INADDR_ANY })
-     }
- 
--    pub fn octets(&self) -> [u8; 4] {
-+    pub fn octets(self) -> [u8; 4] {
-         let bits = u32::from_be(self.0.s_addr);
-         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
-     }
- 
--    pub fn to_std(&self) -> net::Ipv4Addr {
-+    pub fn to_std(self) -> net::Ipv4Addr {
-         let bits = self.octets();
-         net::Ipv4Addr::new(bits[0], bits[1], bits[2], bits[3])
-     }
-@@ -467,10 +473,10 @@ macro_rules! to_u16_array {
- }
- 
- impl Ipv6Addr {
-+    #[allow(clippy::many_single_char_names)]
-+    #[allow(clippy::too_many_arguments)]
-     pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
--        let mut in6_addr_var: libc::in6_addr = unsafe{mem::uninitialized()};
--        in6_addr_var.s6_addr = to_u8_array!(a,b,c,d,e,f,g,h);
--        Ipv6Addr(in6_addr_var)
-+        Ipv6Addr(libc::in6_addr{s6_addr: to_u8_array!(a,b,c,d,e,f,g,h)})
-     }
- 
-     pub fn from_std(std: &net::Ipv6Addr) -> Ipv6Addr {
-@@ -555,7 +561,7 @@ impl UnixAddr {
-                                      ret.sun_path.as_mut_ptr().offset(1) as *mut u8,
-                                      path.len());
- 
--            Ok(UnixAddr(ret, ret.sun_path.len()))
-+            Ok(UnixAddr(ret, path.len() + 1))
-         }
-     }
- 
-@@ -643,7 +649,7 @@ pub enum SockAddr {
-               target_os = "netbsd",
-               target_os = "openbsd"))]
-     Link(LinkAddr),
--    #[cfg(target_os = "linux")]
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-     Vsock(VsockAddr),
- }
- 
-@@ -671,7 +677,7 @@ impl SockAddr {
-         SysControlAddr::from_name(sockfd, name, unit).map(|a| SockAddr::SysControl(a))
-     }
- 
--    #[cfg(target_os = "linux")]
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-     pub fn new_vsock(cid: u32, port: u32) -> SockAddr {
-         SockAddr::Vsock(VsockAddr::new(cid, port))
-     }
-@@ -696,7 +702,7 @@ impl SockAddr {
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
-             SockAddr::Link(..) => AddressFamily::Link,
--            #[cfg(target_os = "linux")]
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-             SockAddr::Vsock(..) => AddressFamily::Vsock,
-         }
-     }
-@@ -709,11 +715,17 @@ impl SockAddr {
-     ///
-     /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
-     /// Returns None for unsupported families.
--    pub unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
-+    ///
-+    /// # Safety
-+    ///
-+    /// unsafe because it takes a raw pointer as argument.  The caller must
-+    /// ensure that the pointer is valid.
-+    #[cfg(not(target_os = "fuchsia"))]
-+    pub(crate) unsafe fn from_libc_sockaddr(addr: *const libc::sockaddr) -> Option<SockAddr> {
-         if addr.is_null() {
-             None
-         } else {
--            match AddressFamily::from_i32((*addr).sa_family as i32) {
-+            match AddressFamily::from_i32(i32::from((*addr).sa_family)) {
-                 Some(AddressFamily::Unix) => None,
-                 Some(AddressFamily::Inet) => Some(SockAddr::Inet(
-                     InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
-@@ -742,7 +754,7 @@ impl SockAddr {
-                         Some(SockAddr::Link(ether_addr))
-                     }
-                 },
--                #[cfg(target_os = "linux")]
-+                #[cfg(any(target_os = "android", target_os = "linux"))]
-                 Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
-                     VsockAddr(*(addr as *const libc::sockaddr_vm)))),
-                 // Other address families are currently not supported and simply yield a None
-@@ -759,28 +771,83 @@ impl SockAddr {
-     /// with the size of the actual data type. sockaddr is commonly used as a proxy for
-     /// a superclass as C doesn't support inheritance, so many functions that take
-     /// a sockaddr * need to take the size of the underlying type as well and then internally cast it back.
--    pub unsafe fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
-+    pub fn as_ffi_pair(&self) -> (&libc::sockaddr, libc::socklen_t) {
-         match *self {
--            SockAddr::Inet(InetAddr::V4(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in>() as libc::socklen_t),
--            SockAddr::Inet(InetAddr::V6(ref addr)) => (mem::transmute(addr), mem::size_of::<libc::sockaddr_in6>() as libc::socklen_t),
--            SockAddr::Unix(UnixAddr(ref addr, len)) => (mem::transmute(addr), (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t),
-+            SockAddr::Inet(InetAddr::V4(ref addr)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(addr as *const libc::sockaddr_in as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(addr) as libc::socklen_t
-+            ),
-+            SockAddr::Inet(InetAddr::V6(ref addr)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(addr as *const libc::sockaddr_in6 as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(addr) as libc::socklen_t
-+            ),
-+            SockAddr::Unix(UnixAddr(ref addr, len)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(addr as *const libc::sockaddr_un as *const libc::sockaddr)
-+                },
-+                (len + offset_of!(libc::sockaddr_un, sun_path)) as libc::socklen_t
-+            ),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            SockAddr::Netlink(NetlinkAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_nl>() as libc::socklen_t),
-+            SockAddr::Netlink(NetlinkAddr(ref sa)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(sa as *const libc::sockaddr_nl as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(sa) as libc::socklen_t
-+            ),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            SockAddr::Alg(AlgAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_alg>() as libc::socklen_t),
-+            SockAddr::Alg(AlgAddr(ref sa)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(sa as *const libc::sockaddr_alg as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(sa) as libc::socklen_t
-+            ),
-             #[cfg(any(target_os = "ios", target_os = "macos"))]
--            SockAddr::SysControl(SysControlAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_ctl>() as libc::socklen_t),
-+            SockAddr::SysControl(SysControlAddr(ref sa)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(sa as *const libc::sockaddr_ctl as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(sa) as libc::socklen_t
-+
-+            ),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_ll>() as libc::socklen_t),
-+            SockAddr::Link(LinkAddr(ref addr)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(addr as *const libc::sockaddr_ll as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(addr) as libc::socklen_t
-+            ),
-             #[cfg(any(target_os = "dragonfly",
-                       target_os = "freebsd",
-                       target_os = "ios",
-                       target_os = "macos",
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
--            SockAddr::Link(LinkAddr(ref ether_addr)) => (mem::transmute(ether_addr), mem::size_of::<libc::sockaddr_dl>() as libc::socklen_t),
--            #[cfg(target_os = "linux")]
--            SockAddr::Vsock(VsockAddr(ref sa)) => (mem::transmute(sa), mem::size_of::<libc::sockaddr_vm>() as libc::socklen_t),
-+            SockAddr::Link(LinkAddr(ref addr)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(addr as *const libc::sockaddr_dl as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(addr) as libc::socklen_t
-+            ),
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-+            SockAddr::Vsock(VsockAddr(ref sa)) => (
-+                // This cast is always allowed in C
-+                unsafe {
-+                    &*(sa as *const libc::sockaddr_vm as *const libc::sockaddr)
-+                },
-+                mem::size_of_val(sa) as libc::socklen_t
-+            ),
-         }
-     }
- }
-@@ -805,7 +872,7 @@ impl fmt::Display for SockAddr {
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
-             SockAddr::Link(ref ether_addr) => ether_addr.fmt(f),
--            #[cfg(target_os = "linux")]
-+            #[cfg(any(target_os = "android", target_os = "linux"))]
-             SockAddr::Vsock(ref svm) => svm.fmt(f),
-         }
-     }
-@@ -813,7 +880,7 @@ impl fmt::Display for SockAddr {
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub mod netlink {
--    use ::sys::socket::addr::AddressFamily;
-+    use crate::sys::socket::addr::AddressFamily;
-     use libc::{sa_family_t, sockaddr_nl};
-     use std::{fmt, mem};
- 
-@@ -911,11 +978,11 @@ pub mod alg {
- 
- #[cfg(any(target_os = "ios", target_os = "macos"))]
- pub mod sys_control {
--    use ::sys::socket::addr::AddressFamily;
-+    use crate::sys::socket::addr::AddressFamily;
-     use libc::{self, c_uchar};
-     use std::{fmt, mem};
-     use std::os::unix::io::RawFd;
--    use {Errno, Error, Result};
-+    use crate::{Errno, Error, Result};
- 
-     // FIXME: Move type into `libc`
-     #[repr(C)]
-@@ -957,7 +1024,7 @@ pub mod sys_control {
- 
-             let mut ctl_name = [0; MAX_KCTL_NAME];
-             ctl_name[..name.len()].clone_from_slice(name.as_bytes());
--            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name: ctl_name };
-+            let mut info = ctl_ioc_info { ctl_id: 0, ctl_name };
- 
-             unsafe { ctl_info(sockfd, &mut info)?; }
- 
-@@ -981,9 +1048,9 @@ pub mod sys_control {
- }
- 
- 
--#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[cfg(any(target_os = "android", target_os = "linux", target_os = "fuchsia"))]
- mod datalink {
--    use super::{libc, fmt, AddressFamily};
-+    use super::{fmt, AddressFamily};
- 
-     /// Hardware Address
-     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-@@ -1023,14 +1090,14 @@ mod datalink {
- 
-         /// Physical-layer address (MAC)
-         pub fn addr(&self) -> [u8; 6] {
--            let a = self.0.sll_addr[0] as u8;
--            let b = self.0.sll_addr[1] as u8;
--            let c = self.0.sll_addr[2] as u8;
--            let d = self.0.sll_addr[3] as u8;
--            let e = self.0.sll_addr[4] as u8;
--            let f = self.0.sll_addr[5] as u8;
--
--            [a, b, c, d, e, f]
-+            [
-+                self.0.sll_addr[0] as u8,
-+                self.0.sll_addr[1] as u8,
-+                self.0.sll_addr[2] as u8,
-+                self.0.sll_addr[3] as u8,
-+                self.0.sll_addr[4] as u8,
-+                self.0.sll_addr[5] as u8,
-+            ]
-         }
-     }
- 
-@@ -1055,7 +1122,7 @@ mod datalink {
-           target_os = "netbsd",
-           target_os = "openbsd"))]
- mod datalink {
--    use super::{libc, fmt, AddressFamily};
-+    use super::{fmt, AddressFamily};
- 
-     /// Hardware Address
-     #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-@@ -1069,7 +1136,7 @@ mod datalink {
- 
-         /// always == AF_LINK
-         pub fn family(&self) -> AddressFamily {
--            assert_eq!(self.0.sdl_family as i32, libc::AF_LINK);
-+            assert_eq!(i32::from(self.0.sdl_family), libc::AF_LINK);
-             AddressFamily::Link
-         }
- 
-@@ -1105,11 +1172,7 @@ mod datalink {
-             let alen = self.alen();
-             let data_len = self.0.sdl_data.len();
- 
--            if alen > 0 && nlen + alen < data_len {
--                false
--            } else {
--                true
--            }
-+            alen == 0 || nlen + alen >= data_len
-         }
- 
-         /// Physical-layer address (MAC)
-@@ -1119,14 +1182,14 @@ mod datalink {
- 
-             assert!(!self.is_empty());
- 
--            let a = data[nlen] as u8;
--            let b = data[nlen + 1] as u8;
--            let c = data[nlen + 2] as u8;
--            let d = data[nlen + 3] as u8;
--            let e = data[nlen + 4] as u8;
--            let f = data[nlen + 5] as u8;
--
--            [a, b, c, d, e, f]
-+            [
-+                data[nlen] as u8,
-+                data[nlen + 1] as u8,
-+                data[nlen + 2] as u8,
-+                data[nlen + 3] as u8,
-+                data[nlen + 4] as u8,
-+                data[nlen + 5] as u8,
-+            ]
-         }
-     }
- 
-@@ -1144,9 +1207,9 @@ mod datalink {
-     }
- }
- 
--#[cfg(target_os = "linux")]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
- pub mod vsock {
--    use ::sys::socket::addr::AddressFamily;
-+    use crate::sys::socket::addr::AddressFamily;
-     use libc::{sa_family_t, sockaddr_vm};
-     use std::{fmt, mem};
-     use std::hash::{Hash, Hasher};
-@@ -1269,7 +1332,7 @@ mod tests {
-         let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
- 
-         let sun_path1 = addr.sun_path();
--        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
-+        let sun_path2 = [0u8, 110, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116];
-         assert_eq!(sun_path1.len(), sun_path2.len());
-         for i in 0..sun_path1.len() {
-             assert_eq!(sun_path1[i], sun_path2[i]);
-diff --git a/third_party/rust/nix/src/sys/socket/mod.rs b/third_party/rust/nix/src/sys/socket/mod.rs
-index 1c12c5f851734..631d281ed16af 100644
---- a/third_party/rust/nix/src/sys/socket/mod.rs
-+++ b/third_party/rust/nix/src/sys/socket/mod.rs
-@@ -1,14 +1,15 @@
- //! Socket interface functions
- //!
- //! [Further reading](http://man7.org/linux/man-pages/man7/socket.7.html)
--use {Error, Result};
--use errno::Errno;
-+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;
--use sys::time::TimeVal;
--use sys::uio::IoVec;
-+use crate::sys::time::TimeVal;
-+use crate::sys::uio::IoVec;
- 
- mod addr;
- pub mod sockopt;
-@@ -30,11 +31,11 @@ pub use self::addr::{
-     LinkAddr,
- };
- #[cfg(any(target_os = "android", target_os = "linux"))]
--pub use ::sys::socket::addr::netlink::NetlinkAddr;
-+pub use crate::sys::socket::addr::netlink::NetlinkAddr;
- #[cfg(any(target_os = "android", target_os = "linux"))]
--pub use sys::socket::addr::alg::AlgAddr;
--#[cfg(target_os = "linux")]
--pub use sys::socket::addr::vsock::VsockAddr;
-+pub use crate::sys::socket::addr::alg::AlgAddr;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+pub use crate::sys::socket::addr::vsock::VsockAddr;
- 
- pub use libc::{
-     cmsghdr,
-@@ -92,6 +93,64 @@ pub enum SockProtocol {
-     /// ([ref](https://developer.apple.com/library/content/documentation/Darwin/Conceptual/NKEConceptual/control/control.html))
-     #[cfg(any(target_os = "ios", target_os = "macos"))]
-     KextControl = libc::SYSPROTO_CONTROL,
-+    /// Receives routing and link updates and may be used to modify the routing tables (both IPv4 and IPv6), IP addresses, link
-+    // parameters, neighbor setups, queueing disciplines, traffic classes and packet classifiers
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkRoute = libc::NETLINK_ROUTE,
-+    /// Reserved for user-mode socket protocols
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkUserSock = libc::NETLINK_USERSOCK,
-+    /// Query information about sockets of various protocol families from the kernel
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkSockDiag = libc::NETLINK_SOCK_DIAG,
-+    /// SELinux event notifications.
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkSELinux = libc::NETLINK_SELINUX,
-+    /// Open-iSCSI
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkISCSI = libc::NETLINK_ISCSI,
-+    /// Auditing
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkAudit = libc::NETLINK_AUDIT,
-+    /// Access to FIB lookup from user space
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkFIBLookup = libc::NETLINK_FIB_LOOKUP,
-+    /// Netfilter subsystem
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkNetFilter = libc::NETLINK_NETFILTER,
-+    /// SCSI Transports
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkSCSITransport = libc::NETLINK_SCSITRANSPORT,
-+    /// Infiniband RDMA
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkRDMA = libc::NETLINK_RDMA,
-+    /// Transport IPv6 packets from netfilter to user space.  Used by ip6_queue kernel module.
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkIPv6Firewall = libc::NETLINK_IP6_FW,
-+    /// DECnet routing messages
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkDECNetRoutingMessage = libc::NETLINK_DNRTMSG,
-+    /// Kernel messages to user space
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkKObjectUEvent = libc::NETLINK_KOBJECT_UEVENT,
-+    /// Netlink interface to request information about ciphers registered with the kernel crypto API as well as allow
-+    /// configuration of the kernel crypto API.
-+    /// ([ref](https://www.man7.org/linux/man-pages/man7/netlink.7.html))
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    NetlinkCrypto = libc::NETLINK_CRYPTO,
- }
- 
- libc_bitflags!{
-@@ -189,12 +248,22 @@ cfg_if! {
-     if #[cfg(any(target_os = "android", target_os = "linux"))] {
-         /// Unix credentials of the sending process.
-         ///
--        /// This struct is used with the `SO_PEERCRED` ancillary message for UNIX sockets.
--        #[repr(C)]
-+        /// This struct is used with the `SO_PEERCRED` ancillary message
-+        /// and the `SCM_CREDENTIALS` control message for UNIX sockets.
-+        #[repr(transparent)]
-         #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-         pub struct UnixCredentials(libc::ucred);
- 
-         impl UnixCredentials {
-+            /// Creates a new instance with the credentials of the current process
-+            pub fn new() -> Self {
-+                UnixCredentials(libc::ucred {
-+                    pid: crate::unistd::getpid().as_raw(),
-+                    uid: crate::unistd::getuid().as_raw(),
-+                    gid: crate::unistd::getgid().as_raw(),
-+                })
-+            }
-+
-             /// Returns the process identifier
-             pub fn pid(&self) -> libc::pid_t {
-                 self.0.pid
-@@ -211,6 +280,12 @@ cfg_if! {
-             }
-         }
- 
-+        impl Default for UnixCredentials {
-+            fn default() -> Self {
-+                Self::new()
-+            }
-+        }
-+
-         impl From<libc::ucred> for UnixCredentials {
-             fn from(cred: libc::ucred) -> Self {
-                 UnixCredentials(cred)
-@@ -222,13 +297,53 @@ cfg_if! {
-                 self.0
-             }
-         }
-+    } else if #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))] {
-+        /// Unix credentials of the sending process.
-+        ///
-+        /// This struct is used with the `SCM_CREDS` ancillary message for UNIX sockets.
-+        #[repr(transparent)]
-+        #[derive(Clone, Copy, Debug, Eq, PartialEq)]
-+        pub struct UnixCredentials(libc::cmsgcred);
-+
-+        impl UnixCredentials {
-+            /// Returns the process identifier
-+            pub fn pid(&self) -> libc::pid_t {
-+                self.0.cmcred_pid
-+            }
-+
-+            /// Returns the real user identifier
-+            pub fn uid(&self) -> libc::uid_t {
-+                self.0.cmcred_uid
-+            }
-+
-+            /// Returns the effective user identifier
-+            pub fn euid(&self) -> libc::uid_t {
-+                self.0.cmcred_euid
-+            }
-+
-+            /// Returns the real group identifier
-+            pub fn gid(&self) -> libc::gid_t {
-+                self.0.cmcred_gid
-+            }
-+
-+            /// Returns a list group identifiers (the first one being the effective GID)
-+            pub fn groups(&self) -> &[libc::gid_t] {
-+                unsafe { slice::from_raw_parts(self.0.cmcred_groups.as_ptr() as *const libc::gid_t, self.0.cmcred_ngroups as _) }
-+            }
-+        }
-+
-+        impl From<libc::cmsgcred> for UnixCredentials {
-+            fn from(cred: libc::cmsgcred) -> Self {
-+                UnixCredentials(cred)
-+            }
-+        }
-     }
- }
- 
- /// Request for multicast socket operations
- ///
- /// This is a wrapper type around `ip_mreq`.
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct IpMembershipRequest(libc::ip_mreq);
- 
-@@ -247,7 +362,7 @@ impl IpMembershipRequest {
- /// Request for ipv6 multicast socket operations
- ///
- /// This is a wrapper type around `ipv6_mreq`.
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct Ipv6MembershipRequest(libc::ipv6_mreq);
- 
-@@ -261,21 +376,6 @@ impl Ipv6MembershipRequest {
-     }
- }
- 
--cfg_if! {
--    // Darwin and DragonFly BSD always align struct cmsghdr to 32-bit only.
--    if #[cfg(any(target_os = "dragonfly", target_os = "ios", target_os = "macos"))] {
--        type align_of_cmsg_data = u32;
--    } else {
--        type align_of_cmsg_data = size_t;
--    }
--}
--
--/// A type that can be used to store ancillary data received by
--/// [`recvmsg`](fn.recvmsg.html)
--pub trait CmsgBuffer {
--    fn as_bytes_mut(&mut self) -> &mut [u8];
--}
--
- /// Create a buffer large enough for storing some control messages as returned
- /// by [`recvmsg`](fn.recvmsg.html).
- ///
-@@ -311,61 +411,11 @@ macro_rules! cmsg_space {
-                     CMSG_SPACE(mem::size_of::<$x>() as c_uint)
-                 } as usize;
-             )*
--            let mut v = Vec::<u8>::with_capacity(space);
--            // safe because any bit pattern is a valid u8
--            unsafe {v.set_len(space)};
--            v
-+            Vec::<u8>::with_capacity(space)
-         }
-     }
- }
- 
--/// A structure used to make room in a cmsghdr passed to recvmsg. The
--/// size and alignment match that of a cmsghdr followed by a T, but the
--/// fields are not accessible, as the actual types will change on a call
--/// to recvmsg.
--///
--/// To make room for multiple messages, nest the type parameter with
--/// tuples:
--///
--/// ```
--/// use std::os::unix::io::RawFd;
--/// use nix::sys::socket::CmsgSpace;
--/// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
--/// ```
--#[repr(C)]
--#[derive(Clone, Copy, Debug, Eq, PartialEq)]
--pub struct CmsgSpace<T> {
--    _hdr: cmsghdr,
--    _pad: [align_of_cmsg_data; 0],
--    _data: T,
--}
--
--impl<T> CmsgSpace<T> {
--    /// Create a CmsgSpace<T>. The structure is used only for space, so
--    /// the fields are uninitialized.
--    #[deprecated( since="0.14.0", note="Use the cmsg_space! macro instead")]
--    pub fn new() -> Self {
--        // Safe because the fields themselves aren't accessible.
--        unsafe { mem::uninitialized() }
--    }
--}
--
--impl<T> CmsgBuffer for CmsgSpace<T> {
--    fn as_bytes_mut(&mut self) -> &mut [u8] {
--        // Safe because nothing ever attempts to access CmsgSpace's fields
--        unsafe {
--            slice::from_raw_parts_mut(self as *mut CmsgSpace<T> as *mut u8,
--                                      mem::size_of::<Self>())
--        }
--    }
--}
--
--impl CmsgBuffer for Vec<u8> {
--    fn as_bytes_mut(&mut self) -> &mut [u8] {
--        &mut self[..]
--    }
--}
--
- #[derive(Clone, Copy, Debug, Eq, PartialEq)]
- pub struct RecvMsg<'a> {
-     pub bytes: usize,
-@@ -433,7 +483,11 @@ pub enum ControlMessageOwned {
-     /// Received version of
-     /// [`ControlMessage::ScmCredentials`][#enum.ControlMessage.html#variant.ScmCredentials]
-     #[cfg(any(target_os = "android", target_os = "linux"))]
--    ScmCredentials(libc::ucred),
-+    ScmCredentials(UnixCredentials),
-+    /// Received version of
-+    /// [`ControlMessage::ScmCreds`][#enum.ControlMessage.html#variant.ScmCreds]
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    ScmCreds(UnixCredentials),
-     /// A message of type `SCM_TIMESTAMP`, containing the time the
-     /// packet was received by the kernel.
-     ///
-@@ -442,10 +496,6 @@ pub enum ControlMessageOwned {
-     ///
-     /// # Examples
-     ///
--    // Disable this test on FreeBSD i386
--    // https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=222039
--    #[cfg_attr(not(all(target_os = "freebsd", target_arch = "x86")), doc = " ```")]
--    #[cfg_attr(all(target_os = "freebsd", target_arch = "x86"), doc = " ```no_run")]
-     /// # #[macro_use] extern crate nix;
-     /// # use nix::sys::socket::*;
-     /// # use nix::sys::uio::IoVec;
-@@ -528,6 +578,18 @@ pub enum ControlMessageOwned {
-         target_os = "openbsd",
-     ))]
-     Ipv4RecvDstAddr(libc::in_addr),
-+
-+    /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP
-+    /// packets from a single sender.
-+    /// Fixed-size payloads are following one by one in a receive buffer.
-+    /// This Control Message indicates the size of all smaller packets,
-+    /// except, maybe, the last one.
-+    ///
-+    /// `UdpGroSegment` socket option should be enabled on a socket
-+    /// to allow receiving GRO packets.
-+    #[cfg(target_os = "linux")]
-+    UdpGroSegments(u16),
-+
-     /// Catch-all variant for unimplemented cmsg types.
-     #[doc(hidden)]
-     Unknown(UnknownCmsg),
-@@ -540,9 +602,9 @@ impl ControlMessageOwned {
-     /// specified in the header. Normally, the kernel ensures that this is the
-     /// case. "Correct" in this case includes correct length, alignment and
-     /// actual content.
--    ///
--    /// Returns `None` if the data may be unaligned.  In that case use
--    /// `ControlMessageOwned::decode_from`.
-+    // Clippy complains about the pointer alignment of `p`, not understanding
-+    // that it's being fed to a function that can handle that.
-+    #[allow(clippy::cast_ptr_alignment)]
-     unsafe fn decode_from(header: &cmsghdr) -> ControlMessageOwned
-     {
-         let p = CMSG_DATA(header);
-@@ -553,16 +615,20 @@ impl ControlMessageOwned {
-                 let n = len / mem::size_of::<RawFd>();
-                 let mut fds = Vec::with_capacity(n);
-                 for i in 0..n {
--                    let fdp = (p as *const RawFd).offset(i as isize);
-+                    let fdp = (p as *const RawFd).add(i);
-                     fds.push(ptr::read_unaligned(fdp));
-                 }
--                let cmo = ControlMessageOwned::ScmRights(fds);
--                cmo
-+                ControlMessageOwned::ScmRights(fds)
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
-             (libc::SOL_SOCKET, libc::SCM_CREDENTIALS) => {
-                 let cred: libc::ucred = ptr::read_unaligned(p as *const _);
--                ControlMessageOwned::ScmCredentials(cred)
-+                ControlMessageOwned::ScmCredentials(cred.into())
-+            }
-+            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+            (libc::SOL_SOCKET, libc::SCM_CREDS) => {
-+                let cred: libc::cmsgcred = ptr::read_unaligned(p as *const _);
-+                ControlMessageOwned::ScmCreds(cred.into())
-             }
-             (libc::SOL_SOCKET, libc::SCM_TIMESTAMP) => {
-                 let tv: libc::timeval = ptr::read_unaligned(p as *const _);
-@@ -612,6 +678,11 @@ impl ControlMessageOwned {
-                 let dl = ptr::read_unaligned(p as *const libc::in_addr);
-                 ControlMessageOwned::Ipv4RecvDstAddr(dl)
-             },
-+            #[cfg(target_os = "linux")]
-+            (libc::SOL_UDP, libc::UDP_GRO) => {
-+                let gso_size: u16 = ptr::read_unaligned(p as *const _);
-+                ControlMessageOwned::UdpGroSegments(gso_size)
-+            },
-             (_, _) => {
-                 let sl = slice::from_raw_parts(p, len);
-                 let ucmsg = UnknownCmsg(*header, Vec::<u8>::from(&sl[..]));
-@@ -650,10 +721,22 @@ pub enum ControlMessage<'a> {
-     ///
-     /// For further information, please refer to the
-     /// [`unix(7)`](http://man7.org/linux/man-pages/man7/unix.7.html) man page.
--    // FIXME: When `#[repr(transparent)]` is stable, use it on `UnixCredentials`
--    // and put that in here instead of a raw ucred.
-     #[cfg(any(target_os = "android", target_os = "linux"))]
--    ScmCredentials(&'a libc::ucred),
-+    ScmCredentials(&'a UnixCredentials),
-+    /// A message of type `SCM_CREDS`, containing the pid, uid, euid, gid and groups of
-+    /// a process connected to the socket.
-+    ///
-+    /// This is similar to the socket options `LOCAL_CREDS` and `LOCAL_PEERCRED`, but
-+    /// requires a process to explicitly send its credentials.
-+    ///
-+    /// Credentials are always overwritten by the kernel, so this variant does have
-+    /// any data, unlike the receive-side
-+    /// [`ControlMessageOwned::ScmCreds`][#enum.ControlMessageOwned.html#variant.ScmCreds].
-+    ///
-+    /// For further information, please refer to the
-+    /// [`unix(4)`](https://www.freebsd.org/cgi/man.cgi?query=unix) man page.
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    ScmCreds,
- 
-     /// Set IV for `AF_ALG` crypto API.
-     ///
-@@ -685,6 +768,39 @@ pub enum ControlMessage<'a> {
-     ))]
-     AlgSetAeadAssoclen(&'a u32),
- 
-+    /// UDP GSO makes it possible for applications to generate network packets
-+    /// for a virtual MTU much greater than the real one.
-+    /// The length of the send data no longer matches the expected length on
-+    /// the wire.
-+    /// The size of the datagram payload as it should appear on the wire may be
-+    /// passed through this control message.
-+    /// Send buffer should consist of multiple fixed-size wire payloads
-+    /// following one by one, and the last, possibly smaller one.
-+    #[cfg(target_os = "linux")]
-+    UdpGsoSegments(&'a u16),
-+
-+    /// 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.
-+    #[cfg(any(target_os = "linux",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "android",
-+              target_os = "ios",))]
-+    Ipv4PacketInfo(&'a libc::in_pktinfo),
-+
-+    /// 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.
-+    #[cfg(any(target_os = "linux",
-+              target_os = "macos",
-+              target_os = "netbsd",
-+              target_os = "freebsd",
-+              target_os = "android",
-+              target_os = "ios",))]
-+    Ipv6PacketInfo(&'a libc::in6_pktinfo),
- }
- 
- // An opaque structure used to prevent cmsghdr from being a public type
-@@ -715,35 +831,66 @@ impl<'a> ControlMessage<'a> {
- 
-     /// Return a reference to the payload data as a byte pointer
-     fn copy_to_cmsg_data(&self, cmsg_data: *mut u8) {
--        let data_ptr = match self {
--            &ControlMessage::ScmRights(fds) => {
-+        let data_ptr = match *self {
-+            ControlMessage::ScmRights(fds) => {
-                 fds as *const _ as *const u8
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::ScmCredentials(creds) => {
--                creds as *const libc::ucred as *const u8
-+            ControlMessage::ScmCredentials(creds) => {
-+                &creds.0 as *const libc::ucred as *const u8
-+            }
-+            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+            ControlMessage::ScmCreds => {
-+                // The kernel overwrites the data, we just zero it
-+                // to make sure it's not uninitialized memory
-+                unsafe { ptr::write_bytes(cmsg_data, 0, self.len()) };
-+                return
-             }
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetIv(iv) => {
-+            ControlMessage::AlgSetIv(iv) => {
-+                #[allow(deprecated)] // https://github.com/rust-lang/libc/issues/1501
-+                let af_alg_iv = libc::af_alg_iv {
-+                    ivlen: iv.len() as u32,
-+                    iv: [0u8; 0],
-+                };
-+
-+                let size = mem::size_of_val(&af_alg_iv);
-+
-                 unsafe {
--                    let alg_iv = cmsg_data as *mut libc::af_alg_iv;
--                    (*alg_iv).ivlen = iv.len() as u32;
-+                    ptr::copy_nonoverlapping(
-+                        &af_alg_iv as *const _ as *const u8,
-+                        cmsg_data,
-+                        size,
-+                    );
-                     ptr::copy_nonoverlapping(
-                         iv.as_ptr(),
--                        (*alg_iv).iv.as_mut_ptr(),
-+                        cmsg_data.add(size),
-                         iv.len()
-                     );
-                 };
-+
-                 return
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetOp(op) => {
-+            ControlMessage::AlgSetOp(op) => {
-                 op as *const _ as *const u8
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetAeadAssoclen(len) => {
-+            ControlMessage::AlgSetAeadAssoclen(len) => {
-                 len as *const _ as *const u8
-             },
-+            #[cfg(target_os = "linux")]
-+            ControlMessage::UdpGsoSegments(gso_size) => {
-+                gso_size as *const _ as *const u8
-+            },
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+                      target_os = "netbsd", target_os = "android",
-+                      target_os = "ios",))]
-+            ControlMessage::Ipv4PacketInfo(info) => info as *const _ as *const u8,
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+                      target_os = "netbsd", target_os = "freebsd",
-+                      target_os = "android", target_os = "ios",))]
-+            ControlMessage::Ipv6PacketInfo(info) => info as *const _ as *const u8,
-         };
-         unsafe {
-             ptr::copy_nonoverlapping(
-@@ -756,60 +903,101 @@ impl<'a> ControlMessage<'a> {
- 
-     /// The size of the payload, excluding its cmsghdr
-     fn len(&self) -> usize {
--        match self {
--            &ControlMessage::ScmRights(fds) => {
-+        match *self {
-+            ControlMessage::ScmRights(fds) => {
-                 mem::size_of_val(fds)
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::ScmCredentials(creds) => {
-+            ControlMessage::ScmCredentials(creds) => {
-                 mem::size_of_val(creds)
-             }
-+            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+            ControlMessage::ScmCreds => {
-+                mem::size_of::<libc::cmsgcred>()
-+            }
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetIv(iv) => {
--                mem::size_of::<libc::af_alg_iv>() + iv.len()
-+            ControlMessage::AlgSetIv(iv) => {
-+                mem::size_of_val(&iv) + iv.len()
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetOp(op) => {
-+            ControlMessage::AlgSetOp(op) => {
-                 mem::size_of_val(op)
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetAeadAssoclen(len) => {
-+            ControlMessage::AlgSetAeadAssoclen(len) => {
-                 mem::size_of_val(len)
-             },
-+            #[cfg(target_os = "linux")]
-+            ControlMessage::UdpGsoSegments(gso_size) => {
-+                mem::size_of_val(gso_size)
-+            },
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+              target_os = "netbsd", target_os = "android",
-+              target_os = "ios",))]
-+            ControlMessage::Ipv4PacketInfo(info) => mem::size_of_val(info),
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+              target_os = "netbsd", target_os = "freebsd",
-+              target_os = "android", target_os = "ios",))]
-+            ControlMessage::Ipv6PacketInfo(info) => mem::size_of_val(info),
-         }
-     }
- 
-     /// Returns the value to put into the `cmsg_level` field of the header.
-     fn cmsg_level(&self) -> libc::c_int {
--        match self {
--            &ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
-+        match *self {
-+            ControlMessage::ScmRights(_) => libc::SOL_SOCKET,
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
-+            ControlMessage::ScmCredentials(_) => libc::SOL_SOCKET,
-+            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+            ControlMessage::ScmCreds => libc::SOL_SOCKET,
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetIv(_) | &ControlMessage::AlgSetOp(_) | &ControlMessage::AlgSetAeadAssoclen(_) => {
--                libc::SOL_ALG
--            },
-+            ControlMessage::AlgSetIv(_) | ControlMessage::AlgSetOp(_) |
-+                ControlMessage::AlgSetAeadAssoclen(_) => libc::SOL_ALG,
-+            #[cfg(target_os = "linux")]
-+            ControlMessage::UdpGsoSegments(_) => libc::SOL_UDP,
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+                      target_os = "netbsd", target_os = "android",
-+                      target_os = "ios",))]
-+            ControlMessage::Ipv4PacketInfo(_) => libc::IPPROTO_IP,
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+              target_os = "netbsd", target_os = "freebsd",
-+              target_os = "android", target_os = "ios",))]
-+            ControlMessage::Ipv6PacketInfo(_) => libc::IPPROTO_IPV6,
-         }
-     }
- 
-     /// Returns the value to put into the `cmsg_type` field of the header.
-     fn cmsg_type(&self) -> libc::c_int {
--        match self {
--            &ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
-+        match *self {
-+            ControlMessage::ScmRights(_) => libc::SCM_RIGHTS,
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
-+            ControlMessage::ScmCredentials(_) => libc::SCM_CREDENTIALS,
-+            #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+            ControlMessage::ScmCreds => libc::SCM_CREDS,
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetIv(_) => {
-+            ControlMessage::AlgSetIv(_) => {
-                 libc::ALG_SET_IV
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetOp(_) => {
-+            ControlMessage::AlgSetOp(_) => {
-                 libc::ALG_SET_OP
-             },
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            &ControlMessage::AlgSetAeadAssoclen(_) => {
-+            ControlMessage::AlgSetAeadAssoclen(_) => {
-                 libc::ALG_SET_AEAD_ASSOCLEN
-             },
-+            #[cfg(target_os = "linux")]
-+            ControlMessage::UdpGsoSegments(_) => {
-+                libc::UDP_SEGMENT
-+            },
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+                      target_os = "netbsd", target_os = "android",
-+                      target_os = "ios",))]
-+            ControlMessage::Ipv4PacketInfo(_) => libc::IP_PKTINFO,
-+            #[cfg(any(target_os = "linux", target_os = "macos",
-+                      target_os = "netbsd", target_os = "freebsd",
-+                      target_os = "android", target_os = "ios",))]
-+            ControlMessage::Ipv6PacketInfo(_) => libc::IPV6_PKTINFO,
-         }
-     }
- 
-@@ -836,12 +1024,303 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
- 
-     // First size the buffer needed to hold the cmsgs.  It must be zeroed,
-     // because subsequent code will not clear the padding bytes.
--    let cmsg_buffer = vec![0u8; capacity];
-+    let mut cmsg_buffer = vec![0u8; capacity];
-+
-+    let mhdr = pack_mhdr_to_send(&mut cmsg_buffer[..], &iov, &cmsgs, addr);
-+
-+    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
-+
-+    Errno::result(ret).map(|r| r as usize)
-+}
-+
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "netbsd",
-+))]
-+#[derive(Debug)]
-+pub struct SendMmsgData<'a, I, C>
-+    where
-+        I: AsRef<[IoVec<&'a [u8]>]>,
-+        C: AsRef<[ControlMessage<'a>]>
-+{
-+    pub iov: I,
-+    pub cmsgs: C,
-+    pub addr: Option<SockAddr>,
-+    pub _lt: std::marker::PhantomData<&'a I>,
-+}
-+
-+/// An extension of `sendmsg` that allows the caller to transmit multiple
-+/// messages on a socket using a single system call. This has performance
-+/// benefits for some applications.
-+///
-+/// Allocations are performed for cmsgs and to build `msghdr` buffer
-+///
-+/// # Arguments
-+///
-+/// * `fd`:             Socket file descriptor
-+/// * `data`:           Struct that implements `IntoIterator` with `SendMmsgData` items
-+/// * `flags`:          Optional flags passed directly to the operating system.
-+///
-+/// # Returns
-+/// `Vec` with numbers of sent bytes on each sent message.
-+///
-+/// # References
-+/// [`sendmsg`](fn.sendmsg.html)
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "netbsd",
-+))]
-+pub fn sendmmsg<'a, I, C>(
-+    fd: RawFd,
-+    data: impl std::iter::IntoIterator<Item=&'a SendMmsgData<'a, I, C>>,
-+    flags: MsgFlags
-+) -> Result<Vec<usize>>
-+    where
-+        I: AsRef<[IoVec<&'a [u8]>]> + 'a,
-+        C: AsRef<[ControlMessage<'a>]> + 'a,
-+{
-+    let iter = data.into_iter();
-+
-+    let size_hint = iter.size_hint();
-+    let reserve_items = size_hint.1.unwrap_or(size_hint.0);
-+
-+    let mut output = Vec::<libc::mmsghdr>::with_capacity(reserve_items);
-+
-+    let mut cmsgs_buffer = vec![0u8; 0];
-+
-+    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);
-+
-+        output.push(libc::mmsghdr {
-+            msg_hdr: pack_mhdr_to_send(
-+                &mut cmsgs_buffer[cmsgs_start..],
-+                &d.iov,
-+                &d.cmsgs,
-+                d.addr.as_ref()
-+            ),
-+            msg_len: 0,
-+        });
-+    };
-+
-+    let ret = unsafe { libc::sendmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _) };
-+
-+    let sent_messages = Errno::result(ret)? as usize;
-+    let mut sent_bytes = Vec::with_capacity(sent_messages);
-+
-+    for item in &output {
-+        sent_bytes.push(item.msg_len as usize);
-+    }
-+
-+    Ok(sent_bytes)
-+}
-+
-+
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "netbsd",
-+))]
-+#[derive(Debug)]
-+pub struct RecvMmsgData<'a, I>
-+    where
-+        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-+{
-+    pub iov: I,
-+    pub cmsg_buffer: Option<&'a mut Vec<u8>>,
-+}
-+
-+/// An extension of `recvmsg` that allows the caller to receive multiple
-+/// messages from a socket using a single system call. This has
-+/// performance benefits for some applications.
-+///
-+/// `iov` and `cmsg_buffer` should be constructed similarly to `recvmsg`
-+///
-+/// Multiple allocations are performed
-+///
-+/// # Arguments
-+///
-+/// * `fd`:             Socket file descriptor
-+/// * `data`:           Struct that implements `IntoIterator` with `RecvMmsgData` items
-+/// * `flags`:          Optional flags passed directly to the operating system.
-+///
-+/// # RecvMmsgData
-+///
-+/// * `iov`:            Scatter-gather list of buffers to receive the message
-+/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
-+///                     [`cmsg_space!`](macro.cmsg_space.html)
-+///
-+/// # Returns
-+/// A `Vec` with multiple `RecvMsg`, one per received message
-+///
-+/// # References
-+/// - [`recvmsg`](fn.recvmsg.html)
-+/// - [`RecvMsg`](struct.RecvMsg.html)
-+#[cfg(any(
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "freebsd",
-+    target_os = "netbsd",
-+))]
-+pub fn recvmmsg<'a, I>(
-+    fd: RawFd,
-+    data: impl std::iter::IntoIterator<Item=&'a mut RecvMmsgData<'a, I>,
-+        IntoIter=impl ExactSizeIterator + Iterator<Item=&'a mut RecvMmsgData<'a, I>>>,
-+    flags: MsgFlags,
-+    timeout: Option<crate::sys::time::TimeSpec>
-+) -> Result<Vec<RecvMsg<'a>>>
-+    where
-+        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-+{
-+    let iter = data.into_iter();
-+
-+    let num_messages = iter.len();
-+
-+    let mut output: Vec<libc::mmsghdr> = Vec::with_capacity(num_messages);
-+
-+    // Addresses should be pre-allocated.  pack_mhdr_to_receive will store them
-+    // as raw pointers, so we may not move them.  Turn the vec into a boxed
-+    // slice so we won't inadvertently reallocate the vec.
-+    let mut addresses = vec![mem::MaybeUninit::uninit(); num_messages]
-+        .into_boxed_slice();
-+
-+    let results: Vec<_> = iter.enumerate().map(|(i, d)| {
-+        let (msg_controllen, mhdr) = unsafe {
-+            pack_mhdr_to_receive(
-+                d.iov.as_ref(),
-+                &mut d.cmsg_buffer,
-+                addresses[i].as_mut_ptr(),
-+            )
-+        };
-+
-+        output.push(
-+            libc::mmsghdr {
-+                msg_hdr: mhdr,
-+                msg_len: 0,
-+            }
-+        );
-+
-+        (msg_controllen as usize, &mut d.cmsg_buffer)
-+    }).collect();
-+
-+    let timeout = if let Some(mut t) = timeout {
-+        t.as_mut() as *mut libc::timespec
-+    } else {
-+        ptr::null_mut()
-+    };
-+
-+    let ret = unsafe { libc::recvmmsg(fd, output.as_mut_ptr(), output.len() as _, flags.bits() as _, timeout) };
-+
-+    let _ = Errno::result(ret)?;
-+
-+    Ok(output
-+        .into_iter()
-+        .take(ret as usize)
-+        .zip(addresses.iter().map(|addr| unsafe{addr.assume_init()}))
-+        .zip(results.into_iter())
-+        .map(|((mmsghdr, address), (msg_controllen, cmsg_buffer))| {
-+            unsafe {
-+                read_mhdr(
-+                    mmsghdr.msg_hdr,
-+                    mmsghdr.msg_len as isize,
-+                    msg_controllen,
-+                    address,
-+                    cmsg_buffer
-+                )
-+            }
-+        })
-+        .collect())
-+}
-+
-+unsafe fn read_mhdr<'a, 'b>(
-+    mhdr: msghdr,
-+    r: isize,
-+    msg_controllen: usize,
-+    address: sockaddr_storage,
-+    cmsg_buffer: &'a mut Option<&'b mut Vec<u8>>
-+) -> RecvMsg<'b> {
-+    let cmsghdr = {
-+        if mhdr.msg_controllen > 0 {
-+            // got control message(s)
-+            cmsg_buffer
-+                .as_mut()
-+                .unwrap()
-+                .set_len(mhdr.msg_controllen as usize);
-+            debug_assert!(!mhdr.msg_control.is_null());
-+            debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
-+            CMSG_FIRSTHDR(&mhdr as *const msghdr)
-+        } else {
-+            ptr::null()
-+        }.as_ref()
-+    };
-+
-+    let address = sockaddr_storage_to_addr(
-+        &address ,
-+         mhdr.msg_namelen as usize
-+    ).ok();
-+
-+    RecvMsg {
-+        bytes: r as usize,
-+        cmsghdr,
-+        address,
-+        flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
-+        mhdr,
-+    }
-+}
-+
-+unsafe fn pack_mhdr_to_receive<'a, I>(
-+    iov: I,
-+    cmsg_buffer: &mut Option<&mut Vec<u8>>,
-+    address: *mut sockaddr_storage,
-+) -> (usize, msghdr)
-+    where
-+        I: AsRef<[IoVec<&'a mut [u8]>]> + 'a,
-+{
-+    let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
-+        .map(|v| (v.as_mut_ptr(), v.capacity()))
-+        .unwrap_or((ptr::null_mut(), 0));
-+
-+    let mhdr = {
-+        // Musl's msghdr has private fields, so this is the only way to
-+        // initialize it.
-+        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
-+        let p = mhdr.as_mut_ptr();
-+        (*p).msg_name = address as *mut c_void;
-+        (*p).msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
-+        (*p).msg_iov = iov.as_ref().as_ptr() as *mut iovec;
-+        (*p).msg_iovlen = iov.as_ref().len() as _;
-+        (*p).msg_control = msg_control as *mut c_void;
-+        (*p).msg_controllen = msg_controllen as _;
-+        (*p).msg_flags = 0;
-+        mhdr.assume_init()
-+    };
-+
-+    (msg_controllen, mhdr)
-+}
-+
-+fn pack_mhdr_to_send<'a, I, C>(
-+    cmsg_buffer: &mut [u8],
-+    iov: I,
-+    cmsgs: C,
-+    addr: Option<&SockAddr>
-+) -> msghdr
-+    where
-+        I: AsRef<[IoVec<&'a [u8]>]>,
-+        C: AsRef<[ControlMessage<'a>]>
-+{
-+    let capacity = cmsg_buffer.len();
- 
-     // Next encode the sending address, if provided
-     let (name, namelen) = match addr {
-         Some(addr) => {
--            let (x, y) = unsafe { addr.as_ffi_pair() };
-+            let (x, y) = addr.as_ffi_pair();
-             (x as *const _, y)
-         },
-         None => (ptr::null(), 0),
-@@ -854,97 +1333,68 @@ pub fn sendmsg(fd: RawFd, iov: &[IoVec<&[u8]>], cmsgs: &[ControlMessage],
-         ptr::null_mut()
-     };
- 
--    let mhdr = {
-+    let mhdr = unsafe {
-         // Musl's msghdr has private fields, so this is the only way to
-         // initialize it.
--        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
--        mhdr.msg_name = name as *mut _;
--        mhdr.msg_namelen = namelen;
-+        let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
-+        let p = mhdr.as_mut_ptr();
-+        (*p).msg_name = name as *mut _;
-+        (*p).msg_namelen = namelen;
-         // transmute iov into a mutable pointer.  sendmsg doesn't really mutate
-         // the buffer, but the standard says that it takes a mutable pointer
--        mhdr.msg_iov = iov.as_ptr() as *mut _;
--        mhdr.msg_iovlen = iov.len() as _;
--        mhdr.msg_control = cmsg_ptr;
--        mhdr.msg_controllen = capacity as _;
--        mhdr.msg_flags = 0;
--        mhdr
-+        (*p).msg_iov = iov.as_ref().as_ptr() as *mut _;
-+        (*p).msg_iovlen = iov.as_ref().len() as _;
-+        (*p).msg_control = cmsg_ptr;
-+        (*p).msg_controllen = capacity as _;
-+        (*p).msg_flags = 0;
-+        mhdr.assume_init()
-     };
- 
-     // Encode each cmsg.  This must happen after initializing the header because
-     // CMSG_NEXT_HDR and friends read the msg_control and msg_controllen fields.
-     // CMSG_FIRSTHDR is always safe
--    let mut pmhdr: *mut cmsghdr = unsafe{CMSG_FIRSTHDR(&mhdr as *const msghdr)};
--    for cmsg in cmsgs {
-+    let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(&mhdr as *const msghdr) };
-+    for cmsg in cmsgs.as_ref() {
-         assert_ne!(pmhdr, ptr::null_mut());
-         // Safe because we know that pmhdr is valid, and we initialized it with
-         // sufficient space
-         unsafe { cmsg.encode_into(pmhdr) };
-         // Safe because mhdr is valid
--        pmhdr = unsafe{CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr)};
-+        pmhdr = unsafe { CMSG_NXTHDR(&mhdr as *const msghdr, pmhdr) };
-     }
- 
--    let ret = unsafe { libc::sendmsg(fd, &mhdr, flags.bits()) };
--
--    Errno::result(ret).map(|r| r as usize)
-+    mhdr
- }
- 
- /// Receive message in scatter-gather vectors from a socket, and
- /// optionally receive ancillary data into the provided buffer.
- /// If no ancillary data is desired, use () as the type parameter.
- ///
-+/// # Arguments
-+///
-+/// * `fd`:             Socket file descriptor
-+/// * `iov`:            Scatter-gather list of buffers to receive the message
-+/// * `cmsg_buffer`:    Space to receive ancillary data.  Should be created by
-+///                     [`cmsg_space!`](macro.cmsg_space.html)
-+/// * `flags`:          Optional flags passed directly to the operating system.
-+///
- /// # References
- /// [recvmsg(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html)
- pub fn recvmsg<'a>(fd: RawFd, iov: &[IoVec<&mut [u8]>],
--                   cmsg_buffer: Option<&'a mut dyn CmsgBuffer>,
-+                   mut cmsg_buffer: Option<&'a mut Vec<u8>>,
-                    flags: MsgFlags) -> Result<RecvMsg<'a>>
- {
--    let mut address: sockaddr_storage = unsafe { mem::uninitialized() };
--    let (msg_control, msg_controllen) = match cmsg_buffer {
--        Some(cmsgspace) => {
--            let msg_buf = cmsgspace.as_bytes_mut();
--            (msg_buf.as_mut_ptr(), msg_buf.len())
--        },
--        None => (ptr::null_mut(), 0),
--    };
--    let mut mhdr = {
--        // Musl's msghdr has private fields, so this is the only way to
--        // initialize it.
--        let mut mhdr: msghdr = unsafe{mem::uninitialized()};
--        mhdr.msg_name = &mut address as *mut sockaddr_storage as *mut c_void;
--        mhdr.msg_namelen = mem::size_of::<sockaddr_storage>() as socklen_t;
--        mhdr.msg_iov = iov.as_ptr() as *mut iovec;
--        mhdr.msg_iovlen = iov.len() as _;
--        mhdr.msg_control = msg_control as *mut c_void;
--        mhdr.msg_controllen = msg_controllen as _;
--        mhdr.msg_flags = 0;
--        mhdr
-+    let mut address = mem::MaybeUninit::uninit();
-+
-+    let (msg_controllen, mut mhdr) = unsafe {
-+        pack_mhdr_to_receive(&iov, &mut cmsg_buffer, address.as_mut_ptr())
-     };
- 
-     let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
- 
--    Errno::result(ret).map(|r| {
--        let cmsghdr = unsafe {
--            if mhdr.msg_controllen > 0 {
--                // got control message(s)
--                debug_assert!(!mhdr.msg_control.is_null());
--                debug_assert!(msg_controllen >= mhdr.msg_controllen as usize);
--                CMSG_FIRSTHDR(&mhdr as *const msghdr)
--            } else {
--                ptr::null()
--            }.as_ref()
--        };
-+    let r = Errno::result(ret)?;
- 
--        let address = unsafe {
--            sockaddr_storage_to_addr(&address, mhdr.msg_namelen as usize).ok()
--        };
--        RecvMsg {
--            bytes: r as usize,
--            cmsghdr,
--            address,
--            flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
--            mhdr,
--        }
--    })
-+    Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init(), &mut cmsg_buffer) })
- }
- 
- 
-@@ -1071,12 +1521,15 @@ pub fn recv(sockfd: RawFd, buf: &mut [u8], flags: MsgFlags) -> Result<usize> {
- }
- 
- /// Receive data from a connectionless or connection-oriented socket. Returns
--/// the number of bytes read and the socket address of the sender.
-+/// 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)
--pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
-+pub fn recvfrom(sockfd: RawFd, buf: &mut [u8])
-+    -> Result<(usize, Option<SockAddr>)>
-+{
-     unsafe {
--        let addr: sockaddr_storage = mem::zeroed();
-+        let mut addr: sockaddr_storage = mem::zeroed();
-         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
- 
-         let ret = Errno::result(libc::recvfrom(
-@@ -1084,11 +1537,14 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
-             buf.as_ptr() as *mut c_void,
-             buf.len() as size_t,
-             0,
--            mem::transmute(&addr),
--            &mut len as *mut socklen_t))?;
-+            &mut addr as *mut libc::sockaddr_storage as *mut libc::sockaddr,
-+            &mut len as *mut socklen_t))? as usize;
- 
--        sockaddr_storage_to_addr(&addr, len as usize)
--            .map(|addr| (ret as usize, addr))
-+        match sockaddr_storage_to_addr(&addr, len as usize) {
-+            Err(Error::Sys(Errno::ENOTCONN)) => Ok((ret, None)),
-+            Ok(addr) => Ok((ret, Some(addr))),
-+            Err(e) => Err(e)
-+        }
-     }
- }
- 
-@@ -1121,24 +1577,6 @@ pub fn send(fd: RawFd, buf: &[u8], flags: MsgFlags) -> Result<usize> {
-  *
-  */
- 
--/// The protocol level at which to get / set socket options. Used as an
--/// argument to `getsockopt` and `setsockopt`.
--///
--/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/setsockopt.html)
--#[repr(i32)]
--#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
--pub enum SockLevel {
--    Socket = libc::SOL_SOCKET,
--    Tcp = libc::IPPROTO_TCP,
--    Ip = libc::IPPROTO_IP,
--    Ipv6 = libc::IPPROTO_IPV6,
--    Udp = libc::IPPROTO_UDP,
--    #[cfg(any(target_os = "android", target_os = "linux"))]
--    Netlink = libc::SOL_NETLINK,
--    #[cfg(any(target_os = "android", target_os = "linux"))]
--    Alg = libc::SOL_ALG,
--}
--
- /// Represents a socket option that can be accessed or set. Used as an argument
- /// to `getsockopt`
- pub trait GetSockOpt : Copy {
-@@ -1190,14 +1628,18 @@ pub fn setsockopt<O: SetSockOpt>(fd: RawFd, opt: O, val: &O::Val) -> Result<()>
- /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpeername.html)
- pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
-     unsafe {
--        let addr: sockaddr_storage = mem::uninitialized();
-+        let mut addr = mem::MaybeUninit::uninit();
-         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
- 
--        let ret = libc::getpeername(fd, mem::transmute(&addr), &mut len);
-+        let ret = libc::getpeername(
-+            fd,
-+            addr.as_mut_ptr() as *mut libc::sockaddr,
-+            &mut len
-+        );
- 
-         Errno::result(ret)?;
- 
--        sockaddr_storage_to_addr(&addr, len as usize)
-+        sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
-     }
- }
- 
-@@ -1206,60 +1648,92 @@ pub fn getpeername(fd: RawFd) -> Result<SockAddr> {
- /// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getsockname.html)
- pub fn getsockname(fd: RawFd) -> Result<SockAddr> {
-     unsafe {
--        let addr: sockaddr_storage = mem::uninitialized();
-+        let mut addr = mem::MaybeUninit::uninit();
-         let mut len = mem::size_of::<sockaddr_storage>() as socklen_t;
- 
--        let ret = libc::getsockname(fd, mem::transmute(&addr), &mut len);
-+        let ret = libc::getsockname(
-+            fd,
-+            addr.as_mut_ptr() as *mut libc::sockaddr,
-+            &mut len
-+        );
- 
-         Errno::result(ret)?;
- 
--        sockaddr_storage_to_addr(&addr, len as usize)
-+        sockaddr_storage_to_addr(&addr.assume_init(), len as usize)
-     }
- }
- 
--/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain
--/// size.  In C this would usually be done by casting.  The `len` argument
-+/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a
-+/// certain size.
-+///
-+/// In C this would usually be done by casting.  The `len` argument
- /// should be the number of bytes in the `sockaddr_storage` that are actually
- /// allocated and valid.  It must be at least as large as all the useful parts
- /// of the structure.  Note that in the case of a `sockaddr_un`, `len` need not
- /// include the terminating null.
--pub unsafe fn sockaddr_storage_to_addr(
-+pub fn sockaddr_storage_to_addr(
-     addr: &sockaddr_storage,
-     len: usize) -> Result<SockAddr> {
- 
-+    assert!(len <= mem::size_of::<sockaddr_un>());
-     if len < mem::size_of_val(&addr.ss_family) {
-         return Err(Error::Sys(Errno::ENOTCONN));
-     }
- 
--    match addr.ss_family as c_int {
-+    match c_int::from(addr.ss_family) {
-         libc::AF_INET => {
--            assert!(len as usize == mem::size_of::<sockaddr_in>());
--            let ret = *(addr as *const _ as *const sockaddr_in);
--            Ok(SockAddr::Inet(InetAddr::V4(ret)))
-+            assert_eq!(len as usize, mem::size_of::<sockaddr_in>());
-+            let sin = unsafe {
-+                *(addr as *const sockaddr_storage as *const sockaddr_in)
-+            };
-+            Ok(SockAddr::Inet(InetAddr::V4(sin)))
-         }
-         libc::AF_INET6 => {
--            assert!(len as usize == mem::size_of::<sockaddr_in6>());
--            Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6))))
-+            assert_eq!(len as usize, mem::size_of::<sockaddr_in6>());
-+            let sin6 = unsafe {
-+                *(addr as *const _ as *const sockaddr_in6)
-+            };
-+            Ok(SockAddr::Inet(InetAddr::V6(sin6)))
-         }
-         libc::AF_UNIX => {
--            let sun = *(addr as *const _ as *const sockaddr_un);
-             let pathlen = len - offset_of!(sockaddr_un, sun_path);
-+            let sun = unsafe {
-+                *(addr as *const _ as *const sockaddr_un)
-+            };
-             Ok(SockAddr::Unix(UnixAddr(sun, pathlen)))
-         }
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-+        libc::AF_PACKET => {
-+            use libc::sockaddr_ll;
-+            assert_eq!(len as usize, mem::size_of::<sockaddr_ll>());
-+            let sll = unsafe {
-+                *(addr as *const _ as *const sockaddr_ll)
-+            };
-+            Ok(SockAddr::Link(LinkAddr(sll)))
-+        }
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-         libc::AF_NETLINK => {
-             use libc::sockaddr_nl;
--            Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl))))
-+            let snl = unsafe {
-+                *(addr as *const _ as *const sockaddr_nl)
-+            };
-+            Ok(SockAddr::Netlink(NetlinkAddr(snl)))
-         }
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-         libc::AF_ALG => {
-             use libc::sockaddr_alg;
--            Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg))))
-+            let salg = unsafe {
-+                *(addr as *const _ as *const sockaddr_alg)
-+            };
-+            Ok(SockAddr::Alg(AlgAddr(salg)))
-         }
--        #[cfg(target_os = "linux")]
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-         libc::AF_VSOCK => {
-             use libc::sockaddr_vm;
--            Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm))))
-+            let svm = unsafe {
-+                *(addr as *const _ as *const sockaddr_vm)
-+            };
-+            Ok(SockAddr::Vsock(VsockAddr(svm)))
-         }
-         af => panic!("unexpected address family {}", af),
-     }
-diff --git a/third_party/rust/nix/src/sys/socket/sockopt.rs b/third_party/rust/nix/src/sys/socket/sockopt.rs
-index a996010018d5b..5b7b4feafb49a 100644
---- a/third_party/rust/nix/src/sys/socket/sockopt.rs
-+++ b/third_party/rust/nix/src/sys/socket/sockopt.rs
-@@ -1,9 +1,13 @@
-+use cfg_if::cfg_if;
- use super::{GetSockOpt, SetSockOpt};
--use Result;
--use errno::Errno;
--use sys::time::TimeVal;
-+use crate::Result;
-+use crate::errno::Errno;
-+use crate::sys::time::TimeVal;
- use libc::{self, c_int, c_void, socklen_t};
--use std::mem;
-+use std::mem::{
-+    self,
-+    MaybeUninit
-+};
- use std::os::unix::io::RawFd;
- use std::ffi::{OsStr, OsString};
- #[cfg(target_family = "unix")]
-@@ -84,14 +88,14 @@ macro_rules! getsockopt_impl {
- 
-             fn get(&self, fd: RawFd) -> Result<$ty> {
-                 unsafe {
--                    let mut getter: $getter = Get::blank();
-+                    let mut getter: $getter = Get::uninit();
- 
-                     let res = libc::getsockopt(fd, $level, $flag,
-                                                getter.ffi_ptr(),
-                                                getter.ffi_len());
-                     Errno::result(res)?;
- 
--                    Ok(getter.unwrap())
-+                    Ok(getter.assume_init())
-                 }
-             }
-         }
-@@ -248,6 +252,10 @@ sockopt_impl!(Both, TcpKeepAlive, libc::IPPROTO_TCP, libc::TCP_KEEPALIVE, u32);
-           target_os = "linux",
-           target_os = "nacl"))]
- sockopt_impl!(Both, TcpKeepIdle, libc::IPPROTO_TCP, libc::TCP_KEEPIDLE, u32);
-+#[cfg(not(target_os = "openbsd"))]
-+sockopt_impl!(Both, TcpKeepCount, libc::IPPROTO_TCP, libc::TCP_KEEPCNT, u32);
-+#[cfg(not(target_os = "openbsd"))]
-+sockopt_impl!(Both, TcpKeepInterval, libc::IPPROTO_TCP, libc::TCP_KEEPINTVL, u32);
- sockopt_impl!(Both, RcvBuf, libc::SOL_SOCKET, libc::SO_RCVBUF, usize);
- sockopt_impl!(Both, SndBuf, libc::SOL_SOCKET, libc::SO_SNDBUF, usize);
- #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -257,6 +265,8 @@ sockopt_impl!(SetOnly, SndBufForce, libc::SOL_SOCKET, libc::SO_SNDBUFFORCE, usiz
- sockopt_impl!(GetOnly, SockType, libc::SOL_SOCKET, libc::SO_TYPE, super::SockType);
- sockopt_impl!(GetOnly, AcceptConn, libc::SOL_SOCKET, libc::SO_ACCEPTCONN, bool);
- #[cfg(any(target_os = "android", target_os = "linux"))]
-+sockopt_impl!(Both, BindToDevice, libc::SOL_SOCKET, libc::SO_BINDTODEVICE, OsString<[u8; libc::IFNAMSIZ]>);
-+#[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(any(target_os = "android", target_os = "linux"))]
-@@ -305,7 +315,10 @@ sockopt_impl!(Both, Ipv4RecvIf, libc::IPPROTO_IP, libc::IP_RECVIF, bool);
-     target_os = "openbsd",
- ))]
- sockopt_impl!(Both, Ipv4RecvDstAddr, libc::IPPROTO_IP, libc::IP_RECVDSTADDR, bool);
--
-+#[cfg(target_os = "linux")]
-+sockopt_impl!(Both, UdpGsoSegment, libc::SOL_UDP, libc::UDP_SEGMENT, libc::c_int);
-+#[cfg(target_os = "linux")]
-+sockopt_impl!(Both, UdpGroSegment, libc::IPPROTO_UDP, libc::UDP_GRO, bool);
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[derive(Copy, Clone, Debug)]
-@@ -364,16 +377,16 @@ impl<T> SetSockOpt for AlgSetKey<T> where T: AsRef<[u8]> + Clone {
- 
- /// Helper trait that describes what is expected from a `GetSockOpt` getter.
- unsafe trait Get<T> {
--    /// Returns an empty value.
--    unsafe fn blank() -> Self;
-+    /// Returns an uninitialized value.
-+    unsafe fn uninit() -> Self;
-     /// Returns a pointer to the stored value. This pointer will be passed to the system's
-     /// `getsockopt` call (`man 3p getsockopt`, argument `option_value`).
-     fn ffi_ptr(&mut self) -> *mut c_void;
-     /// Returns length of the stored value. This pointer will be passed to the system's
-     /// `getsockopt` call (`man 3p getsockopt`, argument `option_len`).
-     fn ffi_len(&mut self) -> *mut socklen_t;
--    /// Returns the stored value.
--    unsafe fn unwrap(self) -> T;
-+    /// Returns the hopefully initialized inner value.
-+    unsafe fn assume_init(self) -> T;
- }
- 
- /// Helper trait that describes what is expected from a `SetSockOpt` setter.
-@@ -391,28 +404,28 @@ unsafe trait Set<'a, T> {
- /// Getter for an arbitrary `struct`.
- struct GetStruct<T> {
-     len: socklen_t,
--    val: T,
-+    val: MaybeUninit<T>,
- }
- 
- unsafe impl<T> Get<T> for GetStruct<T> {
--    unsafe fn blank() -> Self {
-+    unsafe fn uninit() -> Self {
-         GetStruct {
-             len: mem::size_of::<T>() as socklen_t,
--            val: mem::zeroed(),
-+            val: MaybeUninit::uninit(),
-         }
-     }
- 
-     fn ffi_ptr(&mut self) -> *mut c_void {
--        &mut self.val as *mut T as *mut c_void
-+        self.val.as_mut_ptr() as *mut c_void
-     }
- 
-     fn ffi_len(&mut self) -> *mut socklen_t {
-         &mut self.len
-     }
- 
--    unsafe fn unwrap(self) -> T {
--        assert!(self.len as usize == mem::size_of::<T>(), "invalid getsockopt implementation");
--        self.val
-+    unsafe fn assume_init(self) -> T {
-+        assert_eq!(self.len as usize, mem::size_of::<T>(), "invalid getsockopt implementation");
-+        self.val.assume_init()
-     }
- }
- 
-@@ -423,7 +436,7 @@ struct SetStruct<'a, T: 'static> {
- 
- unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
-     fn new(ptr: &'a T) -> SetStruct<'a, T> {
--        SetStruct { ptr: ptr }
-+        SetStruct { ptr }
-     }
- 
-     fn ffi_ptr(&self) -> *const c_void {
-@@ -438,28 +451,28 @@ unsafe impl<'a, T> Set<'a, T> for SetStruct<'a, T> {
- /// Getter for a boolean value.
- struct GetBool {
-     len: socklen_t,
--    val: c_int,
-+    val: MaybeUninit<c_int>,
- }
- 
- unsafe impl Get<bool> for GetBool {
--    unsafe fn blank() -> Self {
-+    unsafe fn uninit() -> Self {
-         GetBool {
-             len: mem::size_of::<c_int>() as socklen_t,
--            val: mem::zeroed(),
-+            val: MaybeUninit::uninit(),
-         }
-     }
- 
-     fn ffi_ptr(&mut self) -> *mut c_void {
--        &mut self.val as *mut c_int as *mut c_void
-+        self.val.as_mut_ptr() as *mut c_void
-     }
- 
-     fn ffi_len(&mut self) -> *mut socklen_t {
-         &mut self.len
-     }
- 
--    unsafe fn unwrap(self) -> bool {
--        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
--        self.val != 0
-+    unsafe fn assume_init(self) -> bool {
-+        assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
-+        self.val.assume_init() != 0
-     }
- }
- 
-@@ -485,28 +498,28 @@ unsafe impl<'a> Set<'a, bool> for SetBool {
- /// Getter for an `u8` value.
- struct GetU8 {
-     len: socklen_t,
--    val: u8,
-+    val: MaybeUninit<u8>,
- }
- 
- unsafe impl Get<u8> for GetU8 {
--    unsafe fn blank() -> Self {
-+    unsafe fn uninit() -> Self {
-         GetU8 {
-             len: mem::size_of::<u8>() as socklen_t,
--            val: mem::zeroed(),
-+            val: MaybeUninit::uninit(),
-         }
-     }
- 
-     fn ffi_ptr(&mut self) -> *mut c_void {
--        &mut self.val as *mut u8 as *mut c_void
-+        self.val.as_mut_ptr() as *mut c_void
-     }
- 
-     fn ffi_len(&mut self) -> *mut socklen_t {
-         &mut self.len
-     }
- 
--    unsafe fn unwrap(self) -> u8 {
--        assert!(self.len as usize == mem::size_of::<u8>(), "invalid getsockopt implementation");
--        self.val as u8
-+    unsafe fn assume_init(self) -> u8 {
-+        assert_eq!(self.len as usize, mem::size_of::<u8>(), "invalid getsockopt implementation");
-+        self.val.assume_init()
-     }
- }
- 
-@@ -532,28 +545,28 @@ unsafe impl<'a> Set<'a, u8> for SetU8 {
- /// Getter for an `usize` value.
- struct GetUsize {
-     len: socklen_t,
--    val: c_int,
-+    val: MaybeUninit<c_int>,
- }
- 
- unsafe impl Get<usize> for GetUsize {
--    unsafe fn blank() -> Self {
-+    unsafe fn uninit() -> Self {
-         GetUsize {
-             len: mem::size_of::<c_int>() as socklen_t,
--            val: mem::zeroed(),
-+            val: MaybeUninit::uninit(),
-         }
-     }
- 
-     fn ffi_ptr(&mut self) -> *mut c_void {
--        &mut self.val as *mut c_int as *mut c_void
-+        self.val.as_mut_ptr() as *mut c_void
-     }
- 
-     fn ffi_len(&mut self) -> *mut socklen_t {
-         &mut self.len
-     }
- 
--    unsafe fn unwrap(self) -> usize {
--        assert!(self.len as usize == mem::size_of::<c_int>(), "invalid getsockopt implementation");
--        self.val as usize
-+    unsafe fn assume_init(self) -> usize {
-+        assert_eq!(self.len as usize, mem::size_of::<c_int>(), "invalid getsockopt implementation");
-+        self.val.assume_init() as usize
-     }
- }
- 
-@@ -579,27 +592,29 @@ unsafe impl<'a> Set<'a, usize> for SetUsize {
- /// Getter for a `OsString` value.
- struct GetOsString<T: AsMut<[u8]>> {
-     len: socklen_t,
--    val: T,
-+    val: MaybeUninit<T>,
- }
- 
- unsafe impl<T: AsMut<[u8]>> Get<OsString> for GetOsString<T> {
--    unsafe fn blank() -> Self {
-+    unsafe fn uninit() -> Self {
-         GetOsString {
-             len: mem::size_of::<T>() as socklen_t,
--            val: mem::zeroed(),
-+            val: MaybeUninit::uninit(),
-         }
-     }
- 
-     fn ffi_ptr(&mut self) -> *mut c_void {
--        &mut self.val as *mut T as *mut c_void
-+        self.val.as_mut_ptr() as *mut c_void
-     }
- 
-     fn ffi_len(&mut self) -> *mut socklen_t {
-         &mut self.len
-     }
- 
--    unsafe fn unwrap(mut self) -> OsString {
--        OsStr::from_bytes(self.val.as_mut()).to_owned()
-+    unsafe fn assume_init(self) -> OsString {
-+        let len = self.len as usize;
-+        let mut v = self.val.assume_init();
-+        OsStr::from_bytes(&v.as_mut()[0..len]).to_owned()
-     }
- }
- 
-@@ -640,11 +655,11 @@ mod test {
-     #[test]
-     fn is_socket_type_unix() {
-         use super::super::*;
--        use ::unistd::close;
-+        use crate::unistd::close;
- 
-         let (a, b) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty()).unwrap();
-         let a_type = getsockopt(a, super::SockType).unwrap();
--        assert!(a_type == SockType::Stream);
-+        assert_eq!(a_type, SockType::Stream);
-         close(a).unwrap();
-         close(b).unwrap();
-     }
-@@ -652,11 +667,11 @@ mod test {
-     #[test]
-     fn is_socket_type_dgram() {
-         use super::super::*;
--        use ::unistd::close;
-+        use crate::unistd::close;
- 
-         let s = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), None).unwrap();
-         let s_type = getsockopt(s, super::SockType).unwrap();
--        assert!(s_type == SockType::Datagram);
-+        assert_eq!(s_type, SockType::Datagram);
-         close(s).unwrap();
-     }
- 
-@@ -666,7 +681,7 @@ mod test {
-     #[test]
-     fn can_get_listen_on_tcp_socket() {
-         use super::super::*;
--        use ::unistd::close;
-+        use crate::unistd::close;
- 
-         let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-         let s_listening = getsockopt(s, super::AcceptConn).unwrap();
-diff --git a/third_party/rust/nix/src/sys/stat.rs b/third_party/rust/nix/src/sys/stat.rs
-index 66c8c9dd1b720..df81a2cb329d6 100644
---- a/third_party/rust/nix/src/sys/stat.rs
-+++ b/third_party/rust/nix/src/sys/stat.rs
-@@ -1,13 +1,12 @@
- pub use libc::{dev_t, mode_t};
- pub use libc::stat as FileStat;
- 
--use {Result, NixPath};
--use errno::Errno;
--use fcntl::{AtFlags, at_rawfd};
--use libc;
-+use crate::{Result, NixPath, errno::Errno};
-+#[cfg(not(target_os = "redox"))]
-+use crate::fcntl::{AtFlags, at_rawfd};
- use std::mem;
- use std::os::unix::io::RawFd;
--use sys::time::{TimeSpec, TimeVal};
-+use crate::sys::time::{TimeSpec, TimeVal};
- 
- libc_bitflags!(
-     pub struct SFlag: mode_t {
-@@ -78,49 +77,50 @@ pub fn umask(mode: Mode) -> Mode {
- }
- 
- pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
--    let mut dst = unsafe { mem::uninitialized() };
-+    let mut dst = mem::MaybeUninit::uninit();
-     let res = path.with_nix_path(|cstr| {
-         unsafe {
--            libc::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
-+            libc::stat(cstr.as_ptr(), dst.as_mut_ptr())
-         }
-     })?;
- 
-     Errno::result(res)?;
- 
--    Ok(dst)
-+    Ok(unsafe{dst.assume_init()})
- }
- 
- pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
--    let mut dst = unsafe { mem::uninitialized() };
-+    let mut dst = mem::MaybeUninit::uninit();
-     let res = path.with_nix_path(|cstr| {
-         unsafe {
--            libc::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
-+            libc::lstat(cstr.as_ptr(), dst.as_mut_ptr())
-         }
-     })?;
- 
-     Errno::result(res)?;
- 
--    Ok(dst)
-+    Ok(unsafe{dst.assume_init()})
- }
- 
- pub fn fstat(fd: RawFd) -> Result<FileStat> {
--    let mut dst = unsafe { mem::uninitialized() };
--    let res = unsafe { libc::fstat(fd, &mut dst as *mut FileStat) };
-+    let mut dst = mem::MaybeUninit::uninit();
-+    let res = unsafe { libc::fstat(fd, dst.as_mut_ptr()) };
- 
-     Errno::result(res)?;
- 
--    Ok(dst)
-+    Ok(unsafe{dst.assume_init()})
- }
- 
-+#[cfg(not(target_os = "redox"))]
- pub fn fstatat<P: ?Sized + NixPath>(dirfd: RawFd, pathname: &P, f: AtFlags) -> Result<FileStat> {
--    let mut dst = unsafe { mem::uninitialized() };
-+    let mut dst = mem::MaybeUninit::uninit();
-     let res = pathname.with_nix_path(|cstr| {
--        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), &mut dst as *mut FileStat, f.bits() as libc::c_int) }
-+        unsafe { libc::fstatat(dirfd, cstr.as_ptr(), dst.as_mut_ptr(), f.bits() as libc::c_int) }
-     })?;
- 
-     Errno::result(res)?;
- 
--    Ok(dst)
-+    Ok(unsafe{dst.assume_init()})
- }
- 
- /// Change the file permission bits of the file specified by a file descriptor.
-@@ -150,13 +150,14 @@ pub enum FchmodatFlags {
- /// If `flag` is `FchmodatFlags::NoFollowSymlink` and `path` names a symbolic link,
- /// then the mode of the symbolic link is changed.
- ///
--/// `fchmod(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
-+/// `fchmodat(None, path, mode, FchmodatFlags::FollowSymlink)` is identical to
- /// a call `libc::chmod(path, mode)`. That's why `chmod` is unimplemented
- /// in the `nix` crate.
- ///
- /// # References
- ///
- /// [fchmodat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchmodat.html).
-+#[cfg(not(target_os = "redox"))]
- pub fn fchmodat<P: ?Sized + NixPath>(
-     dirfd: Option<RawFd>,
-     path: &P,
-@@ -260,6 +261,7 @@ pub enum UtimensatFlags {
- /// # References
- ///
- /// [utimensat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/utimens.html).
-+#[cfg(not(target_os = "redox"))]
- pub fn utimensat<P: ?Sized + NixPath>(
-     dirfd: Option<RawFd>,
-     path: &P,
-@@ -285,6 +287,7 @@ pub fn utimensat<P: ?Sized + NixPath>(
-     Errno::result(res).map(drop)
- }
- 
-+#[cfg(not(target_os = "redox"))]
- pub fn mkdirat<P: ?Sized + NixPath>(fd: RawFd, path: &P, mode: Mode) -> Result<()> {
-     let res = path.with_nix_path(|cstr| {
-         unsafe { libc::mkdirat(fd, cstr.as_ptr(), mode.bits() as mode_t) }
-diff --git a/third_party/rust/nix/src/sys/statfs.rs b/third_party/rust/nix/src/sys/statfs.rs
-index d4596bf336958..27b72592b9a30 100644
---- a/third_party/rust/nix/src/sys/statfs.rs
-+++ b/third_party/rust/nix/src/sys/statfs.rs
-@@ -4,10 +4,7 @@ use std::os::unix::io::AsRawFd;
- #[cfg(not(any(target_os = "linux", target_os = "android")))]
- use std::ffi::CStr;
- 
--use libc;
--
--use {NixPath, Result};
--use errno::Errno;
-+use crate::{NixPath, Result, errno::Errno};
- 
- #[cfg(target_os = "android")]
- pub type fsid_t = libc::__fsid_t;
-@@ -15,81 +12,95 @@ pub type fsid_t = libc::__fsid_t;
- pub type fsid_t = libc::fsid_t;
- 
- #[derive(Clone, Copy)]
-+#[repr(transparent)]
- pub struct Statfs(libc::statfs);
- 
- #[cfg(target_os = "freebsd")]
--#[derive(Eq, Copy, Clone, PartialEq, Debug)]
--pub struct FsType(u32);
-+type fs_type_t = u32;
- #[cfg(target_os = "android")]
--#[derive(Eq, Copy, Clone, PartialEq, Debug)]
--pub struct FsType(libc::c_ulong);
-+type fs_type_t = libc::c_ulong;
- #[cfg(all(target_os = "linux", target_arch = "s390x"))]
--#[derive(Eq, Copy, Clone, PartialEq, Debug)]
--pub struct FsType(u32);
-+type fs_type_t = libc::c_uint;
- #[cfg(all(target_os = "linux", target_env = "musl"))]
--#[derive(Eq, Copy, Clone, PartialEq, Debug)]
--pub struct FsType(libc::c_ulong);
-+type fs_type_t = libc::c_ulong;
- #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+type fs_type_t = libc::__fsword_t;
-+
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "android",
-+    all(target_os = "linux", target_arch = "s390x"),
-+    all(target_os = "linux", target_env = "musl"),
-+    all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))),
-+))]
- #[derive(Eq, Copy, Clone, PartialEq, Debug)]
--pub struct FsType(libc::c_long);
--
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC);
--#[cfg(all(target_os = "linux", not(target_env = "musl"), not(target_arch = "s390x")))]
--pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC);
-+pub struct FsType(pub fs_type_t);
-+
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const ADFS_SUPER_MAGIC: FsType = FsType(libc::ADFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const AFFS_SUPER_MAGIC: FsType = FsType(libc::AFFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const CODA_SUPER_MAGIC: FsType = FsType(libc::CODA_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const CRAMFS_MAGIC: FsType = FsType(libc::CRAMFS_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const EFS_SUPER_MAGIC: FsType = FsType(libc::EFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const EXT2_SUPER_MAGIC: FsType = FsType(libc::EXT2_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const EXT3_SUPER_MAGIC: FsType = FsType(libc::EXT3_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const EXT4_SUPER_MAGIC: FsType = FsType(libc::EXT4_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const HPFS_SUPER_MAGIC: FsType = FsType(libc::HPFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const HUGETLBFS_MAGIC: FsType = FsType(libc::HUGETLBFS_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const ISOFS_SUPER_MAGIC: FsType = FsType(libc::ISOFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const JFFS2_SUPER_MAGIC: FsType = FsType(libc::JFFS2_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const MINIX_SUPER_MAGIC: FsType = FsType(libc::MINIX_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const MINIX_SUPER_MAGIC2: FsType = FsType(libc::MINIX_SUPER_MAGIC2 as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const MINIX2_SUPER_MAGIC: FsType = FsType(libc::MINIX2_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const MINIX2_SUPER_MAGIC2: FsType = FsType(libc::MINIX2_SUPER_MAGIC2 as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const MSDOS_SUPER_MAGIC: FsType = FsType(libc::MSDOS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const NCP_SUPER_MAGIC: FsType = FsType(libc::NCP_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const NFS_SUPER_MAGIC: FsType = FsType(libc::NFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const OPENPROM_SUPER_MAGIC: FsType = FsType(libc::OPENPROM_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const OVERLAYFS_SUPER_MAGIC: FsType = FsType(libc::OVERLAYFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const PROC_SUPER_MAGIC: FsType = FsType(libc::PROC_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const QNX4_SUPER_MAGIC: FsType = FsType(libc::QNX4_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const REISERFS_SUPER_MAGIC: FsType = FsType(libc::REISERFS_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const SMB_SUPER_MAGIC: FsType = FsType(libc::SMB_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const TMPFS_MAGIC: FsType = FsType(libc::TMPFS_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const USBDEVICE_SUPER_MAGIC: FsType = FsType(libc::USBDEVICE_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const CGROUP_SUPER_MAGIC: FsType = FsType(libc::CGROUP_SUPER_MAGIC as fs_type_t);
-+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
-+pub const CGROUP2_SUPER_MAGIC: FsType = FsType(libc::CGROUP2_SUPER_MAGIC as fs_type_t);
-+
- 
- impl Statfs {
-     /// Magic code defining system type
-     #[cfg(not(any(
-         target_os = "openbsd",
-+        target_os = "dragonfly",
-         target_os = "ios",
-         target_os = "macos"
-     )))]
-@@ -105,32 +116,35 @@ impl Statfs {
-     }
- 
-     /// Optimal transfer block size
--    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "openbsd"))]
-+    #[cfg(any(target_os = "ios", target_os = "macos"))]
-     pub fn optimal_transfer_size(&self) -> i32 {
-         self.0.f_iosize
-     }
- 
-     /// Optimal transfer block size
--    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+    #[cfg(target_os = "openbsd")]
-     pub fn optimal_transfer_size(&self) -> u32 {
--        self.0.f_bsize
-+        self.0.f_iosize
-     }
- 
-     /// Optimal transfer block size
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
--    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
-+    #[cfg(all(target_os = "linux", target_arch = "s390x"))]
-+    pub fn optimal_transfer_size(&self) -> u32 {
-         self.0.f_bsize
-     }
- 
-     /// Optimal transfer block size
--    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
--    pub fn optimal_transfer_size(&self) -> libc::c_long {
-+    #[cfg(any(
-+        target_os = "android",
-+        all(target_os = "linux", target_env = "musl")
-+    ))]
-+    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
-         self.0.f_bsize
-     }
- 
-     /// Optimal transfer block size
--    #[cfg(target_os = "android")]
--    pub fn optimal_transfer_size(&self) -> libc::c_ulong {
-+    #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
-+    pub fn optimal_transfer_size(&self) -> libc::__fsword_t {
-         self.0.f_bsize
-     }
- 
-@@ -169,7 +183,7 @@ impl Statfs {
-     /// Size of a block
-     // f_bsize on linux: https://github.com/torvalds/linux/blob/master/fs/nfs/super.c#L471
-     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
--    pub fn block_size(&self) -> libc::c_long {
-+    pub fn block_size(&self) -> libc::__fsword_t {
-         self.0.f_bsize
-     }
- 
-@@ -211,7 +225,7 @@ impl Statfs {
- 
-     /// Maximum length of filenames
-     #[cfg(all(target_os = "linux", not(any(target_arch = "s390x", target_env = "musl"))))]
--    pub fn maximum_name_length(&self) -> libc::c_long {
-+    pub fn maximum_name_length(&self) -> libc::__fsword_t {
-         self.0.f_namelen
-     }
- 
-@@ -240,7 +254,7 @@ impl Statfs {
-     }
- 
-     /// Total data blocks in filesystem
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
-     pub fn blocks(&self) -> u64 {
-         self.0.f_blocks
-     }
-@@ -253,7 +267,7 @@ impl Statfs {
-         target_os = "freebsd",
-         target_os = "openbsd",
-         target_os = "dragonfly",
--        all(target_os = "linux", target_env = "musl")
-+        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
-     )))]
-     pub fn blocks(&self) -> libc::c_ulong {
-         self.0.f_blocks
-@@ -278,7 +292,7 @@ impl Statfs {
-     }
- 
-     /// Free blocks in filesystem
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
-     pub fn blocks_free(&self) -> u64 {
-         self.0.f_bfree
-     }
-@@ -291,7 +305,7 @@ impl Statfs {
-         target_os = "freebsd",
-         target_os = "openbsd",
-         target_os = "dragonfly",
--        all(target_os = "linux", target_env = "musl")
-+        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
-     )))]
-     pub fn blocks_free(&self) -> libc::c_ulong {
-         self.0.f_bfree
-@@ -316,7 +330,7 @@ impl Statfs {
-     }
- 
-     /// Free blocks available to unprivileged user
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
-+    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
-     pub fn blocks_available(&self) -> u64 {
-         self.0.f_bavail
-     }
-@@ -329,7 +343,7 @@ impl Statfs {
-         target_os = "freebsd",
-         target_os = "openbsd",
-         target_os = "dragonfly",
--        all(target_os = "linux", target_env = "musl")
-+        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
-     )))]
-     pub fn blocks_available(&self) -> libc::c_ulong {
-         self.0.f_bavail
-@@ -354,8 +368,8 @@ impl Statfs {
-     }
- 
-     /// Total file nodes in filesystem
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
--    pub fn files(&self) -> u64 {
-+    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
-+    pub fn files(&self) -> libc::fsfilcnt_t {
-         self.0.f_files
-     }
- 
-@@ -367,14 +381,19 @@ impl Statfs {
-         target_os = "freebsd",
-         target_os = "openbsd",
-         target_os = "dragonfly",
--        all(target_os = "linux", target_env = "musl")
-+        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
-     )))]
-     pub fn files(&self) -> libc::c_ulong {
-         self.0.f_files
-     }
- 
-     /// Free file nodes in filesystem
--    #[cfg(any(target_os = "ios", target_os = "macos", target_os = "android"))]
-+    #[cfg(any(
-+            target_os = "android",
-+            target_os = "ios",
-+            target_os = "macos",
-+            target_os = "openbsd"
-+    ))]
-     pub fn files_free(&self) -> u64 {
-         self.0.f_ffree
-     }
-@@ -386,14 +405,14 @@ impl Statfs {
-     }
- 
-     /// Free file nodes in filesystem
--    #[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
-+    #[cfg(target_os = "freebsd")]
-     pub fn files_free(&self) -> i64 {
-         self.0.f_ffree
-     }
- 
-     /// Free file nodes in filesystem
--    #[cfg(all(target_os = "linux", target_env = "musl"))]
--    pub fn files_free(&self) -> u64 {
-+    #[cfg(all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32"))))]
-+    pub fn files_free(&self) -> libc::fsfilcnt_t {
-         self.0.f_ffree
-     }
- 
-@@ -405,7 +424,7 @@ impl Statfs {
-         target_os = "freebsd",
-         target_os = "openbsd",
-         target_os = "dragonfly",
--        all(target_os = "linux", target_env = "musl")
-+        all(target_os = "linux", any(target_env = "musl", all(target_arch = "x86_64", target_pointer_width = "32")))
-     )))]
-     pub fn files_free(&self) -> libc::c_ulong {
-         self.0.f_ffree
-@@ -434,16 +453,17 @@ impl Debug for Statfs {
- 
- pub fn statfs<P: ?Sized + NixPath>(path: &P) -> Result<Statfs> {
-     unsafe {
--        let mut stat: Statfs = mem::uninitialized();
--        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), &mut stat.0))?;
--        Errno::result(res).map(|_| stat)
-+        let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
-+        let res = path.with_nix_path(|path| libc::statfs(path.as_ptr(), stat.as_mut_ptr()))?;
-+        Errno::result(res).map(|_| Statfs(stat.assume_init()))
-     }
- }
- 
- pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
-     unsafe {
--        let mut stat: Statfs = mem::uninitialized();
--        Errno::result(libc::fstatfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
-+        let mut stat = mem::MaybeUninit::<libc::statfs>::uninit();
-+        Errno::result(libc::fstatfs(fd.as_raw_fd(), stat.as_mut_ptr()))
-+            .map(|_| Statfs(stat.assume_init()))
-     }
- }
- 
-@@ -451,8 +471,8 @@ pub fn fstatfs<T: AsRawFd>(fd: &T) -> Result<Statfs> {
- mod test {
-     use std::fs::File;
- 
--    use sys::statfs::*;
--    use sys::statvfs::*;
-+    use crate::sys::statfs::*;
-+    use crate::sys::statvfs::*;
-     use std::path::Path;
- 
-     #[test]
-diff --git a/third_party/rust/nix/src/sys/statvfs.rs b/third_party/rust/nix/src/sys/statvfs.rs
-index e5980369d5119..9bea9734925f0 100644
---- a/third_party/rust/nix/src/sys/statvfs.rs
-+++ b/third_party/rust/nix/src/sys/statvfs.rs
-@@ -7,9 +7,9 @@ use std::os::unix::io::AsRawFd;
- 
- use libc::{self, c_ulong};
- 
--use {Result, NixPath};
--use errno::Errno;
-+use crate::{Result, NixPath, errno::Errno};
- 
-+#[cfg(not(target_os = "redox"))]
- libc_bitflags!(
-     /// File system mount Flags
-     #[repr(C)]
-@@ -55,8 +55,7 @@ libc_bitflags!(
- /// 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).
--// FIXME: Replace with repr(transparent)
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct Statvfs(libc::statvfs);
- 
-@@ -109,6 +108,7 @@ impl Statvfs {
-     }
- 
-     /// Get the mount flags
-+    #[cfg(not(target_os = "redox"))]
-     pub fn flags(&self) -> FsFlags {
-         FsFlags::from_bits_truncate(self.0.f_flag)
-     }
-@@ -124,12 +124,12 @@ impl Statvfs {
- pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
-     unsafe {
-         Errno::clear();
--        let mut stat: Statvfs = mem::uninitialized();
-+        let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
-         let res = path.with_nix_path(|path|
--            libc::statvfs(path.as_ptr(), &mut stat.0)
-+            libc::statvfs(path.as_ptr(), stat.as_mut_ptr())
-         )?;
- 
--        Errno::result(res).map(|_| stat)
-+        Errno::result(res).map(|_| Statvfs(stat.assume_init()))
-     }
- }
- 
-@@ -137,15 +137,16 @@ pub fn statvfs<P: ?Sized + NixPath>(path: &P) -> Result<Statvfs> {
- pub fn fstatvfs<T: AsRawFd>(fd: &T) -> Result<Statvfs> {
-     unsafe {
-         Errno::clear();
--        let mut stat: Statvfs = mem::uninitialized();
--        Errno::result(libc::fstatvfs(fd.as_raw_fd(), &mut stat.0)).map(|_| stat)
-+        let mut stat = mem::MaybeUninit::<libc::statvfs>::uninit();
-+        Errno::result(libc::fstatvfs(fd.as_raw_fd(), stat.as_mut_ptr()))
-+            .map(|_| Statvfs(stat.assume_init()))
-     }
- }
- 
- #[cfg(test)]
- mod test {
-     use std::fs::File;
--    use sys::statvfs::*;
-+    use crate::sys::statvfs::*;
- 
-     #[test]
-     fn statvfs_call() {
-diff --git a/third_party/rust/nix/src/sys/sysinfo.rs b/third_party/rust/nix/src/sys/sysinfo.rs
-index 4c8e38988886d..222a2fc0480c3 100644
---- a/third_party/rust/nix/src/sys/sysinfo.rs
-+++ b/third_party/rust/nix/src/sys/sysinfo.rs
-@@ -2,13 +2,20 @@ use libc::{self, SI_LOAD_SHIFT};
- use std::{cmp, mem};
- use std::time::Duration;
- 
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- 
- /// System info structure returned by `sysinfo`.
- #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
-+#[repr(transparent)]
- pub struct SysInfo(libc::sysinfo);
- 
-+// The fields are c_ulong on 32-bit linux, u64 on 64-bit linux; x32's ulong is u32
-+#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-+type mem_blocks_t = u64;
-+#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-+type mem_blocks_t = libc::c_ulong;
-+
- impl SysInfo {
-     /// Returns the load average tuple.
-     ///
-@@ -57,7 +64,7 @@ impl SysInfo {
-         self.scale_mem(self.0.freeram)
-     }
- 
--    fn scale_mem(&self, units: libc::c_ulong) -> u64 {
-+    fn scale_mem(&self, units: mem_blocks_t) -> u64 {
-         units as u64 * self.0.mem_unit as u64
-     }
- }
-@@ -66,7 +73,7 @@ impl SysInfo {
- ///
- /// [See `sysinfo(2)`](http://man7.org/linux/man-pages/man2/sysinfo.2.html).
- pub fn sysinfo() -> Result<SysInfo> {
--    let mut info: libc::sysinfo = unsafe { mem::uninitialized() };
--    let res = unsafe { libc::sysinfo(&mut info) };
--    Errno::result(res).map(|_| SysInfo(info))
-+    let mut info = mem::MaybeUninit::uninit();
-+    let res = unsafe { libc::sysinfo(info.as_mut_ptr()) };
-+    Errno::result(res).map(|_| unsafe{ SysInfo(info.assume_init()) })
- }
-diff --git a/third_party/rust/nix/src/sys/termios.rs b/third_party/rust/nix/src/sys/termios.rs
-index c7cdf10b461c1..95148360495f1 100644
---- a/third_party/rust/nix/src/sys/termios.rs
-+++ b/third_party/rust/nix/src/sys/termios.rs
-@@ -25,7 +25,7 @@
- //! ```
- //! # use self::nix::sys::termios::SpecialCharacterIndices::VEOF;
- //! # use self::nix::sys::termios::{_POSIX_VDISABLE, Termios};
--//! # let mut termios = unsafe { Termios::default_uninit() };
-+//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
- //! termios.control_chars[VEOF as usize] = _POSIX_VDISABLE;
- //! ```
- //!
-@@ -38,7 +38,7 @@
- //!
- //! ```
- //! # use self::nix::sys::termios::{ControlFlags, Termios};
--//! # let mut termios = unsafe { Termios::default_uninit() };
-+//! # let mut termios: Termios = unsafe { std::mem::zeroed() };
- //! termios.control_flags & ControlFlags::CSIZE == ControlFlags::CS5;
- //! termios.control_flags |= ControlFlags::CS5;
- //! ```
-@@ -61,10 +61,9 @@
- //! platforms:
- //!
- //! ```rust
--//! # #[macro_use] extern crate nix;
- //! # use nix::sys::termios::{BaudRate, cfsetispeed, cfsetospeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! cfsetispeed(&mut t, BaudRate::B9600);
- //! cfsetospeed(&mut t, BaudRate::B9600);
- //! cfsetspeed(&mut t, BaudRate::B9600);
-@@ -74,102 +73,94 @@
- //! Additionally round-tripping baud rates is consistent across platforms:
- //!
- //! ```rust
--//! # extern crate nix;
- //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetispeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! # cfsetspeed(&mut t, BaudRate::B9600);
- //! let speed = cfgetispeed(&t);
--//! assert!(speed == cfgetospeed(&t));
-+//! assert_eq!(speed, cfgetospeed(&t));
- //! cfsetispeed(&mut t, speed);
- //! # }
- //! ```
- //!
- //! On non-BSDs, `cfgetispeed()` and `cfgetospeed()` both return a `BaudRate`:
- //!
--// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
- #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-             doc = " ```rust,ignore")]
- #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-             doc = " ```rust")]
--//! # extern crate nix;
- //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! # cfsetspeed(&mut t, BaudRate::B9600);
--//! assert!(cfgetispeed(&t) == BaudRate::B9600);
--//! assert!(cfgetospeed(&t) == BaudRate::B9600);
-+//! assert_eq!(cfgetispeed(&t), BaudRate::B9600);
-+//! assert_eq!(cfgetospeed(&t), BaudRate::B9600);
- //! # }
- //! ```
- //!
- //! But on the BSDs, `cfgetispeed()` and `cfgetospeed()` both return `u32`s:
- //!
--// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
- #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-             doc = " ```rust")]
- #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-             doc = " ```rust,ignore")]
--//! # extern crate nix;
- //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfgetospeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! # cfsetspeed(&mut t, 9600u32);
--//! assert!(cfgetispeed(&t) == 9600u32);
--//! assert!(cfgetospeed(&t) == 9600u32);
-+//! assert_eq!(cfgetispeed(&t), 9600u32);
-+//! assert_eq!(cfgetospeed(&t), 9600u32);
- //! # }
- //! ```
- //!
- //! It's trivial to convert from a `BaudRate` to a `u32` on BSDs:
- //!
--// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
- #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-             doc = " ```rust")]
- #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-             doc = " ```rust,ignore")]
--//! # extern crate nix;
- //! # use nix::sys::termios::{BaudRate, cfgetispeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! # cfsetspeed(&mut t, 9600u32);
--//! assert!(cfgetispeed(&t) == BaudRate::B9600.into());
--//! assert!(u32::from(BaudRate::B9600) == 9600u32);
-+//! assert_eq!(cfgetispeed(&t), BaudRate::B9600.into());
-+//! assert_eq!(u32::from(BaudRate::B9600), 9600u32);
- //! # }
- //! ```
- //!
- //! And on BSDs you can specify arbitrary baud rates (**note** this depends on hardware support)
- //! by specifying baud rates directly using `u32`s:
- //!
--// FIXME: Replace `ignore` with `compile_fail` once 1.22 is the minimum support Rust version
- #![cfg_attr(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                 target_os = "macos", target_os = "netbsd", target_os = "openbsd"),
-             doc = " ```rust")]
- #![cfg_attr(not(any(target_os = "freebsd", target_os = "dragonfly", target_os = "ios",
-                     target_os = "macos", target_os = "netbsd", target_os = "openbsd")),
-             doc = " ```rust,ignore")]
--//! # extern crate nix;
- //! # use nix::sys::termios::{cfsetispeed, cfsetospeed, cfsetspeed, Termios};
- //! # fn main() {
--//! # let mut t = unsafe { Termios::default_uninit() };
-+//! # let mut t: Termios = unsafe { std::mem::zeroed() };
- //! cfsetispeed(&mut t, 9600u32);
- //! cfsetospeed(&mut t, 9600u32);
- //! cfsetspeed(&mut t, 9600u32);
- //! # }
- //! ```
--use Result;
--use errno::Errno;
-+use cfg_if::cfg_if;
-+use crate::{Error, Result};
-+use crate::errno::Errno;
- use libc::{self, c_int, tcflag_t};
- use std::cell::{Ref, RefCell};
--use std::convert::From;
-+use std::convert::{From, TryFrom};
- use std::mem;
- use std::os::unix::io::RawFd;
- 
--use ::unistd::Pid;
-+use crate::unistd::Pid;
- 
- /// Stores settings for the termios API
- ///
-@@ -194,24 +185,9 @@ pub struct Termios {
- impl Termios {
-     /// Exposes an immutable reference to the underlying `libc::termios` data structure.
-     ///
--    /// This can be used for interfacing with other FFI functions like:
--    ///
--    /// ```rust
--    /// # extern crate libc;
--    /// # extern crate nix;
--    /// # fn main() {
--    /// # use nix::sys::termios::Termios;
--    /// # let mut termios = unsafe { Termios::default_uninit() };
--    /// let inner_termios = termios.get_libc_termios();
--    /// unsafe { libc::cfgetispeed(&*inner_termios) };
--    /// # }
--    /// ```
--    ///
--    /// There is no public API exposed for functions that modify the underlying `libc::termios`
--    /// data because it requires additional work to maintain type safety.
--    // FIXME: Switch this over to use pub(crate)
--    #[doc(hidden)]
--    pub fn get_libc_termios(&self) -> Ref<libc::termios> {
-+    /// This is not part of `nix`'s public API because it requires additional work to maintain type
-+    /// safety.
-+    pub(crate) fn get_libc_termios(&self) -> Ref<libc::termios> {
-         {
-             let mut termios = self.inner.borrow_mut();
-             termios.c_iflag = self.input_flags.bits();
-@@ -225,12 +201,11 @@ impl Termios {
- 
-     /// Exposes the inner `libc::termios` datastore within `Termios`.
-     ///
--    /// This is unsafe because if this is used to modify the inner libc::termios struct, it will not
--    /// automatically update the safe wrapper type around it. Therefore we disable docs to
--    /// effectively limit its use to nix internals. In this case it should also be paired with a
--    /// call to `update_wrapper()` so that the wrapper-type and internal representation stay
--    /// consistent.
--    unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
-+    /// This is unsafe because if this is used to modify the inner `libc::termios` struct, it will
-+    /// not automatically update the safe wrapper type around it. In this case it should also be
-+    /// paired with a call to `update_wrapper()` so that the wrapper-type and internal
-+    /// representation stay consistent.
-+    pub(crate) unsafe fn get_libc_termios_mut(&mut self) -> *mut libc::termios {
-         {
-             let mut termios = self.inner.borrow_mut();
-             termios.c_iflag = self.input_flags.bits();
-@@ -242,26 +217,8 @@ impl Termios {
-         self.inner.as_ptr()
-     }
- 
--    /// Allows for easily creating new `Termios` structs that will be overwritten with real data.
--    ///
--    /// This should only be used when the inner libc::termios struct will be overwritten before it's
--    /// read.
--    // FIXME: Switch this over to use pub(crate)
--    #[doc(hidden)]
--    pub unsafe fn default_uninit() -> Self {
--        Termios {
--            inner: RefCell::new(mem::uninitialized()),
--            input_flags: InputFlags::empty(),
--            output_flags: OutputFlags::empty(),
--            control_flags: ControlFlags::empty(),
--            local_flags: LocalFlags::empty(),
--            control_chars: [0 as libc::cc_t; NCCS],
--        }
--    }
--
-     /// Updates the wrapper values from the internal `libc::termios` data structure.
--    #[doc(hidden)]
--    pub fn update_wrapper(&mut self) {
-+    pub(crate) fn update_wrapper(&mut self) {
-         let termios = *self.inner.borrow_mut();
-         self.input_flags = InputFlags::from_bits_truncate(termios.c_iflag);
-         self.output_flags = OutputFlags::from_bits_truncate(termios.c_oflag);
-@@ -376,9 +333,10 @@ libc_enum!{
-     }
- }
- 
--impl From<libc::speed_t> for BaudRate {
--    fn from(s: libc::speed_t) -> BaudRate {
-+impl TryFrom<libc::speed_t> for BaudRate {
-+    type Error = Error;
- 
-+    fn try_from(s: libc::speed_t) -> Result<BaudRate> {
-         use libc::{B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800,
-                    B9600, B19200, B38400, B57600, B115200, B230400};
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -398,85 +356,84 @@ impl From<libc::speed_t> for BaudRate {
-         use libc::{B460800, B921600};
- 
-         match s {
--            B0 => BaudRate::B0,
--            B50 => BaudRate::B50,
--            B75 => BaudRate::B75,
--            B110 => BaudRate::B110,
--            B134 => BaudRate::B134,
--            B150 => BaudRate::B150,
--            B200 => BaudRate::B200,
--            B300 => BaudRate::B300,
--            B600 => BaudRate::B600,
--            B1200 => BaudRate::B1200,
--            B1800 => BaudRate::B1800,
--            B2400 => BaudRate::B2400,
--            B4800 => BaudRate::B4800,
-+            B0 => Ok(BaudRate::B0),
-+            B50 => Ok(BaudRate::B50),
-+            B75 => Ok(BaudRate::B75),
-+            B110 => Ok(BaudRate::B110),
-+            B134 => Ok(BaudRate::B134),
-+            B150 => Ok(BaudRate::B150),
-+            B200 => Ok(BaudRate::B200),
-+            B300 => Ok(BaudRate::B300),
-+            B600 => Ok(BaudRate::B600),
-+            B1200 => Ok(BaudRate::B1200),
-+            B1800 => Ok(BaudRate::B1800),
-+            B2400 => Ok(BaudRate::B2400),
-+            B4800 => Ok(BaudRate::B4800),
-             #[cfg(any(target_os = "dragonfly",
-                       target_os = "freebsd",
-                       target_os = "macos",
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
--            B7200 => BaudRate::B7200,
--            B9600 => BaudRate::B9600,
-+            B7200 => Ok(BaudRate::B7200),
-+            B9600 => Ok(BaudRate::B9600),
-             #[cfg(any(target_os = "dragonfly",
-                       target_os = "freebsd",
-                       target_os = "macos",
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
--            B14400 => BaudRate::B14400,
--            B19200 => BaudRate::B19200,
-+            B14400 => Ok(BaudRate::B14400),
-+            B19200 => Ok(BaudRate::B19200),
-             #[cfg(any(target_os = "dragonfly",
-                       target_os = "freebsd",
-                       target_os = "macos",
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
--            B28800 => BaudRate::B28800,
--            B38400 => BaudRate::B38400,
--            B57600 => BaudRate::B57600,
-+            B28800 => Ok(BaudRate::B28800),
-+            B38400 => Ok(BaudRate::B38400),
-+            B57600 => Ok(BaudRate::B57600),
-             #[cfg(any(target_os = "dragonfly",
-                       target_os = "freebsd",
-                       target_os = "macos",
-                       target_os = "netbsd",
-                       target_os = "openbsd"))]
--            B76800 => BaudRate::B76800,
--            B115200 => BaudRate::B115200,
--            B230400 => BaudRate::B230400,
-+            B76800 => Ok(BaudRate::B76800),
-+            B115200 => Ok(BaudRate::B115200),
-+            B230400 => Ok(BaudRate::B230400),
-             #[cfg(any(target_os = "android",
-                       target_os = "freebsd",
-                       target_os = "linux",
-                       target_os = "netbsd"))]
--            B460800 => BaudRate::B460800,
-+            B460800 => Ok(BaudRate::B460800),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B500000 => BaudRate::B500000,
-+            B500000 => Ok(BaudRate::B500000),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B576000 => BaudRate::B576000,
-+            B576000 => Ok(BaudRate::B576000),
-             #[cfg(any(target_os = "android",
-                       target_os = "freebsd",
-                       target_os = "linux",
-                       target_os = "netbsd"))]
--            B921600 => BaudRate::B921600,
-+            B921600 => Ok(BaudRate::B921600),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B1000000 => BaudRate::B1000000,
-+            B1000000 => Ok(BaudRate::B1000000),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B1152000 => BaudRate::B1152000,
-+            B1152000 => Ok(BaudRate::B1152000),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B1500000 => BaudRate::B1500000,
-+            B1500000 => Ok(BaudRate::B1500000),
-             #[cfg(any(target_os = "android", target_os = "linux"))]
--            B2000000 => BaudRate::B2000000,
-+            B2000000 => Ok(BaudRate::B2000000),
-             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
--            B2500000 => BaudRate::B2500000,
-+            B2500000 => Ok(BaudRate::B2500000),
-             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
--            B3000000 => BaudRate::B3000000,
-+            B3000000 => Ok(BaudRate::B3000000),
-             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
--            B3500000 => BaudRate::B3500000,
-+            B3500000 => Ok(BaudRate::B3500000),
-             #[cfg(any(target_os = "android", all(target_os = "linux", not(target_arch = "sparc64"))))]
--            B4000000 => BaudRate::B4000000,
--            b => unreachable!("Invalid baud constant: {}", b),
-+            B4000000 => Ok(BaudRate::B4000000),
-+            _ => Err(Error::invalid_argument())
-         }
-     }
- }
- 
--// TODO: Include `TryFrom<u32> for BaudRate` once that API stabilizes
- #[cfg(any(target_os = "freebsd",
-           target_os = "dragonfly",
-           target_os = "ios",
-@@ -583,6 +540,12 @@ libc_enum! {
-     }
- }
- 
-+#[cfg(all(target_os = "linux", target_arch = "sparc64"))]
-+impl SpecialCharacterIndices {
-+    pub const VMIN: SpecialCharacterIndices = SpecialCharacterIndices::VEOF;
-+    pub const VTIME: SpecialCharacterIndices = SpecialCharacterIndices::VEOL;
-+}
-+
- pub use libc::NCCS;
- #[cfg(any(target_os = "dragonfly",
-           target_os = "freebsd",
-@@ -606,7 +569,9 @@ libc_bitflags! {
-         ICRNL;
-         IXON;
-         IXOFF;
-+        #[cfg(not(target_os = "redox"))]
-         IXANY;
-+        #[cfg(not(target_os = "redox"))]
-         IMAXBEL;
-         #[cfg(any(target_os = "android", target_os = "linux", target_os = "macos"))]
-         IUTF8;
-@@ -816,6 +781,7 @@ libc_bitflags! {
-         PARODD;
-         HUPCL;
-         CLOCAL;
-+        #[cfg(not(target_os = "redox"))]
-         CRTSCTS;
-         #[cfg(any(target_os = "android", target_os = "linux"))]
-         CBAUD;
-@@ -866,12 +832,15 @@ libc_bitflags! {
- libc_bitflags! {
-     /// Flags for setting any local modes
-     pub struct LocalFlags: tcflag_t {
-+        #[cfg(not(target_os = "redox"))]
-         ECHOKE;
-         ECHOE;
-         ECHOK;
-         ECHO;
-         ECHONL;
-+        #[cfg(not(target_os = "redox"))]
-         ECHOPRT;
-+        #[cfg(not(target_os = "redox"))]
-         ECHOCTL;
-         ISIG;
-         ICANON;
-@@ -883,8 +852,10 @@ libc_bitflags! {
-                   target_os = "openbsd"))]
-         ALTWERASE;
-         IEXTEN;
-+        #[cfg(not(target_os = "redox"))]
-         EXTPROC;
-         TOSTOP;
-+        #[cfg(not(target_os = "redox"))]
-         FLUSHO;
-         #[cfg(any(target_os = "freebsd",
-                   target_os = "dragonfly",
-@@ -893,6 +864,7 @@ libc_bitflags! {
-                   target_os = "netbsd",
-                   target_os = "openbsd"))]
-         NOKERNINFO;
-+        #[cfg(not(target_os = "redox"))]
-         PENDIN;
-         NOFLSH;
-     }
-@@ -957,13 +929,15 @@ cfg_if!{
-             Errno::result(res).map(drop)
-         }
-     } else {
-+        use std::convert::TryInto;
-+
-         /// Get input baud rate (see
-         /// [cfgetispeed(3p)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/cfgetispeed.html)).
-         ///
-         /// `cfgetispeed()` extracts the input baud rate from the given `Termios` structure.
-         pub fn cfgetispeed(termios: &Termios) -> BaudRate {
-             let inner_termios = termios.get_libc_termios();
--            unsafe { libc::cfgetispeed(&*inner_termios) }.into()
-+            unsafe { libc::cfgetispeed(&*inner_termios) }.try_into().unwrap()
-         }
- 
-         /// Get output baud rate (see
-@@ -972,7 +946,7 @@ cfg_if!{
-         /// `cfgetospeed()` extracts the output baud rate from the given `Termios` structure.
-         pub fn cfgetospeed(termios: &Termios) -> BaudRate {
-             let inner_termios = termios.get_libc_termios();
--            unsafe { libc::cfgetospeed(&*inner_termios) }.into()
-+            unsafe { libc::cfgetospeed(&*inner_termios) }.try_into().unwrap()
-         }
- 
-         /// Set input baud rate (see
-@@ -1045,13 +1019,13 @@ pub fn cfmakesane(termios: &mut Termios) {
- /// this structure *will not* reconfigure the port, instead the modifications should be done to
- /// the `Termios` structure and then the port should be reconfigured using `tcsetattr()`.
- pub fn tcgetattr(fd: RawFd) -> Result<Termios> {
--    let mut termios: libc::termios = unsafe { mem::uninitialized() };
-+    let mut termios = mem::MaybeUninit::uninit();
- 
--    let res = unsafe { libc::tcgetattr(fd, &mut termios) };
-+    let res = unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) };
- 
-     Errno::result(res)?;
- 
--    Ok(termios.into())
-+    unsafe { Ok(termios.assume_init().into()) }
- }
- 
- /// Set the configuration for a terminal (see
-@@ -1105,3 +1079,14 @@ pub fn tcgetsid(fd: RawFd) -> Result<Pid> {
- 
-     Errno::result(res).map(Pid::from_raw)
- }
-+
-+#[cfg(test)]
-+mod test {
-+    use super::*;
-+
-+    #[test]
-+    fn try_from() {
-+        assert_eq!(Ok(BaudRate::B0), BaudRate::try_from(libc::B0));
-+        assert!(BaudRate::try_from(999999999).is_err());
-+    }
-+}
-diff --git a/third_party/rust/nix/src/sys/time.rs b/third_party/rust/nix/src/sys/time.rs
-index 3ad57543b18a7..7546d1b367c5e 100644
---- a/third_party/rust/nix/src/sys/time.rs
-+++ b/third_party/rust/nix/src/sys/time.rs
-@@ -1,6 +1,8 @@
- use std::{cmp, fmt, ops};
-+use std::time::Duration;
- use std::convert::From;
--use libc::{c_long, timespec, timeval};
-+use libc::{timespec, timeval};
-+#[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
- pub use libc::{time_t, suseconds_t};
- 
- pub trait TimeValLike: Sized {
-@@ -60,6 +62,34 @@ const TS_MAX_SECONDS: i64 = ::std::isize::MAX as i64;
- 
- const TS_MIN_SECONDS: i64 = -TS_MAX_SECONDS;
- 
-+// x32 compatibility
-+// See https://sourceware.org/bugzilla/show_bug.cgi?id=16437
-+#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
-+type timespec_tv_nsec_t = i64;
-+#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
-+type timespec_tv_nsec_t = libc::c_long;
-+
-+impl From<timespec> for TimeSpec {
-+    fn from(ts: timespec) -> Self {
-+        Self(ts)
-+    }
-+}
-+
-+impl From<Duration> for TimeSpec {
-+    fn from(duration: Duration) -> Self {
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-+        TimeSpec(timespec {
-+            tv_sec: duration.as_secs() as time_t,
-+            tv_nsec: duration.subsec_nanos() as timespec_tv_nsec_t
-+        })
-+    }
-+}
-+
-+impl From<TimeSpec> for Duration {
-+    fn from(timespec: TimeSpec) -> Self {
-+        Duration::new(timespec.0.tv_sec as u64, timespec.0.tv_nsec as u32)
-+    }
-+}
- 
- impl AsRef<timespec> for TimeSpec {
-     fn as_ref(&self) -> &timespec {
-@@ -67,6 +97,12 @@ impl AsRef<timespec> for TimeSpec {
-     }
- }
- 
-+impl AsMut<timespec> for TimeSpec {
-+    fn as_mut(&mut self) -> &mut timespec {
-+        &mut self.0
-+    }
-+}
-+
- impl Ord for TimeSpec {
-     // The implementation of cmp is simplified by assuming that the struct is
-     // normalized.  That is, tv_nsec must always be within [0, 1_000_000_000)
-@@ -90,6 +126,7 @@ impl TimeValLike for TimeSpec {
-     fn seconds(seconds: i64) -> TimeSpec {
-         assert!(seconds >= TS_MIN_SECONDS && seconds <= TS_MAX_SECONDS,
-                 "TimeSpec out of bounds; seconds={}", seconds);
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-         TimeSpec(timespec {tv_sec: seconds as time_t, tv_nsec: 0 })
-     }
- 
-@@ -116,8 +153,9 @@ impl TimeValLike for TimeSpec {
-         let (secs, nanos) = div_mod_floor_64(nanoseconds, NANOS_PER_SEC);
-         assert!(secs >= TS_MIN_SECONDS && secs <= TS_MAX_SECONDS,
-                 "TimeSpec out of bounds");
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-         TimeSpec(timespec {tv_sec: secs as time_t,
--                           tv_nsec: nanos as c_long })
-+                           tv_nsec: nanos as timespec_tv_nsec_t })
-     }
- 
-     fn num_seconds(&self) -> i64 {
-@@ -144,19 +182,20 @@ impl TimeValLike for TimeSpec {
- }
- 
- impl TimeSpec {
--    fn nanos_mod_sec(&self) -> c_long {
-+    fn nanos_mod_sec(&self) -> timespec_tv_nsec_t {
-         if self.tv_sec() < 0 && self.tv_nsec() > 0 {
--            self.tv_nsec() - NANOS_PER_SEC as c_long
-+            self.tv_nsec() - NANOS_PER_SEC as timespec_tv_nsec_t
-         } else {
-             self.tv_nsec()
-         }
-     }
- 
-+    #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-     pub fn tv_sec(&self) -> time_t {
-         self.0.tv_sec
-     }
- 
--    pub fn tv_nsec(&self) -> c_long {
-+    pub fn tv_nsec(&self) -> timespec_tv_nsec_t {
-         self.0.tv_nsec
-     }
- }
-@@ -191,7 +230,7 @@ impl ops::Mul<i32> for TimeSpec {
-     type Output = TimeSpec;
- 
-     fn mul(self, rhs: i32) -> TimeSpec {
--        let usec = self.num_nanoseconds().checked_mul(rhs as i64)
-+        let usec = self.num_nanoseconds().checked_mul(i64::from(rhs))
-             .expect("TimeSpec multiply out of bounds");
- 
-         TimeSpec::nanoseconds(usec)
-@@ -202,7 +241,7 @@ impl ops::Div<i32> for TimeSpec {
-     type Output = TimeSpec;
- 
-     fn div(self, rhs: i32) -> TimeSpec {
--        let usec = self.num_nanoseconds() / rhs as i64;
-+        let usec = self.num_nanoseconds() / i64::from(rhs);
-         TimeSpec::nanoseconds(usec)
-     }
- }
-@@ -239,7 +278,7 @@ impl fmt::Display for TimeSpec {
- 
- 
- 
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct TimeVal(timeval);
- 
-@@ -259,6 +298,12 @@ impl AsRef<timeval> for TimeVal {
-     }
- }
- 
-+impl AsMut<timeval> for TimeVal {
-+    fn as_mut(&mut self) -> &mut timeval {
-+        &mut self.0
-+    }
-+}
-+
- impl Ord for TimeVal {
-     // The implementation of cmp is simplified by assuming that the struct is
-     // normalized.  That is, tv_usec must always be within [0, 1_000_000)
-@@ -282,6 +327,7 @@ impl TimeValLike for TimeVal {
-     fn seconds(seconds: i64) -> TimeVal {
-         assert!(seconds >= TV_MIN_SECONDS && seconds <= TV_MAX_SECONDS,
-                 "TimeVal out of bounds; seconds={}", seconds);
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-         TimeVal(timeval {tv_sec: seconds as time_t, tv_usec: 0 })
-     }
- 
-@@ -299,6 +345,7 @@ impl TimeValLike for TimeVal {
-         let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
-         assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
-                 "TimeVal out of bounds");
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-         TimeVal(timeval {tv_sec: secs as time_t,
-                            tv_usec: micros as suseconds_t })
-     }
-@@ -311,6 +358,7 @@ impl TimeValLike for TimeVal {
-         let (secs, micros) = div_mod_floor_64(microseconds, MICROS_PER_SEC);
-         assert!(secs >= TV_MIN_SECONDS && secs <= TV_MAX_SECONDS,
-                 "TimeVal out of bounds");
-+        #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-         TimeVal(timeval {tv_sec: secs as time_t,
-                            tv_usec: micros as suseconds_t })
-     }
-@@ -347,6 +395,7 @@ impl TimeVal {
-         }
-     }
- 
-+    #[cfg_attr(target_env = "musl", allow(deprecated))] // https://github.com/rust-lang/libc/issues/1848
-     pub fn tv_sec(&self) -> time_t {
-         self.0.tv_sec
-     }
-@@ -386,7 +435,7 @@ impl ops::Mul<i32> for TimeVal {
-     type Output = TimeVal;
- 
-     fn mul(self, rhs: i32) -> TimeVal {
--        let usec = self.num_microseconds().checked_mul(rhs as i64)
-+        let usec = self.num_microseconds().checked_mul(i64::from(rhs))
-             .expect("TimeVal multiply out of bounds");
- 
-         TimeVal::microseconds(usec)
-@@ -397,7 +446,7 @@ impl ops::Div<i32> for TimeVal {
-     type Output = TimeVal;
- 
-     fn div(self, rhs: i32) -> TimeVal {
--        let usec = self.num_microseconds() / rhs as i64;
-+        let usec = self.num_microseconds() / i64::from(rhs);
-         TimeVal::microseconds(usec)
-     }
- }
-@@ -467,6 +516,7 @@ fn div_rem_64(this: i64, other: i64) -> (i64, i64) {
- #[cfg(test)]
- mod test {
-     use super::{TimeSpec, TimeVal, TimeValLike};
-+    use std::time::Duration;
- 
-     #[test]
-     pub fn test_timespec() {
-@@ -477,6 +527,15 @@ mod test {
-                    TimeSpec::seconds(182));
-     }
- 
-+    #[test]
-+    pub fn test_timespec_from() {
-+        let duration = Duration::new(123, 123_456_789);
-+        let timespec = TimeSpec::nanoseconds(123_123_456_789);
-+
-+        assert_eq!(TimeSpec::from(duration), timespec);
-+        assert_eq!(Duration::from(timespec), duration);
-+    }
-+
-     #[test]
-     pub fn test_timespec_neg() {
-         let a = TimeSpec::seconds(1) + TimeSpec::nanoseconds(123);
-diff --git a/third_party/rust/nix/src/sys/timerfd.rs b/third_party/rust/nix/src/sys/timerfd.rs
-new file mode 100644
-index 0000000000000..4a24719498602
---- /dev/null
-+++ b/third_party/rust/nix/src/sys/timerfd.rs
-@@ -0,0 +1,285 @@
-+//! Timer API via file descriptors.
-+//!
-+//! 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).
-+//!
-+//! # Examples
-+//!
-+//! Create a new one-shot timer that expires after 1 second.
-+//! ```
-+//! # use std::os::unix::io::AsRawFd;
-+//! # use nix::sys::timerfd::{TimerFd, ClockId, TimerFlags, TimerSetTimeFlags,
-+//! #    Expiration};
-+//! # use nix::sys::time::{TimeSpec, TimeValLike};
-+//! # use nix::unistd::read;
-+//! #
-+//! // We create a new monotonic timer.
-+//! let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty())
-+//!     .unwrap();
-+//!
-+//! // We set a new one-shot timer in 1 seconds.
-+//! timer.set(
-+//!     Expiration::OneShot(TimeSpec::seconds(1)),
-+//!     TimerSetTimeFlags::empty()
-+//! ).unwrap();
-+//!
-+//! // We wait for the timer to expire.
-+//! timer.wait().unwrap();
-+//! ```
-+use crate::sys::time::TimeSpec;
-+use crate::unistd::read;
-+use crate::{errno::Errno, Error, Result};
-+use bitflags::bitflags;
-+use libc::c_int;
-+use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
-+
-+/// A timerfd instance. This is also a file descriptor, you can feed it to
-+/// other interfaces consuming file descriptors, epoll for example.
-+#[derive(Debug)]
-+pub struct TimerFd {
-+    fd: RawFd,
-+}
-+
-+impl AsRawFd for TimerFd {
-+    fn as_raw_fd(&self) -> RawFd {
-+        self.fd
-+    }
-+}
-+
-+impl FromRawFd for TimerFd {
-+    unsafe fn from_raw_fd(fd: RawFd) -> Self {
-+        TimerFd { fd }
-+    }
-+}
-+
-+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).
-+    #[repr(i32)]
-+    pub enum ClockId {
-+        CLOCK_REALTIME,
-+        CLOCK_MONOTONIC,
-+        CLOCK_BOOTTIME,
-+        CLOCK_REALTIME_ALARM,
-+        CLOCK_BOOTTIME_ALARM,
-+    }
-+}
-+
-+libc_bitflags! {
-+    /// Additional flags to change the behaviour of the file descriptor at the
-+    /// time of creation.
-+    pub struct TimerFlags: c_int {
-+        TFD_NONBLOCK;
-+        TFD_CLOEXEC;
-+    }
-+}
-+
-+bitflags! {
-+    /// Flags that are used for arming the timer.
-+    pub struct TimerSetTimeFlags: libc::c_int {
-+        const TFD_TIMER_ABSTIME = libc::TFD_TIMER_ABSTIME;
-+    }
-+}
-+
-+#[derive(Debug, Clone, Copy)]
-+struct TimerSpec(libc::itimerspec);
-+
-+impl TimerSpec {
-+    pub fn none() -> Self {
-+        Self(libc::itimerspec {
-+            it_interval: libc::timespec {
-+                tv_sec: 0,
-+                tv_nsec: 0,
-+            },
-+            it_value: libc::timespec {
-+                tv_sec: 0,
-+                tv_nsec: 0,
-+            },
-+        })
-+    }
-+}
-+
-+impl AsRef<libc::itimerspec> for TimerSpec {
-+    fn as_ref(&self) -> &libc::itimerspec {
-+        &self.0
-+    }
-+}
-+
-+impl From<Expiration> for TimerSpec {
-+    fn from(expiration: Expiration) -> TimerSpec {
-+        match expiration {
-+            Expiration::OneShot(t) => TimerSpec(libc::itimerspec {
-+                it_interval: libc::timespec {
-+                    tv_sec: 0,
-+                    tv_nsec: 0,
-+                },
-+                it_value: *t.as_ref(),
-+            }),
-+            Expiration::IntervalDelayed(start, interval) => TimerSpec(libc::itimerspec {
-+                it_interval: *interval.as_ref(),
-+                it_value: *start.as_ref(),
-+            }),
-+            Expiration::Interval(t) => TimerSpec(libc::itimerspec {
-+                it_interval: *t.as_ref(),
-+                it_value: *t.as_ref(),
-+            }),
-+        }
-+    }
-+}
-+
-+impl From<TimerSpec> for Expiration {
-+    fn from(timerspec: TimerSpec) -> Expiration {
-+        match timerspec {
-+            TimerSpec(libc::itimerspec {
-+                it_interval:
-+                    libc::timespec {
-+                        tv_sec: 0,
-+                        tv_nsec: 0,
-+                    },
-+                it_value: ts,
-+            }) => Expiration::OneShot(ts.into()),
-+            TimerSpec(libc::itimerspec {
-+                it_interval: int_ts,
-+                it_value: val_ts,
-+            }) => {
-+                if (int_ts.tv_sec == val_ts.tv_sec) && (int_ts.tv_nsec == val_ts.tv_nsec) {
-+                    Expiration::Interval(int_ts.into())
-+                } else {
-+                    Expiration::IntervalDelayed(val_ts.into(), int_ts.into())
-+                }
-+            }
-+        }
-+    }
-+}
-+
-+/// An enumeration allowing the definition of the expiration time of an alarm,
-+/// recurring or not.
-+#[derive(Debug, Clone, Copy, PartialEq)]
-+pub enum Expiration {
-+    OneShot(TimeSpec),
-+    IntervalDelayed(TimeSpec, TimeSpec),
-+    Interval(TimeSpec),
-+}
-+
-+impl TimerFd {
-+    /// Creates a new timer based on the clock defined by `clockid`. The
-+    /// underlying fd can be assigned specific flags with `flags` (CLOEXEC,
-+    /// NONBLOCK). The underlying fd will be closed on drop.
-+    pub fn new(clockid: ClockId, flags: TimerFlags) -> Result<Self> {
-+        Errno::result(unsafe { libc::timerfd_create(clockid as i32, flags.bits()) })
-+            .map(|fd| Self { fd })
-+    }
-+
-+    /// Sets a new alarm on the timer.
-+    ///
-+    /// # Types of alarm
-+    ///
-+    /// There are 3 types of alarms you can set:
-+    ///
-+    ///   - one shot: the alarm will trigger once after the specified amount of
-+    /// time.
-+    ///     Example: I want an alarm to go off in 60s and then disables itself.
-+    ///
-+    ///   - interval: the alarm will trigger every specified interval of time.
-+    ///     Example: I want an alarm to go off every 60s. The alarm will first
-+    ///     go off 60s after I set it and every 60s after that. The alarm will
-+    ///     not disable itself.
-+    ///
-+    ///   - interval delayed: the alarm will trigger after a certain amount of
-+    ///     time and then trigger at a specified interval.
-+    ///     Example: I want an alarm to go off every 60s but only start in 1h.
-+    ///     The alarm will first trigger 1h after I set it and then every 60s
-+    ///     after that. The alarm will not disable itself.
-+    ///
-+    /// # Relative vs absolute alarm
-+    ///
-+    /// If you do not set any `TimerSetTimeFlags`, then the `TimeSpec` you pass
-+    /// to the `Expiration` you want is relative. If however you want an alarm
-+    /// to go off at a certain point in time, you can set `TFD_TIMER_ABSTIME`.
-+    /// Then the one shot TimeSpec and the delay TimeSpec of the delayed
-+    /// interval are going to be interpreted as absolute.
-+    ///
-+    /// # Disabling alarms
-+    ///
-+    /// Note: Only one alarm can be set for any given timer. Setting a new alarm
-+    /// actually removes the previous one.
-+    ///
-+    /// Note: Setting a one shot alarm with a 0s TimeSpec disables the alarm
-+    /// altogether.
-+    pub fn set(&self, expiration: Expiration, flags: TimerSetTimeFlags) -> Result<()> {
-+        let timerspec: TimerSpec = expiration.into();
-+        Errno::result(unsafe {
-+            libc::timerfd_settime(
-+                self.fd,
-+                flags.bits(),
-+                timerspec.as_ref(),
-+                std::ptr::null_mut(),
-+            )
-+        })
-+        .map(drop)
-+    }
-+
-+    /// Get the parameters for the alarm currently set, if any.
-+    pub fn get(&self) -> Result<Option<Expiration>> {
-+        let mut timerspec = TimerSpec::none();
-+        let timerspec_ptr: *mut libc::itimerspec = &mut timerspec.0;
-+
-+        Errno::result(unsafe { libc::timerfd_gettime(self.fd, timerspec_ptr) }).map(|_| {
-+            if timerspec.0.it_interval.tv_sec == 0
-+                && timerspec.0.it_interval.tv_nsec == 0
-+                && timerspec.0.it_value.tv_sec == 0
-+                && timerspec.0.it_value.tv_nsec == 0
-+            {
-+                None
-+            } else {
-+                Some(timerspec.into())
-+            }
-+        })
-+    }
-+
-+    /// Remove the alarm if any is set.
-+    pub fn unset(&self) -> Result<()> {
-+        Errno::result(unsafe {
-+            libc::timerfd_settime(
-+                self.fd,
-+                TimerSetTimeFlags::empty().bits(),
-+                TimerSpec::none().as_ref(),
-+                std::ptr::null_mut(),
-+            )
-+        })
-+        .map(drop)
-+    }
-+
-+    /// Wait for the configured alarm to expire.
-+    ///
-+    /// Note: If the alarm is unset, then you will wait forever.
-+    pub fn wait(&self) -> Result<()> {
-+        loop {
-+            if let Err(e) = read(self.fd, &mut [0u8; 8]) {
-+                match e {
-+                    Error::Sys(Errno::EINTR) => continue,
-+                    _ => return Err(e),
-+                }
-+            } else {
-+                break;
-+            }
-+        }
-+
-+        Ok(())
-+    }
-+}
-+
-+impl Drop for TimerFd {
-+    fn drop(&mut self) {
-+        if !std::thread::panicking() {
-+            let result = Errno::result(unsafe {
-+                libc::close(self.fd)
-+            });
-+            if let Err(Error::Sys(Errno::EBADF)) = result {
-+                panic!("close of TimerFd encountered EBADF");
-+            }
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix/src/sys/uio.rs b/third_party/rust/nix/src/sys/uio.rs
-index d089084eed711..65334227b4d1d 100644
---- a/third_party/rust/nix/src/sys/uio.rs
-+++ b/third_party/rust/nix/src/sys/uio.rs
-@@ -1,8 +1,8 @@
- // Silence invalid warnings due to rust-lang/rust#16719
- #![allow(improper_ctypes)]
- 
--use Result;
--use errno::Errno;
-+use crate::Result;
-+use crate::errno::Errno;
- use libc::{self, c_int, c_void, size_t, off_t};
- use std::marker::PhantomData;
- use std::os::unix::io::RawFd;
-@@ -117,7 +117,11 @@ pub struct RemoteIoVec {
- /// [`IoVec`]: struct.IoVec.html
- /// [`RemoteIoVec`]: struct.RemoteIoVec.html
- #[cfg(target_os = "linux")]
--pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
-+pub fn process_vm_writev(
-+    pid: crate::unistd::Pid,
-+    local_iov: &[IoVec<&[u8]>],
-+    remote_iov: &[RemoteIoVec]) -> Result<usize>
-+{
-     let res = unsafe {
-         libc::process_vm_writev(pid.into(),
-                                 local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
-@@ -148,7 +152,11 @@ pub fn process_vm_writev(pid: ::unistd::Pid, local_iov: &[IoVec<&[u8]>], remote_
- /// [`IoVec`]: struct.IoVec.html
- /// [`RemoteIoVec`]: struct.RemoteIoVec.html
- #[cfg(any(target_os = "linux"))]
--pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remote_iov: &[RemoteIoVec]) -> Result<usize> {
-+pub fn process_vm_readv(
-+    pid: crate::unistd::Pid,
-+    local_iov: &[IoVec<&mut [u8]>],
-+    remote_iov: &[RemoteIoVec]) -> Result<usize>
-+{
-     let res = unsafe {
-         libc::process_vm_readv(pid.into(),
-                                local_iov.as_ptr() as *const libc::iovec, local_iov.len() as libc::c_ulong,
-@@ -158,7 +166,7 @@ pub fn process_vm_readv(pid: ::unistd::Pid, local_iov: &[IoVec<&mut [u8]>], remo
-     Errno::result(res).map(|r| r as usize)
- }
- 
--#[repr(C)]
-+#[repr(transparent)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct IoVec<T>(libc::iovec, PhantomData<T>);
- 
-diff --git a/third_party/rust/nix/src/sys/utsname.rs b/third_party/rust/nix/src/sys/utsname.rs
-index ab09c7d23232a..bf1a814d6d863 100644
---- a/third_party/rust/nix/src/sys/utsname.rs
-+++ b/third_party/rust/nix/src/sys/utsname.rs
-@@ -3,8 +3,8 @@ use libc::{self, c_char};
- use std::ffi::CStr;
- use std::str::from_utf8_unchecked;
- 
--#[repr(C)]
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
-+#[repr(transparent)]
- pub struct UtsName(libc::utsname);
- 
- impl UtsName {
-@@ -31,9 +31,9 @@ impl UtsName {
- 
- pub fn uname() -> UtsName {
-     unsafe {
--        let mut ret: UtsName = mem::uninitialized();
--        libc::uname(&mut ret.0);
--        ret
-+        let mut ret = mem::MaybeUninit::uninit();
-+        libc::uname(ret.as_mut_ptr());
-+        UtsName(ret.assume_init())
-     }
- }
- 
-diff --git a/third_party/rust/nix/src/sys/wait.rs b/third_party/rust/nix/src/sys/wait.rs
-index c54f7ec579667..faf8543cb1589 100644
---- a/third_party/rust/nix/src/sys/wait.rs
-+++ b/third_party/rust/nix/src/sys/wait.rs
-@@ -1,9 +1,10 @@
-+use crate::errno::Errno;
-+use crate::sys::signal::Signal;
-+use crate::unistd::Pid;
-+use crate::Result;
-+use cfg_if::cfg_if;
- use libc::{self, c_int};
--use Result;
--use errno::Errno;
--use unistd::Pid;
--
--use sys::signal::Signal;
-+use std::convert::TryFrom;
- 
- libc_bitflags!(
-     pub struct WaitPidFlag: c_int {
-@@ -14,6 +15,7 @@ libc_bitflags!(
-                   target_os = "haiku",
-                   target_os = "ios",
-                   target_os = "linux",
-+                  target_os = "redox",
-                   target_os = "macos",
-                   target_os = "netbsd"))]
-         WEXITED;
-@@ -23,6 +25,7 @@ libc_bitflags!(
-                   target_os = "haiku",
-                   target_os = "ios",
-                   target_os = "linux",
-+                  target_os = "redox",
-                   target_os = "macos",
-                   target_os = "netbsd"))]
-         WSTOPPED;
-@@ -32,16 +35,17 @@ libc_bitflags!(
-                   target_os = "haiku",
-                   target_os = "ios",
-                   target_os = "linux",
-+                  target_os = "redox",
-                   target_os = "macos",
-                   target_os = "netbsd"))]
-         WNOWAIT;
-         /// Don't wait on children of other threads in this group
--        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-         __WNOTHREAD;
-         /// Wait on all children, regardless of type
--        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-         __WALL;
--        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        #[cfg(any(target_os = "android", target_os = "linux", target_os = "redox"))]
-         __WCLONE;
-     }
- );
-@@ -104,8 +108,7 @@ impl WaitStatus {
-     pub fn pid(&self) -> Option<Pid> {
-         use self::WaitStatus::*;
-         match *self {
--            Exited(p, _)  | Signaled(p, _, _) |
--                Stopped(p, _) | Continued(p) => Some(p),
-+            Exited(p, _) | Signaled(p, _, _) | Stopped(p, _) | Continued(p) => Some(p),
-             StillAlive => None,
-             #[cfg(any(target_os = "android", target_os = "linux"))]
-             PtraceEvent(p, _, _) | PtraceSyscall(p) => Some(p),
-@@ -114,31 +117,31 @@ impl WaitStatus {
- }
- 
- fn exited(status: i32) -> bool {
--    unsafe { libc::WIFEXITED(status) }
-+    libc::WIFEXITED(status)
- }
- 
- fn exit_status(status: i32) -> i32 {
--    unsafe { libc::WEXITSTATUS(status) }
-+    libc::WEXITSTATUS(status)
- }
- 
- fn signaled(status: i32) -> bool {
--    unsafe { libc::WIFSIGNALED(status) }
-+    libc::WIFSIGNALED(status)
- }
- 
- fn term_signal(status: i32) -> Result<Signal> {
--    Signal::from_c_int(unsafe { libc::WTERMSIG(status) })
-+    Signal::try_from(libc::WTERMSIG(status))
- }
- 
- fn dumped_core(status: i32) -> bool {
--    unsafe { libc::WCOREDUMP(status) }
-+    libc::WCOREDUMP(status)
- }
- 
- fn stopped(status: i32) -> bool {
--    unsafe { libc::WIFSTOPPED(status) }
-+    libc::WIFSTOPPED(status)
- }
- 
- fn stop_signal(status: i32) -> Result<Signal> {
--    Signal::from_c_int(unsafe { libc::WSTOPSIG(status) })
-+    Signal::try_from(libc::WSTOPSIG(status))
- }
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -147,7 +150,7 @@ fn syscall_stop(status: i32) -> bool {
-     // of delivering SIGTRAP | 0x80 as the signal number for syscall
-     // stops. This allows easily distinguishing syscall stops from
-     // genuine SIGTRAP signals.
--    unsafe { libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80 }
-+    libc::WSTOPSIG(status) == libc::SIGTRAP | 0x80
- }
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
-@@ -156,7 +159,7 @@ fn stop_additional(status: i32) -> c_int {
- }
- 
- fn continued(status: i32) -> bool {
--    unsafe { libc::WIFCONTINUED(status) }
-+    libc::WIFCONTINUED(status)
- }
- 
- impl WaitStatus {
-@@ -222,7 +225,7 @@ pub fn waitpid<P: Into<Option<Pid>>>(pid: P, options: Option<WaitPidFlag>) -> Re
- 
-     let res = unsafe {
-         libc::waitpid(
--            pid.into().unwrap_or(Pid::from_raw(-1)).into(),
-+            pid.into().unwrap_or_else(|| Pid::from_raw(-1)).into(),
-             &mut status as *mut c_int,
-             option_bits,
-         )
-diff --git a/third_party/rust/nix/src/time.rs b/third_party/rust/nix/src/time.rs
-new file mode 100644
-index 0000000000000..e6c3f8ded5a52
---- /dev/null
-+++ b/third_party/rust/nix/src/time.rs
-@@ -0,0 +1,260 @@
-+use crate::sys::time::TimeSpec;
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+))]
-+use crate::{unistd::Pid, Error};
-+use crate::{Errno, Result};
-+use libc::{self, clockid_t};
-+use std::mem::MaybeUninit;
-+
-+/// Clock identifier
-+///
-+/// Newtype pattern around `clockid_t` (which is just alias). It pervents bugs caused by
-+/// accidentally passing wrong value.
-+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
-+pub struct ClockId(clockid_t);
-+
-+impl ClockId {
-+    /// Creates `ClockId` from raw `clockid_t`
-+    pub fn from_raw(clk_id: clockid_t) -> Self {
-+        ClockId(clk_id)
-+    }
-+
-+    /// Returns `ClockId` of a `pid` CPU-time clock
-+    #[cfg(any(
-+        target_os = "freebsd",
-+        target_os = "dragonfly",
-+        target_os = "linux",
-+        target_os = "android",
-+        target_os = "emscripten",
-+    ))]
-+    pub fn pid_cpu_clock_id(pid: Pid) -> Result<Self> {
-+        clock_getcpuclockid(pid)
-+    }
-+
-+    /// Returns resolution of the clock id
-+    #[cfg(not(target_os = "redox"))]
-+    pub fn res(self) -> Result<TimeSpec> {
-+        clock_getres(self)
-+    }
-+
-+    /// Returns the current time on the clock id
-+    pub fn now(self) -> Result<TimeSpec> {
-+        clock_gettime(self)
-+    }
-+
-+    /// Sets time to `timespec` on the clock id
-+    #[cfg(not(any(
-+        target_os = "macos",
-+        target_os = "ios",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlibc")),
-+            any(target_os = "redox", target_os = "hermit",),
-+        ),
-+    )))]
-+    pub fn set_time(self, timespec: TimeSpec) -> Result<()> {
-+        clock_settime(self, timespec)
-+    }
-+
-+    /// Gets the raw `clockid_t` wrapped by `self`
-+    pub fn as_raw(self) -> clockid_t {
-+        self.0
-+    }
-+
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten"),
-+        )
-+    ))]
-+    pub const CLOCK_BOOTTIME: ClockId = ClockId(libc::CLOCK_BOOTTIME);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_BOOTTIME_ALARM: ClockId = ClockId(libc::CLOCK_BOOTTIME_ALARM);
-+    pub const CLOCK_MONOTONIC: ClockId = ClockId(libc::CLOCK_MONOTONIC);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_MONOTONIC_COARSE: ClockId = ClockId(libc::CLOCK_MONOTONIC_COARSE);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_MONOTONIC_FAST: ClockId = ClockId(libc::CLOCK_MONOTONIC_FAST);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_MONOTONIC_PRECISE: ClockId = ClockId(libc::CLOCK_MONOTONIC_PRECISE);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_MONOTONIC_RAW: ClockId = ClockId(libc::CLOCK_MONOTONIC_RAW);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        target_env = "uclibc",
-+        target_os = "macos",
-+        target_os = "ios",
-+        target_os = "freebsd",
-+        target_os = "dragonfly",
-+        all(
-+            not(target_env = "newlib"),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_PROCESS_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_PROCESS_CPUTIME_ID);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_PROF: ClockId = ClockId(libc::CLOCK_PROF);
-+    pub const CLOCK_REALTIME: ClockId = ClockId(libc::CLOCK_REALTIME);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_REALTIME_ALARM: ClockId = ClockId(libc::CLOCK_REALTIME_ALARM);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten")
-+        )
-+    ))]
-+    pub const CLOCK_REALTIME_COARSE: ClockId = ClockId(libc::CLOCK_REALTIME_COARSE);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_REALTIME_FAST: ClockId = ClockId(libc::CLOCK_REALTIME_FAST);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_REALTIME_PRECISE: ClockId = ClockId(libc::CLOCK_REALTIME_PRECISE);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_SECOND: ClockId = ClockId(libc::CLOCK_SECOND);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(
-+                target_os = "emscripten",
-+                all(target_os = "linux", target_env = "musl")
-+            )
-+        )
-+    ))]
-+    pub const CLOCK_SGI_CYCLE: ClockId = ClockId(libc::CLOCK_SGI_CYCLE);
-+    #[cfg(any(
-+        target_os = "fuchsia",
-+        all(
-+            not(any(target_env = "uclibc", target_env = "newlib")),
-+            any(
-+                target_os = "emscripten",
-+                all(target_os = "linux", target_env = "musl")
-+            )
-+        )
-+    ))]
-+    pub const CLOCK_TAI: ClockId = ClockId(libc::CLOCK_TAI);
-+    #[cfg(any(
-+        target_env = "uclibc",
-+        target_os = "fuchsia",
-+        target_os = "ios",
-+        target_os = "macos",
-+        target_os = "freebsd",
-+        target_os = "dragonfly",
-+        all(
-+            not(target_env = "newlib"),
-+            any(target_os = "linux", target_os = "android", target_os = "emscripten",),
-+        ),
-+    ))]
-+    pub const CLOCK_THREAD_CPUTIME_ID: ClockId = ClockId(libc::CLOCK_THREAD_CPUTIME_ID);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_UPTIME: ClockId = ClockId(libc::CLOCK_UPTIME);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_UPTIME_FAST: ClockId = ClockId(libc::CLOCK_UPTIME_FAST);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    pub const CLOCK_UPTIME_PRECISE: ClockId = ClockId(libc::CLOCK_UPTIME_PRECISE);
-+    #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+    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_t> for ClockId {
-+    fn from(clk_id: clockid_t) -> Self {
-+        ClockId::from_raw(clk_id)
-+    }
-+}
-+
-+impl std::fmt::Display for ClockId {
-+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-+        std::fmt::Display::fmt(&self.0, f)
-+    }
-+}
-+
-+/// Get the resolution of the specified clock, (see
-+/// [clock_getres(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_getres.html)).
-+#[cfg(not(target_os = "redox"))]
-+pub fn clock_getres(clock_id: ClockId) -> Result<TimeSpec> {
-+    let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
-+    let ret = unsafe { libc::clock_getres(clock_id.as_raw(), c_time.as_mut_ptr()) };
-+    Errno::result(ret)?;
-+    let res = unsafe { c_time.assume_init() };
-+    Ok(TimeSpec::from(res))
-+}
-+
-+/// Get the time of the specified clock, (see
-+/// [clock_gettime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_gettime.html)).
-+pub fn clock_gettime(clock_id: ClockId) -> Result<TimeSpec> {
-+    let mut c_time: MaybeUninit<libc::timespec> = MaybeUninit::uninit();
-+    let ret = unsafe { libc::clock_gettime(clock_id.as_raw(), c_time.as_mut_ptr()) };
-+    Errno::result(ret)?;
-+    let res = unsafe { c_time.assume_init() };
-+    Ok(TimeSpec::from(res))
-+}
-+
-+/// Set the time of the specified clock, (see
-+/// [clock_settime(2)](https://pubs.opengroup.org/onlinepubs/7908799/xsh/clock_settime.html)).
-+#[cfg(not(any(
-+    target_os = "macos",
-+    target_os = "ios",
-+    all(
-+        not(any(target_env = "uclibc", target_env = "newlibc")),
-+        any(target_os = "redox", target_os = "hermit",),
-+    ),
-+)))]
-+pub fn clock_settime(clock_id: ClockId, timespec: TimeSpec) -> Result<()> {
-+    let ret = unsafe { libc::clock_settime(clock_id.as_raw(), timespec.as_ref()) };
-+    Errno::result(ret).map(drop)
-+}
-+
-+/// Get the clock id of the specified process id, (see
-+/// [clock_getcpuclockid(3)](https://pubs.opengroup.org/onlinepubs/009695399/functions/clock_getcpuclockid.html)).
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+))]
-+pub fn clock_getcpuclockid(pid: Pid) -> Result<ClockId> {
-+    let mut clk_id: MaybeUninit<libc::clockid_t> = MaybeUninit::uninit();
-+    let ret = unsafe { libc::clock_getcpuclockid(pid.into(), clk_id.as_mut_ptr()) };
-+    if ret == 0 {
-+        let res = unsafe { clk_id.assume_init() };
-+        Ok(ClockId::from(res))
-+    } else {
-+        Err(Error::Sys(Errno::from_i32(ret)))
-+    }
-+}
-diff --git a/third_party/rust/nix/src/ucontext.rs b/third_party/rust/nix/src/ucontext.rs
-index 5e10e7d1f8934..a5b8cc75cb330 100644
---- a/third_party/rust/nix/src/ucontext.rs
-+++ b/third_party/rust/nix/src/ucontext.rs
-@@ -1,10 +1,11 @@
- use libc;
- #[cfg(not(target_env = "musl"))]
--use Result;
-+use crate::Result;
-+#[cfg(not(target_env = "musl"))]
-+use crate::errno::Errno;
- #[cfg(not(target_env = "musl"))]
--use errno::Errno;
- use std::mem;
--use sys::signal::SigSet;
-+use crate::sys::signal::SigSet;
- 
- #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
- pub struct UContext {
-@@ -14,11 +15,11 @@ pub struct UContext {
- impl UContext {
-     #[cfg(not(target_env = "musl"))]
-     pub fn get() -> Result<UContext> {
--        let mut context: libc::ucontext_t = unsafe { mem::uninitialized() };
--        let res = unsafe {
--            libc::getcontext(&mut context as *mut libc::ucontext_t)
--        };
--        Errno::result(res).map(|_| UContext { context: context })
-+        let mut context = mem::MaybeUninit::<libc::ucontext_t>::uninit();
-+        let res = unsafe { libc::getcontext(context.as_mut_ptr()) };
-+        Errno::result(res).map(|_| unsafe {
-+            UContext { context: context.assume_init()}
-+        })
-     }
- 
-     #[cfg(not(target_env = "musl"))]
-@@ -30,10 +31,14 @@ impl UContext {
-     }
- 
-     pub fn sigmask_mut(&mut self) -> &mut SigSet {
--        unsafe { mem::transmute(&mut self.context.uc_sigmask) }
-+        unsafe {
-+            &mut *(&mut self.context.uc_sigmask as *mut libc::sigset_t as *mut SigSet)
-+        }
-     }
- 
-     pub fn sigmask(&self) -> &SigSet {
--        unsafe { mem::transmute(&self.context.uc_sigmask) }
-+        unsafe {
-+            &*(&self.context.uc_sigmask as *const libc::sigset_t as *const SigSet)
-+        }
-     }
- }
-diff --git a/third_party/rust/nix/src/unistd.rs b/third_party/rust/nix/src/unistd.rs
-index f422f09198655..59cb1ed8b5901 100644
---- a/third_party/rust/nix/src/unistd.rs
-+++ b/third_party/rust/nix/src/unistd.rs
-@@ -1,18 +1,26 @@
- //! Safe wrappers around functions found in libc "unistd.h" header
- 
--use errno::{self, Errno};
--use {Error, Result, NixPath};
--use fcntl::{AtFlags, at_rawfd, fcntl, FdFlag, OFlag};
--use fcntl::FcntlArg::F_SETFD;
-+#[cfg(not(target_os = "redox"))]
-+use cfg_if::cfg_if;
-+use crate::errno::{self, Errno};
-+use crate::{Error, Result, NixPath};
-+#[cfg(not(target_os = "redox"))]
-+use crate::fcntl::{AtFlags, at_rawfd};
-+use crate::fcntl::{FdFlag, OFlag, fcntl};
-+use crate::fcntl::FcntlArg::F_SETFD;
- use libc::{self, c_char, c_void, c_int, c_long, c_uint, size_t, pid_t, off_t,
--           uid_t, gid_t, mode_t};
-+           uid_t, gid_t, mode_t, PATH_MAX};
- use std::{fmt, mem, ptr};
--use std::ffi::{CString, CStr, OsString, OsStr};
--use std::os::unix::ffi::{OsStringExt, OsStrExt};
-+use std::convert::Infallible;
-+use std::ffi::{CStr, OsString};
-+#[cfg(not(target_os = "redox"))]
-+use std::ffi::{CString, OsStr};
-+use std::os::unix::ffi::OsStringExt;
-+#[cfg(not(target_os = "redox"))]
-+use std::os::unix::ffi::OsStrExt;
- use std::os::unix::io::RawFd;
- use std::path::PathBuf;
--use void::Void;
--use sys::stat::Mode;
-+use crate::sys::stat::Mode;
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- pub use self::pivot_root::*;
-@@ -45,12 +53,12 @@ impl Uid {
-     }
- 
-     /// Returns true if the `Uid` represents privileged user - root. (If it equals zero.)
--    pub fn is_root(&self) -> bool {
--        *self == ROOT
-+    pub fn is_root(self) -> bool {
-+        self == ROOT
-     }
- 
-     /// Get the raw `uid_t` wrapped by `self`.
--    pub fn as_raw(&self) -> uid_t {
-+    pub fn as_raw(self) -> uid_t {
-         self.0
-     }
- }
-@@ -88,13 +96,13 @@ impl Gid {
-         getgid()
-     }
- 
--    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getgid`.
-+    /// Returns effective Gid of calling process. This is practically a more Rusty alias for `getegid`.
-     pub fn effective() -> Self {
-         getegid()
-     }
- 
-     /// Get the raw `gid_t` wrapped by `self`.
--    pub fn as_raw(&self) -> gid_t {
-+    pub fn as_raw(self) -> gid_t {
-         self.0
-     }
- }
-@@ -115,7 +123,7 @@ impl fmt::Display for Gid {
- ///
- /// Newtype pattern around `pid_t` (which is just alias). It prevents bugs caused by accidentally
- /// passing wrong value.
--#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
- pub struct Pid(pid_t);
- 
- impl Pid {
-@@ -135,7 +143,7 @@ impl Pid {
-     }
- 
-     /// Get the raw `pid_t` wrapped by `self`.
--    pub fn as_raw(&self) -> pid_t {
-+    pub fn as_raw(self) -> pid_t {
-         self.0
-     }
- }
-@@ -168,8 +176,8 @@ impl ForkResult {
- 
-     /// Return `true` if this is the child process of the `fork()`
-     #[inline]
--    pub fn is_child(&self) -> bool {
--        match *self {
-+    pub fn is_child(self) -> bool {
-+        match self {
-             ForkResult::Child => true,
-             _ => false
-         }
-@@ -177,7 +185,7 @@ impl ForkResult {
- 
-     /// Returns `true` if this is the parent process of the `fork()`
-     #[inline]
--    pub fn is_parent(&self) -> bool {
-+    pub fn is_parent(self) -> bool {
-         !self.is_child()
-     }
- }
-@@ -192,7 +200,7 @@ impl ForkResult {
- /// ```no_run
- /// use nix::unistd::{fork, ForkResult};
- ///
--/// match fork() {
-+/// match unsafe{fork()} {
- ///    Ok(ForkResult::Parent { child, .. }) => {
- ///        println!("Continuing execution in parent process, new child has pid: {}", child);
- ///    }
-@@ -222,9 +230,9 @@ impl ForkResult {
- ///
- /// [async-signal-safe]: http://man7.org/linux/man-pages/man7/signal-safety.7.html
- #[inline]
--pub fn fork() -> Result<ForkResult> {
-+pub unsafe fn fork() -> Result<ForkResult> {
-     use self::ForkResult::*;
--    let res = unsafe { libc::fork() };
-+    let res = libc::fork();
- 
-     Errno::result(res).map(|res| match res {
-         0 => Child,
-@@ -285,6 +293,7 @@ pub fn setsid() -> Result<Pid> {
- /// 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.
- #[inline]
-+#[cfg(not(target_os = "redox"))]
- pub fn getsid(pid: Option<Pid>) -> Result<Pid> {
-     let res = unsafe { libc::getsid(pid.unwrap_or(Pid(0)).into()) };
-     Errno::result(res).map(Pid)
-@@ -417,6 +426,7 @@ pub fn chdir<P: ?Sized + NixPath>(path: &P) -> Result<()> {
- /// This function may fail in a number of different scenarios.  See the man
- /// pages for additional details on possible failure cases.
- #[inline]
-+#[cfg(not(target_os = "fuchsia"))]
- pub fn fchdir(dirfd: RawFd) -> Result<()> {
-     let res = unsafe { libc::fchdir(dirfd) };
- 
-@@ -436,9 +446,6 @@ pub fn fchdir(dirfd: RawFd) -> Result<()> {
- /// # Example
- ///
- /// ```rust
--/// extern crate tempfile;
--/// extern crate nix;
--///
- /// use nix::unistd;
- /// use nix::sys::stat;
- /// use tempfile::tempdir;
-@@ -479,9 +486,6 @@ pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
- /// # Example
- ///
- /// ```rust
--/// extern crate tempfile;
--/// extern crate nix;
--///
- /// use nix::unistd;
- /// use nix::sys::stat;
- /// use tempfile::tempdir;
-@@ -498,6 +502,7 @@ pub fn mkdir<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
- /// }
- /// ```
- #[inline]
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support fifo yet
- pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
-     let res = path.with_nix_path(|cstr| {
-         unsafe { libc::mkfifo(cstr.as_ptr(), mode.bits() as mode_t) }
-@@ -506,6 +511,28 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
-     Errno::result(res).map(drop)
- }
- 
-+/// Creates new fifo special file (named pipe) with path `path` and access rights `mode`.
-+///
-+/// If `dirfd` has a value, then `path` is relative to directory associated with the file descriptor.
-+///
-+/// If `dirfd` is `None`, then `path` is relative to the current working directory.
-+///
-+/// # References
-+///
-+/// [mkfifoat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/mkfifoat.html).
-+// mkfifoat is not implemented in OSX or android
-+#[inline]
-+#[cfg(not(any(
-+    target_os = "macos", target_os = "ios",
-+    target_os = "android", target_os = "redox")))]
-+pub fn mkfifoat<P: ?Sized + NixPath>(dirfd: Option<RawFd>, path: &P, mode: Mode) -> Result<()> {
-+    let res = path.with_nix_path(|cstr| unsafe {
-+        libc::mkfifoat(at_rawfd(dirfd), cstr.as_ptr(), mode.bits() as mode_t)
-+    })?;
-+
-+    Errno::result(res).map(drop)
-+}
-+
- /// Creates a symbolic link at `path2` which points to `path1`.
- ///
- /// If `dirfd` has a value, then `path2` is relative to directory associated
-@@ -515,6 +542,7 @@ pub fn mkfifo<P: ?Sized + NixPath>(path: &P, mode: Mode) -> Result<()> {
- /// directory. This is identical to `libc::symlink(path1, path2)`.
- ///
- /// See also [symlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/symlinkat.html).
-+#[cfg(not(target_os = "redox"))]
- pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-     path1: &P1,
-     dirfd: Option<RawFd>,
-@@ -534,6 +562,21 @@ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-     Errno::result(res).map(drop)
- }
- 
-+// Double the buffer capacity up to limit. In case it already has
-+// reached the limit, return Errno::ERANGE.
-+fn reserve_double_buffer_size<T>(buf: &mut Vec<T>, limit: usize) -> Result<()> {
-+    use std::cmp::min;
-+
-+    if buf.capacity() >= limit {
-+        return Err(Error::Sys(Errno::ERANGE))
-+    }
-+
-+    let capacity = min(buf.capacity() * 2, limit);
-+    buf.reserve(capacity);
-+
-+    Ok(())
-+}
-+
- /// Returns the current directory as a `PathBuf`
- ///
- /// Err is returned if the current user doesn't have the permission to read or search a component
-@@ -542,8 +585,6 @@ pub fn symlinkat<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
- /// # Example
- ///
- /// ```rust
--/// extern crate nix;
--///
- /// use nix::unistd;
- ///
- /// fn main() {
-@@ -576,11 +617,8 @@ pub fn getcwd() -> Result<PathBuf> {
-                 }
-             }
- 
--            // Trigger the internal buffer resizing logic of `Vec` by requiring
--            // more space than the current capacity.
--            let cap = buf.capacity();
--            buf.set_len(cap);
--            buf.reserve(1);
-+            // Trigger the internal buffer resizing logic.
-+            reserve_double_buffer_size(&mut buf, PATH_MAX as usize)?;
-         }
-     }
- }
-@@ -590,8 +628,10 @@ fn chown_raw_ids(owner: Option<Uid>, group: Option<Gid>) -> (libc::uid_t, libc::
-     // 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
-     // around to get -1.
--    let uid = owner.map(Into::into).unwrap_or((0 as uid_t).wrapping_sub(1));
--    let gid = group.map(Into::into).unwrap_or((0 as gid_t).wrapping_sub(1));
-+    let uid = owner.map(Into::into)
-+        .unwrap_or_else(|| (0 as uid_t).wrapping_sub(1));
-+    let gid = group.map(Into::into)
-+        .unwrap_or_else(|| (0 as gid_t).wrapping_sub(1));
-     (uid, gid)
- }
- 
-@@ -612,6 +652,20 @@ pub fn chown<P: ?Sized + NixPath>(path: &P, owner: Option<Uid>, group: Option<Gi
-     Errno::result(res).map(drop)
- }
- 
-+/// Change the ownership of the file referred to by the open file descriptor `fd` to be owned by
-+/// the specified `owner` (user) and `group` (see
-+/// [fchown(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/fchown.html)).
-+///
-+/// The owner/group for the provided file will not be modified if `None` is
-+/// provided for that argument.  Ownership change will be attempted for the path
-+/// only if `Some` owner/group is provided.
-+#[inline]
-+pub fn fchown(fd: RawFd, owner: Option<Uid>, group: Option<Gid>) -> Result<()> {
-+    let (uid, gid) = chown_raw_ids(owner, group);
-+    let res = unsafe { libc::fchown(fd, uid, gid) };
-+    Errno::result(res).map(drop)
-+}
-+
- /// Flags for `fchownat` function.
- #[derive(Clone, Copy, Debug)]
- pub enum FchownatFlags {
-@@ -640,6 +694,7 @@ pub enum FchownatFlags {
- /// # References
- ///
- /// [fchownat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fchownat.html).
-+#[cfg(not(target_os = "redox"))]
- pub fn fchownat<P: ?Sized + NixPath>(
-     dirfd: Option<RawFd>,
-     path: &P,
-@@ -661,10 +716,9 @@ pub fn fchownat<P: ?Sized + NixPath>(
-     Errno::result(res).map(drop)
- }
- 
--fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
--    let mut args_p: Vec<*const c_char> = args.iter().map(|s| s.as_ptr()).collect();
--    args_p.push(ptr::null());
--    args_p
-+fn to_exec_array<S: AsRef<CStr>>(args: &[S]) -> Vec<*const c_char> {
-+    use std::iter::once;
-+    args.iter().map(|s| s.as_ref().as_ptr()).chain(once(ptr::null())).collect()
- }
- 
- /// Replace the current process image with a new one (see
-@@ -674,7 +728,7 @@ fn to_exec_array(args: &[CString]) -> Vec<*const c_char> {
- /// performs the same action but does not allow for customization of the
- /// environment for the new process.
- #[inline]
--pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
-+pub fn execv<S: AsRef<CStr>>(path: &CStr, argv: &[S]) -> Result<Infallible> {
-     let args_p = to_exec_array(argv);
- 
-     unsafe {
-@@ -698,7 +752,7 @@ pub fn execv(path: &CString, argv: &[CString]) -> Result<Void> {
- /// in the `args` list is an argument to the new process. Each element in the
- /// `env` list should be a string in the form "key=value".
- #[inline]
--pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
-+pub fn execve<SA: AsRef<CStr>, SE: AsRef<CStr>>(path: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
-     let args_p = to_exec_array(args);
-     let env_p = to_exec_array(env);
- 
-@@ -719,7 +773,7 @@ pub fn execve(path: &CString, args: &[CString], env: &[CString]) -> Result<Void>
- /// would not work if "bash" was specified for the path argument, but `execvp`
- /// would assuming that a bash executable was on the system `PATH`.
- #[inline]
--pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
-+pub fn execvp<S: AsRef<CStr>>(filename: &CStr, args: &[S]) -> Result<Infallible> {
-     let args_p = to_exec_array(args);
- 
-     unsafe {
-@@ -739,7 +793,7 @@ pub fn execvp(filename: &CString, args: &[CString]) -> Result<Void> {
- #[cfg(any(target_os = "haiku",
-           target_os = "linux",
-           target_os = "openbsd"))]
--pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<Void> {
-+pub fn execvpe<SA: AsRef<CStr>, SE: AsRef<CStr>>(filename: &CStr, args: &[SA], env: &[SE]) -> Result<Infallible> {
-     let args_p = to_exec_array(args);
-     let env_p = to_exec_array(env);
- 
-@@ -767,7 +821,7 @@ pub fn execvpe(filename: &CString, args: &[CString], env: &[CString]) -> Result<
-           target_os = "linux",
-           target_os = "freebsd"))]
- #[inline]
--pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
-+pub fn fexecve<SA: AsRef<CStr> ,SE: AsRef<CStr>>(fd: RawFd, args: &[SA], env: &[SE]) -> Result<Infallible> {
-     let args_p = to_exec_array(args);
-     let env_p = to_exec_array(env);
- 
-@@ -790,8 +844,8 @@ pub fn fexecve(fd: RawFd, args: &[CString], env: &[CString]) -> Result<Void> {
- /// is referenced as a file descriptor to the base directory plus a path.
- #[cfg(any(target_os = "android", target_os = "linux"))]
- #[inline]
--pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
--                env: &[CString], flags: super::fcntl::AtFlags) -> Result<Void> {
-+pub fn execveat<SA: AsRef<CStr>,SE: AsRef<CStr>>(dirfd: RawFd, pathname: &CStr, args: &[SA],
-+                env: &[SE], flags: super::fcntl::AtFlags) -> Result<Infallible> {
-     let args_p = to_exec_array(args);
-     let env_p = to_exec_array(env);
- 
-@@ -828,11 +882,12 @@ pub fn execveat(dirfd: RawFd, pathname: &CString, args: &[CString],
- ///   descriptors will remain identical after daemonizing.
- /// * `noclose = false`: The process' stdin, stdout, and stderr will point to
- ///   `/dev/null` after daemonizing.
--#[cfg_attr(any(target_os = "macos", target_os = "ios"), deprecated(
--    since="0.14.0",
--    note="Deprecated in MacOSX 10.5"
--))]
--#[cfg_attr(any(target_os = "macos", target_os = "ios"), allow(deprecated))]
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "netbsd",
-+          target_os = "openbsd"))]
- pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
-     let res = unsafe { libc::daemon(nochdir as c_int, noclose as c_int) };
-     Errno::result(res).map(drop)
-@@ -845,6 +900,7 @@ pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
- /// On some systems, the host name is limited to as few as 64 bytes.  An error
- /// will be return if the name is not valid or the current process does not have
- /// permissions to update the host name.
-+#[cfg(not(target_os = "redox"))]
- pub fn sethostname<S: AsRef<OsStr>>(name: S) -> Result<()> {
-     // Handle some differences in type of the len arg across platforms.
-     cfg_if! {
-@@ -906,9 +962,6 @@ pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
- /// # Examples
- ///
- /// ```no_run
--/// extern crate tempfile;
--/// extern crate nix;
--///
- /// use std::os::unix::io::AsRawFd;
- /// use nix::unistd::close;
- ///
-@@ -919,9 +972,6 @@ pub fn gethostname(buffer: &mut [u8]) -> Result<&CStr> {
- /// ```
- ///
- /// ```rust
--/// extern crate tempfile;
--/// extern crate nix;
--///
- /// use std::os::unix::io::IntoRawFd;
- /// use nix::unistd::close;
- ///
-@@ -969,20 +1019,14 @@ pub enum Whence {
-     /// 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",
--          all(target_os = "linux", not(any(target_env = "musl",
--                                           target_arch = "mips",
--                                           target_arch = "mips64")))))]
-+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-     SeekData = libc::SEEK_DATA,
-     /// Specify an offset relative to the next hole in the file greater than
-     /// or equal to offset. If offset points into the middle of a hole, then
-     /// the file offset should be set to offset. If there is no hole past offset,
-     /// then the file offset should be adjusted to the end of the file (i.e., there
-     /// is an implicit hole at the end of any file).
--    #[cfg(any(target_os = "dragonfly", target_os = "freebsd",
--          all(target_os = "linux", not(any(target_env = "musl",
--                                           target_arch = "mips",
--                                           target_arch = "mips64")))))]
-+    #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux"))]
-     SeekHole = libc::SEEK_HOLE
- }
- 
-@@ -1007,13 +1051,13 @@ pub fn lseek64(fd: RawFd, offset: libc::off64_t, whence: Whence) -> Result<libc:
- /// See also [pipe(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pipe.html)
- pub fn pipe() -> Result<(RawFd, RawFd)> {
-     unsafe {
--        let mut fds: [c_int; 2] = mem::uninitialized();
-+        let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
- 
--        let res = libc::pipe(fds.as_mut_ptr());
-+        let res = libc::pipe(fds.as_mut_ptr() as *mut c_int);
- 
-         Errno::result(res)?;
- 
--        Ok((fds[0], fds[1]))
-+        Ok((fds.assume_init()[0], fds.assume_init()[1]))
-     }
- }
- 
-@@ -1022,7 +1066,9 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
- /// 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)
-@@ -1031,74 +1077,26 @@ pub fn pipe() -> Result<(RawFd, RawFd)> {
-           target_os = "emscripten",
-           target_os = "freebsd",
-           target_os = "linux",
-+          target_os = "redox",
-           target_os = "netbsd",
-           target_os = "openbsd"))]
- pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
--    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
--
--    let res = unsafe { libc::pipe2(fds.as_mut_ptr(), flags.bits()) };
--
--    Errno::result(res)?;
--
--    Ok((fds[0], fds[1]))
--}
-+    let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit();
- 
--/// Like `pipe`, but allows setting certain file descriptor flags.
--///
--/// The following flags are supported, and will be set after the pipe is
--/// created:
--///
--/// `O_CLOEXEC`:    Set the close-on-exec flag for the new file descriptors.
--/// `O_NONBLOCK`:   Set the non-blocking flag for the ends of the pipe.
--#[cfg(any(target_os = "ios", target_os = "macos"))]
--#[deprecated(
--    since="0.10.0",
--    note="pipe2(2) is not actually atomic on these platforms.  Use pipe(2) and fcntl(2) instead"
--)]
--pub fn pipe2(flags: OFlag) -> Result<(RawFd, RawFd)> {
--    let mut fds: [c_int; 2] = unsafe { mem::uninitialized() };
--
--    let res = unsafe { libc::pipe(fds.as_mut_ptr()) };
-+    let res = unsafe {
-+        libc::pipe2(fds.as_mut_ptr() as *mut c_int, flags.bits())
-+    };
- 
-     Errno::result(res)?;
- 
--    pipe2_setflags(fds[0], fds[1], flags)?;
--
--    Ok((fds[0], fds[1]))
--}
--
--#[cfg(any(target_os = "ios", target_os = "macos"))]
--fn pipe2_setflags(fd1: RawFd, fd2: RawFd, flags: OFlag) -> Result<()> {
--    use fcntl::FcntlArg::F_SETFL;
--
--    let mut res = Ok(0);
--
--    if flags.contains(OFlag::O_CLOEXEC) {
--        res = res
--            .and_then(|_| fcntl(fd1, F_SETFD(FdFlag::FD_CLOEXEC)))
--            .and_then(|_| fcntl(fd2, F_SETFD(FdFlag::FD_CLOEXEC)));
--    }
--
--    if flags.contains(OFlag::O_NONBLOCK) {
--        res = res
--            .and_then(|_| fcntl(fd1, F_SETFL(OFlag::O_NONBLOCK)))
--            .and_then(|_| fcntl(fd2, F_SETFL(OFlag::O_NONBLOCK)));
--    }
--
--    match res {
--        Ok(_) => Ok(()),
--        Err(e) => {
--            let _ = close(fd1);
--            let _ = close(fd2);
--            Err(e)
--        }
--    }
-+    unsafe { Ok((fds.assume_init()[0], fds.assume_init()[1])) }
- }
- 
- /// Truncate a file to a specified length
- ///
- /// See also
- /// [truncate(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/truncate.html)
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- pub fn truncate<P: ?Sized + NixPath>(path: &P, len: off_t) -> Result<()> {
-     let res = path.with_nix_path(|cstr| {
-         unsafe {
-@@ -1132,6 +1130,59 @@ pub fn isatty(fd: RawFd) -> Result<bool> {
-     }
- }
- 
-+/// Flags for `linkat` function.
-+#[derive(Clone, Copy, Debug)]
-+pub enum LinkatFlags {
-+    SymlinkFollow,
-+    NoSymlinkFollow,
-+}
-+
-+/// Link one file to another file
-+///
-+/// Creates a new link (directory entry) at `newpath` for the existing file at `oldpath`. In the
-+/// case of a relative `oldpath`, the path is interpreted relative to the directory associated
-+/// with file descriptor `olddirfd` instead of the current working directory and similiarly for
-+/// `newpath` and file descriptor `newdirfd`. In case `flag` is LinkatFlags::SymlinkFollow and
-+/// `oldpath` names a symoblic link, a new link for the target of the symbolic link is created.
-+/// If either `olddirfd` or `newdirfd` is `None`, `AT_FDCWD` is used respectively where `oldpath`
-+/// and/or `newpath` is then interpreted relative to the current working directory of the calling
-+/// 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)
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support symlinks yet
-+pub fn linkat<P: ?Sized + NixPath>(
-+    olddirfd: Option<RawFd>,
-+    oldpath: &P,
-+    newdirfd: Option<RawFd>,
-+    newpath: &P,
-+    flag: LinkatFlags,
-+) -> Result<()> {
-+
-+    let atflag =
-+        match flag {
-+            LinkatFlags::SymlinkFollow => AtFlags::AT_SYMLINK_FOLLOW,
-+            LinkatFlags::NoSymlinkFollow => AtFlags::empty(),
-+        };
-+
-+    let res =
-+        oldpath.with_nix_path(|oldcstr| {
-+            newpath.with_nix_path(|newcstr| {
-+            unsafe {
-+                libc::linkat(
-+                    at_rawfd(olddirfd),
-+                    oldcstr.as_ptr(),
-+                    at_rawfd(newdirfd),
-+                    newcstr.as_ptr(),
-+                    atflag.bits() as libc::c_int
-+                    )
-+                }
-+            })
-+        })??;
-+    Errno::result(res).map(drop)
-+}
-+
-+
- /// Remove a directory entry
- ///
- /// See also [unlink(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlink.html)
-@@ -1161,6 +1212,7 @@ pub enum UnlinkatFlags {
- ///
- /// # References
- /// See also [unlinkat(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/unlinkat.html)
-+#[cfg(not(target_os = "redox"))]
- pub fn unlinkat<P: ?Sized + NixPath>(
-     dirfd: Option<RawFd>,
-     path: &P,
-@@ -1181,6 +1233,7 @@ pub fn unlinkat<P: ?Sized + NixPath>(
- 
- 
- #[inline]
-+#[cfg(not(target_os = "fuchsia"))]
- pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
-     let res = path.with_nix_path(|cstr| {
-         unsafe { libc::chroot(cstr.as_ptr()) }
-@@ -1199,7 +1252,7 @@ pub fn chroot<P: ?Sized + NixPath>(path: &P) -> Result<()> {
-     target_os = "netbsd",
-     target_os = "openbsd"
- ))]
--pub fn sync() -> () {
-+pub fn sync() {
-     unsafe { libc::sync() };
- }
- 
-@@ -1309,6 +1362,28 @@ pub fn setgid(gid: Gid) -> Result<()> {
-     Errno::result(res).map(drop)
- }
- 
-+/// Set the user identity used for filesystem checks per-thread.
-+/// 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)
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn setfsuid(uid: Uid) -> Uid {
-+    let prev_fsuid = unsafe { libc::setfsuid(uid.into()) };
-+    Uid::from_raw(prev_fsuid as uid_t)
-+}
-+
-+/// Set the group identity used for filesystem checks per-thread.
-+/// 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)
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+pub fn setfsgid(gid: Gid) -> Gid {
-+    let prev_fsgid = unsafe { libc::setfsgid(gid.into()) };
-+    Gid::from_raw(prev_fsgid as gid_t)
-+}
-+
- /// Get the list of supplementary group IDs of the calling process.
- ///
- /// [Further reading](http://pubs.opengroup.org/onlinepubs/009695399/functions/getgroups.html)
-@@ -1318,33 +1393,39 @@ pub fn setgid(gid: Gid) -> Result<()> {
- /// with the `opendirectoryd` service.
- #[cfg(not(any(target_os = "ios", target_os = "macos")))]
- pub fn getgroups() -> Result<Vec<Gid>> {
--    // First get the number of groups so we can size our Vec
--    let ret = unsafe { libc::getgroups(0, ptr::null_mut()) };
-+    // First get the maximum number of groups. The value returned
-+    // shall always be greater than or equal to one and less than or
-+    // equal to the value of {NGROUPS_MAX} + 1.
-+    let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
-+        Ok(Some(n)) => (n + 1) as usize,
-+        Ok(None) | Err(_) => <usize>::max_value(),
-+    };
-+
-+    // Next, get the number of groups so we can size our Vec
-+    let ngroups = unsafe { libc::getgroups(0, ptr::null_mut()) };
- 
-     // Now actually get the groups. We try multiple times in case the number of
-     // groups has changed since the first call to getgroups() and the buffer is
-     // now too small.
--    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ret)? as usize);
-+    let mut groups = Vec::<Gid>::with_capacity(Errno::result(ngroups)? as usize);
-     loop {
-         // FIXME: On the platforms we currently support, the `Gid` struct has
-         // the same representation in memory as a bare `gid_t`. This is not
-         // necessarily the case on all Rust platforms, though. See RFC 1785.
--        let ret = unsafe {
-+        let ngroups = unsafe {
-             libc::getgroups(groups.capacity() as c_int, groups.as_mut_ptr() as *mut gid_t)
-         };
- 
--        match Errno::result(ret) {
-+        match Errno::result(ngroups) {
-             Ok(s) => {
-                 unsafe { groups.set_len(s as usize) };
-                 return Ok(groups);
-             },
-             Err(Error::Sys(Errno::EINVAL)) => {
--                // EINVAL indicates that the buffer size was too small. Trigger
--                // the internal buffer resizing logic of `Vec` by requiring
--                // more space than the current capacity.
--                let cap = groups.capacity();
--                unsafe { groups.set_len(cap) };
--                groups.reserve(1);
-+                // EINVAL indicates that the buffer size was too
-+                // small, resize it up to ngroups_max as limit.
-+                reserve_double_buffer_size(&mut groups, ngroups_max)
-+                    .or(Err(Error::Sys(Errno::EINVAL)))?;
-             },
-             Err(e) => return Err(e)
-         }
-@@ -1380,11 +1461,9 @@ pub fn getgroups() -> Result<Vec<Gid>> {
- /// #     Ok(())
- /// # }
- /// #
--/// # fn main() {
--/// #     try_main().unwrap();
--/// # }
-+/// # try_main().unwrap();
- /// ```
--#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
- pub fn setgroups(groups: &[Gid]) -> Result<()> {
-     cfg_if! {
-         if #[cfg(any(target_os = "dragonfly",
-@@ -1428,15 +1507,14 @@ pub fn setgroups(groups: &[Gid]) -> Result<()> {
- /// 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")))]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
- pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
-     let ngroups_max = match sysconf(SysconfVar::NGROUPS_MAX) {
-         Ok(Some(n)) => n as c_int,
-         Ok(None) | Err(_) => <c_int>::max_value(),
-     };
-     use std::cmp::min;
--    let mut ngroups = min(ngroups_max, 8);
--    let mut groups = Vec::<Gid>::with_capacity(ngroups as usize);
-+    let mut groups = Vec::<Gid>::with_capacity(min(ngroups_max, 8) as usize);
-     cfg_if! {
-         if #[cfg(any(target_os = "ios", target_os = "macos"))] {
-             type getgrouplist_group_t = c_int;
-@@ -1446,6 +1524,7 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
-     }
-     let gid: gid_t = group.into();
-     loop {
-+        let mut ngroups = groups.capacity() as i32;
-         let ret = unsafe {
-             libc::getgrouplist(user.as_ptr(),
-                                gid as getgrouplist_group_t,
-@@ -1462,19 +1541,8 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
-             // BSD systems will still fill the groups buffer with as many
-             // groups as possible, but Linux manpages do not mention this
-             // behavior.
--
--            let cap = groups.capacity();
--            if cap >= ngroups_max as usize {
--                // We already have the largest capacity we can, give up
--                return Err(Error::invalid_argument());
--            }
--
--            // Reserve space for at least ngroups
--            groups.reserve(ngroups as usize);
--
--            // Even if the buffer gets resized to bigger than ngroups_max,
--            // don't ever ask for more than ngroups_max groups
--            ngroups = min(ngroups_max, groups.capacity() as c_int);
-+            reserve_double_buffer_size(&mut groups, ngroups_max as usize)
-+                .or_else(|_| Err(Error::invalid_argument()))?;
-         }
-     }
- }
-@@ -1515,11 +1583,9 @@ pub fn getgrouplist(user: &CStr, group: Gid) -> Result<Vec<Gid>> {
- /// #     Ok(())
- /// # }
- /// #
--/// # fn main() {
--/// #     try_main().unwrap();
--/// # }
-+/// # try_main().unwrap();
- /// ```
--#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
- pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
-     cfg_if! {
-         if #[cfg(any(target_os = "ios", target_os = "macos"))] {
-@@ -1538,6 +1604,7 @@ pub fn initgroups(user: &CStr, group: Gid) -> Result<()> {
- ///
- /// See also [pause(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/pause.html).
- #[inline]
-+#[cfg(not(target_os = "redox"))]
- pub fn pause() {
-     unsafe { libc::pause() };
- }
-@@ -1568,7 +1635,8 @@ pub mod alarm {
-     //!
-     //! Scheduling an alarm and waiting for the signal:
-     //!
--    //! ```
-+#![cfg_attr(target_os = "redox", doc = " ```rust,ignore")]
-+#![cfg_attr(not(target_os = "redox"), doc = " ```rust")]
-     //! use std::time::{Duration, Instant};
-     //!
-     //! use nix::unistd::{alarm, pause};
-@@ -1577,14 +1645,23 @@ pub mod alarm {
-     //! // We need to setup an empty signal handler to catch the alarm signal,
-     //! // otherwise the program will be terminated once the signal is delivered.
-     //! extern fn signal_handler(_: nix::libc::c_int) { }
--    //! unsafe { sigaction(Signal::SIGALRM, &SigAction::new(SigHandler::Handler(signal_handler), SaFlags::empty(), SigSet::empty())); }
-+    //! let sa = SigAction::new(
-+    //!     SigHandler::Handler(signal_handler),
-+    //!     SaFlags::empty(),
-+    //!     SigSet::empty()
-+    //! );
-+    //! unsafe {
-+    //!     sigaction(Signal::SIGALRM, &sa);
-+    //! }
-     //!
-     //! // Set an alarm for 1 second from now.
-     //! alarm::set(1);
-     //!
-     //! let start = Instant::now();
-     //! // Pause the process until the alarm signal is received.
--    //! pause();
-+    //! let mut sigset = SigSet::empty();
-+    //! sigset.add(Signal::SIGALRM);
-+    //! sigset.wait();
-     //!
-     //! assert!(start.elapsed() >= Duration::from_secs(1));
-     //! ```
-@@ -1593,8 +1670,6 @@ pub mod alarm {
-     //!
-     //! See also [alarm(2)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/alarm.html).
- 
--    use libc;
--
-     /// Schedule an alarm signal.
-     ///
-     /// This will cause the system to generate a `SIGALRM` signal for the
-@@ -1630,10 +1705,10 @@ pub fn sleep(seconds: c_uint) -> c_uint {
-     unsafe { libc::sleep(seconds) }
- }
- 
-+#[cfg(not(target_os = "redox"))]
- pub mod acct {
--    use libc;
--    use {Result, NixPath};
--    use errno::Errno;
-+    use crate::{Result, NixPath};
-+    use crate::errno::Errno;
-     use std::ptr;
- 
-     /// Enable process accounting
-@@ -1711,7 +1786,7 @@ pub fn mkstemp<P: ?Sized + NixPath>(template: &P) -> Result<(RawFd, PathBuf)> {
- #[repr(i32)]
- pub enum PathconfVar {
-     #[cfg(any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux",
--              target_os = "netbsd", target_os = "openbsd"))]
-+              target_os = "netbsd", target_os = "openbsd", target_os = "redox"))]
-     /// Minimum number of bits needed to represent, as a signed integer value,
-     /// the maximum size of a regular file allowed in the specified directory.
-     FILESIZEBITS = libc::_PC_FILESIZEBITS,
-@@ -1735,11 +1810,11 @@ pub enum PathconfVar {
-     /// 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 = "netbsd", target_os = "openbsd", target_os = "redox"))]
-     /// Symbolic links can be created.
-     POSIX2_SYMLINKS = libc::_PC_2_SYMLINKS,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
-     /// Minimum number of bytes of storage actually allocated for any portion of
-     /// a file.
-     POSIX_ALLOC_SIZE_MIN = libc::_PC_ALLOC_SIZE_MIN,
-@@ -1749,19 +1824,20 @@ pub enum PathconfVar {
-     /// `POSIX_REC_MIN_XFER_SIZE` and `POSIX_REC_MAX_XFER_SIZE` values.
-     POSIX_REC_INCR_XFER_SIZE = libc::_PC_REC_INCR_XFER_SIZE,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
-     /// Maximum recommended file transfer size.
-     POSIX_REC_MAX_XFER_SIZE = libc::_PC_REC_MAX_XFER_SIZE,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
-     /// Minimum recommended file transfer size.
-     POSIX_REC_MIN_XFER_SIZE = libc::_PC_REC_MIN_XFER_SIZE,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
-     ///  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 = "linux", target_os = "netbsd", target_os = "openbsd",
-+              target_os = "redox"))]
-     /// Maximum number of bytes in a symbolic link.
-     SYMLINK_MAX = libc::_PC_SYMLINK_MAX,
-     /// The use of `chown` and `fchown` is restricted to a process with
-@@ -1775,17 +1851,18 @@ pub enum PathconfVar {
-     /// 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 = "linux", target_os = "openbsd", target_os = "redox"))]
-     /// Asynchronous input or output operations may be performed for the
-     /// associated file.
-     _POSIX_ASYNC_IO = libc::_PC_ASYNC_IO,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "openbsd", target_os = "redox"))]
-     /// Prioritized input or output operations may be performed for the
-     /// associated file.
-     _POSIX_PRIO_IO = libc::_PC_PRIO_IO,
-     #[cfg(any(target_os = "android", target_os = "dragonfly", target_os = "freebsd",
--              target_os = "linux", target_os = "netbsd", target_os = "openbsd"))]
-+              target_os = "linux", target_os = "netbsd", target_os = "openbsd",
-+              target_os = "redox"))]
-     /// Synchronized input or output operations may be performed for the
-     /// associated file.
-     _POSIX_SYNC_IO = libc::_PC_SYNC_IO,
-@@ -1886,9 +1963,11 @@ pub fn pathconf<P: ?Sized + NixPath>(path: &P, var: PathconfVar) -> Result<Optio
- pub enum SysconfVar {
-     /// Maximum number of I/O operations in a single list I/O call supported by
-     /// the implementation.
-+    #[cfg(not(target_os = "redox"))]
-     AIO_LISTIO_MAX = libc::_SC_AIO_LISTIO_MAX,
-     /// Maximum number of outstanding asynchronous I/O operations supported by
-     /// the implementation.
-+    #[cfg(not(target_os = "redox"))]
-     AIO_MAX = libc::_SC_AIO_MAX,
-     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-               target_os = "ios", target_os="linux", target_os = "macos",
-@@ -1899,25 +1978,34 @@ pub enum SysconfVar {
-     /// Maximum length of argument to the exec functions including environment data.
-     ARG_MAX = libc::_SC_ARG_MAX,
-     /// Maximum number of functions that may be registered with `atexit`.
-+    #[cfg(not(target_os = "redox"))]
-     ATEXIT_MAX = libc::_SC_ATEXIT_MAX,
-     /// Maximum obase values allowed by the bc utility.
-+    #[cfg(not(target_os = "redox"))]
-     BC_BASE_MAX = libc::_SC_BC_BASE_MAX,
-     /// Maximum number of elements permitted in an array by the bc utility.
-+    #[cfg(not(target_os = "redox"))]
-     BC_DIM_MAX = libc::_SC_BC_DIM_MAX,
-     /// Maximum scale value allowed by the bc utility.
-+    #[cfg(not(target_os = "redox"))]
-     BC_SCALE_MAX = libc::_SC_BC_SCALE_MAX,
-     /// Maximum length of a string constant accepted by the bc utility.
-+    #[cfg(not(target_os = "redox"))]
-     BC_STRING_MAX = libc::_SC_BC_STRING_MAX,
-     /// Maximum number of simultaneous processes per real user ID.
-     CHILD_MAX = libc::_SC_CHILD_MAX,
--    // _SC_CLK_TCK is obsolete
-+    // The number of clock ticks per second.
-+    CLK_TCK = libc::_SC_CLK_TCK,
-     /// Maximum number of weights that can be assigned to an entry of the
-     /// LC_COLLATE order keyword in the locale definition file
-+    #[cfg(not(target_os = "redox"))]
-     COLL_WEIGHTS_MAX = libc::_SC_COLL_WEIGHTS_MAX,
-     /// Maximum number of timer expiration overruns.
-+    #[cfg(not(target_os = "redox"))]
-     DELAYTIMER_MAX = libc::_SC_DELAYTIMER_MAX,
-     /// Maximum number of expressions that can be nested within parentheses by
-     /// 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",
-@@ -1927,23 +2015,29 @@ pub enum SysconfVar {
-     HOST_NAME_MAX = libc::_SC_HOST_NAME_MAX,
-     /// Maximum number of iovec structures that one process has available for
-     /// use with `readv` or `writev`.
-+    #[cfg(not(target_os = "redox"))]
-     IOV_MAX = libc::_SC_IOV_MAX,
-     /// Unless otherwise noted, the maximum length, in bytes, of a utility's
-     /// input line (either standard input or another file), when the utility is
-     /// described as processing text files. The length includes room for the
-     /// trailing <newline>.
-+    #[cfg(not(target_os = "redox"))]
-     LINE_MAX = libc::_SC_LINE_MAX,
-     /// Maximum length of a login name.
-     LOGIN_NAME_MAX = libc::_SC_LOGIN_NAME_MAX,
-     /// Maximum number of simultaneous supplementary group IDs per process.
-     NGROUPS_MAX = libc::_SC_NGROUPS_MAX,
-     /// Initial size of `getgrgid_r` and `getgrnam_r` data buffers
-+    #[cfg(not(target_os = "redox"))]
-     GETGR_R_SIZE_MAX = libc::_SC_GETGR_R_SIZE_MAX,
-     /// Initial size of `getpwuid_r` and `getpwnam_r` data buffers
-+    #[cfg(not(target_os = "redox"))]
-     GETPW_R_SIZE_MAX = libc::_SC_GETPW_R_SIZE_MAX,
-     /// The maximum number of open message queue descriptors a process may hold.
-+    #[cfg(not(target_os = "redox"))]
-     MQ_OPEN_MAX = libc::_SC_MQ_OPEN_MAX,
-     /// The maximum number of message priorities supported by the implementation.
-+    #[cfg(not(target_os = "redox"))]
-     MQ_PRIO_MAX = libc::_SC_MQ_PRIO_MAX,
-     /// A value one greater than the maximum value that the system may assign to
-     /// a newly-created file descriptor.
-@@ -1958,6 +2052,7 @@ pub enum SysconfVar {
-     /// 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",
-@@ -1970,24 +2065,32 @@ pub enum SysconfVar {
-     /// 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"))]
-     /// The implementation supports the IPv6 option.
-     _POSIX_IPV6 = libc::_SC_IPV6,
-     /// The implementation supports job control.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_JOB_CONTROL = libc::_SC_JOB_CONTROL,
-     /// The implementation supports memory mapped Files.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_MAPPED_FILES = libc::_SC_MAPPED_FILES,
-     /// The implementation supports the Process Memory Locking option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_MEMLOCK = libc::_SC_MEMLOCK,
-     /// The implementation supports the Range Memory Locking option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_MEMLOCK_RANGE = libc::_SC_MEMLOCK_RANGE,
-     /// The implementation supports memory protection.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_MEMORY_PROTECTION = libc::_SC_MEMORY_PROTECTION,
-     /// The implementation supports the Message Passing option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_MESSAGE_PASSING = libc::_SC_MESSAGE_PASSING,
-     /// The implementation supports the Monotonic Clock option.
-+    #[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",
-@@ -1995,6 +2098,7 @@ pub enum SysconfVar {
-     /// 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"))]
-@@ -2016,10 +2120,13 @@ pub enum SysconfVar {
-     /// 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.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_SAVED_IDS = libc::_SC_SAVED_IDS,
-     /// The implementation supports semaphores.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_SEMAPHORES = libc::_SC_SEMAPHORES,
-     /// The implementation supports the Shared Memory Objects option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_SHARED_MEMORY_OBJECTS = libc::_SC_SHARED_MEMORY_OBJECTS,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="netbsd",
-@@ -2044,10 +2151,13 @@ pub enum SysconfVar {
-               target_os="openbsd"))]
-     _POSIX_SS_REPL_MAX = libc::_SC_SS_REPL_MAX,
-     /// The implementation supports the Synchronized Input and Output option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_SYNCHRONIZED_IO = libc::_SC_SYNCHRONIZED_IO,
-     /// The implementation supports the Thread Stack Address Attribute option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_ATTR_STACKADDR = libc::_SC_THREAD_ATTR_STACKADDR,
-     /// The implementation supports the Thread Stack Size Attribute option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_ATTR_STACKSIZE = libc::_SC_THREAD_ATTR_STACKSIZE,
-     #[cfg(any(target_os = "ios", target_os="linux", target_os = "macos",
-               target_os="netbsd", target_os="openbsd"))]
-@@ -2055,10 +2165,13 @@ pub enum SysconfVar {
-     _POSIX_THREAD_CPUTIME = libc::_SC_THREAD_CPUTIME,
-     /// The implementation supports the Non-Robust Mutex Priority Inheritance
-     /// option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_PRIO_INHERIT = libc::_SC_THREAD_PRIO_INHERIT,
-     /// The implementation supports the Non-Robust Mutex Priority Protection option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_PRIO_PROTECT = libc::_SC_THREAD_PRIO_PROTECT,
-     /// The implementation supports the Thread Execution Scheduling option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_PRIORITY_SCHEDULING = libc::_SC_THREAD_PRIORITY_SCHEDULING,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="netbsd",
-@@ -2073,18 +2186,21 @@ pub enum SysconfVar {
-     /// The implementation supports the Robust Mutex Priority Protection option.
-     _POSIX_THREAD_ROBUST_PRIO_PROTECT = libc::_SC_THREAD_ROBUST_PRIO_PROTECT,
-     /// The implementation supports thread-safe functions.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREAD_SAFE_FUNCTIONS = libc::_SC_THREAD_SAFE_FUNCTIONS,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="openbsd"))]
-     /// The implementation supports the Thread Sporadic Server option.
-     _POSIX_THREAD_SPORADIC_SERVER = libc::_SC_THREAD_SPORADIC_SERVER,
-     /// The implementation supports threads.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_THREADS = libc::_SC_THREADS,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="openbsd"))]
-     /// The implementation supports timeouts.
-     _POSIX_TIMEOUTS = libc::_SC_TIMEOUTS,
-     /// The implementation supports timers.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX_TIMERS = libc::_SC_TIMERS,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="openbsd"))]
-@@ -2149,17 +2265,23 @@ pub enum SysconfVar {
-     /// using at least 64 bits.
-     _POSIX_V6_LPBIG_OFFBIG = libc::_SC_V6_LPBIG_OFFBIG,
-     /// The implementation supports the C-Language Binding option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_C_BIND = libc::_SC_2_C_BIND,
-     /// The implementation supports the C-Language Development Utilities option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_C_DEV = libc::_SC_2_C_DEV,
-     /// The implementation supports the Terminal Characteristics option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_CHAR_TERM = libc::_SC_2_CHAR_TERM,
-     /// The implementation supports the FORTRAN Development Utilities option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_FORT_DEV = libc::_SC_2_FORT_DEV,
-     /// The implementation supports the FORTRAN Runtime Utilities option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_FORT_RUN = libc::_SC_2_FORT_RUN,
-     /// The implementation supports the creation of locales by the localedef
-     /// utility.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_LOCALEDEF = libc::_SC_2_LOCALEDEF,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="netbsd",
-@@ -2193,26 +2315,34 @@ pub enum SysconfVar {
-     /// The implementation supports the Track Batch Job Request option.
-     _POSIX2_PBS_TRACK = libc::_SC_2_PBS_TRACK,
-     /// The implementation supports the Software Development Utilities option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_SW_DEV = libc::_SC_2_SW_DEV,
-     /// The implementation supports the User Portability Utilities option.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_UPE = libc::_SC_2_UPE,
-     /// Integer value indicating version of the Shell and Utilities volume of
-     /// POSIX.1 to which the implementation conforms.
-+    #[cfg(not(target_os = "redox"))]
-     _POSIX2_VERSION = libc::_SC_2_VERSION,
-     /// The size of a system page in bytes.
-     ///
-     /// POSIX also defines an alias named `PAGESIZE`, but Rust does not allow two
-     /// enum constants to have the same value, so nix omits `PAGESIZE`.
-     PAGE_SIZE = libc::_SC_PAGE_SIZE,
-+    #[cfg(not(target_os = "redox"))]
-     PTHREAD_DESTRUCTOR_ITERATIONS = libc::_SC_THREAD_DESTRUCTOR_ITERATIONS,
-+    #[cfg(not(target_os = "redox"))]
-     PTHREAD_KEYS_MAX = libc::_SC_THREAD_KEYS_MAX,
-+    #[cfg(not(target_os = "redox"))]
-     PTHREAD_STACK_MIN = libc::_SC_THREAD_STACK_MIN,
-+    #[cfg(not(target_os = "redox"))]
-     PTHREAD_THREADS_MAX = libc::_SC_THREAD_THREADS_MAX,
-     RE_DUP_MAX = libc::_SC_RE_DUP_MAX,
-     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-               target_os = "ios", target_os="linux", target_os = "macos",
-               target_os="openbsd"))]
-     RTSIG_MAX = libc::_SC_RTSIG_MAX,
-+    #[cfg(not(target_os = "redox"))]
-     SEM_NSEMS_MAX = libc::_SC_SEM_NSEMS_MAX,
-     #[cfg(any(target_os="android", target_os="dragonfly", target_os="freebsd",
-               target_os = "ios", target_os="linux", target_os = "macos",
-@@ -2227,6 +2357,7 @@ pub enum SysconfVar {
-               target_os="linux", target_os = "macos", target_os="netbsd",
-               target_os="openbsd"))]
-     SYMLOOP_MAX = libc::_SC_SYMLOOP_MAX,
-+    #[cfg(not(target_os = "redox"))]
-     TIMER_MAX = libc::_SC_TIMER_MAX,
-     TTY_NAME_MAX = libc::_SC_TTY_NAME_MAX,
-     TZNAME_MAX = libc::_SC_TZNAME_MAX,
-@@ -2257,6 +2388,7 @@ pub enum SysconfVar {
-     _XOPEN_REALTIME_THREADS = libc::_SC_XOPEN_REALTIME_THREADS,
-     /// The implementation supports the Issue 4, Version 2 Shared Memory Option
-     /// Group.
-+    #[cfg(not(target_os = "redox"))]
-     _XOPEN_SHM = libc::_SC_XOPEN_SHM,
-     #[cfg(any(target_os="dragonfly", target_os="freebsd", target_os = "ios",
-               target_os="linux", target_os = "macos", target_os="openbsd"))]
-@@ -2309,9 +2441,8 @@ pub fn sysconf(var: SysconfVar) -> Result<Option<c_long>> {
- 
- #[cfg(any(target_os = "android", target_os = "linux"))]
- mod pivot_root {
--    use libc;
--    use {Result, NixPath};
--    use errno::Errno;
-+    use crate::{Result, NixPath};
-+    use crate::errno::Errno;
- 
-     pub fn pivot_root<P1: ?Sized + NixPath, P2: ?Sized + NixPath>(
-             new_root: &P1, put_old: &P2) -> Result<()> {
-@@ -2330,9 +2461,8 @@ mod pivot_root {
- #[cfg(any(target_os = "android", target_os = "freebsd",
-           target_os = "linux", target_os = "openbsd"))]
- mod setres {
--    use libc;
--    use Result;
--    use errno::Errno;
-+    use crate::Result;
-+    use crate::errno::Errno;
-     use super::{Uid, Gid};
- 
-     /// Sets the real, effective, and saved uid.
-@@ -2392,3 +2522,308 @@ pub fn access<P: ?Sized + NixPath>(path: &P, amode: AccessFlags) -> Result<()> {
-     })?;
-     Errno::result(res).map(drop)
- }
-+
-+/// Representation of a User, based on `libc::passwd`
-+///
-+/// The reason some fields in this struct are `String` and others are `CString` is because some
-+/// fields are based on the user's locale, which could be non-UTF8, while other fields are
-+/// guaranteed to conform to [`NAME_REGEX`](https://serverfault.com/a/73101/407341), which only
-+/// contains ASCII.
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+#[derive(Debug, Clone, PartialEq)]
-+pub struct User {
-+    /// Username
-+    pub name: String,
-+    /// User password (probably encrypted)
-+    pub passwd: CString,
-+    /// User ID
-+    pub uid: Uid,
-+    /// Group ID
-+    pub gid: Gid,
-+    /// User information
-+    #[cfg(not(target_os = "android"))]
-+    pub gecos: CString,
-+    /// Home directory
-+    pub dir: PathBuf,
-+    /// Path to shell
-+    pub shell: PathBuf,
-+    /// Login class
-+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                  target_os = "linux")))]
-+    pub class: CString,
-+    /// Last password change
-+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                  target_os = "linux")))]
-+    pub change: libc::time_t,
-+    /// Expiration time of account
-+    #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                  target_os = "linux")))]
-+    pub expire: libc::time_t
-+}
-+
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+impl From<&libc::passwd> for User {
-+    fn from(pw: &libc::passwd) -> User {
-+        unsafe {
-+            User {
-+                name: CStr::from_ptr((*pw).pw_name).to_string_lossy().into_owned(),
-+                passwd: CString::new(CStr::from_ptr((*pw).pw_passwd).to_bytes()).unwrap(),
-+                #[cfg(not(target_os = "android"))]
-+                gecos: CString::new(CStr::from_ptr((*pw).pw_gecos).to_bytes()).unwrap(),
-+                dir: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_dir).to_bytes())),
-+                shell: PathBuf::from(OsStr::from_bytes(CStr::from_ptr((*pw).pw_shell).to_bytes())),
-+                uid: Uid::from_raw((*pw).pw_uid),
-+                gid: Gid::from_raw((*pw).pw_gid),
-+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                              target_os = "linux")))]
-+                class: CString::new(CStr::from_ptr((*pw).pw_class).to_bytes()).unwrap(),
-+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                              target_os = "linux")))]
-+                change: (*pw).pw_change,
-+                #[cfg(not(any(target_os = "android", target_os = "fuchsia",
-+                              target_os = "linux")))]
-+                expire: (*pw).pw_expire
-+            }
-+        }
-+    }
-+}
-+
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+impl User {
-+    fn from_anything<F>(f: F) -> Result<Option<Self>>
-+    where
-+        F: Fn(*mut libc::passwd,
-+              *mut libc::c_char,
-+              libc::size_t,
-+              *mut *mut libc::passwd) -> libc::c_int
-+    {
-+        let buflimit = 16384;
-+        let bufsize = match sysconf(SysconfVar::GETPW_R_SIZE_MAX) {
-+            Ok(Some(n)) => n as usize,
-+            Ok(None) | Err(_) => buflimit as usize,
-+        };
-+
-+        let mut cbuf = Vec::with_capacity(bufsize);
-+        let mut pwd = mem::MaybeUninit::<libc::passwd>::uninit();
-+        let mut res = ptr::null_mut();
-+
-+        loop {
-+            let error = f(pwd.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
-+            if error == 0 {
-+                if res.is_null() {
-+                    return Ok(None);
-+                } else {
-+                    let pwd = unsafe { pwd.assume_init() };
-+                    return Ok(Some(User::from(&pwd)));
-+                }
-+            } else if Errno::last() == Errno::ERANGE {
-+                // Trigger the internal buffer resizing logic.
-+                reserve_double_buffer_size(&mut cbuf, buflimit)?;
-+            } else {
-+                return Err(Error::Sys(Errno::last()));
-+            }
-+        }
-+    }
-+
-+    /// Get a user by UID.
-+    ///
-+    /// Internally, this function calls
-+    /// [getpwuid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
-+    ///
-+    /// # Examples
-+    ///
-+    /// ```
-+    /// use nix::unistd::{Uid, User};
-+    /// // Returns an Result<Option<User>>, thus the double unwrap.
-+    /// let res = User::from_uid(Uid::from_raw(0)).unwrap().unwrap();
-+    /// assert!(res.name == "root");
-+    /// ```
-+    pub fn from_uid(uid: Uid) -> Result<Option<Self>> {
-+        User::from_anything(|pwd, cbuf, cap, res| {
-+            unsafe { libc::getpwuid_r(uid.0, pwd, cbuf, cap, res) }
-+        })
-+    }
-+
-+    /// Get a user by name.
-+    ///
-+    /// Internally, this function calls
-+    /// [getpwnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
-+    ///
-+    /// # Examples
-+    ///
-+    /// ```
-+    /// use nix::unistd::User;
-+    /// // Returns an Result<Option<User>>, thus the double unwrap.
-+    /// let res = User::from_name("root").unwrap().unwrap();
-+    /// assert!(res.name == "root");
-+    /// ```
-+    pub fn from_name(name: &str) -> Result<Option<Self>> {
-+        let name = CString::new(name).unwrap();
-+        User::from_anything(|pwd, cbuf, cap, res| {
-+            unsafe { libc::getpwnam_r(name.as_ptr(), pwd, cbuf, cap, res) }
-+        })
-+    }
-+}
-+
-+/// Representation of a Group, based on `libc::group`
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+#[derive(Debug, Clone, PartialEq)]
-+pub struct Group {
-+    /// Group name
-+    pub name: String,
-+    /// Group password
-+    pub passwd: CString,
-+    /// Group ID
-+    pub gid: Gid,
-+    /// List of Group members
-+    pub mem: Vec<String>
-+}
-+
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+impl From<&libc::group> for Group {
-+    fn from(gr: &libc::group) -> Group {
-+        unsafe {
-+            Group {
-+                name: CStr::from_ptr((*gr).gr_name).to_string_lossy().into_owned(),
-+                passwd: CString::new(CStr::from_ptr((*gr).gr_passwd).to_bytes()).unwrap(),
-+                gid: Gid::from_raw((*gr).gr_gid),
-+                mem: Group::members((*gr).gr_mem)
-+            }
-+        }
-+    }
-+}
-+
-+#[cfg(not(target_os = "redox"))] // RedoxFS does not support passwd
-+impl Group {
-+    unsafe fn members(mem: *mut *mut c_char) -> Vec<String> {
-+        let mut ret = Vec::new();
-+
-+        for i in 0.. {
-+            let u = mem.offset(i);
-+            if (*u).is_null() {
-+                break;
-+            } else {
-+                let s = CStr::from_ptr(*u).to_string_lossy().into_owned();
-+                ret.push(s);
-+            }
-+        }
-+
-+        ret
-+    }
-+
-+    fn from_anything<F>(f: F) -> Result<Option<Self>>
-+    where
-+        F: Fn(*mut libc::group,
-+              *mut libc::c_char,
-+              libc::size_t,
-+              *mut *mut libc::group) -> libc::c_int
-+    {
-+        let buflimit = 16384;
-+        let bufsize = match sysconf(SysconfVar::GETGR_R_SIZE_MAX) {
-+            Ok(Some(n)) => n as usize,
-+            Ok(None) | Err(_) => buflimit as usize,
-+        };
-+
-+        let mut cbuf = Vec::with_capacity(bufsize);
-+        let mut grp = mem::MaybeUninit::<libc::group>::uninit();
-+        let mut res = ptr::null_mut();
-+
-+        loop {
-+            let error = f(grp.as_mut_ptr(), cbuf.as_mut_ptr(), cbuf.capacity(), &mut res);
-+            if error == 0 {
-+                if res.is_null() {
-+                    return Ok(None);
-+                } else {
-+                    let grp = unsafe { grp.assume_init() };
-+                    return Ok(Some(Group::from(&grp)));
-+                }
-+            } else if Errno::last() == Errno::ERANGE {
-+                // Trigger the internal buffer resizing logic.
-+                reserve_double_buffer_size(&mut cbuf, buflimit)?;
-+            } else {
-+                return Err(Error::Sys(Errno::last()));
-+            }
-+        }
-+    }
-+
-+    /// Get a group by GID.
-+    ///
-+    /// Internally, this function calls
-+    /// [getgrgid_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
-+    ///
-+    /// # Examples
-+    ///
-+    // Disable this test on all OS except Linux as root group may not exist.
-+    #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
-+    #[cfg_attr(target_os = "linux", doc = " ```")]
-+    /// use nix::unistd::{Gid, Group};
-+    /// // Returns an Result<Option<Group>>, thus the double unwrap.
-+    /// let res = Group::from_gid(Gid::from_raw(0)).unwrap().unwrap();
-+    /// assert!(res.name == "root");
-+    /// ```
-+    pub fn from_gid(gid: Gid) -> Result<Option<Self>> {
-+        Group::from_anything(|grp, cbuf, cap, res| {
-+            unsafe { libc::getgrgid_r(gid.0, grp, cbuf, cap, res) }
-+        })
-+    }
-+
-+    /// Get a group by name.
-+    ///
-+    /// Internally, this function calls
-+    /// [getgrnam_r(3)](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getpwuid_r.html)
-+    ///
-+    /// # Examples
-+    ///
-+    // Disable this test on all OS except Linux as root group may not exist.
-+    #[cfg_attr(not(target_os = "linux"), doc = " ```no_run")]
-+    #[cfg_attr(target_os = "linux", doc = " ```")]
-+    /// use nix::unistd::Group;
-+    /// // Returns an Result<Option<Group>>, thus the double unwrap.
-+    /// let res = Group::from_name("root").unwrap().unwrap();
-+    /// assert!(res.name == "root");
-+    /// ```
-+    pub fn from_name(name: &str) -> Result<Option<Self>> {
-+        let name = CString::new(name).unwrap();
-+        Group::from_anything(|grp, cbuf, cap, res| {
-+            unsafe { libc::getgrnam_r(name.as_ptr(), grp, cbuf, cap, res) }
-+        })
-+    }
-+}
-+
-+/// 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)).
-+#[cfg(not(target_os = "fuchsia"))]
-+pub fn ttyname(fd: RawFd) -> Result<PathBuf> {
-+    const PATH_MAX: usize = libc::PATH_MAX as usize;
-+    let mut buf = vec![0_u8; PATH_MAX];
-+    let c_buf = buf.as_mut_ptr() as *mut libc::c_char;
-+
-+    let ret = unsafe { libc::ttyname_r(fd, c_buf, buf.len()) };
-+    if ret != 0 {
-+        return Err(Error::Sys(Errno::from_i32(ret)));
-+    }
-+
-+    let nul = buf.iter().position(|c| *c == b'\0').unwrap();
-+    buf.truncate(nul);
-+    Ok(OsString::from_vec(buf).into())
-+}
-+
-+/// Get the effective user ID and group ID associated with a Unix domain socket.
-+///
-+/// See also [getpeereid(3)](https://www.freebsd.org/cgi/man.cgi?query=getpeereid)
-+#[cfg(any(
-+    target_os = "macos",
-+    target_os = "ios",
-+    target_os = "freebsd",
-+    target_os = "openbsd",
-+    target_os = "netbsd",
-+    target_os = "dragonfly",
-+))]
-+pub fn getpeereid(fd: RawFd) -> Result<(Uid, Gid)> {
-+    let mut uid = 1;
-+    let mut gid = 1;
-+
-+    let ret = unsafe { libc::getpeereid(fd, &mut uid, &mut gid) };
-+
-+    Errno::result(ret).map(|_| (Uid(uid), Gid(gid)))
-+}
-diff --git a/third_party/rust/nix/test/common/mod.rs b/third_party/rust/nix/test/common/mod.rs
-new file mode 100644
-index 0000000000000..a871b47041d3e
---- /dev/null
-+++ b/third_party/rust/nix/test/common/mod.rs
-@@ -0,0 +1,127 @@
-+use cfg_if::cfg_if;
-+
-+#[macro_export] macro_rules! skip {
-+    ($($reason: expr),+) => {
-+        use ::std::io::{self, Write};
-+
-+        let stderr = io::stderr();
-+        let mut handle = stderr.lock();
-+        writeln!(handle, $($reason),+).unwrap();
-+        return;
-+    }
-+}
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        #[macro_export] macro_rules! require_capability {
-+            ($capname:ident) => {
-+                use ::caps::{Capability, CapSet, has_cap};
-+
-+                if !has_cap(None, CapSet::Effective, Capability::$capname)
-+                    .unwrap()
-+                {
-+                    skip!("Insufficient capabilities. Skipping test.");
-+                }
-+            }
-+        }
-+    } else if #[cfg(not(target_os = "redox"))] {
-+        #[macro_export] macro_rules! require_capability {
-+            ($capname:ident) => {}
-+        }
-+    }
-+}
-+
-+#[cfg(any(target_os = "linux", target_os= "android"))]
-+#[macro_export] macro_rules! skip_if_cirrus {
-+    ($reason:expr) => {
-+        if std::env::var_os("CIRRUS_CI").is_some() {
-+            skip!("{}", $reason);
-+        }
-+    }
-+}
-+
-+#[cfg(target_os = "freebsd")]
-+#[macro_export] macro_rules! skip_if_jailed {
-+    ($name:expr) => {
-+        use ::sysctl::CtlValue;
-+
-+        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
-+            .unwrap()
-+        {
-+            skip!("{} cannot run in a jail. Skipping test.", $name);
-+        }
-+    }
-+}
-+
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+#[macro_export] macro_rules! skip_if_not_root {
-+    ($name:expr) => {
-+        use nix::unistd::Uid;
-+
-+        if !Uid::current().is_root() {
-+            skip!("{} requires root privileges. Skipping test.", $name);
-+        }
-+    };
-+}
-+
-+cfg_if! {
-+    if #[cfg(any(target_os = "android", target_os = "linux"))] {
-+        #[macro_export] macro_rules! skip_if_seccomp {
-+            ($name:expr) => {
-+                if let Ok(s) = std::fs::read_to_string("/proc/self/status") {
-+                    for l in s.lines() {
-+                        let mut fields = l.split_whitespace();
-+                        if fields.next() == Some("Seccomp:") &&
-+                            fields.next() != Some("0")
-+                        {
-+                            skip!("{} cannot be run in Seccomp mode.  Skipping test.",
-+                                stringify!($name));
-+                        }
-+                    }
-+                }
-+            }
-+        }
-+    } else if #[cfg(not(target_os = "redox"))] {
-+        #[macro_export] macro_rules! skip_if_seccomp {
-+            ($name:expr) => {}
-+        }
-+    }
-+}
-+
-+cfg_if! {
-+    if #[cfg(target_os = "linux")] {
-+        #[macro_export] macro_rules! require_kernel_version {
-+            ($name:expr, $version_requirement:expr) => {
-+                use semver::{Version, VersionReq};
-+
-+                let version_requirement = VersionReq::parse($version_requirement)
-+                        .expect("Bad match_version provided");
-+
-+                let uname = nix::sys::utsname::uname();
-+                println!("{}", uname.sysname());
-+                println!("{}", uname.nodename());
-+                println!("{}", uname.release());
-+                println!("{}", uname.version());
-+                println!("{}", uname.machine());
-+
-+                // Fix stuff that the semver parser can't handle
-+                let fixed_release = &uname.release().to_string()
-+                    // Fedora 33 reports version as 4.18.el8_2.x86_64 or
-+                    // 5.18.200-fc33.x86_64.  Remove the underscore.
-+                    .replace("_", "-")
-+                    // Cirrus-CI reports version as 4.19.112+ .  Remove the +
-+                    .replace("+", "");
-+                let mut version = Version::parse(fixed_release).unwrap();
-+
-+                //Keep only numeric parts
-+                version.pre.clear();
-+                version.build.clear();
-+
-+                if !version_requirement.matches(&version) {
-+                    skip!("Skip {} because kernel version `{}` doesn't match the requirement `{}`",
-+                        stringify!($name), version, version_requirement);
-+                }
-+            }
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix/test/sys/mod.rs b/third_party/rust/nix/test/sys/mod.rs
-index 60a58dd106f19..14b03784a0a57 100644
---- a/third_party/rust/nix/test/sys/mod.rs
-+++ b/third_party/rust/nix/test/sys/mod.rs
-@@ -13,12 +13,17 @@ mod test_signal;
- mod test_aio;
- #[cfg(target_os = "linux")]
- mod test_signalfd;
-+#[cfg(not(target_os = "redox"))]
- mod test_socket;
-+#[cfg(not(target_os = "redox"))]
- mod test_sockopt;
-+#[cfg(not(target_os = "redox"))]
- mod test_select;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- mod test_sysinfo;
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- mod test_termios;
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- mod test_ioctl;
- mod test_wait;
- mod test_uio;
-@@ -36,3 +41,5 @@ mod test_pthread;
-           target_os = "netbsd",
-           target_os = "openbsd"))]
- mod test_ptrace;
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+mod test_timerfd;
-diff --git a/third_party/rust/nix/test/sys/test_aio.rs b/third_party/rust/nix/test/sys/test_aio.rs
-index d4b09b0b81905..3878da94a6ef6 100644
---- a/third_party/rust/nix/test/sys/test_aio.rs
-+++ b/third_party/rust/nix/test/sys/test_aio.rs
-@@ -47,7 +47,7 @@ fn test_accessors() {
- // our bindings.  So it's sufficient to check that AioCb.cancel returned any
- // AioCancelStat value.
- #[test]
--#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+#[cfg_attr(target_env = "musl", ignore)]
- fn test_cancel() {
-     let wbuf: &[u8] = b"CDEF";
- 
-@@ -72,7 +72,7 @@ fn test_cancel() {
- 
- // Tests using aio_cancel_all for all outstanding IOs.
- #[test]
--#[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+#[cfg_attr(target_env = "musl", ignore)]
- fn test_aio_cancel_all() {
-     let wbuf: &[u8] = b"CDEF";
- 
-@@ -133,6 +133,13 @@ fn test_fsync_error() {
- 
- #[test]
- #[cfg_attr(all(target_env = "musl", target_arch = "x86_64"), ignore)]
-+// On Travis, aio_suspend hits an assertion within glibc.  This is either a bug
-+// in Travis's version of glibc or Linux.  Either way, we must skip the test.
-+// https://github.com/nix-rust/nix/issues/1099
-+#[cfg_attr(target_os = "linux", ignore)]
-+// On Cirrus, aio_suspend is failing with EINVAL
-+// https://github.com/nix-rust/nix/issues/1361
-+#[cfg_attr(target_os = "macos", ignore)]
- fn test_aio_suspend() {
-     const INITIAL: &[u8] = b"abcdef123456";
-     const WBUF: &[u8] = b"CDEFG";
-@@ -160,7 +167,12 @@ fn test_aio_suspend() {
-     loop {
-         {
-             let cbbuf = [&wcb, &rcb];
--            assert!(aio_suspend(&cbbuf[..], Some(timeout)).is_ok());
-+            let r = aio_suspend(&cbbuf[..], Some(timeout));
-+            match r {
-+                Err(Error::Sys(Errno::EINTR)) => continue,
-+                Err(e) => panic!("aio_suspend returned {:?}", e),
-+                Ok(_) => ()
-+            };
-         }
-         if rcb.error() != Err(Error::from(Errno::EINPROGRESS)) &&
-            wcb.error() != Err(Error::from(Errno::EINPROGRESS)) {
-@@ -168,8 +180,8 @@ fn test_aio_suspend() {
-         }
-     }
- 
--    assert!(wcb.aio_return().unwrap() as usize == WBUF.len());
--    assert!(rcb.aio_return().unwrap() as usize == rlen);
-+    assert_eq!(wcb.aio_return().unwrap() as usize, WBUF.len());
-+    assert_eq!(rcb.aio_return().unwrap() as usize, rlen);
- }
- 
- // Test a simple aio operation with no completion notification.  We must poll
-@@ -192,11 +204,11 @@ fn test_read() {
-         aiocb.read().unwrap();
- 
-         let err = poll_aio(&mut aiocb);
--        assert!(err == Ok(()));
--        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+        assert_eq!(err, Ok(()));
-+        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-     }
- 
--    assert!(EXPECT == rbuf.deref().deref());
-+    assert_eq!(EXPECT, rbuf.deref().deref());
- }
- 
- /// `AioCb::read` should not modify the `AioCb` object if `libc::aio_read`
-@@ -238,11 +250,11 @@ fn test_read_into_mut_slice() {
-         aiocb.read().unwrap();
- 
-         let err = poll_aio(&mut aiocb);
--        assert!(err == Ok(()));
--        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+        assert_eq!(err, Ok(()));
-+        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-     }
- 
--    assert!(rbuf == EXPECT);
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- // Tests from_ptr
-@@ -268,11 +280,11 @@ fn test_read_into_pointer() {
-         aiocb.read().unwrap();
- 
-         let err = poll_aio(&mut aiocb);
--        assert!(err == Ok(()));
--        assert!(aiocb.aio_return().unwrap() as usize == EXPECT.len());
-+        assert_eq!(err, Ok(()));
-+        assert_eq!(aiocb.aio_return().unwrap() as usize, EXPECT.len());
-     }
- 
--    assert!(rbuf == EXPECT);
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- // Test reading into an immutable buffer.  It should fail
-@@ -314,13 +326,13 @@ fn test_write() {
-     aiocb.write().unwrap();
- 
-     let err = poll_aio(&mut aiocb);
--    assert!(err == Ok(()));
--    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
-+    assert_eq!(err, Ok(()));
-+    assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- // Tests `AioCb::from_boxed_slice` with `Bytes`
-@@ -344,13 +356,13 @@ fn test_write_bytes() {
-     aiocb.write().unwrap();
- 
-     let err = poll_aio(&mut aiocb);
--    assert!(err == Ok(()));
--    assert!(aiocb.aio_return().unwrap() as usize == expected_len);
-+    assert_eq!(err, Ok(()));
-+    assert_eq!(aiocb.aio_return().unwrap() as usize, expected_len);
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- // Tests `AioCb::from_boxed_mut_slice` with `BytesMut`
-@@ -402,13 +414,13 @@ fn test_write_from_pointer() {
-     aiocb.write().unwrap();
- 
-     let err = poll_aio(&mut aiocb);
--    assert!(err == Ok(()));
--    assert!(aiocb.aio_return().unwrap() as usize == wbuf.len());
-+    assert_eq!(err, Ok(()));
-+    assert_eq!(aiocb.aio_return().unwrap() as usize, wbuf.len());
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- /// `AioCb::write` should not modify the `AioCb` object if `libc::aio_write`
-@@ -441,7 +453,7 @@ extern fn sigfunc(_: c_int) {
- #[test]
- #[cfg_attr(any(all(target_env = "musl", target_arch = "x86_64"), target_arch = "mips", target_arch = "mips64"), ignore)]
- fn test_write_sigev_signal() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-     let sa = SigAction::new(SigHandler::Handler(sigfunc),
-                             SaFlags::SA_RESETHAND,
-                             SigSet::empty());
-@@ -469,11 +481,11 @@ fn test_write_sigev_signal() {
-         thread::sleep(time::Duration::from_millis(10));
-     }
- 
--    assert!(aiocb.aio_return().unwrap() as usize == WBUF.len());
-+    assert_eq!(aiocb.aio_return().unwrap() as usize, WBUF.len());
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf, EXPECT);
- }
- 
- // Test LioCb::listio with LIO_WAIT, so all AIO ops should be complete by the
-@@ -512,15 +524,15 @@ fn test_liocb_listio_wait() {
-         let err = liocb.listio(LioMode::LIO_WAIT, SigevNotify::SigevNone);
-         err.expect("lio_listio");
- 
--        assert!(liocb.aio_return(0).unwrap() as usize == WBUF.len());
--        assert!(liocb.aio_return(1).unwrap() as usize == rlen);
-+        assert_eq!(liocb.aio_return(0).unwrap() as usize, WBUF.len());
-+        assert_eq!(liocb.aio_return(1).unwrap() as usize, rlen);
-     }
--    assert!(rbuf.deref().deref() == b"3456");
-+    assert_eq!(rbuf.deref().deref(), b"3456");
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf2).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf2 == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf2, EXPECT);
- }
- 
- // Test LioCb::listio with LIO_NOWAIT and no SigEvent, so we must use some other
-@@ -561,15 +573,15 @@ fn test_liocb_listio_nowait() {
- 
-         poll_aio(&mut liocb.aiocbs[0]).unwrap();
-         poll_aio(&mut liocb.aiocbs[1]).unwrap();
--        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
--        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
-+        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
-+        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
-     }
--    assert!(rbuf.deref().deref() == b"3456");
-+    assert_eq!(rbuf.deref().deref(), b"3456");
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf2).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf2 == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf2, EXPECT);
- }
- 
- // Test LioCb::listio with LIO_NOWAIT and a SigEvent to indicate when all
-@@ -579,7 +591,7 @@ fn test_liocb_listio_nowait() {
- #[cfg(not(any(target_os = "ios", target_os = "macos")))]
- #[cfg_attr(any(target_arch = "mips", target_arch = "mips64", target_env = "musl"), ignore)]
- fn test_liocb_listio_signal() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-     const INITIAL: &[u8] = b"abcdef123456";
-     const WBUF: &[u8] = b"CDEF";
-     let mut rbuf = vec![0; 4];
-@@ -620,15 +632,15 @@ fn test_liocb_listio_signal() {
-             thread::sleep(time::Duration::from_millis(10));
-         }
- 
--        assert!(liocb.aiocbs[0].aio_return().unwrap() as usize == WBUF.len());
--        assert!(liocb.aiocbs[1].aio_return().unwrap() as usize == rlen);
-+        assert_eq!(liocb.aiocbs[0].aio_return().unwrap() as usize, WBUF.len());
-+        assert_eq!(liocb.aiocbs[1].aio_return().unwrap() as usize, rlen);
-     }
--    assert!(rbuf.deref().deref() == b"3456");
-+    assert_eq!(rbuf.deref().deref(), b"3456");
- 
-     f.seek(SeekFrom::Start(0)).unwrap();
-     let len = f.read_to_end(&mut rbuf2).unwrap();
--    assert!(len == EXPECT.len());
--    assert!(rbuf2 == EXPECT);
-+    assert_eq!(len, EXPECT.len());
-+    assert_eq!(rbuf2, EXPECT);
- }
- 
- // Try to use LioCb::listio to read into an immutable buffer.  It should fail
-diff --git a/third_party/rust/nix/test/sys/test_aio_drop.rs b/third_party/rust/nix/test/sys/test_aio_drop.rs
-index 492da401ef726..784ee3ef6c75e 100644
---- a/third_party/rust/nix/test/sys/test_aio_drop.rs
-+++ b/third_party/rust/nix/test/sys/test_aio_drop.rs
-@@ -1,6 +1,3 @@
--extern crate nix;
--extern crate tempfile;
--
- // Test dropping an AioCb that hasn't yet finished.
- // This must happen in its own process, because on OSX this test seems to hose
- // the AIO subsystem and causes subsequent tests to fail
-@@ -12,6 +9,7 @@ extern crate tempfile;
-               target_os = "macos",
-               target_os = "freebsd",
-               target_os = "netbsd")))]
-+#[cfg_attr(target_env = "gnu", ignore = "Occasionally fails in Travis; glibc bug suspected")]
- fn test_drop() {
-     use nix::sys::aio::*;
-     use nix::sys::signal::*;
-diff --git a/third_party/rust/nix/test/sys/test_ioctl.rs b/third_party/rust/nix/test/sys/test_ioctl.rs
-index 0a439b3346f53..fa4510a69c089 100644
---- a/third_party/rust/nix/test/sys/test_ioctl.rs
-+++ b/third_party/rust/nix/test/sys/test_ioctl.rs
-@@ -33,22 +33,22 @@ mod linux {
-     #[test]
-     fn test_op_none() {
-         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
--            assert_eq!(request_code_none!(b'q', 10), 0x2000_710A);
--            assert_eq!(request_code_none!(b'a', 255), 0x2000_61FF);
-+            assert_eq!(request_code_none!(b'q', 10) as u32, 0x2000_710A);
-+            assert_eq!(request_code_none!(b'a', 255) as u32, 0x2000_61FF);
-         } else {
--            assert_eq!(request_code_none!(b'q', 10), 0x0000_710A);
--            assert_eq!(request_code_none!(b'a', 255), 0x0000_61FF);
-+            assert_eq!(request_code_none!(b'q', 10) as u32, 0x0000_710A);
-+            assert_eq!(request_code_none!(b'a', 255) as u32, 0x0000_61FF);
-         }
-     }
- 
-     #[test]
-     fn test_op_write() {
-         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
--            assert_eq!(request_code_write!(b'z', 10, 1), 0x8001_7A0A);
--            assert_eq!(request_code_write!(b'z', 10, 512), 0x8200_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x8001_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x8200_7A0A);
-         } else {
--            assert_eq!(request_code_write!(b'z', 10, 1), 0x4001_7A0A);
--            assert_eq!(request_code_write!(b'z', 10, 512), 0x4200_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 1) as u32, 0x4001_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, 512) as u32, 0x4200_7A0A);
-         }
-     }
- 
-@@ -56,9 +56,11 @@ mod linux {
-     #[test]
-     fn test_op_write_64() {
-         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
--            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
-+                       0x8000_7A0A);
-         } else {
--            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
-+            assert_eq!(request_code_write!(b'z', 10, (1 as u64) << 32) as u32,
-+                       0x4000_7A0A);
-         }
- 
-     }
-@@ -66,11 +68,11 @@ mod linux {
-     #[test]
-     fn test_op_read() {
-         if cfg!(any(target_arch = "mips", target_arch = "mips64", target_arch="powerpc", target_arch="powerpc64")){
--            assert_eq!(request_code_read!(b'z', 10, 1), 0x4001_7A0A);
--            assert_eq!(request_code_read!(b'z', 10, 512), 0x4200_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x4001_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x4200_7A0A);
-         } else {
--            assert_eq!(request_code_read!(b'z', 10, 1), 0x8001_7A0A);
--            assert_eq!(request_code_read!(b'z', 10, 512), 0x8200_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 1) as u32, 0x8001_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, 512) as u32, 0x8200_7A0A);
-         }
-     }
- 
-@@ -78,22 +80,25 @@ mod linux {
-     #[test]
-     fn test_op_read_64() {
-         if cfg!(any(target_arch = "mips64", target_arch="powerpc64")){
--            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x4000_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
-+                       0x4000_7A0A);
-         } else {
--            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32), 0x8000_7A0A);
-+            assert_eq!(request_code_read!(b'z', 10, (1 as u64) << 32) as u32,
-+                       0x8000_7A0A);
-         }
-     }
- 
-     #[test]
-     fn test_op_read_write() {
--        assert_eq!(request_code_readwrite!(b'z', 10, 1), 0xC001_7A0A);
--        assert_eq!(request_code_readwrite!(b'z', 10, 512), 0xC200_7A0A);
-+        assert_eq!(request_code_readwrite!(b'z', 10, 1) as u32, 0xC001_7A0A);
-+        assert_eq!(request_code_readwrite!(b'z', 10, 512) as u32, 0xC200_7A0A);
-     }
- 
-     #[cfg(target_pointer_width = "64")]
-     #[test]
-     fn test_op_read_write_64() {
--        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32), 0xC000_7A0A);
-+        assert_eq!(request_code_readwrite!(b'z', 10, (1 as u64) << 32) as u32,
-+                   0xC000_7A0A);
-     }
- }
- 
-@@ -177,7 +182,7 @@ mod linux_ioctls {
-     #[test]
-     fn test_ioctl_read_bad() {
-         let file = tempfile().unwrap();
--        let mut termios = unsafe { mem::uninitialized() };
-+        let mut termios = unsafe { mem::zeroed() };
-         let res = unsafe { tcgets(file.as_raw_fd(), &mut termios) };
-         assert_eq!(res, Err(Sys(ENOTTY)));
-     }
-@@ -194,7 +199,7 @@ mod linux_ioctls {
-     #[test]
-     fn test_ioctl_write_ptr_bad() {
-         let file = tempfile().unwrap();
--        let termios: termios = unsafe { mem::uninitialized() };
-+        let termios: termios = unsafe { mem::zeroed() };
-         let res = unsafe { tcsets(file.as_raw_fd(), &termios) };
-         assert_eq!(res, Err(Sys(ENOTTY)));
-     }
-@@ -245,7 +250,7 @@ mod linux_ioctls {
-     #[test]
-     fn test_ioctl_read() {
-         let file = tempfile().unwrap();
--        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
-+        let mut data: v4l2_audio = unsafe { mem::zeroed() };
-         let res = unsafe { g_audio(file.as_raw_fd(), &mut data) };
-         assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-     }
-@@ -255,7 +260,7 @@ mod linux_ioctls {
-     #[test]
-     fn test_ioctl_readwrite() {
-         let file = tempfile().unwrap();
--        let mut data: v4l2_audio = unsafe { mem::uninitialized() };
-+        let mut data: v4l2_audio = unsafe { mem::zeroed() };
-         let res = unsafe { enum_audio(file.as_raw_fd(), &mut data) };
-         assert!(res == Err(Sys(ENOTTY)) || res == Err(Sys(ENOSYS)));
-     }
-@@ -318,7 +323,7 @@ mod freebsd_ioctls {
-     #[test]
-     fn test_ioctl_read() {
-         let file = tempfile().unwrap();
--        let mut termios = unsafe { mem::uninitialized() };
-+        let mut termios = unsafe { mem::zeroed() };
-         let res = unsafe { tiocgeta(file.as_raw_fd(), &mut termios) };
-         assert_eq!(res, Err(Sys(ENOTTY)));
-     }
-@@ -327,7 +332,7 @@ mod freebsd_ioctls {
-     #[test]
-     fn test_ioctl_write_ptr() {
-         let file = tempfile().unwrap();
--        let termios: termios = unsafe { mem::uninitialized() };
-+        let termios: termios = unsafe { mem::zeroed() };
-         let res = unsafe { tiocseta(file.as_raw_fd(), &termios) };
-         assert_eq!(res, Err(Sys(ENOTTY)));
-     }
-diff --git a/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs b/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
-index 19ee3facf87d7..0795370b8c448 100644
---- a/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
-+++ b/third_party/rust/nix/test/sys/test_lio_listio_resubmit.rs
-@@ -4,10 +4,6 @@
- // we must disable the test here rather than in Cargo.toml
- #![cfg(target_os = "freebsd")]
- 
--extern crate nix;
--extern crate sysctl;
--extern crate tempfile;
--
- use nix::Error;
- use nix::errno::*;
- use nix::libc::off_t;
-diff --git a/third_party/rust/nix/test/sys/test_mman.rs b/third_party/rust/nix/test/sys/test_mman.rs
-new file mode 100644
-index 0000000000000..152fff69c24de
---- /dev/null
-+++ b/third_party/rust/nix/test/sys/test_mman.rs
-@@ -0,0 +1,80 @@
-+use nix::Error;
-+use nix::libc::{c_void, size_t};
-+use nix::sys::mman::{mmap, MapFlags, ProtFlags};
-+
-+#[cfg(target_os = "linux")]
-+use nix::sys::mman::{mremap, MRemapFlags};
-+
-+#[test]
-+fn test_mmap_anonymous() {
-+    let ref mut byte = unsafe {
-+        let ptr = mmap(std::ptr::null_mut(), 1,
-+                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
-+                       MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, -1, 0)
-+                      .unwrap();
-+        *(ptr as * mut u8)
-+    };
-+    assert_eq !(*byte, 0x00u8);
-+    *byte = 0xffu8;
-+    assert_eq !(*byte, 0xffu8);
-+}
-+
-+#[test]
-+#[cfg(target_os = "linux")]
-+fn test_mremap_grow() {
-+    const ONE_K : size_t = 1024;
-+    let slice : &mut[u8] = unsafe {
-+        let mem = mmap(std::ptr::null_mut(), ONE_K,
-+                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
-+                       MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
-+                      .unwrap();
-+        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
-+    };
-+    assert_eq !(slice[ONE_K - 1], 0x00);
-+    slice[ONE_K - 1] = 0xFF;
-+    assert_eq !(slice[ONE_K - 1], 0xFF);
-+
-+    let slice : &mut[u8] = unsafe {
-+        let mem = mremap(slice.as_mut_ptr() as * mut c_void, ONE_K, 10 * ONE_K,
-+                         MRemapFlags::MREMAP_MAYMOVE, None)
-+                      .unwrap();
-+        std::slice::from_raw_parts_mut(mem as * mut u8, 10 * ONE_K)
-+    };
-+
-+    // The first KB should still have the old data in it.
-+    assert_eq !(slice[ONE_K - 1], 0xFF);
-+
-+    // The additional range should be zero-init'd and accessible.
-+    assert_eq !(slice[10 * ONE_K - 1], 0x00);
-+    slice[10 * ONE_K - 1] = 0xFF;
-+    assert_eq !(slice[10 * ONE_K - 1], 0xFF);
-+}
-+
-+#[test]
-+#[cfg(target_os = "linux")]
-+fn test_mremap_shrink() {
-+    const ONE_K : size_t = 1024;
-+    let slice : &mut[u8] = unsafe {
-+        let mem = mmap(std::ptr::null_mut(), 10 * ONE_K,
-+                       ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
-+                       MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE, -1, 0)
-+                      .unwrap();
-+        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
-+    };
-+    assert_eq !(slice[ONE_K - 1], 0x00);
-+    slice[ONE_K - 1] = 0xFF;
-+    assert_eq !(slice[ONE_K - 1], 0xFF);
-+
-+    let slice : &mut[u8] = unsafe {
-+        let mem = mremap(slice.as_mut_ptr() as * mut c_void, 10 * ONE_K, ONE_K,
-+                         MRemapFlags::empty(), None)
-+                      .unwrap();
-+        // Since we didn't supply MREMAP_MAYMOVE, the address should be the
-+        // same.
-+        assert_eq !(mem, slice.as_mut_ptr() as * mut c_void);
-+        std::slice::from_raw_parts_mut(mem as * mut u8, ONE_K)
-+    };
-+
-+    // The first KB should still be accessible and have the old data in it.
-+    assert_eq !(slice[ONE_K - 1], 0xFF);
-+}
-diff --git a/third_party/rust/nix/test/sys/test_pthread.rs b/third_party/rust/nix/test/sys/test_pthread.rs
-index 8928010087a13..1fc3dd900f382 100644
---- a/third_party/rust/nix/test/sys/test_pthread.rs
-+++ b/third_party/rust/nix/test/sys/test_pthread.rs
-@@ -1,13 +1,13 @@
- use nix::sys::pthread::*;
- 
--#[cfg(target_env = "musl")]
-+#[cfg(any(target_env = "musl", target_os = "redox"))]
- #[test]
- fn test_pthread_self() {
-     let tid = pthread_self();
-     assert!(tid != ::std::ptr::null_mut());
- }
- 
--#[cfg(not(target_env = "musl"))]
-+#[cfg(not(any(target_env = "musl", target_os = "redox")))]
- #[test]
- fn test_pthread_self() {
-     let tid = pthread_self();
-diff --git a/third_party/rust/nix/test/sys/test_ptrace.rs b/third_party/rust/nix/test/sys/test_ptrace.rs
-index 24d9b522ee4e5..b9793b39c54ae 100644
---- a/third_party/rust/nix/test/sys/test_ptrace.rs
-+++ b/third_party/rust/nix/test/sys/test_ptrace.rs
-@@ -8,10 +8,13 @@ use nix::sys::ptrace::Options;
- #[cfg(any(target_os = "android", target_os = "linux"))]
- use std::mem;
- 
-+use crate::*;
-+
- #[test]
- fn test_ptrace() {
-     // Just make sure ptrace can be called at all, for now.
-     // FIXME: qemu-user doesn't implement ptrace on all arches, so permit ENOSYS
-+    require_capability!(CAP_SYS_PTRACE);
-     let err = ptrace::attach(getpid()).unwrap_err();
-     assert!(err == Error::Sys(Errno::EPERM) || err == Error::Sys(Errno::EINVAL) ||
-             err == Error::Sys(Errno::ENOSYS));
-@@ -21,6 +24,7 @@ fn test_ptrace() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptrace_setoptions() {
-+    require_capability!(CAP_SYS_PTRACE);
-     let err = ptrace::setoptions(getpid(), Options::PTRACE_O_TRACESYSGOOD).unwrap_err();
-     assert!(err != Error::UnsupportedOperation);
- }
-@@ -29,6 +33,7 @@ fn test_ptrace_setoptions() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptrace_getevent() {
-+    require_capability!(CAP_SYS_PTRACE);
-     let err = ptrace::getevent(getpid()).unwrap_err();
-     assert!(err != Error::UnsupportedOperation);
- }
-@@ -37,6 +42,7 @@ fn test_ptrace_getevent() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptrace_getsiginfo() {
-+    require_capability!(CAP_SYS_PTRACE);
-     if let Err(Error::UnsupportedOperation) = ptrace::getsiginfo(getpid()) {
-         panic!("ptrace_getsiginfo returns Error::UnsupportedOperation!");
-     }
-@@ -46,7 +52,8 @@ fn test_ptrace_getsiginfo() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptrace_setsiginfo() {
--    let siginfo = unsafe { mem::uninitialized() };
-+    require_capability!(CAP_SYS_PTRACE);
-+    let siginfo = unsafe { mem::zeroed() };
-     if let Err(Error::UnsupportedOperation) = ptrace::setsiginfo(getpid(), &siginfo) {
-         panic!("ptrace_setsiginfo returns Error::UnsupportedOperation!");
-     }
-@@ -61,7 +68,9 @@ fn test_ptrace_cont() {
-     use nix::unistd::fork;
-     use nix::unistd::ForkResult::*;
- 
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    require_capability!(CAP_SYS_PTRACE);
-+
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // FIXME: qemu-user doesn't implement ptrace on all architectures
-     // and retunrs ENOSYS in this case.
-@@ -74,7 +83,7 @@ fn test_ptrace_cont() {
-         return;
-     }
- 
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-         Child => {
-             ptrace::traceme().unwrap();
-             // As recommended by ptrace(2), raise SIGTRAP to pause the child
-@@ -91,7 +100,7 @@ fn test_ptrace_cont() {
-             ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
-             match waitpid(child, None) {
-                 Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _)) if pid == child => {
--                    // FIXME It's been observed on some systems (apple) the 
-+                    // FIXME It's been observed on some systems (apple) the
-                     // tracee may not be killed but remain as a zombie process
-                     // affecting other wait based tests. Add an extra kill just
-                     // to make sure there are no zombies.
-@@ -105,3 +114,65 @@ fn test_ptrace_cont() {
-         },
-     }
- }
-+
-+// ptrace::{setoptions, getregs} are only available in these platforms
-+#[cfg(all(target_os = "linux",
-+          any(target_arch = "x86_64",
-+              target_arch = "x86"),
-+          target_env = "gnu"))]
-+#[test]
-+fn test_ptrace_syscall() {
-+    use nix::sys::signal::kill;
-+    use nix::sys::ptrace;
-+    use nix::sys::signal::Signal;
-+    use nix::sys::wait::{waitpid, WaitStatus};
-+    use nix::unistd::fork;
-+    use nix::unistd::getpid;
-+    use nix::unistd::ForkResult::*;
-+
-+    require_capability!(CAP_SYS_PTRACE);
-+
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-+        Child => {
-+            ptrace::traceme().unwrap();
-+            // first sigstop until parent is ready to continue
-+            let pid = getpid();
-+            kill(pid, Signal::SIGSTOP).unwrap();
-+            kill(pid, Signal::SIGTERM).unwrap();
-+            unsafe { ::libc::_exit(0); }
-+        },
-+
-+        Parent { child } => {
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGSTOP)));
-+
-+            // set this option to recognize syscall-stops
-+            ptrace::setoptions(child, ptrace::Options::PTRACE_O_TRACESYSGOOD).unwrap();
-+
-+            #[cfg(target_arch = "x86_64")]
-+            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_rax as libc::c_long;
-+
-+            #[cfg(target_arch = "x86")]
-+            let get_syscall_id = || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
-+
-+            // kill entry
-+            ptrace::syscall(child, None).unwrap();
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
-+            assert_eq!(get_syscall_id(), ::libc::SYS_kill);
-+
-+            // kill exit
-+            ptrace::syscall(child, None).unwrap();
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
-+            assert_eq!(get_syscall_id(), ::libc::SYS_kill);
-+
-+            // receive signal
-+            ptrace::syscall(child, None).unwrap();
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::Stopped(child, Signal::SIGTERM)));
-+
-+            // inject signal
-+            ptrace::syscall(child, Signal::SIGTERM).unwrap();
-+            assert_eq!(waitpid(child, None), Ok(WaitStatus::Signaled(child, Signal::SIGTERM, false)));
-+        },
-+    }
-+}
-diff --git a/third_party/rust/nix/test/sys/test_select.rs b/third_party/rust/nix/test/sys/test_select.rs
-index cf68700c5e16f..37951086c2d8d 100644
---- a/third_party/rust/nix/test/sys/test_select.rs
-+++ b/third_party/rust/nix/test/sys/test_select.rs
-@@ -5,7 +5,7 @@ use nix::sys::time::{TimeSpec, TimeValLike};
- 
- #[test]
- pub fn test_pselect() {
--    let _mtx = ::SIGNAL_MTX
-+    let _mtx = crate::SIGNAL_MTX
-         .lock()
-         .expect("Mutex got poisoned by another test");
- 
-diff --git a/third_party/rust/nix/test/sys/test_signal.rs b/third_party/rust/nix/test/sys/test_signal.rs
-index 8780763f773ef..ae22527fde278 100644
---- a/third_party/rust/nix/test/sys/test_signal.rs
-+++ b/third_party/rust/nix/test/sys/test_signal.rs
-@@ -1,7 +1,9 @@
- use libc;
-+#[cfg(not(target_os = "redox"))]
- use nix::Error;
- use nix::sys::signal::*;
- use nix::unistd::*;
-+use std::convert::TryFrom;
- use std::sync::atomic::{AtomicBool, Ordering};
- 
- #[test]
-@@ -10,6 +12,7 @@ fn test_kill_none() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "fuchsia"))]
- fn test_killpg_none() {
-     killpg(getpgrp(), None)
-         .expect("Should be able to send signal to my process group.");
-@@ -17,6 +20,8 @@ fn test_killpg_none() {
- 
- #[test]
- fn test_old_sigaction_flags() {
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-     extern "C" fn handler(_: ::libc::c_int) {}
-     let act = SigAction::new(
-         SigHandler::Handler(handler),
-@@ -37,7 +42,7 @@ fn test_sigprocmask_noop() {
- 
- #[test]
- fn test_sigprocmask() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // This needs to be a signal that rust doesn't use in the test harness.
-     const SIGNAL: Signal = Signal::SIGCHLD;
-@@ -75,16 +80,25 @@ lazy_static! {
- }
- 
- extern fn test_sigaction_handler(signal: libc::c_int) {
--    let signal = Signal::from_c_int(signal).unwrap();
-+    let signal = Signal::try_from(signal).unwrap();
-     SIGNALED.store(signal == Signal::SIGINT, Ordering::Relaxed);
- }
- 
--extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {
-+#[cfg(not(target_os = "redox"))]
-+extern fn test_sigaction_action(_: libc::c_int, _: *mut libc::siginfo_t, _: *mut libc::c_void) {}
-+
-+#[test]
-+#[cfg(not(target_os = "redox"))]
-+fn test_signal_sigaction() {
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    let action_handler = SigHandler::SigAction(test_sigaction_action);
-+    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
- }
- 
- #[test]
- fn test_signal() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     unsafe { signal(Signal::SIGINT, SigHandler::SigIgn) }.unwrap();
-     raise(Signal::SIGINT).unwrap();
-@@ -96,9 +110,6 @@ fn test_signal() {
-     assert!(SIGNALED.load(Ordering::Relaxed));
-     assert_eq!(unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap(), handler);
- 
--    let action_handler = SigHandler::SigAction(test_sigaction_action);
--    assert_eq!(unsafe { signal(Signal::SIGINT, action_handler) }.unwrap_err(), Error::UnsupportedOperation);
--
-     // Restore default signal handler
-     unsafe { signal(Signal::SIGINT, SigHandler::SigDfl) }.unwrap();
- }
-diff --git a/third_party/rust/nix/test/sys/test_signalfd.rs b/third_party/rust/nix/test/sys/test_signalfd.rs
-index a3b6098841f1c..af04c222852d8 100644
---- a/third_party/rust/nix/test/sys/test_signalfd.rs
-+++ b/third_party/rust/nix/test/sys/test_signalfd.rs
-@@ -1,10 +1,12 @@
-+use std::convert::TryFrom;
-+
- #[test]
- fn test_signalfd() {
-     use nix::sys::signalfd::SignalFd;
-     use nix::sys::signal::{self, raise, Signal, SigSet};
- 
-     // Grab the mutex for altering signals so we don't interfere with other tests.
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Block the SIGUSR1 signal from automatic processing for this thread
-     let mut mask = SigSet::empty();
-@@ -20,6 +22,6 @@ fn test_signalfd() {
- 
-     // And now catch that same signal.
-     let res = fd.read_signal().unwrap().unwrap();
--    let signo = Signal::from_c_int(res.ssi_signo as i32).unwrap();
-+    let signo = Signal::try_from(res.ssi_signo as i32).unwrap();
-     assert_eq!(signo, signal::SIGUSR1);
- }
-diff --git a/third_party/rust/nix/test/sys/test_socket.rs b/third_party/rust/nix/test/sys/test_socket.rs
-index 7e64d2b77f071..2b89a45336f3e 100644
---- a/third_party/rust/nix/test/sys/test_socket.rs
-+++ b/third_party/rust/nix/test/sys/test_socket.rs
-@@ -1,4 +1,3 @@
--use nix::ifaddrs::InterfaceAddress;
- use nix::sys::socket::{AddressFamily, InetAddr, UnixAddr, getsockname};
- use std::collections::hash_map::DefaultHasher;
- use std::hash::{Hash, Hasher};
-@@ -9,6 +8,8 @@ use std::slice;
- use std::str::FromStr;
- use libc::c_char;
- use tempfile;
-+#[cfg(any(target_os = "linux", target_os= "android"))]
-+use crate::*;
- 
- #[test]
- pub fn test_inetv4_addr_to_sock_addr() {
-@@ -106,7 +107,7 @@ pub fn test_addr_equality_abstract() {
-     assert_eq!(addr1, addr2);
-     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
- 
--    addr2.0.sun_path[18] = 127;
-+    addr2.0.sun_path[17] = 127;
-     assert_ne!(addr1, addr2);
-     assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
- }
-@@ -117,16 +118,13 @@ pub fn test_addr_equality_abstract() {
- pub fn test_abstract_uds_addr() {
-     let empty = String::new();
-     let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
--    let sun_path = [0u8; 107];
-+    let sun_path: [u8; 0] = [];
-     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
- 
-     let name = String::from("nix\0abstract\0test");
-     let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
-     let sun_path = [
--        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116, 0, 0, 0, 0,
--        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
--        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
--        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-+        110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101, 115, 116
-     ];
-     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
-     assert_eq!(addr.path(), None);
-@@ -164,6 +162,360 @@ pub fn test_socketpair() {
-     assert_eq!(&buf[..], b"hello");
- }
- 
-+mod recvfrom {
-+    use nix::Result;
-+    use nix::sys::socket::*;
-+    use std::thread;
-+    use super::*;
-+
-+    const MSG: &'static [u8] = b"Hello, World!";
-+
-+    fn sendrecv<Fs, Fr>(rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr) -> Option<SockAddr>
-+        where
-+            Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static,
-+            Fr: FnMut(usize, Option<SockAddr>),
-+    {
-+        let mut buf: [u8; 13] = [0u8; 13];
-+        let mut l = 0;
-+        let mut from = None;
-+
-+        let send_thread = thread::spawn(move || {
-+            let mut l = 0;
-+            while l < std::mem::size_of_val(MSG) {
-+                l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap();
-+            }
-+        });
-+
-+        while l < std::mem::size_of_val(MSG) {
-+            let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap();
-+            f_recv(len, from_);
-+            from = from_;
-+            l += len;
-+        }
-+        assert_eq!(&buf, MSG);
-+        send_thread.join().unwrap();
-+        from
-+    }
-+
-+    #[test]
-+    pub fn stream() {
-+        let (fd2, fd1) = socketpair(AddressFamily::Unix, SockType::Stream,
-+                                    None, SockFlag::empty()).unwrap();
-+        // Ignore from for stream sockets
-+        let _ = sendrecv(fd1, fd2, |s, m, flags| {
-+            send(s, m, flags)
-+        }, |_, _| {});
-+    }
-+
-+    #[test]
-+    pub fn udp() {
-+        let std_sa = SocketAddr::from_str("127.0.0.1:6789").unwrap();
-+        let inet_addr = InetAddr::from_std(&std_sa);
-+        let sock_addr = SockAddr::new_inet(inet_addr);
-+        let rsock = socket(AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None
-+        ).unwrap();
-+        bind(rsock, &sock_addr).unwrap();
-+        let ssock = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+        let from = sendrecv(rsock, ssock, move |s, m, flags| {
-+            sendto(s, m, &sock_addr, flags)
-+        },|_, _| {});
-+        // UDP sockets should set the from address
-+        assert_eq!(AddressFamily::Inet, from.unwrap().family());
-+    }
-+
-+    #[cfg(target_os = "linux")]
-+    mod udp_offload {
-+        use super::*;
-+        use nix::sys::uio::IoVec;
-+        use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
-+
-+        #[test]
-+        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
-+        // support is suspected.
-+        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-+        pub fn gso() {
-+            require_kernel_version!(udp_offload::gso, ">= 4.18");
-+
-+            // In this test, we send the data and provide a GSO segment size.
-+            // Since we are sending the buffer of size 13, six UDP packets
-+            // with size 2 and two UDP packet with size 1 will be sent.
-+            let segment_size: u16 = 2;
-+
-+            let std_sa = SocketAddr::from_str("127.0.0.1:6791").unwrap();
-+            let inet_addr = InetAddr::from_std(&std_sa);
-+            let sock_addr = SockAddr::new_inet(inet_addr);
-+            let rsock = socket(AddressFamily::Inet,
-+                               SockType::Datagram,
-+                               SockFlag::empty(),
-+                               None
-+            ).unwrap();
-+
-+            setsockopt(rsock, UdpGsoSegment, &(segment_size as _))
-+                .expect("setsockopt UDP_SEGMENT failed");
-+
-+            bind(rsock, &sock_addr).unwrap();
-+            let ssock = socket(
-+                AddressFamily::Inet,
-+                SockType::Datagram,
-+                SockFlag::empty(),
-+                None,
-+            ).expect("send socket failed");
-+
-+            let mut num_packets_received: i32 = 0;
-+
-+            sendrecv(rsock, ssock, move |s, m, flags| {
-+                let iov = [IoVec::from_slice(m)];
-+                let cmsg = ControlMessage::UdpGsoSegments(&segment_size);
-+                sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr))
-+            }, {
-+                let num_packets_received_ref = &mut num_packets_received;
-+
-+                move |len, _| {
-+                    // check that we receive UDP packets with payload size
-+                    // less or equal to segment size
-+                    assert!(len <= segment_size as usize);
-+                    *num_packets_received_ref += 1;
-+                }
-+            });
-+
-+            // Buffer size is 13, we will receive six packets of size 2,
-+            // and one packet of size 1.
-+            assert_eq!(7, num_packets_received);
-+        }
-+
-+        #[test]
-+        // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack of QEMU
-+        // support is suspected.
-+        #[cfg_attr(not(any(target_arch = "x86_64", target_arch="i686")), ignore)]
-+        pub fn gro() {
-+            require_kernel_version!(udp_offload::gro, ">= 5.3");
-+
-+            // It's hard to guarantee receiving GRO packets. Just checking
-+            // that `setsockopt` doesn't fail with error
-+
-+            let rsock = socket(AddressFamily::Inet,
-+                               SockType::Datagram,
-+                               SockFlag::empty(),
-+                               None
-+            ).unwrap();
-+
-+            setsockopt(rsock, UdpGroSegment, &true)
-+                .expect("setsockopt UDP_GRO failed");
-+        }
-+    }
-+
-+    #[cfg(any(
-+        target_os = "linux",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "netbsd",
-+    ))]
-+    #[test]
-+    pub fn udp_sendmmsg() {
-+        use nix::sys::uio::IoVec;
-+
-+        let std_sa = SocketAddr::from_str("127.0.0.1:6793").unwrap();
-+        let std_sa2 = SocketAddr::from_str("127.0.0.1:6794").unwrap();
-+        let inet_addr = InetAddr::from_std(&std_sa);
-+        let inet_addr2 = InetAddr::from_std(&std_sa2);
-+        let sock_addr = SockAddr::new_inet(inet_addr);
-+        let sock_addr2 = SockAddr::new_inet(inet_addr2);
-+
-+        let rsock = socket(AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None
-+        ).unwrap();
-+        bind(rsock, &sock_addr).unwrap();
-+        let ssock = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+
-+        let from = sendrecv(rsock, ssock, move |s, m, flags| {
-+            let iov = [IoVec::from_slice(m)];
-+            let mut msgs = Vec::new();
-+            msgs.push(
-+                SendMmsgData {
-+                    iov: &iov,
-+                    cmsgs: &[],
-+                    addr: Some(sock_addr),
-+                    _lt: Default::default(),
-+                });
-+
-+            let batch_size = 15;
-+
-+            for _ in 0..batch_size {
-+                msgs.push(
-+                    SendMmsgData {
-+                        iov: &iov,
-+                        cmsgs: &[],
-+                        addr: Some(sock_addr2),
-+                        _lt: Default::default(),
-+                    }
-+                );
-+            }
-+            sendmmsg(s, msgs.iter(), flags)
-+                .map(move |sent_bytes| {
-+                    assert!(sent_bytes.len() >= 1);
-+                    for sent in &sent_bytes {
-+                        assert_eq!(*sent, m.len());
-+                    }
-+                    sent_bytes.len()
-+                })
-+        }, |_, _ | {});
-+        // UDP sockets should set the from address
-+        assert_eq!(AddressFamily::Inet, from.unwrap().family());
-+    }
-+
-+    #[cfg(any(
-+        target_os = "linux",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "netbsd",
-+    ))]
-+    #[test]
-+    pub fn udp_recvmmsg() {
-+        use nix::sys::uio::IoVec;
-+        use nix::sys::socket::{MsgFlags, recvmmsg};
-+
-+        const NUM_MESSAGES_SENT: usize = 2;
-+        const DATA: [u8; 2] = [1,2];
-+
-+        let std_sa = SocketAddr::from_str("127.0.0.1:6798").unwrap();
-+        let inet_addr = InetAddr::from_std(&std_sa);
-+        let sock_addr = SockAddr::new_inet(inet_addr);
-+
-+        let rsock = socket(AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None
-+        ).unwrap();
-+        bind(rsock, &sock_addr).unwrap();
-+        let ssock = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+
-+        let send_thread = thread::spawn(move || {
-+            for _ in 0..NUM_MESSAGES_SENT {
-+                sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
-+            }
-+        });
-+
-+        let mut msgs = std::collections::LinkedList::new();
-+
-+        // Buffers to receive exactly `NUM_MESSAGES_SENT` messages
-+        let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT];
-+        let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
-+            [IoVec::from_mut_slice(&mut buf[..])]
-+        }).collect();
-+
-+        for iov in &iovs {
-+            msgs.push_back(RecvMmsgData {
-+                iov: iov,
-+                cmsg_buffer: None,
-+            })
-+        };
-+
-+        let res = recvmmsg(rsock, &mut msgs, MsgFlags::empty(), None).expect("recvmmsg");
-+        assert_eq!(res.len(), DATA.len());
-+
-+        for RecvMsg { address, bytes, .. } in res.into_iter() {
-+            assert_eq!(AddressFamily::Inet, address.unwrap().family());
-+            assert_eq!(DATA.len(), bytes);
-+        }
-+
-+        for buf in &receive_buffers {
-+            assert_eq!(&buf[..DATA.len()], DATA);
-+        }
-+
-+        send_thread.join().unwrap();
-+    }
-+
-+    #[cfg(any(
-+        target_os = "linux",
-+        target_os = "android",
-+        target_os = "freebsd",
-+        target_os = "netbsd",
-+    ))]
-+    #[test]
-+    pub fn udp_recvmmsg_dontwait_short_read() {
-+        use nix::sys::uio::IoVec;
-+        use nix::sys::socket::{MsgFlags, recvmmsg};
-+
-+        const NUM_MESSAGES_SENT: usize = 2;
-+        const DATA: [u8; 4] = [1,2,3,4];
-+
-+        let std_sa = SocketAddr::from_str("127.0.0.1:6799").unwrap();
-+        let inet_addr = InetAddr::from_std(&std_sa);
-+        let sock_addr = SockAddr::new_inet(inet_addr);
-+
-+        let rsock = socket(AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None
-+        ).unwrap();
-+        bind(rsock, &sock_addr).unwrap();
-+        let ssock = socket(
-+            AddressFamily::Inet,
-+            SockType::Datagram,
-+            SockFlag::empty(),
-+            None,
-+        ).expect("send socket failed");
-+
-+        let send_thread = thread::spawn(move || {
-+            for _ in 0..NUM_MESSAGES_SENT {
-+                sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty()).unwrap();
-+            }
-+        });
-+        // Ensure we've sent all the messages before continuing so `recvmmsg`
-+        // will return right away
-+        send_thread.join().unwrap();
-+
-+        let mut msgs = std::collections::LinkedList::new();
-+
-+        // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg`
-+        // will return when there are fewer than requested messages in the
-+        // kernel buffers when using `MSG_DONTWAIT`.
-+        let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
-+        let iovs: Vec<_> = receive_buffers.iter_mut().map(|buf| {
-+            [IoVec::from_mut_slice(&mut buf[..])]
-+        }).collect();
-+
-+        for iov in &iovs {
-+            msgs.push_back(RecvMmsgData {
-+                iov: iov,
-+                cmsg_buffer: None,
-+            })
-+        };
-+
-+        let res = recvmmsg(rsock, &mut msgs, MsgFlags::MSG_DONTWAIT, None).expect("recvmmsg");
-+        assert_eq!(res.len(), NUM_MESSAGES_SENT);
-+
-+        for RecvMsg { address, bytes, .. } in res.into_iter() {
-+            assert_eq!(AddressFamily::Inet, address.unwrap().family());
-+            assert_eq!(DATA.len(), bytes);
-+        }
-+
-+        for buf in &receive_buffers[..NUM_MESSAGES_SENT] {
-+            assert_eq!(&buf[..DATA.len()], DATA);
-+        }
-+    }
-+}
-+
- // Test error handling of our recvmsg wrapper
- #[test]
- pub fn test_recvmsg_ebadf() {
-@@ -247,8 +599,13 @@ pub fn test_af_alg_cipher() {
-                            ControlMessage, MsgFlags};
-     use nix::sys::socket::sockopt::AlgSetKey;
- 
-+    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
-+    // Travis's seccomp profile blocks AF_ALG
-+    // https://docs.docker.com/engine/security/seccomp/
-+    skip_if_seccomp!(test_af_alg_cipher);
-+
-     let alg_type = "skcipher";
--    let alg_name = "ctr(aes)";
-+    let alg_name = "ctr-aes-aesni";
-     // 256-bits secret key
-     let key = vec![0u8; 32];
-     // 16-bytes IV
-@@ -311,6 +668,11 @@ pub fn test_af_alg_aead() {
-                            ControlMessage, MsgFlags};
-     use nix::sys::socket::sockopt::{AlgSetKey, AlgSetAeadAuthSize};
- 
-+    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
-+    // Travis's seccomp profile blocks AF_ALG
-+    // https://docs.docker.com/engine/security/seccomp/
-+    skip_if_seccomp!(test_af_alg_aead);
-+
-     let auth_size = 4usize;
-     let assoc_size = 16u32;
- 
-@@ -383,6 +745,111 @@ pub fn test_af_alg_aead() {
-     assert_eq!(decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))], payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]);
- }
- 
-+// Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`.
-+// This creates a (udp) socket bound to localhost, then sends a message to
-+// itself but uses Ipv4PacketInfo to force the source address to be localhost.
-+//
-+// This would be a more interesting test if we could assume that the test host
-+// has more than one IP address (since we could select a different address to
-+// test from).
-+#[cfg(any(target_os = "linux",
-+        target_os = "macos",
-+        target_os = "netbsd"))]
-+#[test]
-+pub fn test_sendmsg_ipv4packetinfo() {
-+    use nix::sys::uio::IoVec;
-+    use nix::sys::socket::{socket, sendmsg, bind,
-+                           AddressFamily, SockType, SockFlag, SockAddr,
-+                           ControlMessage, MsgFlags};
-+
-+    let sock = socket(AddressFamily::Inet,
-+                      SockType::Datagram,
-+                      SockFlag::empty(),
-+                      None)
-+        .expect("socket failed");
-+
-+    let std_sa = SocketAddr::from_str("127.0.0.1:4000").unwrap();
-+    let inet_addr = InetAddr::from_std(&std_sa);
-+    let sock_addr = SockAddr::new_inet(inet_addr);
-+
-+    bind(sock, &sock_addr).expect("bind failed");
-+
-+    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+    let iov = [IoVec::from_slice(&slice)];
-+
-+    if let InetAddr::V4(sin) = inet_addr {
-+        let pi = libc::in_pktinfo {
-+            ipi_ifindex: 0, /* Unspecified interface */
-+            ipi_addr: libc::in_addr { s_addr: 0 },
-+            ipi_spec_dst: sin.sin_addr,
-+        };
-+
-+        let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
-+
-+        sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
-+            .expect("sendmsg");
-+    } else {
-+        panic!("No IPv4 addresses available for testing?");
-+    }
-+}
-+
-+// Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
-+// This creates a (udp) socket bound to ip6-localhost, then sends a message to
-+// itself but uses Ipv6PacketInfo to force the source address to be
-+// ip6-localhost.
-+//
-+// This would be a more interesting test if we could assume that the test host
-+// has more than one IP address (since we could select a different address to
-+// test from).
-+#[cfg(any(target_os = "linux",
-+        target_os = "macos",
-+        target_os = "netbsd",
-+        target_os = "freebsd"))]
-+#[test]
-+pub fn test_sendmsg_ipv6packetinfo() {
-+    use nix::Error;
-+    use nix::errno::Errno;
-+    use nix::sys::uio::IoVec;
-+    use nix::sys::socket::{socket, sendmsg, bind,
-+                           AddressFamily, SockType, SockFlag, SockAddr,
-+                           ControlMessage, MsgFlags};
-+
-+    let sock = socket(AddressFamily::Inet6,
-+                      SockType::Datagram,
-+                      SockFlag::empty(),
-+                      None)
-+        .expect("socket failed");
-+
-+    let std_sa = SocketAddr::from_str("[::1]:6000").unwrap();
-+    let inet_addr = InetAddr::from_std(&std_sa);
-+    let sock_addr = SockAddr::new_inet(inet_addr);
-+
-+    match bind(sock, &sock_addr) {
-+        Err(Error::Sys(Errno::EADDRNOTAVAIL)) => {
-+            println!("IPv6 not available, skipping test.");
-+            return;
-+        },
-+        _ => (),
-+    }
-+
-+    let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
-+    let iov = [IoVec::from_slice(&slice)];
-+
-+    if let InetAddr::V6(sin) = inet_addr {
-+        let pi = libc::in6_pktinfo {
-+            ipi6_ifindex: 0, /* Unspecified interface */
-+            ipi6_addr: sin.sin6_addr,
-+        };
-+
-+        let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
-+
-+        sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
-+            .expect("sendmsg");
-+    } else {
-+        println!("No IPv6 addresses available for testing: skipping testing Ipv6PacketInfo");
-+    }
-+}
-+
- /// Tests that passing multiple fds using a single `ControlMessage` works.
- // Disable the test on emulated platforms due to a bug in QEMU versions <
- // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
-@@ -468,29 +935,36 @@ pub fn test_sendmsg_empty_cmsgs() {
-     }
- }
- 
--#[cfg(any(target_os = "android", target_os = "linux"))]
-+#[cfg(any(
-+    target_os = "android",
-+    target_os = "linux",
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+))]
- #[test]
- fn test_scm_credentials() {
--    use libc;
-     use nix::sys::uio::IoVec;
-     use nix::unistd::{close, getpid, getuid, getgid};
--    use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
-+    use nix::sys::socket::{socketpair, sendmsg, recvmsg,
-                            AddressFamily, SockType, SockFlag,
--                           ControlMessage, ControlMessageOwned, MsgFlags};
--    use nix::sys::socket::sockopt::PassCred;
-+                           ControlMessage, ControlMessageOwned, MsgFlags,
-+                           UnixCredentials};
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-+    use nix::sys::socket::{setsockopt, sockopt::PassCred};
- 
-     let (send, recv) = socketpair(AddressFamily::Unix, SockType::Stream, None, SockFlag::empty())
-         .unwrap();
-+    #[cfg(any(target_os = "android", target_os = "linux"))]
-     setsockopt(recv, PassCred, &true).unwrap();
- 
-     {
-         let iov = [IoVec::from_slice(b"hello")];
--        let cred = libc::ucred {
--            pid: getpid().as_raw(),
--            uid: getuid().as_raw(),
--            gid: getgid().as_raw(),
--        };
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-+        let cred = UnixCredentials::new();
-+        #[cfg(any(target_os = "android", target_os = "linux"))]
-         let cmsg = ControlMessage::ScmCredentials(&cred);
-+        #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+        let cmsg = ControlMessage::ScmCreds;
-         assert_eq!(sendmsg(send, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(), 5);
-         close(send).unwrap();
-     }
-@@ -498,20 +972,23 @@ fn test_scm_credentials() {
-     {
-         let mut buf = [0u8; 5];
-         let iov = [IoVec::from_mut_slice(&mut buf[..])];
--        let mut cmsgspace = cmsg_space!(libc::ucred);
-+        let mut cmsgspace = cmsg_space!(UnixCredentials);
-         let msg = recvmsg(recv, &iov, Some(&mut cmsgspace), MsgFlags::empty()).unwrap();
-         let mut received_cred = None;
- 
-         for cmsg in msg.cmsgs() {
--            if let ControlMessageOwned::ScmCredentials(cred) = cmsg {
--                assert!(received_cred.is_none());
--                assert_eq!(cred.pid, getpid().as_raw());
--                assert_eq!(cred.uid, getuid().as_raw());
--                assert_eq!(cred.gid, getgid().as_raw());
--                received_cred = Some(cred);
--            } else {
--                panic!("unexpected cmsg");
--            }
-+            let cred = match cmsg {
-+                #[cfg(any(target_os = "android", target_os = "linux"))]
-+                ControlMessageOwned::ScmCredentials(cred) => cred,
-+                #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
-+                ControlMessageOwned::ScmCreds(cred) => cred,
-+                other => panic!("unexpected cmsg {:?}", other),
-+            };
-+            assert!(received_cred.is_none());
-+            assert_eq!(cred.pid(), getpid().as_raw());
-+            assert_eq!(cred.uid(), getuid().as_raw());
-+            assert_eq!(cred.gid(), getgid().as_raw());
-+            received_cred = Some(cred);
-         }
-         received_cred.expect("no creds received");
-         assert_eq!(msg.bytes, 5);
-@@ -550,7 +1027,7 @@ fn test_too_large_cmsgspace() {
- fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
-     use libc::ucred;
-     use nix::sys::uio::IoVec;
--    use nix::unistd::{pipe, read, write, close, getpid, getuid, getgid};
-+    use nix::unistd::{pipe, write, close, getpid, getuid, getgid};
-     use nix::sys::socket::{socketpair, sendmsg, recvmsg, setsockopt,
-                            SockType, SockFlag,
-                            ControlMessage, ControlMessageOwned, MsgFlags};
-@@ -569,7 +1046,7 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
-             pid: getpid().as_raw(),
-             uid: getuid().as_raw(),
-             gid: getgid().as_raw(),
--        };
-+        }.into();
-         let fds = [r];
-         let cmsgs = [
-             ControlMessage::ScmCredentials(&cred),
-@@ -597,9 +1074,9 @@ fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
-                 }
-                 ControlMessageOwned::ScmCredentials(cred) => {
-                     assert!(received_cred.is_none());
--                    assert_eq!(cred.pid, getpid().as_raw());
--                    assert_eq!(cred.uid, getuid().as_raw());
--                    assert_eq!(cred.gid, getgid().as_raw());
-+                    assert_eq!(cred.pid(), getpid().as_raw());
-+                    assert_eq!(cred.uid(), getuid().as_raw());
-+                    assert_eq!(cred.gid(), getgid().as_raw());
-                     received_cred = Some(cred);
-                 }
-                 _ => panic!("unexpected cmsg"),
-@@ -683,7 +1160,7 @@ pub fn test_syscontrol() {
-     target_os = "netbsd",
-     target_os = "openbsd",
- ))]
--fn loopback_address(family: AddressFamily) -> Option<InterfaceAddress> {
-+fn loopback_address(family: AddressFamily) -> Option<nix::ifaddrs::InterfaceAddress> {
-     use std::io;
-     use std::io::Write;
-     use nix::ifaddrs::getifaddrs;
-@@ -1013,7 +1490,7 @@ pub fn test_recv_ipv6pktinfo() {
-     }
- }
- 
--#[cfg(target_os = "linux")]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
- #[test]
- pub fn test_vsock() {
-     use libc;
-@@ -1030,17 +1507,11 @@ pub fn test_vsock() {
-                     SockFlag::empty(), None)
-              .expect("socket failed");
- 
--    // VMADDR_CID_HYPERVISOR and VMADDR_CID_RESERVED are reserved, so we expect
--    // an EADDRNOTAVAIL error.
-+    // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error.
-     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_HYPERVISOR, port);
-     assert_eq!(bind(s1, &sockaddr).err(),
-                Some(Error::Sys(Errno::EADDRNOTAVAIL)));
- 
--    let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_RESERVED, port);
--    assert_eq!(bind(s1, &sockaddr).err(),
--               Some(Error::Sys(Errno::EADDRNOTAVAIL)));
--
--
-     let sockaddr = SockAddr::new_vsock(libc::VMADDR_CID_ANY, port);
-     assert_eq!(bind(s1, &sockaddr), Ok(()));
-     listen(s1, 10).expect("listen failed");
-diff --git a/third_party/rust/nix/test/sys/test_sockopt.rs b/third_party/rust/nix/test/sys/test_sockopt.rs
-index c4860c0d61d3d..56065931322ec 100644
---- a/third_party/rust/nix/test/sys/test_sockopt.rs
-+++ b/third_party/rust/nix/test/sys/test_sockopt.rs
-@@ -1,5 +1,7 @@
- use rand::{thread_rng, Rng};
- use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+use crate::*;
- 
- #[cfg(target_os = "linux")]
- #[test]
-@@ -51,3 +53,44 @@ fn test_tcp_congestion() {
-         val
-     );
- }
-+
-+#[test]
-+#[cfg(any(target_os = "android", target_os = "linux"))]
-+fn test_bindtodevice() {
-+    skip_if_not_root!("test_bindtodevice");
-+
-+    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
-+
-+    let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
-+    setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
-+
-+    assert_eq!(
-+        getsockopt(fd, sockopt::BindToDevice).unwrap(),
-+        val
-+    );
-+}
-+
-+#[test]
-+fn test_so_tcp_keepalive() {
-+    let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
-+    setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
-+    assert_eq!(getsockopt(fd, sockopt::KeepAlive).unwrap(), true);
-+
-+    #[cfg(any(target_os = "android",
-+              target_os = "dragonfly",
-+              target_os = "freebsd",
-+              target_os = "linux",
-+              target_os = "nacl"))] {
-+        let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
-+        setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
-+        assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
-+
-+        let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
-+        setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
-+        assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
-+
-+        let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
-+        setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
-+        assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
-+    }
-+}
-diff --git a/third_party/rust/nix/test/sys/test_termios.rs b/third_party/rust/nix/test/sys/test_termios.rs
-index a14b8ce1a23cb..00aeb2fc57f15 100644
---- a/third_party/rust/nix/test/sys/test_termios.rs
-+++ b/third_party/rust/nix/test/sys/test_termios.rs
-@@ -4,7 +4,7 @@ use tempfile::tempfile;
- use nix::{Error, fcntl};
- use nix::errno::Errno;
- use nix::pty::openpty;
--use nix::sys::termios::{self, LocalFlags, OutputFlags, Termios, tcgetattr};
-+use nix::sys::termios::{self, LocalFlags, OutputFlags, tcgetattr};
- use nix::unistd::{read, write, close};
- 
- /// Helper function analogous to `std::io::Write::write_all`, but for `RawFd`s
-@@ -19,10 +19,10 @@ fn write_all(f: RawFd, buf: &[u8]) {
- #[test]
- fn test_tcgetattr_pty() {
-     // openpty uses ptname(3) internally
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     let pty = openpty(None, None).expect("openpty failed");
--    assert!(termios::tcgetattr(pty.master).is_ok());
-+    assert!(termios::tcgetattr(pty.slave).is_ok());
-     close(pty.master).expect("closing the master failed");
-     close(pty.slave).expect("closing the slave failed");
- }
-@@ -46,14 +46,14 @@ fn test_tcgetattr_ebadf() {
- #[test]
- fn test_output_flags() {
-     // openpty uses ptname(3) internally
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open one pty to get attributes for the second one
-     let mut termios = {
-         let pty = openpty(None, None).expect("openpty failed");
-         assert!(pty.master > 0);
-         assert!(pty.slave > 0);
--        let termios = tcgetattr(pty.master).expect("tcgetattr failed");
-+        let termios = tcgetattr(pty.slave).expect("tcgetattr failed");
-         close(pty.master).unwrap();
-         close(pty.slave).unwrap();
-         termios
-@@ -77,7 +77,7 @@ fn test_output_flags() {
- 
-     // Read from the slave verifying that the output has been properly transformed
-     let mut buf = [0u8; 10];
--    ::read_exact(pty.slave, &mut buf);
-+    crate::read_exact(pty.slave, &mut buf);
-     let transformed_string = "foofoofoo\n";
-     close(pty.master).unwrap();
-     close(pty.slave).unwrap();
-@@ -88,14 +88,14 @@ fn test_output_flags() {
- #[test]
- fn test_local_flags() {
-     // openpty uses ptname(3) internally
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open one pty to get attributes for the second one
-     let mut termios = {
-         let pty = openpty(None, None).unwrap();
-         assert!(pty.master > 0);
-         assert!(pty.slave > 0);
--        let termios = tcgetattr(pty.master).unwrap();
-+        let termios = tcgetattr(pty.slave).unwrap();
-         close(pty.master).unwrap();
-         close(pty.slave).unwrap();
-         termios
-@@ -128,9 +128,3 @@ fn test_local_flags() {
-     close(pty.slave).unwrap();
-     assert_eq!(read, Error::Sys(Errno::EAGAIN));
- }
--
--#[test]
--fn test_cfmakeraw() {
--    let mut termios = unsafe { Termios::default_uninit() };
--    termios::cfmakeraw(&mut termios);
--}
-diff --git a/third_party/rust/nix/test/sys/test_timerfd.rs b/third_party/rust/nix/test/sys/test_timerfd.rs
-new file mode 100644
-index 0000000000000..24fb2ac002e1d
---- /dev/null
-+++ b/third_party/rust/nix/test/sys/test_timerfd.rs
-@@ -0,0 +1,61 @@
-+use nix::sys::time::{TimeSpec, TimeValLike};
-+use nix::sys::timerfd::{ClockId, Expiration, TimerFd, TimerFlags, TimerSetTimeFlags};
-+use std::time::Instant;
-+
-+#[test]
-+pub fn test_timerfd_oneshot() {
-+    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-+
-+    let before = Instant::now();
-+
-+    timer
-+        .set(
-+            Expiration::OneShot(TimeSpec::seconds(1)),
-+            TimerSetTimeFlags::empty(),
-+        )
-+        .unwrap();
-+
-+    timer.wait().unwrap();
-+
-+    let millis = before.elapsed().as_millis();
-+    assert!(millis > 900);
-+}
-+
-+#[test]
-+pub fn test_timerfd_interval() {
-+    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-+
-+    let before = Instant::now();
-+    timer
-+        .set(
-+            Expiration::IntervalDelayed(TimeSpec::seconds(1), TimeSpec::seconds(2)),
-+            TimerSetTimeFlags::empty(),
-+        )
-+        .unwrap();
-+
-+    timer.wait().unwrap();
-+
-+    let start_delay = before.elapsed().as_millis();
-+    assert!(start_delay > 900);
-+
-+    timer.wait().unwrap();
-+
-+    let interval_delay = before.elapsed().as_millis();
-+    assert!(interval_delay > 2900);
-+}
-+
-+#[test]
-+pub fn test_timerfd_unset() {
-+    let timer = TimerFd::new(ClockId::CLOCK_MONOTONIC, TimerFlags::empty()).unwrap();
-+
-+    timer
-+        .set(
-+            Expiration::OneShot(TimeSpec::seconds(1)),
-+            TimerSetTimeFlags::empty(),
-+        )
-+        .unwrap();
-+
-+    timer.unset().unwrap();
-+
-+    assert!(timer.get().unwrap() == None);
-+}
-diff --git a/third_party/rust/nix/test/sys/test_uio.rs b/third_party/rust/nix/test/sys/test_uio.rs
-index 3e4fc28ceb0e4..8d22bf1755a2c 100644
---- a/third_party/rust/nix/test/sys/test_uio.rs
-+++ b/third_party/rust/nix/test/sys/test_uio.rs
-@@ -6,7 +6,9 @@ use std::{cmp, iter};
- use std::fs::{OpenOptions};
- use std::os::unix::io::AsRawFd;
- 
--use tempfile::{tempfile, tempdir};
-+#[cfg(not(target_os = "redox"))]
-+use tempfile::tempfile;
-+use tempfile::tempdir;
- 
- #[test]
- fn test_writev() {
-@@ -53,6 +55,7 @@ fn test_writev() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_readv() {
-     let s:String = thread_rng().sample_iter(&Alphanumeric).take(128).collect();
-     let to_write = s.as_bytes().to_vec();
-@@ -97,6 +100,7 @@ fn test_readv() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_pwrite() {
-     use std::io::Read;
- 
-@@ -199,15 +203,17 @@ fn test_process_vm_readv() {
-     use nix::unistd::ForkResult::*;
-     use nix::sys::signal::*;
-     use nix::sys::wait::*;
-+    use crate::*;
- 
--    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    require_capability!(CAP_SYS_PTRACE);
-+    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Pre-allocate memory in the child, since allocation isn't safe
-     // post-fork (~= async-signal-safe)
-     let mut vector = vec![1u8, 2, 3, 4, 5];
- 
-     let (r, w) = pipe().unwrap();
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-         Parent { child } => {
-             close(w).unwrap();
-             // wait for child
-diff --git a/third_party/rust/nix/test/sys/test_wait.rs b/third_party/rust/nix/test/sys/test_wait.rs
-index d07d82f0d9075..5bb298eba4d29 100644
---- a/third_party/rust/nix/test/sys/test_wait.rs
-+++ b/third_party/rust/nix/test/sys/test_wait.rs
-@@ -6,11 +6,12 @@ use nix::sys::wait::*;
- use libc::_exit;
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_wait_signal() {
--    let _ = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _ = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Safe: The child only calls `pause` and/or `_exit`, which are async-signal-safe.
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-       Child => {
-           pause();
-           unsafe { _exit(123) }
-@@ -24,10 +25,10 @@ fn test_wait_signal() {
- 
- #[test]
- fn test_wait_exit() {
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Safe: Child only calls `_exit`, which is async-signal-safe.
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-       Child => unsafe { _exit(12); },
-       Parent { child } => {
-           assert_eq!(waitpid(child, None), Ok(WaitStatus::Exited(child, 12)));
-@@ -45,9 +46,9 @@ fn test_waitstatus_from_raw() {
- 
- #[test]
- fn test_waitstatus_pid() {
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
--    match fork().unwrap() {
-+    match unsafe{fork()}.unwrap() {
-         Child => unsafe { _exit(0) },
-         Parent { child } => {
-             let status = waitpid(child, None).unwrap();
-@@ -66,6 +67,7 @@ mod ptrace {
-     use nix::unistd::*;
-     use nix::unistd::ForkResult::*;
-     use libc::_exit;
-+    use crate::*;
- 
-     fn ptrace_child() -> ! {
-         ptrace::traceme().unwrap();
-@@ -82,7 +84,7 @@ mod ptrace {
-         assert!(ptrace::setoptions(child, Options::PTRACE_O_TRACESYSGOOD | Options::PTRACE_O_TRACEEXIT).is_ok());
- 
-         // First, stop on the next system call, which will be exit()
--        assert!(ptrace::syscall(child).is_ok());
-+        assert!(ptrace::syscall(child, None).is_ok());
-         assert_eq!(waitpid(child, None), Ok(WaitStatus::PtraceSyscall(child)));
-         // Then get the ptrace event for the process exiting
-         assert!(ptrace::cont(child, None).is_ok());
-@@ -94,9 +96,10 @@ mod ptrace {
- 
-     #[test]
-     fn test_wait_ptrace() {
--        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+        require_capability!(CAP_SYS_PTRACE);
-+        let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
--        match fork().expect("Error: Fork Failed") {
-+        match unsafe{fork()}.expect("Error: Fork Failed") {
-             Child => ptrace_child(),
-             Parent { child } => ptrace_parent(child),
-         }
-diff --git a/third_party/rust/nix/test/test.rs b/third_party/rust/nix/test/test.rs
-index 6a71d261b5712..5a5330b7e4010 100644
---- a/third_party/rust/nix/test/test.rs
-+++ b/third_party/rust/nix/test/test.rs
-@@ -1,69 +1,13 @@
--// XXX Allow deprecated items until release 0.16.0.  See issue #1096.
--#![allow(deprecated)]
--extern crate bytes;
--#[cfg(any(target_os = "android", target_os = "linux"))]
--extern crate caps;
- #[macro_use]
- extern crate cfg_if;
--#[macro_use]
-+#[cfg_attr(not(target_os = "redox"), macro_use)]
- extern crate nix;
- #[macro_use]
- extern crate lazy_static;
--extern crate libc;
--extern crate rand;
--#[cfg(target_os = "freebsd")]
--extern crate sysctl;
--extern crate tempfile;
--
--#[cfg(any(target_os = "android", target_os = "linux"))]
--macro_rules! require_capability {
--    ($capname:ident) => {
--        use ::caps::{Capability, CapSet, has_cap};
--        use ::std::io::{self, Write};
--
--        if !has_cap(None, CapSet::Effective, Capability::$capname).unwrap() {
--            let stderr = io::stderr();
--            let mut handle = stderr.lock();
--            writeln!(handle, "Insufficient capabilities. Skipping test.")
--                .unwrap();
--            return;
--        }
--    }
--}
--
--#[cfg(target_os = "freebsd")]
--macro_rules! skip_if_jailed {
--    ($name:expr) => {
--        use ::sysctl::CtlValue;
--
--        if let CtlValue::Int(1) = ::sysctl::value("security.jail.jailed")
--            .unwrap()
--        {
--            use ::std::io::Write;
--            let stderr = ::std::io::stderr();
--            let mut handle = stderr.lock();
--            writeln!(handle, "{} cannot run in a jail. Skipping test.", $name)
--                .unwrap();
--            return;
--        }
--    }
--}
--
--macro_rules! skip_if_not_root {
--    ($name:expr) => {
--        use nix::unistd::Uid;
--
--        if !Uid::current().is_root() {
--            use ::std::io::Write;
--            let stderr = ::std::io::stderr();
--            let mut handle = stderr.lock();
--            writeln!(handle, "{} requires root privileges. Skipping test.", $name).unwrap();
--            return;
--        }
--    };
--}
- 
-+mod common;
- mod sys;
-+#[cfg(not(target_os = "redox"))]
- mod test_dir;
- mod test_fcntl;
- #[cfg(any(target_os = "android",
-@@ -75,10 +19,15 @@ mod test_kmod;
-           target_os = "linux",
-           target_os = "netbsd"))]
- mod test_mq;
-+#[cfg(not(target_os = "redox"))]
- mod test_net;
- mod test_nix_path;
- mod test_poll;
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- mod test_pty;
-+#[cfg(any(target_os = "android",
-+          target_os = "linux"))]
-+mod test_sched;
- #[cfg(any(target_os = "android",
-           target_os = "freebsd",
-           target_os = "ios",
-@@ -86,6 +35,7 @@ mod test_pty;
-           target_os = "macos"))]
- mod test_sendfile;
- mod test_stat;
-+mod test_time;
- mod test_unistd;
- 
- use std::os::unix::io::RawFd;
-@@ -93,6 +43,7 @@ use std::path::PathBuf;
- use std::sync::{Mutex, RwLock, RwLockWriteGuard};
- use nix::unistd::{chdir, getcwd, read};
- 
-+
- /// Helper function analogous to `std::io::Read::read_exact`, but for `RawFD`s
- fn read_exact(f: RawFd, buf: &mut  [u8]) {
-     let mut len = 0;
-@@ -130,7 +81,7 @@ struct DirRestore<'a> {
- 
- impl<'a> DirRestore<'a> {
-     fn new() -> Self {
--        let guard = ::CWD_LOCK.write()
-+        let guard = crate::CWD_LOCK.write()
-             .expect("Lock got poisoned by another test");
-         DirRestore{
-             _g: guard,
-diff --git a/third_party/rust/nix/test/test_clearenv.rs b/third_party/rust/nix/test/test_clearenv.rs
-new file mode 100644
-index 0000000000000..28a77680498ca
---- /dev/null
-+++ b/third_party/rust/nix/test/test_clearenv.rs
-@@ -0,0 +1,9 @@
-+use std::env;
-+
-+#[test]
-+fn clearenv() {
-+    env::set_var("FOO", "BAR");
-+    unsafe { nix::env::clearenv() }.unwrap();
-+    assert_eq!(env::var("FOO").unwrap_err(), env::VarError::NotPresent);
-+    assert_eq!(env::vars().count(), 0);
-+}
-diff --git a/third_party/rust/nix/test/test_dir.rs b/third_party/rust/nix/test/test_dir.rs
-index c42fbcd18a29d..505277e7143b7 100644
---- a/third_party/rust/nix/test/test_dir.rs
-+++ b/third_party/rust/nix/test/test_dir.rs
-@@ -1,11 +1,8 @@
--extern crate nix;
--extern crate tempfile;
--
- use nix::dir::{Dir, Type};
- use nix::fcntl::OFlag;
- use nix::sys::stat::Mode;
- use std::fs::File;
--use self::tempfile::tempdir;
-+use tempfile::tempdir;
- 
- #[test]
- fn read() {
-@@ -37,7 +34,9 @@ fn rewind() {
-                             Mode::empty()).unwrap();
-     let entries1: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
-     let entries2: Vec<_> = dir.iter().map(|e| e.unwrap().file_name().to_owned()).collect();
-+    let entries3: Vec<_> = dir.into_iter().map(|e| e.unwrap().file_name().to_owned()).collect();
-     assert_eq!(entries1, entries2);
-+    assert_eq!(entries2, entries3);
- }
- 
- #[test]
-diff --git a/third_party/rust/nix/test/test_fcntl.rs b/third_party/rust/nix/test/test_fcntl.rs
-index 6b2bbd679fc31..5d1bafebe195f 100644
---- a/third_party/rust/nix/test/test_fcntl.rs
-+++ b/third_party/rust/nix/test/test_fcntl.rs
-@@ -1,14 +1,28 @@
-+#[cfg(not(target_os = "redox"))]
- use nix::Error;
-+#[cfg(not(target_os = "redox"))]
- use nix::errno::*;
--use nix::fcntl::{openat, open, OFlag, readlink, readlinkat, renameat};
-+#[cfg(not(target_os = "redox"))]
-+use nix::fcntl::{open, OFlag, readlink};
-+#[cfg(not(target_os = "redox"))]
-+use nix::fcntl::{openat, readlinkat, renameat};
-+#[cfg(not(target_os = "redox"))]
- use nix::sys::stat::Mode;
-+#[cfg(not(target_os = "redox"))]
- use nix::unistd::{close, read};
-+#[cfg(not(target_os = "redox"))]
- use tempfile::{self, NamedTempFile};
-+#[cfg(not(target_os = "redox"))]
- use std::fs::File;
-+#[cfg(not(target_os = "redox"))]
- use std::io::prelude::*;
-+#[cfg(not(target_os = "redox"))]
- use std::os::unix::fs;
- 
-+use crate::*;
-+
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_openat() {
-     const CONTENTS: &[u8] = b"abcd";
-     let mut tmp = NamedTempFile::new().unwrap();
-@@ -31,6 +45,7 @@ fn test_openat() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_renameat() {
-     let old_dir = tempfile::tempdir().unwrap();
-     let old_dirfd = open(old_dir.path(), OFlag::empty(), Mode::empty()).unwrap();
-@@ -47,6 +62,7 @@ fn test_renameat() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_readlink() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let src = tempdir.path().join("a");
-@@ -56,28 +72,31 @@ fn test_readlink() {
-     let dirfd = open(tempdir.path(),
-                      OFlag::empty(),
-                      Mode::empty()).unwrap();
-+    let expected_dir = src.to_str().unwrap();
-+
-+    assert_eq!(readlink(&dst).unwrap().to_str().unwrap(), expected_dir);
-+    assert_eq!(readlinkat(dirfd, "b").unwrap().to_str().unwrap(), expected_dir);
- 
--    let mut buf = vec![0; src.to_str().unwrap().len() + 1];
--    assert_eq!(readlink(&dst, &mut buf).unwrap().to_str().unwrap(),
--               src.to_str().unwrap());
--    assert_eq!(readlinkat(dirfd, "b", &mut buf).unwrap().to_str().unwrap(),
--               src.to_str().unwrap());
- }
- 
- #[cfg(any(target_os = "linux", target_os = "android"))]
- mod linux_android {
-+    use std::fs::File;
-     use std::io::prelude::*;
--    use std::io::SeekFrom;
-+    use std::io::{BufRead, BufReader, SeekFrom};
-     use std::os::unix::prelude::*;
- 
-     use libc::loff_t;
- 
-     use nix::fcntl::*;
-+    use nix::sys::stat::fstat;
-     use nix::sys::uio::IoVec;
-     use nix::unistd::{close, pipe, read, write};
- 
-     use tempfile::{tempfile, NamedTempFile};
- 
-+    use crate::*;
-+
-     /// This test creates a temporary file containing the contents
-     /// 'foobarbaz' and uses the `copy_file_range` call to transfer
-     /// 3 bytes at offset 3 (`bar`) to another empty file at offset 0. The
-@@ -198,6 +217,113 @@ mod linux_android {
-         let mut buf = [0u8; 200];
-         assert_eq!(100, read(fd, &mut buf).unwrap());
-     }
-+
-+    // The tests below are disabled for the listed targets
-+    // due to OFD locks not being available in the kernel/libc
-+    // versions used in the CI environment, probably because
-+    // they run under QEMU.
-+
-+    #[test]
-+    #[cfg(not(any(target_arch = "aarch64",
-+                  target_arch = "arm",
-+                  target_arch = "armv7",
-+                  target_arch = "x86",
-+                  target_arch = "mips",
-+                  target_arch = "mips64",
-+                  target_arch = "mips64el",
-+                  target_arch = "powerpc64",
-+                  target_arch = "powerpc64le",
-+                  target_env = "musl")))]
-+    fn test_ofd_write_lock() {
-+        let tmp = NamedTempFile::new().unwrap();
-+
-+        let fd = tmp.as_raw_fd();
-+        let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
-+        if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
-+            // OverlayFS is a union file system.  It returns one inode value in
-+            // stat(2), but a different one shows up in /proc/locks.  So we must
-+            // skip the test.
-+            skip!("/proc/locks does not work on overlayfs");
-+        }
-+        let inode = fstat(fd).expect("fstat failed").st_ino as usize;
-+
-+        let mut flock = libc::flock {
-+            l_type: libc::F_WRLCK as libc::c_short,
-+            l_whence: libc::SEEK_SET as libc::c_short,
-+            l_start: 0,
-+            l_len: 0,
-+            l_pid: 0,
-+        };
-+        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write lock failed");
-+        assert_eq!(
-+            Some(("OFDLCK".to_string(), "WRITE".to_string())),
-+            lock_info(inode)
-+        );
-+
-+        flock.l_type = libc::F_UNLCK as libc::c_short;
-+        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("write unlock failed");
-+        assert_eq!(None, lock_info(inode));
-+    }
-+
-+    #[test]
-+    #[cfg(not(any(target_arch = "aarch64",
-+                  target_arch = "arm",
-+                  target_arch = "armv7",
-+                  target_arch = "x86",
-+                  target_arch = "mips",
-+                  target_arch = "mips64",
-+                  target_arch = "mips64el",
-+                  target_arch = "powerpc64",
-+                  target_arch = "powerpc64le",
-+                  target_env = "musl")))]
-+    fn test_ofd_read_lock() {
-+        let tmp = NamedTempFile::new().unwrap();
-+
-+        let fd = tmp.as_raw_fd();
-+        let statfs = nix::sys::statfs::fstatfs(&tmp).unwrap();
-+        if statfs.filesystem_type() == nix::sys::statfs::OVERLAYFS_SUPER_MAGIC {
-+            // OverlayFS is a union file system.  It returns one inode value in
-+            // stat(2), but a different one shows up in /proc/locks.  So we must
-+            // skip the test.
-+            skip!("/proc/locks does not work on overlayfs");
-+        }
-+        let inode = fstat(fd).expect("fstat failed").st_ino as usize;
-+
-+        let mut flock = libc::flock {
-+            l_type: libc::F_RDLCK as libc::c_short,
-+            l_whence: libc::SEEK_SET as libc::c_short,
-+            l_start: 0,
-+            l_len: 0,
-+            l_pid: 0,
-+        };
-+        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read lock failed");
-+        assert_eq!(
-+            Some(("OFDLCK".to_string(), "READ".to_string())),
-+            lock_info(inode)
-+        );
-+
-+        flock.l_type = libc::F_UNLCK as libc::c_short;
-+        fcntl(fd, FcntlArg::F_OFD_SETLKW(&flock)).expect("read unlock failed");
-+        assert_eq!(None, lock_info(inode));
-+    }
-+
-+    fn lock_info(inode: usize) -> Option<(String, String)> {
-+        let file = File::open("/proc/locks").expect("open /proc/locks failed");
-+        let buf = BufReader::new(file);
-+
-+        for line in buf.lines() {
-+            let line = line.unwrap();
-+            let parts: Vec<_> = line.split_whitespace().collect();
-+            let lock_type = parts[1];
-+            let lock_access = parts[3];
-+            let ino_parts: Vec<_> = parts[5].split(':').collect();
-+            let ino: usize = ino_parts[2].parse().unwrap();
-+            if ino == inode {
-+                return Some((lock_type.to_string(), lock_access.to_string()));
-+            }
-+        }
-+        None
-+    }
- }
- 
- #[cfg(any(target_os = "linux",
-@@ -206,7 +332,7 @@ mod linux_android {
-           target_os = "fuchsia",
-           any(target_os = "wasi", target_env = "wasi"),
-           target_env = "uclibc",
--          target_env = "freebsd"))]
-+          target_os = "freebsd"))]
- mod test_posix_fadvise {
- 
-     use tempfile::NamedTempFile;
-@@ -232,3 +358,60 @@ mod test_posix_fadvise {
-         assert_eq!(errno, Errno::ESPIPE as i32);
-     }
- }
-+
-+#[cfg(any(target_os = "linux",
-+          target_os = "android",
-+          target_os = "emscripten",
-+          target_os = "fuchsia",
-+          any(target_os = "wasi", target_env = "wasi"),
-+          target_os = "freebsd"))]
-+mod test_posix_fallocate {
-+
-+    use tempfile::NamedTempFile;
-+    use std::{io::Read, os::unix::io::{RawFd, AsRawFd}};
-+    use nix::errno::Errno;
-+    use nix::fcntl::*;
-+    use nix::unistd::pipe;
-+
-+    #[test]
-+    fn success() {
-+        const LEN: usize = 100;
-+        let mut tmp = NamedTempFile::new().unwrap();
-+        let fd = tmp.as_raw_fd();
-+        let res = posix_fallocate(fd, 0, LEN as libc::off_t);
-+        match res {
-+            Ok(_) => {
-+                let mut data = [1u8; LEN];
-+                assert_eq!(tmp.read(&mut data).expect("read failure"), LEN);
-+                assert_eq!(&data[..], &[0u8; LEN][..]);
-+            }
-+            Err(nix::Error::Sys(Errno::EINVAL)) => {
-+                // POSIX requires posix_fallocate to return EINVAL both for
-+                // invalid arguments (i.e. len < 0) and if the operation is not
-+                // supported by the file system.
-+                // There's no way to tell for sure whether the file system
-+                // supports posix_fallocate, so we must pass the test if it
-+                // returns EINVAL.
-+            }
-+            _ => res.unwrap(),
-+        }
-+    }
-+
-+    #[test]
-+    fn errno() {
-+        let (rd, _wr) = pipe().unwrap();
-+        let err = posix_fallocate(rd as RawFd, 0, 100).unwrap_err();
-+        use nix::Error::Sys;
-+        match err {
-+            Sys(Errno::EINVAL)
-+                | Sys(Errno::ENODEV)
-+                | Sys(Errno::ESPIPE)
-+                | Sys(Errno::EBADF) => (),
-+            errno =>
-+                panic!(
-+                    "unexpected errno {}",
-+                    errno,
-+                ),
-+        }
-+    }
-+}
-diff --git a/third_party/rust/nix/test/test_kmod/mod.rs b/third_party/rust/nix/test/test_kmod/mod.rs
-index ad406357b06d2..fb7260ba9c9d9 100644
---- a/third_party/rust/nix/test/test_kmod/mod.rs
-+++ b/third_party/rust/nix/test/test_kmod/mod.rs
-@@ -2,9 +2,10 @@ use std::fs::copy;
- use std::path::PathBuf;
- use std::process::Command;
- use tempfile::{tempdir, TempDir};
-+use crate::*;
- 
- fn compile_kernel_module() -> (PathBuf, String, TempDir) {
--    let _m = ::FORK_MTX
-+    let _m = crate::FORK_MTX
-         .lock()
-         .expect("Mutex got poisoned by another test");
- 
-@@ -41,8 +42,8 @@ use std::io::Read;
- #[test]
- fn test_finit_and_delete_module() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
- 
-@@ -59,8 +60,8 @@ fn test_finit_and_delete_module() {
- #[test]
- fn test_finit_and_delete_modul_with_params() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
- 
-@@ -80,8 +81,8 @@ fn test_finit_and_delete_modul_with_params() {
- #[test]
- fn test_init_and_delete_module() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
- 
-@@ -100,8 +101,8 @@ fn test_init_and_delete_module() {
- #[test]
- fn test_init_and_delete_module_with_params() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
- 
-@@ -121,8 +122,8 @@ fn test_init_and_delete_module_with_params() {
- #[test]
- fn test_finit_module_invalid() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let kmod_path = "/dev/zero";
- 
-@@ -135,8 +136,8 @@ fn test_finit_module_invalid() {
- #[test]
- fn test_finit_module_twice_and_delete_module() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let (kmod_path, kmod_name, _kmod_dir) = compile_kernel_module();
- 
-@@ -157,8 +158,8 @@ fn test_finit_module_twice_and_delete_module() {
- #[test]
- fn test_delete_module_not_loaded() {
-     require_capability!(CAP_SYS_MODULE);
--    let _m0 = ::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
--    let _m1 = ::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::KMOD_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
- 
-     let result = delete_module(&CString::new("hello").unwrap(), DeleteModuleFlags::empty());
- 
-diff --git a/third_party/rust/nix/test/test_mount.rs b/third_party/rust/nix/test/test_mount.rs
-index d2e08bc42855d..c1b6c8a3bf2d2 100644
---- a/third_party/rust/nix/test/test_mount.rs
-+++ b/third_party/rust/nix/test/test_mount.rs
-@@ -1,12 +1,10 @@
-+mod common;
-+
- // Impelmentation note: to allow unprivileged users to run it, this test makes
- // use of user and mount namespaces. On systems that allow unprivileged user
- // namespaces (Linux >= 3.8 compiled with CONFIG_USER_NS), the test should run
- // without root.
- 
--extern crate libc;
--extern crate nix;
--extern crate tempfile;
--
- #[cfg(target_os = "linux")]
- mod test_mount {
-     use std::fs::{self, File};
-@@ -226,6 +224,7 @@ fn main() {
-     use test_mount::{setup_namespaces, test_mount_tmpfs_without_flags_allows_rwx,
-                      test_mount_rdonly_disallows_write, test_mount_noexec_disallows_exec,
-                      test_mount_bind};
-+    skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1351");
-     setup_namespaces();
- 
-     run_tests!(test_mount_tmpfs_without_flags_allows_rwx,
-diff --git a/third_party/rust/nix/test/test_mq.rs b/third_party/rust/nix/test/test_mq.rs
-index caac4fc261cd6..1667a35b1a04b 100644
---- a/third_party/rust/nix/test/test_mq.rs
-+++ b/third_party/rust/nix/test/test_mq.rs
-@@ -1,17 +1,15 @@
--use libc::c_long;
--
- use std::ffi::CString;
- use std::str;
- 
- use nix::errno::Errno::*;
- use nix::Error::Sys;
--use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive};
-+use nix::mqueue::{mq_open, mq_close, mq_send, mq_receive, mq_attr_member_t};
- use nix::mqueue::{MqAttr, MQ_OFlag};
- use nix::sys::stat::Mode;
- 
- #[test]
- fn test_mq_send_and_receive() {
--    const MSG_SIZE: c_long =  32;
-+    const MSG_SIZE: mq_attr_member_t = 32;
-     let attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-     let mq_name= &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
- 
-@@ -31,7 +29,7 @@ fn test_mq_send_and_receive() {
-     let mut buf = [0u8; 32];
-     let mut prio = 0u32;
-     let len = mq_receive(mqd1, &mut buf, &mut prio).unwrap();
--    assert!(prio == 1);
-+    assert_eq!(prio, 1);
- 
-     mq_close(mqd1).unwrap();
-     mq_close(mqd0).unwrap();
-@@ -43,7 +41,7 @@ fn test_mq_send_and_receive() {
- #[cfg(not(any(target_os = "netbsd")))]
- fn test_mq_getattr() {
-     use nix::mqueue::mq_getattr;
--    const MSG_SIZE: c_long =  32;
-+    const MSG_SIZE: mq_attr_member_t = 32;
-     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-@@ -66,7 +64,7 @@ fn test_mq_getattr() {
- #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
- fn test_mq_setattr() {
-     use nix::mqueue::{mq_getattr, mq_setattr};
--    const MSG_SIZE: c_long =  32;
-+    const MSG_SIZE: mq_attr_member_t = 32;
-     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-@@ -87,7 +85,7 @@ fn test_mq_setattr() {
-     // O_NONBLOCK can be set (see tests below)
-     assert_ne!(new_attr_get, new_attr);
- 
--    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as c_long, 10, MSG_SIZE, 0);
-+    let new_attr_non_blocking =  MqAttr::new(MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t, 10, MSG_SIZE, 0);
-     mq_setattr(mqd, &new_attr_non_blocking).unwrap();
-     let new_attr_get = mq_getattr(mqd).unwrap();
- 
-@@ -103,7 +101,7 @@ fn test_mq_setattr() {
- #[cfg_attr(any(target_arch = "mips", target_arch = "mips64"), ignore)]
- fn test_mq_set_nonblocking() {
-     use nix::mqueue::{mq_getattr, mq_set_nonblock, mq_remove_nonblock};
--    const MSG_SIZE: c_long =  32;
-+    const MSG_SIZE: mq_attr_member_t = 32;
-     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-     let mq_name = &CString::new(b"/attr_test_get_attr".as_ref()).unwrap();
-     let oflag = MQ_OFlag::O_CREAT | MQ_OFlag::O_WRONLY;
-@@ -116,10 +114,10 @@ fn test_mq_set_nonblocking() {
-     let mqd = r.unwrap();
-     mq_set_nonblock(mqd).unwrap();
-     let new_attr = mq_getattr(mqd);
--    assert!(new_attr.unwrap().flags() == MQ_OFlag::O_NONBLOCK.bits() as c_long);
-+    assert_eq!(new_attr.unwrap().flags(), MQ_OFlag::O_NONBLOCK.bits() as mq_attr_member_t);
-     mq_remove_nonblock(mqd).unwrap();
-     let new_attr = mq_getattr(mqd);
--    assert!(new_attr.unwrap().flags() == 0);
-+    assert_eq!(new_attr.unwrap().flags(), 0);
-     mq_close(mqd).unwrap();
- }
- 
-@@ -127,7 +125,7 @@ fn test_mq_set_nonblocking() {
- #[cfg(not(any(target_os = "netbsd")))]
- fn test_mq_unlink() {
-     use nix::mqueue::mq_unlink;
--    const MSG_SIZE: c_long =  32;
-+    const MSG_SIZE: mq_attr_member_t = 32;
-     let initial_attr =  MqAttr::new(0, 10, MSG_SIZE, 0);
-     let mq_name_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
-     let mq_name_not_opened = &CString::new(b"/mq_unlink_test".as_ref()).unwrap();
-@@ -141,12 +139,12 @@ fn test_mq_unlink() {
-     let mqd = r.unwrap();
- 
-     let res_unlink = mq_unlink(mq_name_opened);
--    assert!(res_unlink == Ok(()) );
-+    assert_eq!(res_unlink, Ok(()) );
- 
-     let res_unlink_not_opened = mq_unlink(mq_name_not_opened);
--    assert!(res_unlink_not_opened == Err(Sys(ENOENT)) );
-+    assert_eq!(res_unlink_not_opened, Err(Sys(ENOENT)) );
- 
-     mq_close(mqd).unwrap();
-     let res_unlink_after_close = mq_unlink(mq_name_opened);
--    assert!(res_unlink_after_close == Err(Sys(ENOENT)) );
-+    assert_eq!(res_unlink_after_close, Err(Sys(ENOENT)) );
- }
-diff --git a/third_party/rust/nix/test/test_poll.rs b/third_party/rust/nix/test/test_poll.rs
-index aef40e4792b5a..acfaad8bea6c0 100644
---- a/third_party/rust/nix/test/test_poll.rs
-+++ b/third_party/rust/nix/test/test_poll.rs
-@@ -1,5 +1,21 @@
--use nix::poll::{PollFlags, poll, PollFd};
--use nix::unistd::{write, pipe};
-+use nix::{
-+    Error,
-+    errno::Errno,
-+    poll::{PollFlags, poll, PollFd},
-+    unistd::{write, pipe}
-+};
-+
-+macro_rules! loop_while_eintr {
-+    ($poll_expr: expr) => {
-+        loop {
-+            match $poll_expr {
-+                Ok(nfds) => break nfds,
-+                Err(Error::Sys(Errno::EINTR)) => (),
-+                Err(e) => panic!("{}", e)
-+            }
-+        }
-+    }
-+}
- 
- #[test]
- fn test_poll() {
-@@ -7,7 +23,7 @@ fn test_poll() {
-     let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
- 
-     // Poll an idle pipe.  Should timeout
--    let nfds = poll(&mut fds, 100).unwrap();
-+    let nfds = loop_while_eintr!(poll(&mut fds, 100));
-     assert_eq!(nfds, 0);
-     assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- 
-@@ -37,14 +53,15 @@ fn test_ppoll() {
-     let mut fds = [PollFd::new(r, PollFlags::POLLIN)];
- 
-     // Poll an idle pipe.  Should timeout
--    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
-+    let sigset = SigSet::empty();
-+    let nfds = loop_while_eintr!(ppoll(&mut fds, Some(timeout), sigset));
-     assert_eq!(nfds, 0);
-     assert!(!fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- 
-     write(w, b".").unwrap();
- 
-     // Poll a readable pipe.  Should return an event.
--    let nfds = ppoll(&mut fds, timeout, SigSet::empty()).unwrap();
-+    let nfds = ppoll(&mut fds, Some(timeout), SigSet::empty()).unwrap();
-     assert_eq!(nfds, 1);
-     assert!(fds[0].revents().unwrap().contains(PollFlags::POLLIN));
- }
-diff --git a/third_party/rust/nix/test/test_pty.rs b/third_party/rust/nix/test/test_pty.rs
-index 476b15c10128c..ab347bb040f5f 100644
---- a/third_party/rust/nix/test/test_pty.rs
-+++ b/third_party/rust/nix/test/test_pty.rs
-@@ -1,4 +1,5 @@
--use std::io::Write;
-+use std::fs::File;
-+use std::io::{Read, Write};
- use std::path::Path;
- use std::os::unix::prelude::*;
- use tempfile::tempfile;
-@@ -28,7 +29,7 @@ fn test_explicit_close() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptsname_equivalence() {
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open a new PTTY master
-     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-@@ -45,7 +46,7 @@ fn test_ptsname_equivalence() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptsname_copy() {
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open a new PTTY master
-     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-@@ -54,7 +55,7 @@ fn test_ptsname_copy() {
-     // Get the name of the slave
-     let slave_name1 = unsafe { ptsname(&master_fd) }.unwrap();
-     let slave_name2 = unsafe { ptsname(&master_fd) }.unwrap();
--    assert!(slave_name1 == slave_name2);
-+    assert_eq!(slave_name1, slave_name2);
-     // Also make sure that the string was actually copied and they point to different parts of
-     // memory.
-     assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
-@@ -71,7 +72,7 @@ fn test_ptsname_r_copy() {
-     // Get the name of the slave
-     let slave_name1 = ptsname_r(&master_fd).unwrap();
-     let slave_name2 = ptsname_r(&master_fd).unwrap();
--    assert!(slave_name1 == slave_name2);
-+    assert_eq!(slave_name1, slave_name2);
-     assert!(slave_name1.as_ptr() != slave_name2.as_ptr());
- }
- 
-@@ -79,7 +80,7 @@ fn test_ptsname_r_copy() {
- #[test]
- #[cfg(any(target_os = "android", target_os = "linux"))]
- fn test_ptsname_unique() {
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open a new PTTY master
-     let master1_fd = posix_openpt(OFlag::O_RDWR).unwrap();
-@@ -95,35 +96,74 @@ fn test_ptsname_unique() {
-     assert!(slave_name1 != slave_name2);
- }
- 
--/// Test opening a master/slave PTTY pair
--///
--/// This is a single larger test because much of these functions aren't useful by themselves. So for
--/// this test we perform the basic act of getting a file handle for a connect master/slave PTTY
--/// pair.
--#[test]
--fn test_open_ptty_pair() {
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+/// Common setup for testing PTTY pairs
-+fn open_ptty_pair() -> (PtyMaster, File) {
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open a new PTTY master
--    let master_fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
--    assert!(master_fd.as_raw_fd() > 0);
-+    let master = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
- 
-     // Allow a slave to be generated for it
--    grantpt(&master_fd).expect("grantpt failed");
--    unlockpt(&master_fd).expect("unlockpt failed");
-+    grantpt(&master).expect("grantpt failed");
-+    unlockpt(&master).expect("unlockpt failed");
- 
-     // Get the name of the slave
--    let slave_name = unsafe { ptsname(&master_fd) }.expect("ptsname failed");
-+    let slave_name = unsafe { ptsname(&master) }.expect("ptsname failed");
- 
-     // Open the slave device
-     let slave_fd = open(Path::new(&slave_name), OFlag::O_RDWR, stat::Mode::empty()).unwrap();
--    assert!(slave_fd > 0);
-+    let slave = unsafe { File::from_raw_fd(slave_fd) };
-+
-+    (master, slave)
-+}
-+
-+/// Test opening a master/slave PTTY pair
-+///
-+/// This uses a common `open_ptty_pair` because much of these functions aren't useful by
-+/// themselves. So for this test we perform the basic act of getting a file handle for a
-+/// master/slave PTTY pair, then just sanity-check the raw values.
-+#[test]
-+fn test_open_ptty_pair() {
-+    let (master, slave) = open_ptty_pair();
-+    assert!(master.as_raw_fd() > 0);
-+    assert!(slave.as_raw_fd() > 0);
-+}
-+
-+/// Put the terminal in raw mode.
-+fn make_raw(fd: RawFd) {
-+    let mut termios = tcgetattr(fd).unwrap();
-+    cfmakeraw(&mut termios);
-+    tcsetattr(fd, SetArg::TCSANOW, &termios).unwrap();
-+}
-+
-+/// Test `io::Read` on the PTTY master
-+#[test]
-+fn test_read_ptty_pair() {
-+    let (mut master, mut slave) = open_ptty_pair();
-+    make_raw(slave.as_raw_fd());
-+
-+    let mut buf = [0u8; 5];
-+    slave.write_all(b"hello").unwrap();
-+    master.read_exact(&mut buf).unwrap();
-+    assert_eq!(&buf, b"hello");
-+}
-+
-+/// Test `io::Write` on the PTTY master
-+#[test]
-+fn test_write_ptty_pair() {
-+    let (mut master, mut slave) = open_ptty_pair();
-+    make_raw(slave.as_raw_fd());
-+
-+    let mut buf = [0u8; 5];
-+    master.write_all(b"adios").unwrap();
-+    slave.read_exact(&mut buf).unwrap();
-+    assert_eq!(&buf, b"adios");
- }
- 
- #[test]
- fn test_openpty() {
-     // openpty uses ptname(3) internally
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     let pty = openpty(None, None).unwrap();
-     assert!(pty.master > 0);
-@@ -133,21 +173,21 @@ fn test_openpty() {
-     let string = "foofoofoo\n";
-     let mut buf = [0u8; 10];
-     write(pty.master, string.as_bytes()).unwrap();
--    ::read_exact(pty.slave, &mut buf);
-+    crate::read_exact(pty.slave, &mut buf);
- 
-     assert_eq!(&buf, string.as_bytes());
- 
-     // Read the echo as well
-     let echoed_string = "foofoofoo\r\n";
-     let mut buf = [0u8; 11];
--    ::read_exact(pty.master, &mut buf);
-+    crate::read_exact(pty.master, &mut buf);
-     assert_eq!(&buf, echoed_string.as_bytes());
- 
-     let string2 = "barbarbarbar\n";
-     let echoed_string2 = "barbarbarbar\r\n";
-     let mut buf = [0u8; 14];
-     write(pty.slave, string2.as_bytes()).unwrap();
--    ::read_exact(pty.master, &mut buf);
-+    crate::read_exact(pty.master, &mut buf);
- 
-     assert_eq!(&buf, echoed_string2.as_bytes());
- 
-@@ -158,14 +198,14 @@ fn test_openpty() {
- #[test]
- fn test_openpty_with_termios() {
-     // openpty uses ptname(3) internally
--    let _m = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Open one pty to get attributes for the second one
-     let mut termios = {
-         let pty = openpty(None, None).unwrap();
-         assert!(pty.master > 0);
-         assert!(pty.slave > 0);
--        let termios = tcgetattr(pty.master).unwrap();
-+        let termios = tcgetattr(pty.slave).unwrap();
-         close(pty.master).unwrap();
-         close(pty.slave).unwrap();
-         termios
-@@ -182,20 +222,20 @@ fn test_openpty_with_termios() {
-     let string = "foofoofoo\n";
-     let mut buf = [0u8; 10];
-     write(pty.master, string.as_bytes()).unwrap();
--    ::read_exact(pty.slave, &mut buf);
-+    crate::read_exact(pty.slave, &mut buf);
- 
-     assert_eq!(&buf, string.as_bytes());
- 
-     // read the echo as well
-     let echoed_string = "foofoofoo\n";
--    ::read_exact(pty.master, &mut buf);
-+    crate::read_exact(pty.master, &mut buf);
-     assert_eq!(&buf, echoed_string.as_bytes());
- 
-     let string2 = "barbarbarbar\n";
-     let echoed_string2 = "barbarbarbar\n";
-     let mut buf = [0u8; 13];
-     write(pty.slave, string2.as_bytes()).unwrap();
--    ::read_exact(pty.master, &mut buf);
-+    crate::read_exact(pty.master, &mut buf);
- 
-     assert_eq!(&buf, echoed_string2.as_bytes());
- 
-@@ -209,9 +249,9 @@ fn test_forkpty() {
-     use nix::sys::signal::*;
-     use nix::sys::wait::wait;
-     // forkpty calls openpty which uses ptname(3) internally.
--    let _m0 = ::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m0 = crate::PTSNAME_MTX.lock().expect("Mutex got poisoned by another test");
-     // forkpty spawns a child process
--    let _m1 = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m1 = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     let string = "naninani\n";
-     let echoed_string = "naninani\r\n";
-@@ -225,7 +265,7 @@ fn test_forkpty() {
-         Parent { child } => {
-             let mut buf = [0u8; 10];
-             assert!(child.as_raw() > 0);
--            ::read_exact(pty.master, &mut buf);
-+            crate::read_exact(pty.master, &mut buf);
-             kill(child, SIGTERM).unwrap();
-             wait().unwrap(); // keep other tests using generic wait from getting our child
-             assert_eq!(&buf, echoed_string.as_bytes());
-diff --git a/third_party/rust/nix/test/test_ptymaster_drop.rs b/third_party/rust/nix/test/test_ptymaster_drop.rs
-index 9b59d66435ed0..ff939b9c63e76 100644
---- a/third_party/rust/nix/test/test_ptymaster_drop.rs
-+++ b/third_party/rust/nix/test/test_ptymaster_drop.rs
-@@ -1,21 +1,24 @@
--extern crate nix;
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+mod t {
-+    use nix::fcntl::OFlag;
-+    use nix::pty::*;
-+    use nix::unistd::close;
-+    use std::os::unix::io::AsRawFd;
- 
--use nix::fcntl::OFlag;
--use nix::pty::*;
--use nix::unistd::close;
--use std::os::unix::io::AsRawFd;
--
--/// Regression test for Issue #659
--/// `PtyMaster` should panic rather than double close the file descriptor
--/// This must run in its own test process because it deliberately creates a race
--/// condition.
--#[test]
--#[should_panic(expected = "Closing an invalid file descriptor!")]
--// In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't know
--// why.  It doesn't happen on any other target, and it doesn't happen on my PC.
--#[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
--fn test_double_close() {
--    let m = posix_openpt(OFlag::O_RDWR).unwrap();
--    close(m.as_raw_fd()).unwrap();
--    drop(m);            // should panic here
-+    /// Regression test for Issue #659
-+    ///
-+    /// `PtyMaster` should panic rather than double close the file descriptor
-+    /// This must run in its own test process because it deliberately creates a
-+    /// race condition.
-+    #[test]
-+    #[should_panic(expected = "Closing an invalid file descriptor!")]
-+    // In Travis on i686-unknown-linux-musl, this test gets SIGABRT.  I don't
-+    // know why.  It doesn't happen on any other target, and it doesn't happen
-+    // on my PC.
-+    #[cfg_attr(all(target_env = "musl", target_arch = "x86"), ignore)]
-+    fn test_double_close() {
-+        let m = posix_openpt(OFlag::O_RDWR).unwrap();
-+        close(m.as_raw_fd()).unwrap();
-+        drop(m);            // should panic here
-+    }
- }
-diff --git a/third_party/rust/nix/test/test_sched.rs b/third_party/rust/nix/test/test_sched.rs
-new file mode 100644
-index 0000000000000..922196a3dba73
---- /dev/null
-+++ b/third_party/rust/nix/test/test_sched.rs
-@@ -0,0 +1,32 @@
-+use nix::sched::{sched_getaffinity, sched_setaffinity, CpuSet};
-+use nix::unistd::Pid;
-+
-+#[test]
-+fn test_sched_affinity() {
-+    // If pid is zero, then the mask of the calling process is returned.
-+    let initial_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
-+    let mut at_least_one_cpu = false;
-+    let mut last_valid_cpu = 0;
-+    for field in 0..CpuSet::count() {
-+        if initial_affinity.is_set(field).unwrap() {
-+            at_least_one_cpu = true;
-+            last_valid_cpu = field;
-+        }
-+    }
-+    assert!(at_least_one_cpu);
-+
-+    // Now restrict the running CPU
-+    let mut new_affinity = CpuSet::new();
-+    new_affinity.set(last_valid_cpu).unwrap();
-+    sched_setaffinity(Pid::from_raw(0), &new_affinity).unwrap();
-+
-+    // And now re-check the affinity which should be only the one we set.
-+    let updated_affinity = sched_getaffinity(Pid::from_raw(0)).unwrap();
-+    for field in 0..CpuSet::count() {
-+        // Should be set only for the CPU we set previously
-+        assert_eq!(updated_affinity.is_set(field).unwrap(), field==last_valid_cpu)
-+    }
-+
-+    // Finally, reset the initial CPU set
-+    sched_setaffinity(Pid::from_raw(0), &initial_affinity).unwrap();
-+}
-diff --git a/third_party/rust/nix/test/test_stat.rs b/third_party/rust/nix/test/test_stat.rs
-index 1173455fae8db..0b9466685607b 100644
---- a/third_party/rust/nix/test/test_stat.rs
-+++ b/third_party/rust/nix/test/test_stat.rs
-@@ -1,15 +1,26 @@
--use std::fs::{self, File};
-+#[cfg(not(target_os = "redox"))]
-+use std::fs;
-+use std::fs::File;
-+#[cfg(not(target_os = "redox"))]
- use std::os::unix::fs::{symlink, PermissionsExt};
- use std::os::unix::prelude::AsRawFd;
-+#[cfg(not(target_os = "redox"))]
- use std::time::{Duration, UNIX_EPOCH};
-+#[cfg(not(target_os = "redox"))]
- use std::path::Path;
- 
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- use libc::{S_IFMT, S_IFLNK, mode_t};
- 
-+#[cfg(not(target_os = "redox"))]
- use nix::{fcntl, Error};
--use nix::errno::{Errno};
--use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat, mkdirat};
-+#[cfg(not(target_os = "redox"))]
-+use nix::errno::Errno;
-+#[cfg(not(target_os = "redox"))]
-+use nix::sys::stat::{self, futimens, utimes};
-+use nix::sys::stat::{fchmod, stat};
-+#[cfg(not(target_os = "redox"))]
-+use nix::sys::stat::{fchmodat, utimensat, mkdirat};
- #[cfg(any(target_os = "linux",
-           target_os = "haiku",
-           target_os = "ios",
-@@ -17,15 +28,19 @@ use nix::sys::stat::{self, fchmod, fchmodat, futimens, stat, utimes, utimensat,
-           target_os = "freebsd",
-           target_os = "netbsd"))]
- use nix::sys::stat::lutimes;
--use nix::sys::stat::{Mode, FchmodatFlags, UtimensatFlags};
-+#[cfg(not(target_os = "redox"))]
-+use nix::sys::stat::{FchmodatFlags, UtimensatFlags};
-+use nix::sys::stat::Mode;
- 
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- use nix::sys::stat::FileStat;
- 
-+#[cfg(not(target_os = "redox"))]
- use nix::sys::time::{TimeSpec, TimeVal, TimeValLike};
-+#[cfg(not(target_os = "redox"))]
- use nix::unistd::chdir;
- 
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- use nix::Result;
- use tempfile;
- 
-@@ -33,27 +48,27 @@ use tempfile;
- // uid and gid are signed on Windows, but not on other platforms. This function
- // allows warning free compiles on all platforms, and can be removed when
- // expression-level #[allow] is available.
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn valid_uid_gid(stat: FileStat) -> bool {
-     // uid could be 0 for the `root` user. This quite possible when
-     // the tests are being run on a rooted Android device.
-     stat.st_uid >= 0 && stat.st_gid >= 0
- }
- 
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn assert_stat_results(stat_result: Result<FileStat>) {
-     let stats = stat_result.expect("stat call failed");
-     assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
-     assert!(stats.st_ino > 0);      // inode is positive integer, exact number machine dependent
-     assert!(stats.st_mode > 0);     // must be positive integer
--    assert!(stats.st_nlink == 1);   // there links created, must be 1
-+    assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
-     assert!(valid_uid_gid(stats));  // must be positive integers
--    assert!(stats.st_size == 0);    // size is 0 because we did not write anything to the file
-+    assert_eq!(stats.st_size, 0);    // size is 0 because we did not write anything to the file
-     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
-     assert!(stats.st_blocks <= 16);  // Up to 16 blocks can be allocated for a blank file
- }
- 
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn assert_lstat_results(stat_result: Result<FileStat>) {
-     let stats = stat_result.expect("stat call failed");
-     assert!(stats.st_dev > 0);      // must be positive integer, exact number machine dependent
-@@ -63,8 +78,8 @@ fn assert_lstat_results(stat_result: Result<FileStat>) {
-     // st_mode is c_uint (u32 on Android) while S_IFMT is mode_t
-     // (u16 on Android), and that will be a compile error.
-     // On other platforms they are the same (either both are u16 or u32).
--    assert!((stats.st_mode as usize) & (S_IFMT as usize) == S_IFLNK as usize); // should be a link
--    assert!(stats.st_nlink == 1);   // there links created, must be 1
-+    assert_eq!((stats.st_mode as usize) & (S_IFMT as usize), S_IFLNK as usize); // should be a link
-+    assert_eq!(stats.st_nlink, 1);   // there links created, must be 1
-     assert!(valid_uid_gid(stats));  // must be positive integers
-     assert!(stats.st_size > 0);    // size is > 0 because it points to another file
-     assert!(stats.st_blksize > 0);  // must be positive integer, exact number machine dependent
-@@ -76,7 +91,7 @@ fn assert_lstat_results(stat_result: Result<FileStat>) {
- }
- 
- #[test]
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn test_stat_and_fstat() {
-     use nix::sys::stat::fstat;
- 
-@@ -92,7 +107,7 @@ fn test_stat_and_fstat() {
- }
- 
- #[test]
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn test_fstatat() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let filename = tempdir.path().join("foo.txt");
-@@ -108,7 +123,7 @@ fn test_fstatat() {
- }
- 
- #[test]
--#[cfg(not(any(target_os = "netbsd")))]
-+#[cfg(not(any(target_os = "netbsd", target_os = "redox")))]
- fn test_stat_fstat_lstat() {
-     use nix::sys::stat::{fstat, lstat};
- 
-@@ -155,8 +170,9 @@ fn test_fchmod() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_fchmodat() {
--    let _dr = ::DirRestore::new();
-+    let _dr = crate::DirRestore::new();
-     let tempdir = tempfile::tempdir().unwrap();
-     let filename = "foo.txt";
-     let fullpath = tempdir.path().join(filename);
-@@ -186,6 +202,7 @@ fn test_fchmodat() {
- ///
- /// The atime and mtime are expressed with a resolution of seconds because some file systems
- /// (like macOS's HFS+) do not have higher granularity.
-+#[cfg(not(target_os = "redox"))]
- fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata) {
-     assert_eq!(
-         Duration::new(exp_atime_sec, 0),
-@@ -196,6 +213,7 @@ fn assert_times_eq(exp_atime_sec: u64, exp_mtime_sec: u64, attr: &fs::Metadata)
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_utimes() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let fullpath = tempdir.path().join("file");
-@@ -231,6 +249,7 @@ fn test_lutimes() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_futimens() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let fullpath = tempdir.path().join("file");
-@@ -243,8 +262,9 @@ fn test_futimens() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_utimensat() {
--    let _dr = ::DirRestore::new();
-+    let _dr = crate::DirRestore::new();
-     let tempdir = tempfile::tempdir().unwrap();
-     let filename = "foo.txt";
-     let fullpath = tempdir.path().join(filename);
-@@ -264,6 +284,7 @@ fn test_utimensat() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_mkdirat_success_path() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let filename = "example_subdir";
-@@ -273,6 +294,7 @@ fn test_mkdirat_success_path() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_mkdirat_success_mode() {
-     let expected_bits = stat::SFlag::S_IFDIR.bits() | stat::Mode::S_IRWXU.bits();
-     let tempdir = tempfile::tempdir().unwrap();
-@@ -285,6 +307,7 @@ fn test_mkdirat_success_mode() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_mkdirat_fail() {
-     let tempdir = tempfile::tempdir().unwrap();
-     let not_dir_filename= "example_not_dir";
-diff --git a/third_party/rust/nix/test/test_time.rs b/third_party/rust/nix/test/test_time.rs
-new file mode 100644
-index 0000000000000..c321352d79c16
---- /dev/null
-+++ b/third_party/rust/nix/test/test_time.rs
-@@ -0,0 +1,56 @@
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+))]
-+use nix::time::clock_getcpuclockid;
-+use nix::time::{clock_getres, clock_gettime, ClockId};
-+
-+#[test]
-+pub fn test_clock_getres() {
-+    assert!(clock_getres(ClockId::CLOCK_REALTIME).is_ok());
-+}
-+
-+#[test]
-+pub fn test_clock_gettime() {
-+    assert!(clock_gettime(ClockId::CLOCK_REALTIME).is_ok());
-+}
-+
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+))]
-+#[test]
-+pub fn test_clock_getcpuclockid() {
-+    let clock_id = clock_getcpuclockid(nix::unistd::Pid::this()).unwrap();
-+    assert!(clock_gettime(clock_id).is_ok());
-+}
-+
-+#[test]
-+pub fn test_clock_id_res() {
-+    assert!(ClockId::CLOCK_REALTIME.res().is_ok());
-+}
-+
-+#[test]
-+pub fn test_clock_id_now() {
-+    assert!(ClockId::CLOCK_REALTIME.now().is_ok());
-+}
-+
-+#[cfg(any(
-+    target_os = "freebsd",
-+    target_os = "dragonfly",
-+    target_os = "linux",
-+    target_os = "android",
-+    target_os = "emscripten",
-+))]
-+#[test]
-+pub fn test_clock_id_pid_cpu_clock_id() {
-+    assert!(ClockId::pid_cpu_clock_id(nix::unistd::Pid::this())
-+        .map(ClockId::now)
-+        .is_ok());
-+}
-diff --git a/third_party/rust/nix/test/test_unistd.rs b/third_party/rust/nix/test/test_unistd.rs
-index 46196dec7ccce..16a8a05dd6d08 100644
---- a/third_party/rust/nix/test/test_unistd.rs
-+++ b/third_party/rust/nix/test/test_unistd.rs
-@@ -1,26 +1,39 @@
--use nix::fcntl::{self, fcntl, FcntlArg, FdFlag, open, OFlag, readlink};
-+#[cfg(not(target_os = "redox"))]
-+use nix::fcntl::{self, open, readlink};
-+use nix::fcntl::{fcntl, FcntlArg, FdFlag, OFlag};
- use nix::unistd::*;
- use nix::unistd::ForkResult::*;
-+#[cfg(not(target_os = "redox"))]
- use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal, sigaction};
- use nix::sys::wait::*;
- use nix::sys::stat::{self, Mode, SFlag};
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+use nix::pty::{posix_openpt, grantpt, unlockpt, ptsname};
- use nix::errno::Errno;
-+#[cfg(not(target_os = "redox"))]
- use nix::Error;
- use std::{env, iter};
-+#[cfg(not(target_os = "redox"))]
- use std::ffi::CString;
--use std::fs::{self, DirBuilder, File};
-+#[cfg(not(target_os = "redox"))]
-+use std::fs::DirBuilder;
-+use std::fs::{self, File};
- use std::io::Write;
- use std::os::unix::prelude::*;
--use tempfile::{self, tempfile};
--use libc::{self, _exit, off_t};
-+#[cfg(not(target_os = "redox"))]
-+use std::path::Path;
-+use tempfile::{tempdir, tempfile};
-+use libc::{_exit, off_t};
-+
-+use crate::*;
- 
- #[test]
- #[cfg(not(any(target_os = "netbsd")))]
- fn test_fork_and_waitpid() {
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Safe: Child only calls `_exit`, which is signal-safe
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-         Child => unsafe { _exit(0) },
-         Parent { child } => {
-             // assert that child was created and pid > 0
-@@ -29,7 +42,7 @@ fn test_fork_and_waitpid() {
-             let wait_status = waitpid(child, None);
-             match wait_status {
-                 // assert that waitpid returned correct status and the pid is the one of the child
--                Ok(WaitStatus::Exited(pid_t, _)) =>  assert!(pid_t == child),
-+                Ok(WaitStatus::Exited(pid_t, _)) =>  assert_eq!(pid_t, child),
- 
-                 // panic, must never happen
-                 s @ Ok(_) => panic!("Child exited {:?}, should never happen", s),
-@@ -45,10 +58,10 @@ fn test_fork_and_waitpid() {
- #[test]
- fn test_wait() {
-     // Grab FORK_MTX so wait doesn't reap a different test's child process
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Safe: Child only calls `_exit`, which is signal-safe
--    match fork().expect("Error: Fork Failed") {
-+    match unsafe{fork()}.expect("Error: Fork Failed") {
-         Child => unsafe { _exit(0) },
-         Parent { child } => {
-             let wait_status = wait();
-@@ -81,8 +94,9 @@ fn test_mkstemp_directory() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_mkfifo() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let mkfifo_fifo = tempdir.path().join("mkfifo_fifo");
- 
-     mkfifo(&mkfifo_fifo, Mode::S_IRUSR).unwrap();
-@@ -93,11 +107,70 @@ fn test_mkfifo() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_mkfifo_directory() {
-     // mkfifo should fail if a directory is given
-     assert!(mkfifo(&env::temp_dir(), Mode::S_IRUSR).is_err());
- }
- 
-+#[test]
-+#[cfg(not(any(
-+    target_os = "macos", target_os = "ios",
-+    target_os = "android", target_os = "redox")))]
-+fn test_mkfifoat_none() {
-+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let tempdir = tempdir().unwrap();
-+    let mkfifoat_fifo = tempdir.path().join("mkfifoat_fifo");
-+
-+    mkfifoat(None, &mkfifoat_fifo, Mode::S_IRUSR).unwrap();
-+
-+    let stats = stat::stat(&mkfifoat_fifo).unwrap();
-+    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
-+    assert_eq!(typ, SFlag::S_IFIFO);
-+}
-+
-+#[test]
-+#[cfg(not(any(
-+    target_os = "macos", target_os = "ios",
-+    target_os = "android", target_os = "redox")))]
-+fn test_mkfifoat() {
-+    let tempdir = tempdir().unwrap();
-+    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+    let mkfifoat_name = "mkfifoat_name";
-+
-+    mkfifoat(Some(dirfd), mkfifoat_name, Mode::S_IRUSR).unwrap();
-+
-+    let stats = stat::fstatat(dirfd, mkfifoat_name, fcntl::AtFlags::empty()).unwrap();
-+    let typ = stat::SFlag::from_bits_truncate(stats.st_mode);
-+    assert_eq!(typ, SFlag::S_IFIFO);
-+}
-+
-+#[test]
-+#[cfg(not(any(
-+    target_os = "macos", target_os = "ios",
-+    target_os = "android", target_os = "redox")))]
-+fn test_mkfifoat_directory_none() {
-+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    // mkfifoat should fail if a directory is given
-+    assert!(!mkfifoat(None, &env::temp_dir(), Mode::S_IRUSR).is_ok());
-+}
-+
-+#[test]
-+#[cfg(not(any(
-+    target_os = "macos", target_os = "ios",
-+    target_os = "android", target_os = "redox")))]
-+fn test_mkfifoat_directory() {
-+    // mkfifoat should fail if a directory is given
-+    let tempdir = tempdir().unwrap();
-+    let dirfd = open(tempdir.path(), OFlag::empty(), Mode::empty()).unwrap();
-+    let mkfifoat_dir = "mkfifoat_dir";
-+    stat::mkdirat(dirfd, mkfifoat_dir, Mode::S_IRUSR).unwrap();
-+
-+    assert!(!mkfifoat(Some(dirfd), mkfifoat_dir, Mode::S_IRUSR).is_ok());
-+}
-+
- #[test]
- fn test_getpid() {
-     let pid: ::libc::pid_t = getpid().into();
-@@ -107,11 +180,12 @@ fn test_getpid() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_getsid() {
-     let none_sid: ::libc::pid_t = getsid(None).unwrap().into();
-     let pid_sid: ::libc::pid_t = getsid(Some(getpid())).unwrap().into();
-     assert!(none_sid > 0);
--    assert!(none_sid == pid_sid);
-+    assert_eq!(none_sid, pid_sid);
- }
- 
- #[cfg(any(target_os = "linux", target_os = "android"))]
-@@ -127,12 +201,12 @@ mod linux_android {
- 
- #[test]
- // `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
--#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
- fn test_setgroups() {
-     // Skip this test when not run as root as `setgroups()` requires root.
-     skip_if_not_root!("test_setgroups");
- 
--    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Save the existing groups
-     let old_groups = getgroups().unwrap();
-@@ -150,13 +224,13 @@ fn test_setgroups() {
- 
- #[test]
- // `getgroups()` and `setgroups()` do not behave as expected on Apple platforms
--#[cfg(not(any(target_os = "ios", target_os = "macos")))]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox", target_os = "fuchsia")))]
- fn test_initgroups() {
-     // Skip this test when not run as root as `initgroups()` and `setgroups()`
-     // require root.
-     skip_if_not_root!("test_initgroups");
- 
--    let _m = ::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::GROUPS_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     // Save the existing groups
-     let old_groups = getgroups().unwrap();
-@@ -180,11 +254,53 @@ fn test_initgroups() {
-     setgroups(&old_groups).unwrap();
- }
- 
-+#[cfg(not(target_os = "redox"))]
- macro_rules! execve_test_factory(
-     ($test_name:ident, $syscall:ident, $exe: expr $(, $pathname:expr, $flags:expr)*) => (
--    #[test]
--    fn $test_name() {
--        let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+
-+    #[cfg(test)]
-+    mod $test_name {
-+    use std::ffi::CStr;
-+    use super::*;
-+
-+    const EMPTY: &'static [u8] = b"\0";
-+    const DASH_C: &'static [u8] = b"-c\0";
-+    const BIGARG: &'static [u8] = b"echo nix!!! && echo foo=$foo && echo baz=$baz\0";
-+    const FOO: &'static [u8] = b"foo=bar\0";
-+    const BAZ: &'static [u8] = b"baz=quux\0";
-+
-+    fn syscall_cstr_ref() -> Result<std::convert::Infallible, nix::Error> {
-+        $syscall(
-+            $exe,
-+            $(CString::new($pathname).unwrap().as_c_str(), )*
-+            &[CStr::from_bytes_with_nul(EMPTY).unwrap(),
-+              CStr::from_bytes_with_nul(DASH_C).unwrap(),
-+              CStr::from_bytes_with_nul(BIGARG).unwrap()],
-+            &[CStr::from_bytes_with_nul(FOO).unwrap(),
-+              CStr::from_bytes_with_nul(BAZ).unwrap()]
-+            $(, $flags)*)
-+    }
-+
-+    fn syscall_cstring() -> Result<std::convert::Infallible, nix::Error> {
-+        $syscall(
-+            $exe,
-+            $(CString::new($pathname).unwrap().as_c_str(), )*
-+            &[CString::from(CStr::from_bytes_with_nul(EMPTY).unwrap()),
-+              CString::from(CStr::from_bytes_with_nul(DASH_C).unwrap()),
-+              CString::from(CStr::from_bytes_with_nul(BIGARG).unwrap())],
-+            &[CString::from(CStr::from_bytes_with_nul(FOO).unwrap()),
-+              CString::from(CStr::from_bytes_with_nul(BAZ).unwrap())]
-+            $(, $flags)*)
-+    }
-+
-+    fn common_test(syscall: fn() -> Result<std::convert::Infallible, nix::Error>) {
-+        if "execveat" == stringify!($syscall) {
-+            // Though undocumented, Docker's default seccomp profile seems to
-+            // block this syscall.  https://github.com/nix-rust/nix/issues/1122
-+            skip_if_seccomp!($test_name);
-+        }
-+
-+        let m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-         // The `exec`d process will write to `writer`, and we'll read that
-         // data from `reader`.
-         let (reader, writer) = pipe().unwrap();
-@@ -192,27 +308,21 @@ macro_rules! execve_test_factory(
-         // Safe: Child calls `exit`, `dup`, `close` and the provided `exec*` family function.
-         // NOTE: Technically, this makes the macro unsafe to use because you could pass anything.
-         //       The tests make sure not to do that, though.
--        match fork().unwrap() {
-+        match unsafe{fork()}.unwrap() {
-             Child => {
--                // Close stdout.
--                close(1).unwrap();
-                 // Make `writer` be the stdout of the new process.
--                dup(writer).unwrap();
--                // exec!
--                $syscall(
--                    $exe,
--                    $(&CString::new($pathname).unwrap(), )*
--                    &[CString::new(b"".as_ref()).unwrap(),
--                      CString::new(b"-c".as_ref()).unwrap(),
--                      CString::new(b"echo nix!!! && echo foo=$foo && echo baz=$baz"
--                                   .as_ref()).unwrap()],
--                    &[CString::new(b"foo=bar".as_ref()).unwrap(),
--                      CString::new(b"baz=quux".as_ref()).unwrap()]
--                    $(, $flags)*).unwrap();
-+                dup2(writer, 1).unwrap();
-+                let r = syscall();
-+                let _ = std::io::stderr()
-+                    .write_all(format!("{:?}", r).as_bytes());
-+                // Should only get here in event of error
-+                unsafe{ _exit(1) };
-             },
-             Parent { child } => {
-                 // Wait for the child to exit.
--                waitpid(child, None).unwrap();
-+                let ws = waitpid(child, None);
-+                drop(m);
-+                assert_eq!(ws, Ok(WaitStatus::Exited(child, 0)));
-                 // Read 1024 bytes.
-                 let mut buf = [0u8; 1024];
-                 read(reader, &mut buf).unwrap();
-@@ -224,23 +334,43 @@ macro_rules! execve_test_factory(
-             }
-         }
-     }
-+
-+    // These tests frequently fail on musl, probably due to
-+        // https://github.com/nix-rust/nix/issues/555
-+    #[cfg_attr(target_env = "musl", ignore)]
-+    #[test]
-+    fn test_cstr_ref() {
-+        common_test(syscall_cstr_ref);
-+    }
-+
-+    // These tests frequently fail on musl, probably due to
-+        // https://github.com/nix-rust/nix/issues/555
-+    #[cfg_attr(target_env = "musl", ignore)]
-+    #[test]
-+    fn test_cstring() {
-+        common_test(syscall_cstring);
-+    }
-+    }
-+
-     )
- );
- 
- cfg_if!{
-     if #[cfg(target_os = "android")] {
--        execve_test_factory!(test_execve, execve, &CString::new("/system/bin/sh").unwrap());
-+        execve_test_factory!(test_execve, execve, CString::new("/system/bin/sh").unwrap().as_c_str());
-         execve_test_factory!(test_fexecve, fexecve, File::open("/system/bin/sh").unwrap().into_raw_fd());
-     } else if #[cfg(any(target_os = "freebsd",
-                         target_os = "linux"))] {
--        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
-+        // These tests frequently fail on musl, probably due to
-+        // https://github.com/nix-rust/nix/issues/555
-+        execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
-         execve_test_factory!(test_fexecve, fexecve, File::open("/bin/sh").unwrap().into_raw_fd());
-     } else if #[cfg(any(target_os = "dragonfly",
-                         target_os = "ios",
-                         target_os = "macos",
-                         target_os = "netbsd",
-                         target_os = "openbsd"))] {
--        execve_test_factory!(test_execve, execve, &CString::new("/bin/sh").unwrap());
-+        execve_test_factory!(test_execve, execve, CString::new("/bin/sh").unwrap().as_c_str());
-         // No fexecve() on DragonFly, ios, macos, NetBSD, OpenBSD.
-         //
-         // Note for NetBSD and OpenBSD: although rust-lang/libc includes it
-@@ -255,13 +385,16 @@ execve_test_factory!(test_execvpe, execvpe, &CString::new("sh").unwrap());
- cfg_if!{
-     if #[cfg(target_os = "android")] {
-         use nix::fcntl::AtFlags;
--        execve_test_factory!(test_execveat_empty, execveat, File::open("/system/bin/sh").unwrap().into_raw_fd(),
-+        execve_test_factory!(test_execveat_empty, execveat,
-+                             File::open("/system/bin/sh").unwrap().into_raw_fd(),
-                              "", AtFlags::AT_EMPTY_PATH);
--        execve_test_factory!(test_execveat_relative, execveat, File::open("/system/bin/").unwrap().into_raw_fd(),
-+        execve_test_factory!(test_execveat_relative, execveat,
-+                             File::open("/system/bin/").unwrap().into_raw_fd(),
-                              "./sh", AtFlags::empty());
--        execve_test_factory!(test_execveat_absolute, execveat, File::open("/").unwrap().into_raw_fd(),
-+        execve_test_factory!(test_execveat_absolute, execveat,
-+                             File::open("/").unwrap().into_raw_fd(),
-                              "/system/bin/sh", AtFlags::empty());
--    } else if #[cfg(all(target_os = "linux"), any(target_arch ="x86_64", target_arch ="x86"))] {
-+    } else if #[cfg(all(target_os = "linux", any(target_arch ="x86_64", target_arch ="x86")))] {
-         use nix::fcntl::AtFlags;
-         execve_test_factory!(test_execveat_empty, execveat, File::open("/bin/sh").unwrap().into_raw_fd(),
-                              "", AtFlags::AT_EMPTY_PATH);
-@@ -273,11 +406,12 @@ cfg_if!{
- }
- 
- #[test]
-+#[cfg(not(target_os = "fuchsia"))]
- fn test_fchdir() {
-     // fchdir changes the process's cwd
--    let _dr = ::DirRestore::new();
-+    let _dr = crate::DirRestore::new();
- 
--    let tmpdir = tempfile::tempdir().unwrap();
-+    let tmpdir = tempdir().unwrap();
-     let tmpdir_path = tmpdir.path().canonicalize().unwrap();
-     let tmpdir_fd = File::open(&tmpdir_path).unwrap().into_raw_fd();
- 
-@@ -290,9 +424,9 @@ fn test_fchdir() {
- #[test]
- fn test_getcwd() {
-     // chdir changes the process's cwd
--    let _dr = ::DirRestore::new();
-+    let _dr = crate::DirRestore::new();
- 
--    let tmpdir = tempfile::tempdir().unwrap();
-+    let tmpdir = tempdir().unwrap();
-     let tmpdir_path = tmpdir.path().canonicalize().unwrap();
-     assert!(chdir(&tmpdir_path).is_ok());
-     assert_eq!(getcwd().unwrap(), tmpdir_path);
-@@ -317,7 +451,7 @@ fn test_chown() {
-     let uid = Some(getuid());
-     let gid = Some(getgid());
- 
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let path = tempdir.path().join("file");
-     {
-         File::create(&path).unwrap();
-@@ -332,13 +466,29 @@ fn test_chown() {
- }
- 
- #[test]
-+fn test_fchown() {
-+    // Testing for anything other than our own UID/GID is hard.
-+    let uid = Some(getuid());
-+    let gid = Some(getgid());
-+
-+    let path = tempfile().unwrap();
-+    let fd = path.as_raw_fd();
-+
-+    fchown(fd, uid, gid).unwrap();
-+    fchown(fd, uid, None).unwrap();
-+    fchown(fd, None, gid).unwrap();
-+    fchown(999999999, uid, gid).unwrap_err();
-+}
-+
-+#[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_fchownat() {
--    let _dr = ::DirRestore::new();
-+    let _dr = crate::DirRestore::new();
-     // Testing for anything other than our own UID/GID is hard.
-     let uid = Some(getuid());
-     let gid = Some(getgid());
- 
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let path = tempdir.path().join("file");
-     {
-         File::create(&path).unwrap();
-@@ -366,7 +516,7 @@ fn test_lseek() {
-     lseek(tmpfd, offset, Whence::SeekSet).unwrap();
- 
-     let mut buf = [0u8; 7];
--    ::read_exact(tmpfd, &mut buf);
-+    crate::read_exact(tmpfd, &mut buf);
-     assert_eq!(b"f123456", &buf);
- 
-     close(tmpfd).unwrap();
-@@ -383,7 +533,7 @@ fn test_lseek64() {
-     lseek64(tmpfd, 5, Whence::SeekSet).unwrap();
- 
-     let mut buf = [0u8; 7];
--    ::read_exact(tmpfd, &mut buf);
-+    crate::read_exact(tmpfd, &mut buf);
-     assert_eq!(b"f123456", &buf);
- 
-     close(tmpfd).unwrap();
-@@ -403,7 +553,7 @@ cfg_if!{
-                 skip_if_jailed!("test_acct");
-             }
-         }
--    } else {
-+    } else if #[cfg(not(any(target_os = "redox", target_os = "fuchsia")))] {
-         macro_rules! require_acct{
-             () => {
-                 skip_if_not_root!("test_acct");
-@@ -413,12 +563,13 @@ cfg_if!{
- }
- 
- #[test]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- fn test_acct() {
-     use tempfile::NamedTempFile;
-     use std::process::Command;
-     use std::{thread, time};
- 
--    let _m = ::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::FORK_MTX.lock().expect("Mutex got poisoned by another test");
-     require_acct!();
- 
-     let file = NamedTempFile::new().unwrap();
-@@ -481,6 +632,14 @@ fn test_pipe() {
- 
- // pipe2(2) is the same as pipe(2), except it allows setting some flags.  Check
- // that we can set a flag.
-+#[cfg(any(target_os = "android",
-+          target_os = "dragonfly",
-+          target_os = "emscripten",
-+          target_os = "freebsd",
-+          target_os = "linux",
-+          target_os = "netbsd",
-+          target_os = "openbsd",
-+          target_os = "redox"))]
- #[test]
- fn test_pipe2() {
-     let (fd0, fd1) = pipe2(OFlag::O_CLOEXEC).unwrap();
-@@ -491,8 +650,9 @@ fn test_pipe2() {
- }
- 
- #[test]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
- fn test_truncate() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let path = tempdir.path().join("file");
- 
-     {
-@@ -509,7 +669,7 @@ fn test_truncate() {
- 
- #[test]
- fn test_ftruncate() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let path = tempdir.path().join("file");
- 
-     let tmpfd = {
-@@ -527,17 +687,26 @@ fn test_ftruncate() {
- }
- 
- // Used in `test_alarm`.
-+#[cfg(not(target_os = "redox"))]
- static mut ALARM_CALLED: bool = false;
- 
- // Used in `test_alarm`.
-+#[cfg(not(target_os = "redox"))]
- pub extern fn alarm_signal_handler(raw_signal: libc::c_int) {
-     assert_eq!(raw_signal, libc::SIGALRM, "unexpected signal: {}", raw_signal);
-     unsafe { ALARM_CALLED = true };
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_alarm() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    use std::{
-+        time::{Duration, Instant,},
-+        thread
-+    };
-+
-+    // Maybe other tests that fork interfere with this one?
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     let handler = SigHandler::Handler(alarm_signal_handler);
-     let signal_action = SigAction::new(handler, SaFlags::SA_RESTART, SigSet::empty());
-@@ -554,8 +723,16 @@ fn test_alarm() {
- 
-     // We should be woken up after 1 second by the alarm, so we'll sleep for 2
-     // seconds to be sure.
--    sleep(2);
--    assert_eq!(unsafe { ALARM_CALLED }, true, "expected our alarm signal handler to be called");
-+    let starttime = Instant::now();
-+    loop {
-+        thread::sleep(Duration::from_millis(100));
-+        if unsafe { ALARM_CALLED} {
-+            break;
-+        }
-+        if starttime.elapsed() > Duration::from_secs(3) {
-+            panic!("Timeout waiting for SIGALRM");
-+        }
-+    }
- 
-     // Reset the signal.
-     unsafe {
-@@ -565,8 +742,9 @@ fn test_alarm() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_canceling_alarm() {
--    let _m = ::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
-+    let _m = crate::SIGNAL_MTX.lock().expect("Mutex got poisoned by another test");
- 
-     assert_eq!(alarm::cancel(), None);
- 
-@@ -575,15 +753,17 @@ fn test_canceling_alarm() {
- }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_symlinkat() {
--    let mut buf = [0; 1024];
--    let tempdir = tempfile::tempdir().unwrap();
-+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let tempdir = tempdir().unwrap();
- 
-     let target = tempdir.path().join("a");
-     let linkpath = tempdir.path().join("b");
-     symlinkat(&target, None, &linkpath).unwrap();
-     assert_eq!(
--        readlink(&linkpath, &mut buf).unwrap().to_str().unwrap(),
-+        readlink(&linkpath).unwrap().to_str().unwrap(),
-         target.to_str().unwrap()
-     );
- 
-@@ -592,7 +772,7 @@ fn test_symlinkat() {
-     let linkpath = "d";
-     symlinkat(target, Some(dirfd), linkpath).unwrap();
-     assert_eq!(
--        readlink(&tempdir.path().join(linkpath), &mut buf)
-+        readlink(&tempdir.path().join(linkpath))
-             .unwrap()
-             .to_str()
-             .unwrap(),
-@@ -600,10 +780,154 @@ fn test_symlinkat() {
-     );
- }
- 
-+#[test]
-+#[cfg(not(target_os = "redox"))]
-+fn test_linkat_file() {
-+    let tempdir = tempdir().unwrap();
-+    let oldfilename = "foo.txt";
-+    let oldfilepath = tempdir.path().join(oldfilename);
-+
-+    let newfilename = "bar.txt";
-+    let newfilepath = tempdir.path().join(newfilename);
-+
-+    // Create file
-+    File::create(&oldfilepath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt hard link file at relative path
-+    linkat(Some(dirfd), oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
-+    assert!(newfilepath.exists());
-+}
-+
-+#[test]
-+#[cfg(not(target_os = "redox"))]
-+fn test_linkat_olddirfd_none() {
-+    let _dr = crate::DirRestore::new();
-+
-+    let tempdir_oldfile = tempdir().unwrap();
-+    let oldfilename = "foo.txt";
-+    let oldfilepath = tempdir_oldfile.path().join(oldfilename);
-+
-+    let tempdir_newfile = tempdir().unwrap();
-+    let newfilename = "bar.txt";
-+    let newfilepath = tempdir_newfile.path().join(newfilename);
-+
-+    // Create file
-+    File::create(&oldfilepath).unwrap();
-+
-+    // Get file descriptor for base directory of new file
-+    let dirfd = fcntl::open(tempdir_newfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt hard link file using curent working directory as relative path for old file path
-+    chdir(tempdir_oldfile.path()).unwrap();
-+    linkat(None, oldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
-+    assert!(newfilepath.exists());
-+}
-+
-+#[test]
-+#[cfg(not(target_os = "redox"))]
-+fn test_linkat_newdirfd_none() {
-+    let _dr = crate::DirRestore::new();
-+
-+    let tempdir_oldfile = tempdir().unwrap();
-+    let oldfilename = "foo.txt";
-+    let oldfilepath = tempdir_oldfile.path().join(oldfilename);
-+
-+    let tempdir_newfile = tempdir().unwrap();
-+    let newfilename = "bar.txt";
-+    let newfilepath = tempdir_newfile.path().join(newfilename);
-+
-+    // Create file
-+    File::create(&oldfilepath).unwrap();
-+
-+    // Get file descriptor for base directory of old file
-+    let dirfd = fcntl::open(tempdir_oldfile.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt hard link file using current working directory as relative path for new file path
-+    chdir(tempdir_newfile.path()).unwrap();
-+    linkat(Some(dirfd), oldfilename, None, newfilename, LinkatFlags::SymlinkFollow).unwrap();
-+    assert!(newfilepath.exists());
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "ios", target_os = "macos", target_os = "redox")))]
-+fn test_linkat_no_follow_symlink() {
-+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let tempdir = tempdir().unwrap();
-+    let oldfilename = "foo.txt";
-+    let oldfilepath = tempdir.path().join(oldfilename);
-+
-+    let symoldfilename = "symfoo.txt";
-+    let symoldfilepath = tempdir.path().join(symoldfilename);
-+
-+    let newfilename = "nofollowsymbar.txt";
-+    let newfilepath = tempdir.path().join(newfilename);
-+
-+    // Create file
-+    File::create(&oldfilepath).unwrap();
-+
-+    // Create symlink to file
-+    symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt link symlink of file at relative path
-+    linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::NoSymlinkFollow).unwrap();
-+
-+    // Assert newfile is actually a symlink to oldfile.
-+    assert_eq!(
-+        readlink(&newfilepath)
-+            .unwrap()
-+            .to_str()
-+            .unwrap(),
-+        oldfilepath.to_str().unwrap()
-+    );
-+}
-+
-+#[test]
-+#[cfg(not(target_os = "redox"))]
-+fn test_linkat_follow_symlink() {
-+    let _m = crate::CWD_LOCK.read().expect("Mutex got poisoned by another test");
-+
-+    let tempdir = tempdir().unwrap();
-+    let oldfilename = "foo.txt";
-+    let oldfilepath = tempdir.path().join(oldfilename);
-+
-+    let symoldfilename = "symfoo.txt";
-+    let symoldfilepath = tempdir.path().join(symoldfilename);
-+
-+    let newfilename = "nofollowsymbar.txt";
-+    let newfilepath = tempdir.path().join(newfilename);
-+
-+    // Create file
-+    File::create(&oldfilepath).unwrap();
-+
-+    // Create symlink to file
-+    symlinkat(&oldfilepath, None, &symoldfilepath).unwrap();
-+
-+    // Get file descriptor for base directory
-+    let dirfd = fcntl::open(tempdir.path(), fcntl::OFlag::empty(), stat::Mode::empty()).unwrap();
-+
-+    // Attempt link target of symlink of file at relative path
-+    linkat(Some(dirfd), symoldfilename, Some(dirfd), newfilename, LinkatFlags::SymlinkFollow).unwrap();
-+
-+    let newfilestat = stat::stat(&newfilepath).unwrap();
-+
-+    // Check the file type of the new link
-+    assert!((stat::SFlag::from_bits_truncate(newfilestat.st_mode) & SFlag::S_IFMT) ==  SFlag::S_IFREG);
-+
-+    // Check the number of hard links to the original file
-+    assert_eq!(newfilestat.st_nlink, 2);
-+}
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_unlinkat_dir_noremovedir() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let dirname = "foo_dir";
-     let dirpath = tempdir.path().join(dirname);
- 
-@@ -619,8 +943,9 @@ fn test_unlinkat_dir_noremovedir() {
-  }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_unlinkat_dir_removedir() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let dirname = "foo_dir";
-     let dirpath = tempdir.path().join(dirname);
- 
-@@ -636,8 +961,9 @@ fn test_unlinkat_dir_removedir() {
-  }
- 
- #[test]
-+#[cfg(not(target_os = "redox"))]
- fn test_unlinkat_file() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let filename = "foo.txt";
-     let filepath = tempdir.path().join(filename);
- 
-@@ -654,7 +980,7 @@ fn test_unlinkat_file() {
- 
- #[test]
- fn test_access_not_existing() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let dir = tempdir.path().join("does_not_exist.txt");
-     assert_eq!(access(&dir, AccessFlags::F_OK).err().unwrap().as_errno().unwrap(),
-                Errno::ENOENT);
-@@ -662,8 +988,123 @@ fn test_access_not_existing() {
- 
- #[test]
- fn test_access_file_exists() {
--    let tempdir = tempfile::tempdir().unwrap();
-+    let tempdir = tempdir().unwrap();
-     let path  = tempdir.path().join("does_exist.txt");
-     let _file = File::create(path.clone()).unwrap();
-     assert!(access(&path, AccessFlags::R_OK | AccessFlags::W_OK).is_ok());
- }
-+
-+/// Tests setting the filesystem UID with `setfsuid`.
-+#[cfg(any(target_os = "linux", target_os = "android"))]
-+#[test]
-+fn test_setfsuid() {
-+    use std::os::unix::fs::PermissionsExt;
-+    use std::{fs, io, thread};
-+    require_capability!(CAP_SETUID);
-+
-+    // get the UID of the "nobody" user
-+    let nobody = User::from_name("nobody").unwrap().unwrap();
-+
-+    // create a temporary file with permissions '-rw-r-----'
-+    let file = tempfile::NamedTempFile::new_in("/var/tmp").unwrap();
-+    let temp_path = file.into_temp_path();
-+    dbg!(&temp_path);
-+    let temp_path_2 = (&temp_path).to_path_buf();
-+    let mut permissions = fs::metadata(&temp_path).unwrap().permissions();
-+    permissions.set_mode(640);
-+
-+    // spawn a new thread where to test setfsuid
-+    thread::spawn(move || {
-+        // set filesystem UID
-+        let fuid = setfsuid(nobody.uid);
-+        // trying to open the temporary file should fail with EACCES
-+        let res = fs::File::open(&temp_path);
-+        assert!(res.is_err());
-+        assert_eq!(res.err().unwrap().kind(), io::ErrorKind::PermissionDenied);
-+
-+        // assert fuid actually changes
-+        let prev_fuid = setfsuid(Uid::from_raw(-1i32 as u32));
-+        assert_ne!(prev_fuid, fuid);
-+    })
-+    .join()
-+    .unwrap();
-+
-+    // open the temporary file with the current thread filesystem UID
-+    fs::File::open(temp_path_2).unwrap();
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+fn test_ttyname() {
-+    let fd = posix_openpt(OFlag::O_RDWR).expect("posix_openpt failed");
-+    assert!(fd.as_raw_fd() > 0);
-+
-+    // on linux, we can just call ttyname on the pty master directly, but
-+    // apparently osx requires that ttyname is called on a slave pty (can't
-+    // find this documented anywhere, but it seems to empirically be the case)
-+    grantpt(&fd).expect("grantpt failed");
-+    unlockpt(&fd).expect("unlockpt failed");
-+    let sname = unsafe { ptsname(&fd) }.expect("ptsname failed");
-+    let fds = open(
-+        Path::new(&sname),
-+        OFlag::O_RDWR,
-+        stat::Mode::empty(),
-+    ).expect("open failed");
-+    assert!(fds > 0);
-+
-+    let name = ttyname(fds).expect("ttyname failed");
-+    assert!(name.starts_with("/dev"));
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+fn test_ttyname_not_pty() {
-+    let fd = File::open("/dev/zero").unwrap();
-+    assert!(fd.as_raw_fd() > 0);
-+    assert_eq!(ttyname(fd.as_raw_fd()), Err(Error::Sys(Errno::ENOTTY)));
-+}
-+
-+#[test]
-+#[cfg(not(any(target_os = "redox", target_os = "fuchsia")))]
-+fn test_ttyname_invalid_fd() {
-+    assert_eq!(ttyname(-1), Err(Error::Sys(Errno::EBADF)));
-+}
-+
-+#[test]
-+#[cfg(any(
-+    target_os = "macos",
-+    target_os = "ios",
-+    target_os = "freebsd",
-+    target_os = "openbsd",
-+    target_os = "netbsd",
-+    target_os = "dragonfly",
-+))]
-+fn test_getpeereid() {
-+    use std::os::unix::net::UnixStream;
-+    let (sock_a, sock_b) = UnixStream::pair().unwrap();
-+
-+    let (uid_a, gid_a) = getpeereid(sock_a.as_raw_fd()).unwrap();
-+    let (uid_b, gid_b) = getpeereid(sock_b.as_raw_fd()).unwrap();
-+
-+    let uid = geteuid();
-+    let gid = getegid();
-+
-+    assert_eq!(uid, uid_a);
-+    assert_eq!(gid, gid_a);
-+    assert_eq!(uid_a, uid_b);
-+    assert_eq!(gid_a, gid_b);
-+}
-+
-+#[test]
-+#[cfg(any(
-+    target_os = "macos",
-+    target_os = "ios",
-+    target_os = "freebsd",
-+    target_os = "openbsd",
-+    target_os = "netbsd",
-+    target_os = "dragonfly",
-+))]
-+fn test_getpeereid_invalid_fd() {
-+    // getpeereid is not POSIX, so error codes are inconsistent between different Unices.
-+    assert!(getpeereid(-1).is_err());
-+}

diff --git a/www-client/firefox/firefox-103.0.1.ebuild b/www-client/firefox/firefox-103.0.1.ebuild
new file mode 100644
index 0000000..d0494bb
--- /dev/null
+++ b/www-client/firefox/firefox-103.0.1.ebuild
@@ -0,0 +1,1301 @@
+# Copyright 1999-2022 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+EAPI="8"
+
+FIREFOX_PATCHSET="firefox-103-patches-03j.tar.xz"
+
+LLVM_MAX_SLOT=14
+
+PYTHON_COMPAT=( python3_{8..11} )
+PYTHON_REQ_USE="ncurses,sqlite,ssl"
+
+WANT_AUTOCONF="2.1"
+
+VIRTUALX_REQUIRED="pgo"
+
+MOZ_ESR=
+
+MOZ_PV=${PV}
+MOZ_PV_SUFFIX=
+if [[ ${PV} =~ (_(alpha|beta|rc).*)$ ]] ; then
+	MOZ_PV_SUFFIX=${BASH_REMATCH[1]}
+
+	# Convert the ebuild version to the upstream Mozilla version
+	MOZ_PV="${MOZ_PV/_alpha/a}" # Handle alpha for SRC_URI
+	MOZ_PV="${MOZ_PV/_beta/b}"  # Handle beta for SRC_URI
+	MOZ_PV="${MOZ_PV%%_rc*}"    # Handle rc for SRC_URI
+fi
+
+if [[ -n ${MOZ_ESR} ]] ; then
+	# ESR releases have slightly different version numbers
+	MOZ_PV="${MOZ_PV}esr"
+fi
+
+MOZ_PN="${PN%-bin}"
+MOZ_P="${MOZ_PN}-${MOZ_PV}"
+MOZ_PV_DISTFILES="${MOZ_PV}${MOZ_PV_SUFFIX}"
+MOZ_P_DISTFILES="${MOZ_PN}-${MOZ_PV_DISTFILES}"
+
+inherit autotools check-reqs desktop flag-o-matic gnome2-utils linux-info \
+	llvm multiprocessing pax-utils python-any-r1 toolchain-funcs \
+	virtualx xdg
+
+MOZ_SRC_BASE_URI="https://archive.mozilla.org/pub/${MOZ_PN}/releases/${MOZ_PV}"
+
+if [[ ${PV} == *_rc* ]] ; then
+	MOZ_SRC_BASE_URI="https://archive.mozilla.org/pub/${MOZ_PN}/candidates/${MOZ_PV}-candidates/build${PV##*_rc}"
+fi
+
+PATCH_URIS=(
+	https://dev.gentoo.org/~{juippis,whissi,slashbeast}/mozilla/patchsets/${FIREFOX_PATCHSET}
+)
+
+SRC_URI="${MOZ_SRC_BASE_URI}/source/${MOZ_P}.source.tar.xz -> ${MOZ_P_DISTFILES}.source.tar.xz
+	${PATCH_URIS[@]}"
+
+DESCRIPTION="Firefox Web Browser"
+HOMEPAGE="https://www.mozilla.com/firefox"
+
+KEYWORDS="~amd64 ~arm64 ~ppc64 ~riscv ~x86"
+
+SLOT="rapid"
+LICENSE="MPL-2.0 GPL-2 LGPL-2.1"
+
+# make clang non-default for now, as lld's relocation relax support is comming in llvm 15 release
+# https://reviews.llvm.org/D127611
+IUSE="clang cpu_flags_arm_neon dbus debug eme-free hardened hwaccel"
+IUSE+=" jack libproxy lto +openh264 pgo pulseaudio sndio selinux"
+IUSE+=" +system-av1 +system-harfbuzz +system-icu +system-jpeg +system-libevent +system-libvpx system-png system-python-libs +system-webp"
+IUSE+=" wayland wifi"
+
+# Firefox-only IUSE
+IUSE+=" geckodriver +gmp-autoupdate screencast +X"
+
+REQUIRED_USE="debug? ( !system-av1 )
+	pgo? ( lto )
+	wifi? ( dbus )"
+
+# Firefox-only REQUIRED_USE flags
+REQUIRED_USE+=" || ( X wayland )"
+REQUIRED_USE+=" pgo? ( X )"
+REQUIRED_USE+=" screencast? ( wayland )"
+
+BDEPEND="${PYTHON_DEPS}
+	app-arch/unzip
+	app-arch/zip
+	>=dev-util/cbindgen-0.24.3
+	net-libs/nodejs
+	virtual/pkgconfig
+	virtual/rust
+	|| (
+		(
+			sys-devel/clang:14
+			sys-devel/llvm:14
+			clang? (
+				=sys-devel/lld-14*
+				pgo? ( =sys-libs/compiler-rt-sanitizers-14*[profile] )
+			)
+		)
+		(
+			sys-devel/clang:13
+			sys-devel/llvm:13
+			clang? (
+				=sys-devel/lld-13*
+				pgo? ( =sys-libs/compiler-rt-sanitizers-13*[profile] )
+			)
+		)
+	)
+	amd64? ( >=dev-lang/nasm-2.14 )
+	x86? ( >=dev-lang/nasm-2.14 )"
+
+COMMON_DEPEND="
+	dev-libs/atk
+	dev-libs/expat
+	dev-libs/glib:2
+	dev-libs/libffi:=
+	>=dev-libs/nss-3.80
+	>=dev-libs/nspr-4.34
+	media-libs/alsa-lib
+	media-libs/fontconfig
+	media-libs/freetype
+	media-libs/mesa
+	media-video/ffmpeg
+	sys-libs/zlib
+	virtual/freedesktop-icon-theme
+	x11-libs/cairo
+	x11-libs/gdk-pixbuf
+	x11-libs/pango
+	x11-libs/pixman
+	dbus? (
+		dev-libs/dbus-glib
+		sys-apps/dbus
+	)
+	jack? ( virtual/jack )
+	libproxy? ( net-libs/libproxy )
+	selinux? ( sec-policy/selinux-mozilla )
+	sndio? ( >=media-sound/sndio-1.8.0-r1 )
+	screencast? ( media-video/pipewire:= )
+	system-av1? (
+		>=media-libs/dav1d-0.9.3:=
+		>=media-libs/libaom-1.0.0:=
+	)
+	system-harfbuzz? (
+		>=media-gfx/graphite2-1.3.13
+		>=media-libs/harfbuzz-2.8.1:0=
+	)
+	system-icu? ( >=dev-libs/icu-71.1:= )
+	system-jpeg? ( >=media-libs/libjpeg-turbo-1.2.1 )
+	system-libevent? ( >=dev-libs/libevent-2.0:0=[threads] )
+	system-libvpx? ( >=media-libs/libvpx-1.8.2:0=[postproc] )
+	system-png? ( >=media-libs/libpng-1.6.35:0=[apng] )
+	system-webp? ( >=media-libs/libwebp-1.1.0:0= )
+	wayland? (
+		>=media-libs/libepoxy-1.5.10-r1
+		x11-libs/gtk+:3[wayland]
+		x11-libs/libdrm
+		x11-libs/libxkbcommon[wayland]
+	)
+	wifi? (
+		kernel_linux? (
+			dev-libs/dbus-glib
+			net-misc/networkmanager
+			sys-apps/dbus
+		)
+	)
+	X? (
+		virtual/opengl
+		x11-libs/cairo[X]
+		x11-libs/gtk+:3[X]
+		x11-libs/libX11
+		x11-libs/libXcomposite
+		x11-libs/libXdamage
+		x11-libs/libXext
+		x11-libs/libXfixes
+		x11-libs/libxkbcommon[X]
+		x11-libs/libXrandr
+		x11-libs/libXtst
+		x11-libs/libxcb:=
+	)"
+
+RDEPEND="${COMMON_DEPEND}
+	!www-client/firefox:0
+	!www-client/firefox:esr
+	jack? ( virtual/jack )
+	openh264? ( media-libs/openh264:*[plugin] )
+	pulseaudio? (
+		|| (
+			media-sound/pulseaudio
+			>=media-sound/apulse-0.1.12-r4
+		)
+	)
+	selinux? ( sec-policy/selinux-mozilla )"
+
+DEPEND="${COMMON_DEPEND}
+	pulseaudio? (
+		|| (
+			media-sound/pulseaudio
+			>=media-sound/apulse-0.1.12-r4[sdk]
+		)
+	)
+	X? (
+		x11-libs/libICE
+		x11-libs/libSM
+	)"
+
+S="${WORKDIR}/${PN}-${PV%_*}"
+RESTRICT=network-sandbox
+
+# Allow MOZ_GMP_PLUGIN_LIST to be set in an eclass or
+# overridden in the enviromnent (advanced hackers only)
+if [[ -z "${MOZ_GMP_PLUGIN_LIST+set}" ]] ; then
+	MOZ_GMP_PLUGIN_LIST=( gmp-gmpopenh264 gmp-widevinecdm )
+fi
+
+llvm_check_deps() {
+	if ! has_version -b "sys-devel/clang:${LLVM_SLOT}" ; then
+		einfo "sys-devel/clang:${LLVM_SLOT} is missing! Cannot use LLVM slot ${LLVM_SLOT} ..." >&2
+		return 1
+	fi
+
+	if use clang ; then
+		if ! has_version -b "=sys-devel/lld-${LLVM_SLOT}*" ; then
+			einfo "=sys-devel/lld-${LLVM_SLOT}* is missing! Cannot use LLVM slot ${LLVM_SLOT} ..." >&2
+			return 1
+		fi
+
+		if use pgo ; then
+			if ! has_version -b "=sys-libs/compiler-rt-sanitizers-${LLVM_SLOT}*" ; then
+				einfo "=sys-libs/compiler-rt-sanitizers-${LLVM_SLOT}* is missing! Cannot use LLVM slot ${LLVM_SLOT} ..." >&2
+				return 1
+			fi
+		fi
+	fi
+
+	einfo "Using LLVM slot ${LLVM_SLOT} to build" >&2
+}
+
+MOZ_LANGS=(
+	af ar ast be bg br ca cak cs cy da de dsb
+	el en-CA en-GB en-US es-AR es-ES et eu
+	fi fr fy-NL ga-IE gd gl he hr hsb hu
+	id is it ja ka kab kk ko lt lv ms nb-NO nl nn-NO
+	pa-IN pl pt-BR pt-PT rm ro ru
+	sk sl sq sr sv-SE th tr uk uz vi zh-CN zh-TW
+)
+
+# Firefox-only LANGS
+MOZ_LANGS+=( ach )
+MOZ_LANGS+=( an )
+MOZ_LANGS+=( az )
+MOZ_LANGS+=( bn )
+MOZ_LANGS+=( bs )
+MOZ_LANGS+=( ca-valencia )
+MOZ_LANGS+=( eo )
+MOZ_LANGS+=( es-CL )
+MOZ_LANGS+=( es-MX )
+MOZ_LANGS+=( fa )
+MOZ_LANGS+=( ff )
+MOZ_LANGS+=( gn )
+MOZ_LANGS+=( gu-IN )
+MOZ_LANGS+=( hi-IN )
+MOZ_LANGS+=( hy-AM )
+MOZ_LANGS+=( ia )
+MOZ_LANGS+=( km )
+MOZ_LANGS+=( kn )
+MOZ_LANGS+=( lij )
+MOZ_LANGS+=( mk )
+MOZ_LANGS+=( mr )
+MOZ_LANGS+=( my )
+MOZ_LANGS+=( ne-NP )
+MOZ_LANGS+=( oc )
+MOZ_LANGS+=( sco )
+MOZ_LANGS+=( si )
+MOZ_LANGS+=( son )
+MOZ_LANGS+=( szl )
+MOZ_LANGS+=( ta )
+MOZ_LANGS+=( te )
+MOZ_LANGS+=( tl )
+MOZ_LANGS+=( trs )
+MOZ_LANGS+=( ur )
+MOZ_LANGS+=( xh )
+
+mozilla_set_globals() {
+	# https://bugs.gentoo.org/587334
+	local MOZ_TOO_REGIONALIZED_FOR_L10N=(
+		fy-NL ga-IE gu-IN hi-IN hy-AM nb-NO ne-NP nn-NO pa-IN sv-SE
+	)
+
+	local lang xflag
+	for lang in "${MOZ_LANGS[@]}" ; do
+		# en and en_US are handled internally
+		if [[ ${lang} == en ]] || [[ ${lang} == en-US ]] ; then
+			continue
+		fi
+
+		# strip region subtag if $lang is in the list
+		if has ${lang} "${MOZ_TOO_REGIONALIZED_FOR_L10N[@]}" ; then
+			xflag=${lang%%-*}
+		else
+			xflag=${lang}
+		fi
+
+		SRC_URI+=" l10n_${xflag/[_@]/-}? ("
+		SRC_URI+=" ${MOZ_SRC_BASE_URI}/linux-x86_64/xpi/${lang}.xpi -> ${MOZ_P_DISTFILES}-${lang}.xpi"
+		SRC_URI+=" )"
+		IUSE+=" l10n_${xflag/[_@]/-}"
+	done
+}
+mozilla_set_globals
+
+moz_clear_vendor_checksums() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -ne 1 ]] ; then
+		die "${FUNCNAME} requires exact one argument"
+	fi
+
+	einfo "Clearing cargo checksums for ${1} ..."
+
+	sed -i \
+		-e 's/\("files":{\)[^}]*/\1/' \
+		"${S}"/third_party/rust/${1}/.cargo-checksum.json \
+		|| die
+}
+
+moz_install_xpi() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -lt 2 ]] ; then
+		die "${FUNCNAME} requires at least two arguments"
+	fi
+
+	local DESTDIR=${1}
+	shift
+
+	insinto "${DESTDIR}"
+
+	local emid xpi_file xpi_tmp_dir
+	for xpi_file in "${@}" ; do
+		emid=
+		xpi_tmp_dir=$(mktemp -d --tmpdir="${T}")
+
+		# Unpack XPI
+		unzip -qq "${xpi_file}" -d "${xpi_tmp_dir}" || die
+
+		# Determine extension ID
+		if [[ -f "${xpi_tmp_dir}/install.rdf" ]] ; then
+			emid=$(sed -n -e '/install-manifest/,$ { /em:id/!d; s/.*[\">]\([^\"<>]*\)[\"<].*/\1/; p; q }' "${xpi_tmp_dir}/install.rdf")
+			[[ -z "${emid}" ]] && die "failed to determine extension id from install.rdf"
+		elif [[ -f "${xpi_tmp_dir}/manifest.json" ]] ; then
+			emid=$(sed -n -e 's/.*"id": "\([^"]*\)".*/\1/p' "${xpi_tmp_dir}/manifest.json")
+			[[ -z "${emid}" ]] && die "failed to determine extension id from manifest.json"
+		else
+			die "failed to determine extension id"
+		fi
+
+		einfo "Installing ${emid}.xpi into ${ED}${DESTDIR} ..."
+		newins "${xpi_file}" "${emid}.xpi"
+	done
+}
+
+mozconfig_add_options_ac() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -lt 2 ]] ; then
+		die "${FUNCNAME} requires at least two arguments"
+	fi
+
+	local reason=${1}
+	shift
+
+	local option
+	for option in ${@} ; do
+		echo "ac_add_options ${option} # ${reason}" >>${MOZCONFIG}
+	done
+}
+
+mozconfig_add_options_mk() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -lt 2 ]] ; then
+		die "${FUNCNAME} requires at least two arguments"
+	fi
+
+	local reason=${1}
+	shift
+
+	local option
+	for option in ${@} ; do
+		echo "mk_add_options ${option} # ${reason}" >>${MOZCONFIG}
+	done
+}
+
+mozconfig_use_enable() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -lt 1 ]] ; then
+		die "${FUNCNAME} requires at least one arguments"
+	fi
+
+	local flag=$(use_enable "${@}")
+	mozconfig_add_options_ac "$(use ${1} && echo +${1} || echo -${1})" "${flag}"
+}
+
+mozconfig_use_with() {
+	debug-print-function ${FUNCNAME} "$@"
+
+	if [[ ${#} -lt 1 ]] ; then
+		die "${FUNCNAME} requires at least one arguments"
+	fi
+
+	local flag=$(use_with "${@}")
+	mozconfig_add_options_ac "$(use ${1} && echo +${1} || echo -${1})" "${flag}"
+}
+
+pkg_pretend() {
+	if [[ ${MERGE_TYPE} != binary ]] ; then
+		if use pgo ; then
+			if ! has usersandbox $FEATURES ; then
+				die "You must enable usersandbox as X server can not run as root!"
+			fi
+		fi
+
+		# Ensure we have enough disk space to compile
+		if use pgo || use lto || use debug ; then
+			CHECKREQS_DISK_BUILD="13500M"
+		else
+			CHECKREQS_DISK_BUILD="6600M"
+		fi
+
+		check-reqs_pkg_pretend
+	fi
+}
+
+pkg_setup() {
+	if [[ ${MERGE_TYPE} != binary ]] ; then
+		if use pgo ; then
+			if ! has userpriv ${FEATURES} ; then
+				eerror "Building ${PN} with USE=pgo and FEATURES=-userpriv is not supported!"
+			fi
+		fi
+
+		# Ensure we have enough disk space to compile
+		if use pgo || use lto || use debug ; then
+			CHECKREQS_DISK_BUILD="13500M"
+		else
+			CHECKREQS_DISK_BUILD="6400M"
+		fi
+
+		check-reqs_pkg_setup
+
+		llvm_pkg_setup
+
+		if use clang && use lto ; then
+			local version_lld=$(ld.lld --version 2>/dev/null | awk '{ print $2 }')
+			[[ -n ${version_lld} ]] && version_lld=$(ver_cut 1 "${version_lld}")
+			[[ -z ${version_lld} ]] && die "Failed to read ld.lld version!"
+
+			local version_llvm_rust=$(rustc -Vv 2>/dev/null | grep -F -- 'LLVM version:' | awk '{ print $3 }')
+			[[ -n ${version_llvm_rust} ]] && version_llvm_rust=$(ver_cut 1 "${version_llvm_rust}")
+			[[ -z ${version_llvm_rust} ]] && die "Failed to read used LLVM version from rustc!"
+
+			if ver_test "${version_lld}" -ne "${version_llvm_rust}" ; then
+				eerror "Rust is using LLVM version ${version_llvm_rust} but ld.lld version belongs to LLVM version ${version_lld}."
+				eerror "You will be unable to link ${CATEGORY}/${PN}. To proceed you have the following options:"
+				eerror "  - Manually switch rust version using 'eselect rust' to match used LLVM version"
+				eerror "  - Switch to dev-lang/rust[system-llvm] which will guarantee matching version"
+				eerror "  - Build ${CATEGORY}/${PN} without USE=lto"
+				eerror "  - Rebuild lld with llvm that was used to build rust (may need to rebuild the whole "
+				eerror "    llvm/clang/lld/rust chain depending on your @world updates)"
+				die "LLVM version used by Rust (${version_llvm_rust}) does not match with ld.lld version (${version_lld})!"
+			fi
+		fi
+
+		if ! use clang && [[ $(gcc-major-version) -eq 11 ]] \
+			&& ! has_version -b ">sys-devel/gcc-11.1.0:11" ; then
+			# bug 792705
+			eerror "Using GCC 11 to compile firefox is currently known to be broken (see bug #792705)."
+			die "Set USE=clang or select <gcc-11 to build ${CATEGORY}/${P}."
+		fi
+
+		python-any-r1_pkg_setup
+
+		# Avoid PGO profiling problems due to enviroment leakage
+		# These should *always* be cleaned up anyway
+		unset \
+			DBUS_SESSION_BUS_ADDRESS \
+			DISPLAY \
+			ORBIT_SOCKETDIR \
+			SESSION_MANAGER \
+			XAUTHORITY \
+			XDG_CACHE_HOME \
+			XDG_SESSION_COOKIE
+
+		# Build system is using /proc/self/oom_score_adj, bug #604394
+		addpredict /proc/self/oom_score_adj
+
+		if use pgo ; then
+			# Allow access to GPU during PGO run
+			local ati_cards mesa_cards nvidia_cards render_cards
+			shopt -s nullglob
+
+			ati_cards=$(echo -n /dev/ati/card* | sed 's/ /:/g')
+			if [[ -n "${ati_cards}" ]] ; then
+				addpredict "${ati_cards}"
+			fi
+
+			mesa_cards=$(echo -n /dev/dri/card* | sed 's/ /:/g')
+			if [[ -n "${mesa_cards}" ]] ; then
+				addpredict "${mesa_cards}"
+			fi
+
+			nvidia_cards=$(echo -n /dev/nvidia* | sed 's/ /:/g')
+			if [[ -n "${nvidia_cards}" ]] ; then
+				addpredict "${nvidia_cards}"
+			fi
+
+			render_cards=$(echo -n /dev/dri/renderD128* | sed 's/ /:/g')
+			if [[ -n "${render_cards}" ]] ; then
+				addpredict "${render_cards}"
+			fi
+
+			shopt -u nullglob
+		fi
+
+		if ! mountpoint -q /dev/shm ; then
+			# If /dev/shm is not available, configure is known to fail with
+			# a traceback report referencing /usr/lib/pythonN.N/multiprocessing/synchronize.py
+			ewarn "/dev/shm is not mounted -- expect build failures!"
+		fi
+
+		# Google API keys (see http://www.chromium.org/developers/how-tos/api-keys)
+		# Note: These are for Gentoo Linux use ONLY. For your own distribution, please
+		# get your own set of keys.
+		if [[ -z "${MOZ_API_KEY_GOOGLE+set}" ]] ; then
+			MOZ_API_KEY_GOOGLE="AIzaSyDEAOvatFogGaPi0eTgsV_ZlEzx0ObmepsMzfAc"
+		fi
+
+		if [[ -z "${MOZ_API_KEY_LOCATION+set}" ]] ; then
+			MOZ_API_KEY_LOCATION="AIzaSyB2h2OuRgGaPicUgy5N-5hsZqiPW6sH3n_rptiQ"
+		fi
+
+		# Mozilla API keys (see https://location.services.mozilla.com/api)
+		# Note: These are for Gentoo Linux use ONLY. For your own distribution, please
+		# get your own set of keys.
+		if [[ -z "${MOZ_API_KEY_MOZILLA+set}" ]] ; then
+			MOZ_API_KEY_MOZILLA="edb3d487-3a84-46m0ap1e3-9dfd-92b5efaaa005"
+		fi
+
+		# Ensure we use C locale when building, bug #746215
+		export LC_ALL=C
+	fi
+
+	CONFIG_CHECK="~SECCOMP"
+	WARNING_SECCOMP="CONFIG_SECCOMP not set! This system will be unable to play DRM-protected content."
+	linux-info_pkg_setup
+}
+
+src_unpack() {
+	local _lp_dir="${WORKDIR}/language_packs"
+	local _src_file
+
+	if [[ ! -d "${_lp_dir}" ]] ; then
+		mkdir "${_lp_dir}" || die
+	fi
+
+	for _src_file in ${A} ; do
+		if [[ ${_src_file} == *.xpi ]]; then
+			cp "${DISTDIR}/${_src_file}" "${_lp_dir}" || die "Failed to copy '${_src_file}' to '${_lp_dir}'!"
+		else
+			unpack ${_src_file}
+		fi
+	done
+}
+
+src_prepare() {
+	use lto && rm -v "${WORKDIR}"/firefox-patches/*-LTO-Only-enable-LTO-*.patch
+	eapply "${WORKDIR}/firefox-patches"
+	# riscv support from https://github.com/makotokato/gecko-dev
+	eapply "${FILESDIR}/firefox-riscv64-support.patch"
+	# disable cargo-vet check in order to do ./mach vendor rust
+	# https://bugzilla.mozilla.org/show_bug.cgi?id=1787601
+	# skip check_macroassembler_style.py
+	eapply "${FILESDIR}/firefox-riscv64-hack.patch"
+
+	# Allow user to apply any additional patches without modifing ebuild
+	eapply_user
+
+	# Make cargo respect MAKEOPTS
+	export CARGO_BUILD_JOBS="$(makeopts_jobs)"
+
+	# Make LTO respect MAKEOPTS
+	sed -i \
+		-e "s/multiprocessing.cpu_count()/$(makeopts_jobs)/" \
+		"${S}"/build/moz.configure/lto-pgo.configure \
+		|| die "sed failed to set num_cores"
+
+	# Make ICU respect MAKEOPTS
+	sed -i \
+		-e "s/multiprocessing.cpu_count()/$(makeopts_jobs)/" \
+		"${S}"/intl/icu_sources_data.py \
+		|| die "sed failed to set num_cores"
+
+	# sed-in toolchain prefix
+	sed -i \
+		-e "s/objdump/${CHOST}-objdump/" \
+		"${S}"/python/mozbuild/mozbuild/configure/check_debug_ranges.py \
+		|| die "sed failed to set toolchain prefix"
+
+	sed -i \
+		-e 's/ccache_stats = None/return None/' \
+		"${S}"/python/mozbuild/mozbuild/controller/building.py \
+		|| die "sed failed to disable ccache stats call"
+
+	einfo "Removing pre-built binaries ..."
+	find "${S}"/third_party -type f \( -name '*.so' -o -name '*.o' \) -print -delete || die
+
+	# Clearing checksums where we have applied patches
+	moz_clear_vendor_checksums audioipc
+	moz_clear_vendor_checksums audioipc-client
+	moz_clear_vendor_checksums audioipc-server
+
+	# Create build dir
+	BUILD_DIR="${WORKDIR}/${PN}_build"
+	mkdir -p "${BUILD_DIR}" || die
+
+	# Write API keys to disk
+	echo -n "${MOZ_API_KEY_GOOGLE//gGaPi/}" > "${S}"/api-google.key || die
+	echo -n "${MOZ_API_KEY_LOCATION//gGaPi/}" > "${S}"/api-location.key || die
+	echo -n "${MOZ_API_KEY_MOZILLA//m0ap1/}" > "${S}"/api-mozilla.key || die
+
+	xdg_environment_reset
+}
+
+src_configure() {
+	# Show flags set at the beginning
+	einfo "Current BINDGEN_CFLAGS:\t${BINDGEN_CFLAGS:-no value set}"
+	einfo "Current CFLAGS:\t\t${CFLAGS:-no value set}"
+	einfo "Current CXXFLAGS:\t\t${CXXFLAGS:-no value set}"
+	einfo "Current LDFLAGS:\t\t${LDFLAGS:-no value set}"
+	einfo "Current RUSTFLAGS:\t\t${RUSTFLAGS:-no value set}"
+
+	local have_switched_compiler=
+	if use clang && ! tc-is-clang ; then
+		# Force clang
+		einfo "Enforcing the use of clang due to USE=clang ..."
+		have_switched_compiler=yes
+		AR=llvm-ar
+		AS=llvm-as
+		CC=${CHOST}-clang
+		CXX=${CHOST}-clang++
+		NM=llvm-nm
+		RANLIB=llvm-ranlib
+	elif ! use clang && ! tc-is-gcc ; then
+		# Force gcc
+		have_switched_compiler=yes
+		einfo "Enforcing the use of gcc due to USE=-clang ..."
+		AR=gcc-ar
+		CC=${CHOST}-gcc
+		CXX=${CHOST}-g++
+		NM=gcc-nm
+		RANLIB=gcc-ranlib
+	fi
+
+	if [[ -n "${have_switched_compiler}" ]] ; then
+		# Because we switched active compiler we have to ensure
+		# that no unsupported flags are set
+		strip-unsupported-flags
+	fi
+
+	# Ensure we use correct toolchain
+	export HOST_CC="$(tc-getBUILD_CC)"
+	export HOST_CXX="$(tc-getBUILD_CXX)"
+	tc-export CC CXX LD AR NM OBJDUMP RANLIB PKG_CONFIG
+
+	# Pass the correct toolchain paths through cbindgen
+	if tc-is-cross-compiler ; then
+		export BINDGEN_CFLAGS="${SYSROOT:+--sysroot=${ESYSROOT}} --target=${CHOST} ${BINDGEN_CFLAGS-}"
+	fi
+
+	# Set MOZILLA_FIVE_HOME
+	export MOZILLA_FIVE_HOME="/usr/$(get_libdir)/${PN}"
+
+	# python/mach/mach/mixin/process.py fails to detect SHELL
+	export SHELL="${EPREFIX}/bin/bash"
+
+	# Set state path
+	export MOZBUILD_STATE_PATH="${BUILD_DIR}"
+
+	# Set MOZCONFIG
+	export MOZCONFIG="${S}/.mozconfig"
+
+	# Initialize MOZCONFIG
+	mozconfig_add_options_ac '' --enable-application=browser
+
+	# Set Gentoo defaults
+	export MOZILLA_OFFICIAL=1
+
+	mozconfig_add_options_ac 'Gentoo default' \
+		--allow-addon-sideload \
+		--disable-cargo-incremental \
+		--disable-crashreporter \
+		--disable-gpsd \
+		--disable-install-strip \
+		--disable-parental-controls \
+		--disable-strip \
+		--disable-updater \
+		--enable-negotiateauth \
+		--enable-new-pass-manager \
+		--enable-official-branding \
+		--enable-release \
+		--enable-system-ffi \
+		--enable-system-pixman \
+		--host="${CBUILD:-${CHOST}}" \
+		--libdir="${EPREFIX}/usr/$(get_libdir)" \
+		--prefix="${EPREFIX}/usr" \
+		--target="${CHOST}" \
+		--without-ccache \
+		--without-wasm-sandboxed-libraries \
+		--with-intl-api \
+		--with-libclang-path="$(llvm-config --libdir)" \
+		--with-system-nspr \
+		--with-system-nss \
+		--with-system-zlib \
+		--with-toolchain-prefix="${CHOST}-" \
+		--with-unsigned-addon-scopes=app,system \
+		--x-includes="${ESYSROOT}/usr/include" \
+		--x-libraries="${ESYSROOT}/usr/$(get_libdir)"
+
+	# Set update channel
+	local update_channel=release
+	[[ -n ${MOZ_ESR} ]] && update_channel=esr
+	mozconfig_add_options_ac '' --update-channel=${update_channel}
+
+	if ! use x86 && [[ ${CHOST} != armv*h* ]] ; then
+		mozconfig_add_options_ac '' --enable-rust-simd
+	fi
+
+	# For future keywording: This is currently (97.0) only supported on:
+	# amd64, arm, arm64 & x86.
+	# Might want to flip the logic around if Firefox is to support more arches.
+	if use ppc64 || use riscv; then
+		mozconfig_add_options_ac '' --disable-sandbox
+	else
+		mozconfig_add_options_ac '' --enable-sandbox
+	fi
+	if use riscv; then
+		mozconfig_add_options_ac '' --disable-jit
+	fi
+
+	if [[ -s "${S}/api-google.key" ]] ; then
+		local key_origin="Gentoo default"
+		if [[ $(cat "${S}/api-google.key" | md5sum | awk '{ print $1 }') != 709560c02f94b41f9ad2c49207be6c54 ]] ; then
+			key_origin="User value"
+		fi
+
+		mozconfig_add_options_ac "${key_origin}" \
+			--with-google-safebrowsing-api-keyfile="${S}/api-google.key"
+	else
+		einfo "Building without Google API key ..."
+	fi
+
+	if [[ -s "${S}/api-location.key" ]] ; then
+		local key_origin="Gentoo default"
+		if [[ $(cat "${S}/api-location.key" | md5sum | awk '{ print $1 }') != ffb7895e35dedf832eb1c5d420ac7420 ]] ; then
+			key_origin="User value"
+		fi
+
+		mozconfig_add_options_ac "${key_origin}" \
+			--with-google-location-service-api-keyfile="${S}/api-location.key"
+	else
+		einfo "Building without Location API key ..."
+	fi
+
+	if [[ -s "${S}/api-mozilla.key" ]] ; then
+		local key_origin="Gentoo default"
+		if [[ $(cat "${S}/api-mozilla.key" | md5sum | awk '{ print $1 }') != 3927726e9442a8e8fa0e46ccc39caa27 ]] ; then
+			key_origin="User value"
+		fi
+
+		mozconfig_add_options_ac "${key_origin}" \
+			--with-mozilla-api-keyfile="${S}/api-mozilla.key"
+	else
+		einfo "Building without Mozilla API key ..."
+	fi
+
+	mozconfig_use_with system-av1
+	mozconfig_use_with system-harfbuzz
+	mozconfig_use_with system-harfbuzz system-graphite2
+	mozconfig_use_with system-icu
+	mozconfig_use_with system-jpeg
+	mozconfig_use_with system-libevent
+	mozconfig_use_with system-libvpx
+	mozconfig_use_with system-png
+	mozconfig_use_with system-webp
+
+	mozconfig_use_enable dbus
+	mozconfig_use_enable libproxy
+
+	use eme-free && mozconfig_add_options_ac '+eme-free' --disable-eme
+
+	mozconfig_use_enable geckodriver
+
+	if use hardened ; then
+		mozconfig_add_options_ac "+hardened" --enable-hardening
+		append-ldflags "-Wl,-z,relro -Wl,-z,now"
+	fi
+
+	local myaudiobackends=""
+	use jack && myaudiobackends+="jack,"
+	use sndio && myaudiobackends+="sndio,"
+	use pulseaudio && myaudiobackends+="pulseaudio,"
+	! use pulseaudio && myaudiobackends+="alsa,"
+
+	mozconfig_add_options_ac '--enable-audio-backends' --enable-audio-backends="${myaudiobackends::-1}"
+
+	mozconfig_use_enable wifi necko-wifi
+
+	if use X && use wayland ; then
+		mozconfig_add_options_ac '+x11+wayland' --enable-default-toolkit=cairo-gtk3-x11-wayland
+	elif ! use X && use wayland ; then
+		mozconfig_add_options_ac '+wayland' --enable-default-toolkit=cairo-gtk3-wayland-only
+	else
+		mozconfig_add_options_ac '+x11' --enable-default-toolkit=cairo-gtk3
+	fi
+
+	if use lto ; then
+		if use clang ; then
+			# Upstream only supports lld when using clang
+			mozconfig_add_options_ac "forcing ld=lld due to USE=clang and USE=lto" --enable-linker=lld
+
+			mozconfig_add_options_ac '+lto' --enable-lto=cross
+
+		else
+			# ThinLTO is currently broken, see bmo#1644409
+			mozconfig_add_options_ac '+lto' --enable-lto=full
+			mozconfig_add_options_ac "linker is set to bfd" --enable-linker=bfd
+		fi
+
+		if use pgo ; then
+			mozconfig_add_options_ac '+pgo' MOZ_PGO=1
+
+			if use clang ; then
+				# Used in build/pgo/profileserver.py
+				export LLVM_PROFDATA="llvm-profdata"
+			fi
+		fi
+	else
+		# Avoid auto-magic on linker
+		if use clang ; then
+			# This is upstream's default
+			mozconfig_add_options_ac "forcing ld=lld due to USE=clang" --enable-linker=lld
+		else
+			mozconfig_add_options_ac "linker is set to bfd" --enable-linker=bfd
+		fi
+	fi
+
+	# LTO flag was handled via configure
+	filter-flags '-flto*'
+
+	mozconfig_use_enable debug
+	if use debug ; then
+		mozconfig_add_options_ac '+debug' --disable-optimize
+	else
+		if is-flag '-g*' ; then
+			if use clang ; then
+				mozconfig_add_options_ac 'from CFLAGS' --enable-debug-symbols=$(get-flag '-g*')
+			else
+				mozconfig_add_options_ac 'from CFLAGS' --enable-debug-symbols
+			fi
+		else
+			mozconfig_add_options_ac 'Gentoo default' --disable-debug-symbols
+		fi
+
+		if is-flag '-O0' ; then
+			mozconfig_add_options_ac "from CFLAGS" --enable-optimize=-O0
+		elif is-flag '-O4' ; then
+			mozconfig_add_options_ac "from CFLAGS" --enable-optimize=-O4
+		elif is-flag '-O3' ; then
+			mozconfig_add_options_ac "from CFLAGS" --enable-optimize=-O3
+		elif is-flag '-O1' ; then
+			mozconfig_add_options_ac "from CFLAGS" --enable-optimize=-O1
+		elif is-flag '-Os' ; then
+			mozconfig_add_options_ac "from CFLAGS" --enable-optimize=-Os
+		else
+			mozconfig_add_options_ac "Gentoo default" --enable-optimize=-O2
+		fi
+	fi
+
+	# Debug flag was handled via configure
+	filter-flags '-g*'
+
+	# Optimization flag was handled via configure
+	filter-flags '-O*'
+
+	# Modifications to better support ARM, bug #553364
+	if use cpu_flags_arm_neon ; then
+		mozconfig_add_options_ac '+cpu_flags_arm_neon' --with-fpu=neon
+
+		if ! tc-is-clang ; then
+			# thumb options aren't supported when using clang, bug 666966
+			mozconfig_add_options_ac '+cpu_flags_arm_neon' \
+				--with-thumb=yes \
+				--with-thumb-interwork=no
+		fi
+	fi
+
+	if [[ ${CHOST} == armv*h* ]] ; then
+		mozconfig_add_options_ac 'CHOST=armv*h*' --with-float-abi=hard
+
+		if ! use system-libvpx ; then
+			sed -i \
+				-e "s|softfp|hard|" \
+				"${S}"/media/libvpx/moz.build \
+				|| die
+		fi
+	fi
+
+	if use clang ; then
+		# https://bugzilla.mozilla.org/show_bug.cgi?id=1482204
+		# https://bugzilla.mozilla.org/show_bug.cgi?id=1483822
+		# toolkit/moz.configure Elfhack section: target.cpu in ('arm', 'x86', 'x86_64')
+		local disable_elf_hack=
+		if use amd64 ; then
+			disable_elf_hack=yes
+		elif use x86 ; then
+			disable_elf_hack=yes
+		elif use arm ; then
+			disable_elf_hack=yes
+		fi
+
+		if [[ -n ${disable_elf_hack} ]] ; then
+			mozconfig_add_options_ac 'elf-hack is broken when using Clang' --disable-elf-hack
+		fi
+	elif tc-is-gcc ; then
+		if ver_test $(gcc-fullversion) -ge 10 ; then
+			einfo "Forcing -fno-tree-loop-vectorize to workaround GCC bug, see bug 758446 ..."
+			append-cxxflags -fno-tree-loop-vectorize
+		fi
+	fi
+
+	# Additional ARCH support
+	case "${ARCH}" in
+		arm)
+			# Reduce the memory requirements for linking
+			if use clang ; then
+				# Nothing to do
+				:;
+			elif use lto ; then
+				append-ldflags -Wl,--no-keep-memory
+			else
+				append-ldflags -Wl,--no-keep-memory -Wl,--reduce-memory-overheads
+			fi
+			;;
+	esac
+
+	if ! use elibc_glibc ; then
+		mozconfig_add_options_ac '!elibc_glibc' --disable-jemalloc
+	fi
+
+	# Allow elfhack to work in combination with unstripped binaries
+	# when they would normally be larger than 2GiB.
+	append-ldflags "-Wl,--compress-debug-sections=zlib"
+
+	# Make revdep-rebuild.sh happy; Also required for musl
+	append-ldflags -Wl,-rpath="${MOZILLA_FIVE_HOME}",--enable-new-dtags
+
+	# Pass $MAKEOPTS to build system
+	export MOZ_MAKE_FLAGS="${MAKEOPTS}"
+
+	# Use system's Python environment
+	PIP_NETWORK_INSTALL_RESTRICTED_VIRTUALENVS=mach
+
+	if use system-python-libs; then
+		export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="system"
+	else
+		export MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="none"
+	fi
+
+	# Disable notification when build system has finished
+	export MOZ_NOSPAM=1
+
+	# Portage sets XARGS environment variable to "xargs -r" by default which
+	# breaks build system's check_prog() function which doesn't support arguments
+	mozconfig_add_options_ac 'Gentoo default' "XARGS=${EPREFIX}/usr/bin/xargs"
+
+	# Set build dir
+	mozconfig_add_options_mk 'Gentoo default' "MOZ_OBJDIR=${BUILD_DIR}"
+
+	# Show flags we will use
+	einfo "Build BINDGEN_CFLAGS:\t${BINDGEN_CFLAGS:-no value set}"
+	einfo "Build CFLAGS:\t\t${CFLAGS:-no value set}"
+	einfo "Build CXXFLAGS:\t\t${CXXFLAGS:-no value set}"
+	einfo "Build LDFLAGS:\t\t${LDFLAGS:-no value set}"
+	einfo "Build RUSTFLAGS:\t\t${RUSTFLAGS:-no value set}"
+
+	# Handle EXTRA_CONF and show summary
+	local ac opt hash reason
+
+	# Apply EXTRA_ECONF entries to $MOZCONFIG
+	if [[ -n ${EXTRA_ECONF} ]] ; then
+		IFS=\! read -a ac <<<${EXTRA_ECONF// --/\!}
+		for opt in "${ac[@]}"; do
+			mozconfig_add_options_ac "EXTRA_ECONF" --${opt#--}
+		done
+	fi
+
+	echo
+	echo "=========================================================="
+	echo "Building ${PF} with the following configuration"
+	grep ^ac_add_options "${MOZCONFIG}" | while read ac opt hash reason; do
+		[[ -z ${hash} || ${hash} == \# ]] \
+			|| die "error reading mozconfig: ${ac} ${opt} ${hash} ${reason}"
+		printf "    %-30s  %s\n" "${opt}" "${reason:-mozilla.org default}"
+	done
+	echo "=========================================================="
+	echo
+
+	# To avoid huge patches of rust library (~200MB), we have to download on the fly
+	einfo "riscv overlay: Performing ./mach vendor rust to update third party libs"
+	./mach vendor rust --ignore-modified || die
+	./mach configure || die
+}
+
+src_compile() {
+	local virtx_cmd=
+
+	if use pgo ; then
+		virtx_cmd=virtx
+
+		# Reset and cleanup environment variables used by GNOME/XDG
+		gnome2_environment_reset
+
+		addpredict /root
+	fi
+
+	if ! use X && use wayland; then
+		local -x GDK_BACKEND=wayland
+	else
+		local -x GDK_BACKEND=x11
+	fi
+
+	${virtx_cmd} ./mach build --verbose \
+		|| die
+}
+
+src_install() {
+	# xpcshell is getting called during install
+	pax-mark m \
+		"${BUILD_DIR}"/dist/bin/xpcshell \
+		"${BUILD_DIR}"/dist/bin/${PN} \
+		"${BUILD_DIR}"/dist/bin/plugin-container
+
+	DESTDIR="${D}" ./mach install || die
+
+	# Upstream cannot ship symlink but we can (bmo#658850)
+	rm "${ED}${MOZILLA_FIVE_HOME}/${PN}-bin" || die
+	dosym ${PN} ${MOZILLA_FIVE_HOME}/${PN}-bin
+
+	# Don't install llvm-symbolizer from sys-devel/llvm package
+	if [[ -f "${ED}${MOZILLA_FIVE_HOME}/llvm-symbolizer" ]] ; then
+		rm -v "${ED}${MOZILLA_FIVE_HOME}/llvm-symbolizer" || die
+	fi
+
+	# Install policy (currently only used to disable application updates)
+	insinto "${MOZILLA_FIVE_HOME}/distribution"
+	newins "${FILESDIR}"/distribution.ini distribution.ini
+	newins "${FILESDIR}"/disable-auto-update.policy.json policies.json
+
+	# Install system-wide preferences
+	local PREFS_DIR="${MOZILLA_FIVE_HOME}/browser/defaults/preferences"
+	insinto "${PREFS_DIR}"
+	newins "${FILESDIR}"/gentoo-default-prefs.js gentoo-prefs.js
+
+	local GENTOO_PREFS="${ED}${PREFS_DIR}/gentoo-prefs.js"
+
+	# Set dictionary path to use system hunspell
+	cat >>"${GENTOO_PREFS}" <<-EOF || die "failed to set spellchecker.dictionary_path pref"
+	pref("spellchecker.dictionary_path",       "${EPREFIX}/usr/share/myspell");
+	EOF
+
+	# Force hwaccel prefs if USE=hwaccel is enabled
+	if use hwaccel ; then
+		cat "${FILESDIR}"/gentoo-hwaccel-prefs.js-r2 \
+		>>"${GENTOO_PREFS}" \
+		|| die "failed to add prefs to force hardware-accelerated rendering to all-gentoo.js"
+
+		if use wayland; then
+			cat >>"${GENTOO_PREFS}" <<-EOF || die "failed to set hwaccel wayland prefs"
+			pref("gfx.x11-egl.force-enabled",          false);
+			EOF
+		else
+			cat >>"${GENTOO_PREFS}" <<-EOF || die "failed to set hwaccel x11 prefs"
+			pref("gfx.x11-egl.force-enabled",          true);
+			EOF
+		fi
+	fi
+
+	if ! use gmp-autoupdate ; then
+		local plugin
+		for plugin in "${MOZ_GMP_PLUGIN_LIST[@]}" ; do
+			einfo "Disabling auto-update for ${plugin} plugin ..."
+			cat >>"${GENTOO_PREFS}" <<-EOF || die "failed to disable autoupdate for ${plugin} media plugin"
+			pref("media.${plugin}.autoupdate",   false);
+			EOF
+		done
+	fi
+
+	# Force the graphite pref if USE=system-harfbuzz is enabled, since the pref cannot disable it
+	if use system-harfbuzz ; then
+		cat >>"${GENTOO_PREFS}" <<-EOF || die "failed to set gfx.font_rendering.graphite.enabled pref"
+		sticky_pref("gfx.font_rendering.graphite.enabled", true);
+		EOF
+	fi
+
+	# Install language packs
+	local langpacks=( $(find "${WORKDIR}/language_packs" -type f -name '*.xpi') )
+	if [[ -n "${langpacks}" ]] ; then
+		moz_install_xpi "${MOZILLA_FIVE_HOME}/distribution/extensions" "${langpacks[@]}"
+	fi
+
+	# Install geckodriver
+	if use geckodriver ; then
+		einfo "Installing geckodriver into ${ED}${MOZILLA_FIVE_HOME} ..."
+		pax-mark m "${BUILD_DIR}"/dist/bin/geckodriver
+		exeinto "${MOZILLA_FIVE_HOME}"
+		doexe "${BUILD_DIR}"/dist/bin/geckodriver
+
+		dosym ${MOZILLA_FIVE_HOME}/geckodriver /usr/bin/geckodriver
+	fi
+
+	# Install icons
+	local icon_srcdir="${S}/browser/branding/official"
+	local icon_symbolic_file="${FILESDIR}/icon/firefox-symbolic.svg"
+
+	insinto /usr/share/icons/hicolor/symbolic/apps
+	newins "${icon_symbolic_file}" ${PN}-symbolic.svg
+
+	local icon size
+	for icon in "${icon_srcdir}"/default*.png ; do
+		size=${icon%.png}
+		size=${size##*/default}
+
+		if [[ ${size} -eq 48 ]] ; then
+			newicon "${icon}" ${PN}.png
+		fi
+
+		newicon -s ${size} "${icon}" ${PN}.png
+	done
+
+	# Install menu
+	local app_name="Mozilla ${MOZ_PN^}"
+	local desktop_file="${FILESDIR}/icon/${PN}-r3.desktop"
+	local desktop_filename="${PN}.desktop"
+	local exec_command="${PN}"
+	local icon="${PN}"
+	local use_wayland="false"
+
+	if use wayland ; then
+		use_wayland="true"
+	fi
+
+	cp "${desktop_file}" "${WORKDIR}/${PN}.desktop-template" || die
+
+	sed -i \
+		-e "s:@NAME@:${app_name}:" \
+		-e "s:@EXEC@:${exec_command}:" \
+		-e "s:@ICON@:${icon}:" \
+		"${WORKDIR}/${PN}.desktop-template" \
+		|| die
+
+	newmenu "${WORKDIR}/${PN}.desktop-template" "${desktop_filename}"
+
+	rm "${WORKDIR}/${PN}.desktop-template" || die
+
+	# Install wrapper script
+	[[ -f "${ED}/usr/bin/${PN}" ]] && rm "${ED}/usr/bin/${PN}"
+	newbin "${FILESDIR}/${PN}-r1.sh" ${PN}
+
+	# Update wrapper
+	sed -i \
+		-e "s:@PREFIX@:${EPREFIX}/usr:" \
+		-e "s:@MOZ_FIVE_HOME@:${MOZILLA_FIVE_HOME}:" \
+		-e "s:@APULSELIB_DIR@:${apulselib}:" \
+		-e "s:@DEFAULT_WAYLAND@:${use_wayland}:" \
+		"${ED}/usr/bin/${PN}" \
+		|| die
+}
+
+pkg_preinst() {
+	xdg_pkg_preinst
+
+	# If the apulse libs are available in MOZILLA_FIVE_HOME then apulse
+	# does not need to be forced into the LD_LIBRARY_PATH
+	if use pulseaudio && has_version ">=media-sound/apulse-0.1.12-r4" ; then
+		einfo "APULSE found; Generating library symlinks for sound support ..."
+		local lib
+		pushd "${ED}${MOZILLA_FIVE_HOME}" &>/dev/null || die
+		for lib in ../apulse/libpulse{.so{,.0},-simple.so{,.0}} ; do
+			# A quickpkg rolled by hand will grab symlinks as part of the package,
+			# so we need to avoid creating them if they already exist.
+			if [[ ! -L ${lib##*/} ]] ; then
+				ln -s "${lib}" ${lib##*/} || die
+			fi
+		done
+		popd &>/dev/null || die
+	fi
+}
+
+pkg_postinst() {
+	xdg_pkg_postinst
+
+	if ! use gmp-autoupdate ; then
+		elog "USE='-gmp-autoupdate' has disabled the following plugins from updating or"
+		elog "installing into new profiles:"
+		local plugin
+		for plugin in "${MOZ_GMP_PLUGIN_LIST[@]}" ; do
+			elog "\t ${plugin}"
+		done
+		elog
+	fi
+
+	if use pulseaudio && has_version ">=media-sound/apulse-0.1.12-r4" ; then
+		elog "Apulse was detected at merge time on this system and so it will always be"
+		elog "used for sound.  If you wish to use pulseaudio instead please unmerge"
+		elog "media-sound/apulse."
+		elog
+	fi
+
+	local show_doh_information
+	local show_normandy_information
+	local show_shortcut_information
+
+	if [[ -z "${REPLACING_VERSIONS}" ]] ; then
+		# New install; Tell user that DoH is disabled by default
+		show_doh_information=yes
+		show_normandy_information=yes
+		show_shortcut_information=no
+	else
+		local replacing_version
+		for replacing_version in ${REPLACING_VERSIONS} ; do
+			if ver_test "${replacing_version}" -lt 91.0 ; then
+				# Tell user that we no longer install a shortcut
+				# per supported display protocol
+				show_shortcut_information=yes
+			fi
+		done
+	fi
+
+	if [[ -n "${show_doh_information}" ]] ; then
+		elog
+		elog "Note regarding Trusted Recursive Resolver aka DNS-over-HTTPS (DoH):"
+		elog "Due to privacy concerns (encrypting DNS might be a good thing, sending all"
+		elog "DNS traffic to Cloudflare by default is not a good idea and applications"
+		elog "should respect OS configured settings), \"network.trr.mode\" was set to 5"
+		elog "(\"Off by choice\") by default."
+		elog "You can enable DNS-over-HTTPS in ${PN^}'s preferences."
+	fi
+
+	# bug 713782
+	if [[ -n "${show_normandy_information}" ]] ; then
+		elog
+		elog "Upstream operates a service named Normandy which allows Mozilla to"
+		elog "push changes for default settings or even install new add-ons remotely."
+		elog "While this can be useful to address problems like 'Armagadd-on 2.0' or"
+		elog "revert previous decisions to disable TLS 1.0/1.1, privacy and security"
+		elog "concerns prevail, which is why we have switched off the use of this"
+		elog "service by default."
+		elog
+		elog "To re-enable this service set"
+		elog
+		elog "    app.normandy.enabled=true"
+		elog
+		elog "in about:config."
+	fi
+
+	if [[ -n "${show_shortcut_information}" ]] ; then
+		elog
+		elog "Since ${PN}-91.0 we no longer install multiple shortcuts for"
+		elog "each supported display protocol.  Instead we will only install"
+		elog "one generic Mozilla ${PN^} shortcut."
+		elog "If you still want to be able to select between running Mozilla ${PN^}"
+		elog "on X11 or Wayland, you have to re-create these shortcuts on your own."
+	fi
+
+	# bug 835078
+	if use hwaccel && has_version "x11-drivers/xf86-video-nouveau"; then
+		ewarn "You have nouveau drivers installed in your system and 'hwaccel' "
+		ewarn "enabled for Firefox. Nouveau / your GPU might not support the "
+		ewarn "required EGL, so either disable 'hwaccel' or try the workaround "
+		ewarn "explained in https://bugs.gentoo.org/835078#c5 if Firefox crashes."
+	fi
+
+	elog
+	elog "Unfortunately Firefox-100.0 breaks compatibility with some sites using "
+	elog "useragent checks. To temporarily fix this, enter about:config and modify "
+	elog "network.http.useragent.forceVersion preference to \"99\"."
+	elog "Or install an addon to change your useragent."
+	elog "See: https://support.mozilla.org/en-US/kb/difficulties-opening-or-using-website-firefox-100"
+	elog
+}


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-08-31  2:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-31  2:30 [gentoo-commits] proj/riscv:master commit in: www-client/firefox/files/, www-client/firefox/ Yixun Lan
  -- strict thread matches above, loose matches on Subject: below --
2022-04-20 13:23 Yixun Lan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox