Update nix to 0.29.0

Test: m rust
Bug: 401100059
Change-Id: I6c3a4f1f65e2b02d6feac9c528487594758abec7
diff --git a/crates/nix/.android-checksum.json b/crates/nix/.android-checksum.json
index 820bd8d..53b43bf 100644
--- a/crates/nix/.android-checksum.json
+++ b/crates/nix/.android-checksum.json
@@ -1 +1 @@
-{"package":null,"files":{".cargo-checksum.json":"ca274fd03609e5e33972bd75ef5311417c785870a100ea269ae9fe8100ecf16c","Android.bp":"7f3bbd078169dddeac50fef3f5474478c091a4972d6a7b0861b9ddedb4070ab6","CHANGELOG.md":"ec9f74c874581251fc0c9ad8443de206e5c1be3e5f5cbfa4527ecb6076136c4f","Cargo.toml":"e5d99e20012bb6525da7890f241f49c7acb467d5988d10f8ccd4bdc7f204d253","LICENSE":"ff4177622b3314b5c7199fb4a42e3807acd8362b7f32e45e26630e235260f943","METADATA":"9d893ec628dcf6ad1486c803f46ff27b8859856c28c06c65f5cc1d6e671c8bc1","MODULE_LICENSE_MIT":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"b77b826d1b503d67b659c9090f46cdd57f6693fd7d3b273f9ad045a9df85d47a","TEST_MAPPING":"51f4b8c9722b9825f6a384bee4c2d246ea00ea385f41867e8f7a104a91ad9e42","build.rs":"56c6ddfe87d8a4c2fa125c4dd7bf7613af8a828092210a581b5bb010ddcd9207","cargo_embargo.json":"98edc205c0c2a15cf2a7bb74956cfbc52d7a3b29da0c7d781751ccad9453e478","module_block.bp.fragment":"d265f83f777285b9c1dd903f4b9f9204c4c58e5ac0f34cc49f0ec5ec6e820e7c","patches/memfd.diff":"f30b12198a1a2f7a695cde6d0f942ce6c319d6164e68c546f8e94db29244bdba","src/dir.rs":"3cc2f422e2ee6dc3d1022edf5f559fba7cf1a8d0b5fdc6f74122e828be06bf18","src/env.rs":"a850356a838368c3b28552a2c9750366d2ceaed742f6754477c1fb5385d91957","src/errno.rs":"9daa17bbc59b33527bbf41d26a6913f60da864cb0ae9ba0be21e5911cc3ad69c","src/fcntl.rs":"783e95aceed616f5f93604f3bea06472acbddab0cd821156ec92285754bf9ea6","src/features.rs":"cce028bd977ef8c69b4b4b0a959e94573f3d1a89b53f0fa23aae135a60dbdb3e","src/ifaddrs.rs":"28708d0d15cd124da68c98c76ebc118ed11caf905bf467b80e3de23758219d98","src/kmod.rs":"b96e40714902ef7941d5489f8b68edd9337c3adddf34cce68d90363f0664e8c0","src/lib.rs":"8260ccaf0224525695f195614f28a376269fcba52ef4491a6b2ca476cb46589e","src/macros.rs":"a2c488d2336b89b89f1d4681aab7f050be4db94d46b276a7172089b2d4998b64","src/mount/bsd.rs":"ca1fd0ea33a6aea6ef036eea6e1cac8f207ff703e5bd955381a292306b46b2d8","src/mount/linux.rs":"26a4c359c5cefe8c365f5c2aa5e3661704357cb1fc1348b4377bae45799300f1","src/mount/mod.rs":"63c8b30d3a7f1641796c528f36541836f5eee6d51eee6ae6d7d8ea01f135537b","src/mqueue.rs":"d3b9a29435f5d02888994f1164d2684d7e3756b80e3448dfc5919284ee23c965","src/net/if_.rs":"109e980467d23c1ab4c816e265302f23f60d1ff0c0f4bd3e5df06d9f41748580","src/net/mod.rs":"a88860334410ed47a1f6594a8563dfeb22bbcd3bb4dec308bb8e3de8866b3af4","src/poll.rs":"f57dbc06aa318841cd0eb035579b8e3fa875aff12d66b1e6692e261d65b9b1c7","src/poll_timeout.rs":"16007737ae9219e120d1b0de017067431fe8fa6223d03575bbdbdfe7aab4c1ea","src/pty.rs":"47a4f8fde03ca88627c29a04e5ca6a35daead0edaee61dcd732bc6d7174c9130","src/sched.rs":"303e5b0c605ca019ffb02472691277e81f6f6be0869411814416fedf2368ef40","src/sys/aio.rs":"c178f0ed3713bf0d100195b53d333b8342a2278c19f494e639607d5296a84c9c","src/sys/epoll.rs":"afabda2906ed2d90dfeecbdd96a220be6b3c50835d395e1be2d87eb1d2222cd1","src/sys/event.rs":"4f9f42e4eb4ddac00ed6fcb5d70b9879f3a1291f3160e72de98e1076ed8a98b8","src/sys/eventfd.rs":"5c465648001444c18e55c3d90db208975c125ce003f38fa9a4ab24f97e15733e","src/sys/fanotify.rs":"99121365e760fde466648d9ce6b5091f8d733788bb940d3cccaf01f29d179f7c","src/sys/inotify.rs":"1d1fdf3263c5ee893dd58877cc458b478ae470e3794d50ca5a4d9cd9d7f31eae","src/sys/ioctl/bsd.rs":"10b2ce4d04e0d28277d4a237204e491e896e3fc377c5dcf8792a45001d0f8a26","src/sys/ioctl/linux.rs":"9242e92f8e8bce63af9693af61fc69355082ca882810ab43ddc55f5557803b3c","src/sys/ioctl/mod.rs":"5ef03b0ec57f3270093da800b466dd8f085e62565db60dd403977231758d712e","src/sys/memfd.rs":"c1791230913192d6931cf0a33c1f6ed0de0db00360326e8538ffa559ee321ae0","src/sys/mman.rs":"c5ca69aebfefb03ea5e29857361a0280a93c08fb72aa6e6df034984542124eed","src/sys/mod.rs":"81608664a2880f27699f08c344e9ef23c7055d7e8b79832b81c702510b8e373d","src/sys/personality.rs":"4fc2b82f1e4aa6bd49bd1cf320127d9a0061974096c01b95454f79fd74ee4294","src/sys/prctl.rs":"28b9ccc3e6f9294d33c6a0822bdb52792e40c66a30634b6a8854760be7752d2b","src/sys/pthread.rs":"270213f8050f8bff48e87fe4ad35453b5f0423b959e974dc2b0b8a35eb2491ac","src/sys/ptrace/bsd.rs":"a387ccefa8adb7b8b7f0fea41be619c54c8091c0e111e7b813ee910870f7414e","src/sys/ptrace/linux.rs":"4f6e0e1a1876e044482ab7dedcfe114acd2c2185885729d8070ae4f1dd1a0e3c","src/sys/ptrace/mod.rs":"641edf21d50f73b5079a85c0aed84698acb927e96694161eedba5d9368c1e5fb","src/sys/quota.rs":"944cd578a34011f4e35c28a002f0dd5b7cb53d87d7da8da5b39011e4c56f8052","src/sys/reboot.rs":"390407d521facc8ea3d66e314e7d5a27999b92db86be864919a6e8b2851d6c88","src/sys/resource.rs":"56ee3355124c32b9f6f9b4fea20eadec72bb3db096c0162072f0f7c0f3318335","src/sys/select.rs":"42d38e91eae5ed7a30c31e1b7974860bc419256e6f461164b15a74d2e9653eab","src/sys/sendfile.rs":"9d518732634e6c69482527e68e3d8c132574f7af2c4ff3612860049558016d04","src/sys/signal.rs":"f533567e059e4e16d41c6938559fda15052efdc14ee29266203a0805f1c5fbfd","src/sys/signalfd.rs":"0ecb4cf3287fef0e4ed66f2e5594962af449bb9f28b3ea03a169d71d6e68a275","src/sys/socket/addr.rs":"e092094e4ddc71c8cf7d62530d8bc3b92d900974d492e45de967e8e15ec2658e","src/sys/socket/mod.rs":"ca7ced3676944acb5cc67327ad2ae8e38529df23a85e7b970082d9bf3f5584df","src/sys/socket/sockopt.rs":"9192ebb4030747d387a03c5b616e6724c25aa9da4169e7b48f5a9d91bf82721a","src/sys/stat.rs":"bec1d3b5a7a930989b9a54d350d47653499deeb560d73f3b63efaecf4ebb351e","src/sys/statfs.rs":"83b095a903858a298c1f6b2135bb035f24381374097dddd09289bd4f23f1b389","src/sys/statvfs.rs":"0256273f711e9d2c1c7b8feed6dbf3328295095a9a328afb341ff08bf27ef941","src/sys/sysinfo.rs":"ceeb8c4d709eb02c6ec2fc0d9ec9b8b8dbd40f5263aa8456d0fb8dbbbc850b9c","src/sys/termios.rs":"39ed1da2bc23294fda06536e8cc850a791d5576f339057d3a2e0b165ae6bcb14","src/sys/time.rs":"cbfc06acea72029e1746070c8355c362154fb42bad35e4fc36fa5e5629758da5","src/sys/timer.rs":"d436c5b043b99afd8de9fb42a8fc7ca3509c324d071937b7719bc7ece6986caf","src/sys/timerfd.rs":"ddc1f4f726d1cbc416006c62fc39d80c9edc10297c5d03d70b55106a9df2c7c8","src/sys/uio.rs":"7fd8fccc97ba5b8ee70d74f18399fbd6af60a7f366b9929d90ded2af59a7eb43","src/sys/utsname.rs":"8ab00cc78f82a44a3d47c3955f030418ad846886fabaa9fd178437896a54fee1","src/sys/wait.rs":"467c35c1d1bf5ed38b5e7c0174a2df0471ac2ce37166931747d887b75d2e1266","src/time.rs":"2588796a51798fa053120b809e503bab9c7526f3582159a68c999630cebb2d57","src/ucontext.rs":"0eb33bfd885d9378a8583a7de7409755b73880bc159d502f974d749db84afbfa","src/unistd.rs":"85c9953019c0e7cc1eaef6c4267c973f7e7f1a23b27fcfa5667cf13165a60cf1","test/common/mod.rs":"bbdddcdbaa55bab3bc037b0449b6537ec2df2d4d52d1a7ee5288aa4c346419ee","test/sys/mod.rs":"ca14fec72e970eaf0033b728087e950c132fbeffb269c09f47c51d27b671e8ba","test/sys/test_aio.rs":"070321a72aede1fdd38e55f90768d88d903f0dddad8868d1d26bf77be220c862","test/sys/test_aio_drop.rs":"2dcc71fb768814ee936a384384b11984f9b2d64a5c8245faf466aa4027b33daf","test/sys/test_epoll.rs":"4081004c6c48cd55b27c61865641cc1bf006d2cffbf1a611e4a54d8108ee8c25","test/sys/test_event.rs":"2ecb6f15941d9819f310a5128ddd29c828cee932d55ba70e7f710466af8f5665","test/sys/test_fanotify.rs":"ece6e64a4b2162686ede921d329b5f1b27745be6c47a3f7e5650ed237852b11a","test/sys/test_inotify.rs":"1b3253db06bd6464f3e9ca46646615e62c3bad889dc6813d2068a96fbaa31d46","test/sys/test_ioctl.rs":"ed458ae18b37aaac45df16f38f815cc9fc7080dd17b2e18acc6a05042737e4cf","test/sys/test_mman.rs":"a4e7cfcbdbda707da74d5b49ef56a5c78e5184fd9674860918bedf31d612483c","test/sys/test_prctl.rs":"5c0a7d4f6678d6433080a72926235e5250e50ac9c4c57f52c07b11680c322cc9","test/sys/test_pthread.rs":"9ecc144f8f253589aabd8d5672d837c3145bd9c28f03e9a3f21d0a43babd33b9","test/sys/test_ptrace.rs":"5a9aa8ee660b84896bb1e74700746b3ef7e915e36df6722fa9e1a49483823ecc","test/sys/test_resource.rs":"669e5b22ef0a9ce69bdfab1e9f63a8f53bf1c5ee7c79c8e2e78f2071dc4b8c01","test/sys/test_select.rs":"5ce391b9928f3e9a3588b17818aecf06226deac34b5593ed86d773e469e5758e","test/sys/test_signal.rs":"a7463b6b6c53b5704878ff41cff172c9f48e71632693a5edfb68534afb8fe211","test/sys/test_signalfd.rs":"b3bf16f0d7e88a055a0c93ada1a9619ea5b7cf08a6bf1eddf43c5b7e4599a71d","test/sys/test_socket.rs":"99a6f0329ebc6790af1be2938e84f1bb8e4a59ed72542d6c082128d9e0dbea70","test/sys/test_sockopt.rs":"057e4f6d39d10a834d66676a689928920affbb0499dacdbf8bebd28e243608a1","test/sys/test_stat.rs":"b481cb6e20659dc5a63849e3151610ef2af50140f2c5d1cc39a43bc58560fc75","test/sys/test_statfs.rs":"4522f3817fb1d54816654b7a24325d3db54e19dbd1a94a4a3f5a010052f69456","test/sys/test_statvfs.rs":"ad13a879a5403f98c623051c8a653cfb78f5a31869d90f139c6ae99d6eba9e11","test/sys/test_sysinfo.rs":"6c42cf86731bcb300c50707d83157af92aca3cd3e3c2d46b1333657e463b41ec","test/sys/test_termios.rs":"7e7bf02b420d0664bcec3e199b63cc5d83fc3af625ce675bc845542a41b75ff8","test/sys/test_time.rs":"4cf4195a77844eb097818c2db7cf47921737c8aa53d061cf49d9080b60b50ac1","test/sys/test_timer.rs":"d2364da7af2fc64a458fd2b16caca2c779ceefac0de322c13066f77039c442fe","test/sys/test_timerfd.rs":"712d876754794031dc7a43636f5af47e4c8ea3a8b13c7460a6da5fbb741f491a","test/sys/test_uio.rs":"25cc97565a7b584a4fd626df7dbc6db4a4da901a36ac160d93f0511ea713e6d2","test/sys/test_utsname.rs":"60cdb81efbfb126593bfbbe0437c0f4fb97d5ad3e423996622cb33ccb4d80ea4","test/sys/test_wait.rs":"dc997b861eb8001dca47f11e7bd9458ca20e169816c7de8d45ee0ac2b9d167e1","test/test.rs":"51894d348fd60e0bbf172de28b89e494f64054c69a7139eff8c28811a4b7d0dd","test/test_clearenv.rs":"323054cad8ce178e1531b470f93e49856ef06e66c8faf9e2f0e2d3398c9e842b","test/test_dir.rs":"5fe95812a13b0bbc8cba9da1f3f59a9979edd01a63078c5bc370b383107bd134","test/test_errno.rs":"db50d2f9a9f03fac417547ce5683a65688b03150fc9c1471e4c2add3d89a2c07","test/test_fcntl.rs":"a05e23890df0965fffe83dbb80089104a944a9ad28aae0284e2ec10797f1c679","test/test_kmod/hello_mod/Makefile":"b406e6c31829f06c93c4c22f5343ac0c6d1d873c0df4bc1132dfca8e636bf041","test/test_kmod/hello_mod/hello.c":"6059ebdeb2d2e050be3046be21bca8e830da6a2f8262511fb12d9402c9dea526","test/test_kmod/mod.rs":"9a4452b7fed034c35554885245be3d0c72a454b6efabc21ec4629b8ad53820d5","test/test_mount.rs":"613455ba98196582655cf46a6fc67bc30e7398280423b4e33fbc300beff1318f","test/test_mq.rs":"f2f42b6b9a9b8567e4a419f090fa19398d83185a98983db7c6feb067caed5559","test/test_net.rs":"d03a6d6f57127fab1a9622a628ab13deab616e817944371e522fcb2bcc23c5a7","test/test_nix_path.rs":"a748d4914f216a6642a07c2743b03033a318ad98daab56096bfcb9120454cff4","test/test_nmount.rs":"a48bc85fdba2b5afa6997cdfa50b0808d72a7a7aa5151e7de504660e657125ba","test/test_poll.rs":"1dbdac16e264e54d781dc7c25b41caacdb00b442f76bc53d9e17ac19cfd91eef","test/test_pty.rs":"2acac2e0f9bacf569f48ca58d1eddaae5d79e7ac11ba24eb2fee5c4347ea70c5","test/test_sched.rs":"031932ac8c512c7f881c80c9fe01ecd4c744d9c41b2b0f5fbf904ac0e0e4bf6a","test/test_sendfile.rs":"5a738737602b242b2139deb6c796e01a0aa5a44e0738a017b091342bba162c83","test/test_stat.rs":"cddebbd15ca1fc0ae0bc89594d8c2b5a8be4ce36ef10c9096b6867ad2cbc6826","test/test_time.rs":"7a41b517288fde2b8f9f439bdabe3df1059526793f0bd2ecee2c8ff23a64329a","test/test_unistd.rs":"25db690608fd72e40c544d6911e25e06674580f86a2faccf7bb989520b3d5995"}}
\ No newline at end of file
+{"package":null,"files":{".cargo-checksum.json":"30bb37dc98f065a00d9e5000681c6494164392c2c127d1809b415fa8d1bd89a4","Android.bp":"5aa5a1d27e979282d6e7268595991b5de3af912807f0c5c9a1f4958f951e2d78","CHANGELOG.md":"9357c8dffb7cfea2644f16b52b6bbcdc85f2344fdb6b9b1fcf6703e4ce196bdd","Cargo.toml":"a9d69cbf2002b3b485a81944e21038a09fc98552edd5977037cbc73339a61fb2","LICENSE":"ff4177622b3314b5c7199fb4a42e3807acd8362b7f32e45e26630e235260f943","METADATA":"4d1017f4d7ccfaca742fe0f1e57eba1988f5565bc8584bba161eccce55ba394f","MODULE_LICENSE_MIT":"0d6f8afa3940b7f06bebee651376d43bc8b0d5b437337be2696d30377451e93a","README.md":"b77b826d1b503d67b659c9090f46cdd57f6693fd7d3b273f9ad045a9df85d47a","TEST_MAPPING":"51f4b8c9722b9825f6a384bee4c2d246ea00ea385f41867e8f7a104a91ad9e42","build.rs":"a3d803c1e739a4a306213eb6914c83ce35b430dda7ad21d7660076f49577da20","cargo_embargo.json":"98edc205c0c2a15cf2a7bb74956cfbc52d7a3b29da0c7d781751ccad9453e478","module_block.bp.fragment":"d265f83f777285b9c1dd903f4b9f9204c4c58e5ac0f34cc49f0ec5ec6e820e7c","patches/memfd.diff":"f30b12198a1a2f7a695cde6d0f942ce6c319d6164e68c546f8e94db29244bdba","src/dir.rs":"7140d727266419ae57ec39ab785469abe52ff0b3fd3b4955f4df2f4a2213dbc7","src/env.rs":"a850356a838368c3b28552a2c9750366d2ceaed742f6754477c1fb5385d91957","src/errno.rs":"9daa17bbc59b33527bbf41d26a6913f60da864cb0ae9ba0be21e5911cc3ad69c","src/fcntl.rs":"6c442b5f2fe32f4033104583601c833e7d308099f1f897dc021a54f411c97e49","src/features.rs":"cce028bd977ef8c69b4b4b0a959e94573f3d1a89b53f0fa23aae135a60dbdb3e","src/ifaddrs.rs":"28708d0d15cd124da68c98c76ebc118ed11caf905bf467b80e3de23758219d98","src/kmod.rs":"b96e40714902ef7941d5489f8b68edd9337c3adddf34cce68d90363f0664e8c0","src/lib.rs":"f954a43d970557cbe94a3ee075525afa1ea37f1498dfb7d39cc38b7255654ca9","src/macros.rs":"a2c488d2336b89b89f1d4681aab7f050be4db94d46b276a7172089b2d4998b64","src/mount/apple.rs":"8108058b35548cbe274acd0b213b2e9ed8dd88a609cda6e589d3e768392ee440","src/mount/bsd_without_apple.rs":"bf859eb02ddc8030ca5c2a0f8a8d80165facd41c27e3300d93505347697b4d1a","src/mount/linux.rs":"e0303501e66addb14ef3b700f2e5490ed5d6dce7e6f75fef6415a60ed8ec9ee9","src/mount/mod.rs":"d7c459aa273c6d068d1fa2b2f3a64c9da2a90e4f81eb6b712b1d3b46fbad84b9","src/mqueue.rs":"d3b9a29435f5d02888994f1164d2684d7e3756b80e3448dfc5919284ee23c965","src/net/if_.rs":"65d71ba2bceaf68e40e27f6cee61578b5414539f9880ec2a1f17efee0b3f8991","src/net/mod.rs":"a88860334410ed47a1f6594a8563dfeb22bbcd3bb4dec308bb8e3de8866b3af4","src/poll.rs":"f57dbc06aa318841cd0eb035579b8e3fa875aff12d66b1e6692e261d65b9b1c7","src/poll_timeout.rs":"16007737ae9219e120d1b0de017067431fe8fa6223d03575bbdbdfe7aab4c1ea","src/pty.rs":"e6ae49216b79e4ca7bf6ec51b6c354fc92c161ff8dacdbe269282b8ca628361a","src/sched.rs":"303e5b0c605ca019ffb02472691277e81f6f6be0869411814416fedf2368ef40","src/sys/aio.rs":"0f8452943cfe71b77606116376a834ab70ed0d5c7c2c8922ed4652f7c6d87b3b","src/sys/epoll.rs":"afabda2906ed2d90dfeecbdd96a220be6b3c50835d395e1be2d87eb1d2222cd1","src/sys/event.rs":"4f9f42e4eb4ddac00ed6fcb5d70b9879f3a1291f3160e72de98e1076ed8a98b8","src/sys/eventfd.rs":"5c465648001444c18e55c3d90db208975c125ce003f38fa9a4ab24f97e15733e","src/sys/fanotify.rs":"06eb950263d5d35afccf215f9c2c1d3cca640c1deef9b043fa5b81d9b0c51c4d","src/sys/inotify.rs":"1d1fdf3263c5ee893dd58877cc458b478ae470e3794d50ca5a4d9cd9d7f31eae","src/sys/ioctl/bsd.rs":"10b2ce4d04e0d28277d4a237204e491e896e3fc377c5dcf8792a45001d0f8a26","src/sys/ioctl/linux.rs":"9242e92f8e8bce63af9693af61fc69355082ca882810ab43ddc55f5557803b3c","src/sys/ioctl/mod.rs":"5ef03b0ec57f3270093da800b466dd8f085e62565db60dd403977231758d712e","src/sys/memfd.rs":"c1791230913192d6931cf0a33c1f6ed0de0db00360326e8538ffa559ee321ae0","src/sys/mman.rs":"c5ca69aebfefb03ea5e29857361a0280a93c08fb72aa6e6df034984542124eed","src/sys/mod.rs":"81608664a2880f27699f08c344e9ef23c7055d7e8b79832b81c702510b8e373d","src/sys/personality.rs":"4fc2b82f1e4aa6bd49bd1cf320127d9a0061974096c01b95454f79fd74ee4294","src/sys/prctl.rs":"974f1509730463abb14dc2f795546f00fb9f44b44c8c542c7e1b99530dd9f4f6","src/sys/pthread.rs":"270213f8050f8bff48e87fe4ad35453b5f0423b959e974dc2b0b8a35eb2491ac","src/sys/ptrace/bsd.rs":"a387ccefa8adb7b8b7f0fea41be619c54c8091c0e111e7b813ee910870f7414e","src/sys/ptrace/linux.rs":"2830cb8add0960b6e2b8f07b1f4fc0e8dcf0b5c23b79bc7e23774038c04ea52f","src/sys/ptrace/mod.rs":"641edf21d50f73b5079a85c0aed84698acb927e96694161eedba5d9368c1e5fb","src/sys/quota.rs":"944cd578a34011f4e35c28a002f0dd5b7cb53d87d7da8da5b39011e4c56f8052","src/sys/reboot.rs":"390407d521facc8ea3d66e314e7d5a27999b92db86be864919a6e8b2851d6c88","src/sys/resource.rs":"9a57f48f39c378f92cd439fb71f70533b4ca282fdb60503f23035af83077fb08","src/sys/select.rs":"42d38e91eae5ed7a30c31e1b7974860bc419256e6f461164b15a74d2e9653eab","src/sys/sendfile.rs":"9d518732634e6c69482527e68e3d8c132574f7af2c4ff3612860049558016d04","src/sys/signal.rs":"f1241639eb51d36ff9fa5b2a516ecbe53e31bd6b1a69623a768b1eb577f7dc2d","src/sys/signalfd.rs":"c4a88ff4d8838ffc37cc58b415b20d88a7b89ea5432c26bf0455efc8a4572180","src/sys/socket/addr.rs":"c21e2b25d0e0982a8cf7c71816f53eaa4b54d3b33bcb267125c13f0c46b221cc","src/sys/socket/mod.rs":"ce07bf90be0a32ec1199526f5dd05e19e2ca6c95fb23bb7cda2b0550cf80594e","src/sys/socket/sockopt.rs":"56b5bb6ed6749e299b1f0dff5533eef213d301a2e38b48ff96526408deb89c40","src/sys/stat.rs":"bec1d3b5a7a930989b9a54d350d47653499deeb560d73f3b63efaecf4ebb351e","src/sys/statfs.rs":"83b095a903858a298c1f6b2135bb035f24381374097dddd09289bd4f23f1b389","src/sys/statvfs.rs":"0256273f711e9d2c1c7b8feed6dbf3328295095a9a328afb341ff08bf27ef941","src/sys/sysinfo.rs":"ab216769fce561e3a123aceb29c8bd9dee94895450becf32c04411295b88d5f8","src/sys/termios.rs":"39ed1da2bc23294fda06536e8cc850a791d5576f339057d3a2e0b165ae6bcb14","src/sys/time.rs":"cbfc06acea72029e1746070c8355c362154fb42bad35e4fc36fa5e5629758da5","src/sys/timer.rs":"d436c5b043b99afd8de9fb42a8fc7ca3509c324d071937b7719bc7ece6986caf","src/sys/timerfd.rs":"ddc1f4f726d1cbc416006c62fc39d80c9edc10297c5d03d70b55106a9df2c7c8","src/sys/uio.rs":"7fd8fccc97ba5b8ee70d74f18399fbd6af60a7f366b9929d90ded2af59a7eb43","src/sys/utsname.rs":"8ab00cc78f82a44a3d47c3955f030418ad846886fabaa9fd178437896a54fee1","src/sys/wait.rs":"467c35c1d1bf5ed38b5e7c0174a2df0471ac2ce37166931747d887b75d2e1266","src/time.rs":"2588796a51798fa053120b809e503bab9c7526f3582159a68c999630cebb2d57","src/ucontext.rs":"0eb33bfd885d9378a8583a7de7409755b73880bc159d502f974d749db84afbfa","src/unistd.rs":"539d4f4834b389d5945044ecf2ac27ae95517518b4eafa48fa498970d3b29334","test/common/mod.rs":"d13b9c054b8fcf0a13dbc7e615ff0cad83e9c85931882ab7058743cb37ad442c","test/mount/mod.rs":"8e8cdd0a1bfde61fb72eef9e3b3e31034eaa118becb21144e9c8ba8a9574bc6f","test/mount/test_mount.rs":"0bb99024cde383a14ba06c9e7f6c540dd34271fc0c7a85b16fca275756c352c2","test/mount/test_mount_apple.rs":"c90372c72c09f4c025c8a7052cfe182b54183675b62b4863c7c9fd81d1a4cba4","test/mount/test_nmount.rs":"a48bc85fdba2b5afa6997cdfa50b0808d72a7a7aa5151e7de504660e657125ba","test/sys/mod.rs":"ca14fec72e970eaf0033b728087e950c132fbeffb269c09f47c51d27b671e8ba","test/sys/test_aio.rs":"4b59e4641c2f682d4eabfa0715ae1b4eb4f192c8b4cc0626e474cbdc1bffe92a","test/sys/test_aio_drop.rs":"19d990e37142a1320ee827e381d43cf95573824887756be19f764f064a9eab10","test/sys/test_epoll.rs":"4081004c6c48cd55b27c61865641cc1bf006d2cffbf1a611e4a54d8108ee8c25","test/sys/test_event.rs":"2ecb6f15941d9819f310a5128ddd29c828cee932d55ba70e7f710466af8f5665","test/sys/test_fanotify.rs":"58f9db09dafbd456c0d58661cf6b9dd21da274bd6705dddf2c3fe99c85c8405e","test/sys/test_inotify.rs":"1b3253db06bd6464f3e9ca46646615e62c3bad889dc6813d2068a96fbaa31d46","test/sys/test_ioctl.rs":"ed458ae18b37aaac45df16f38f815cc9fc7080dd17b2e18acc6a05042737e4cf","test/sys/test_mman.rs":"a4e7cfcbdbda707da74d5b49ef56a5c78e5184fd9674860918bedf31d612483c","test/sys/test_prctl.rs":"551ae558a9450571e9e855050d687ebae6e7cf436b620a03a94e56f012f2c2cf","test/sys/test_pthread.rs":"9ecc144f8f253589aabd8d5672d837c3145bd9c28f03e9a3f21d0a43babd33b9","test/sys/test_ptrace.rs":"16e1ea1c96b35f7ff493b0b277f443b7098d59ec136f014de64ae5d74cffa7ca","test/sys/test_resource.rs":"669e5b22ef0a9ce69bdfab1e9f63a8f53bf1c5ee7c79c8e2e78f2071dc4b8c01","test/sys/test_select.rs":"5ce391b9928f3e9a3588b17818aecf06226deac34b5593ed86d773e469e5758e","test/sys/test_signal.rs":"2dc1bdcd9f3f850b1e1d21ffbf4c9131b3a2c5334d4dd764e5f901b33cfb80cc","test/sys/test_signalfd.rs":"a0f401ebebca1431530f67b3d4343874553d30932f29cf00e882695c7645cbf3","test/sys/test_socket.rs":"8802c70f4c278973894bd1faf488323823d68aebd4de954e30a5dc2eba475ada","test/sys/test_sockopt.rs":"1798960fe94f4947e374c821971816920eeb1735f66a73c4d55621d0a1fb1e8b","test/sys/test_stat.rs":"b481cb6e20659dc5a63849e3151610ef2af50140f2c5d1cc39a43bc58560fc75","test/sys/test_statfs.rs":"563efb7a1ad24919dfa15effb5e459c8d46096655fe557b133228b36ad91216c","test/sys/test_statvfs.rs":"ad13a879a5403f98c623051c8a653cfb78f5a31869d90f139c6ae99d6eba9e11","test/sys/test_sysinfo.rs":"6c42cf86731bcb300c50707d83157af92aca3cd3e3c2d46b1333657e463b41ec","test/sys/test_termios.rs":"7e7bf02b420d0664bcec3e199b63cc5d83fc3af625ce675bc845542a41b75ff8","test/sys/test_time.rs":"4cf4195a77844eb097818c2db7cf47921737c8aa53d061cf49d9080b60b50ac1","test/sys/test_timer.rs":"d2364da7af2fc64a458fd2b16caca2c779ceefac0de322c13066f77039c442fe","test/sys/test_timerfd.rs":"712d876754794031dc7a43636f5af47e4c8ea3a8b13c7460a6da5fbb741f491a","test/sys/test_uio.rs":"25cc97565a7b584a4fd626df7dbc6db4a4da901a36ac160d93f0511ea713e6d2","test/sys/test_utsname.rs":"60cdb81efbfb126593bfbbe0437c0f4fb97d5ad3e423996622cb33ccb4d80ea4","test/sys/test_wait.rs":"dc997b861eb8001dca47f11e7bd9458ca20e169816c7de8d45ee0ac2b9d167e1","test/test.rs":"bc80258bbfc6a567efa419a00137cc05bde654016e1682f5d07b77eed2533a0c","test/test_clearenv.rs":"323054cad8ce178e1531b470f93e49856ef06e66c8faf9e2f0e2d3398c9e842b","test/test_dir.rs":"5fe95812a13b0bbc8cba9da1f3f59a9979edd01a63078c5bc370b383107bd134","test/test_errno.rs":"db50d2f9a9f03fac417547ce5683a65688b03150fc9c1471e4c2add3d89a2c07","test/test_fcntl.rs":"9616c1eaa72c3942edfb14f99525d49175ccb53325767b895366c8c78f4e2e52","test/test_kmod/hello_mod/Makefile":"b406e6c31829f06c93c4c22f5343ac0c6d1d873c0df4bc1132dfca8e636bf041","test/test_kmod/hello_mod/hello.c":"6059ebdeb2d2e050be3046be21bca8e830da6a2f8262511fb12d9402c9dea526","test/test_kmod/mod.rs":"9a4452b7fed034c35554885245be3d0c72a454b6efabc21ec4629b8ad53820d5","test/test_mq.rs":"f2f42b6b9a9b8567e4a419f090fa19398d83185a98983db7c6feb067caed5559","test/test_net.rs":"e1384964c28708ba4ab04955c51b20a71576f7166d010bbcd7f963ae20400422","test/test_nix_path.rs":"a748d4914f216a6642a07c2743b03033a318ad98daab56096bfcb9120454cff4","test/test_poll.rs":"1dbdac16e264e54d781dc7c25b41caacdb00b442f76bc53d9e17ac19cfd91eef","test/test_pty.rs":"00adf9878e9d1ad7c603e5ffce7c52d8927de646f841524cf8eb429e936dcfb6","test/test_sched.rs":"031932ac8c512c7f881c80c9fe01ecd4c744d9c41b2b0f5fbf904ac0e0e4bf6a","test/test_sendfile.rs":"5a738737602b242b2139deb6c796e01a0aa5a44e0738a017b091342bba162c83","test/test_stat.rs":"cddebbd15ca1fc0ae0bc89594d8c2b5a8be4ce36ef10c9096b6867ad2cbc6826","test/test_time.rs":"7a41b517288fde2b8f9f439bdabe3df1059526793f0bd2ecee2c8ff23a64329a","test/test_unistd.rs":"880416fa3ace154ac8856308db8ccd524d804cbdd93e91533928f61c1093d814"}}
\ No newline at end of file
diff --git a/crates/nix/.cargo-checksum.json b/crates/nix/.cargo-checksum.json
index 3cd0495..b0ee1d5 100644
--- a/crates/nix/.cargo-checksum.json
+++ b/crates/nix/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"CHANGELOG.md":"67c8efb2646c390f76029cf2fbb6205bd23e6e15c149ed32a1549e25bef1babe","Cargo.toml":"cd8795ba96b904a16c840e69c94b9493d8032b966579e4589b9adb35efdfec5a","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"de89eb5b6e00eff6eb3043475da16abf3ae63906cbe3103a450c4bf27cad3f3e","build.rs":"f4b3c533039fe39f167251372b4f378ebef43203654f0ac2340dc0e222206787","src/dir.rs":"10a6ff94e56b849ac8ea762905efa85d11812e5539587ce8e5cce932961c7141","src/env.rs":"9d1e7d52c6c5f46d790a8cbc6d5d2ff9097fb7728594c518d51824ebfb70c9b3","src/errno.rs":"204dd49244d461da6827142386a6b491aaeb6c4ca3760bbe9df5fd2f90e9f4ea","src/fcntl.rs":"1014853b9782285f1467dbe79cff435d0bb1d4122dca0b23d7872ddbeb7688c0","src/features.rs":"6edc53dbbadf56a193dc71053f6512b6cf0d09feb5efb8eb991877de1d70c43c","src/ifaddrs.rs":"40ed9c631b5bff403a697889971f44ad87d6fd6bebbd99cb047cf47c190ee87e","src/kmod.rs":"1e77141714fc7da27fcc59caaae0e31b5801f6e164a57f8d6d399a1b4051d5b1","src/lib.rs":"268b7ad111b99ceaf7c78a348824e8a2be84380bdfe8826e8378b6510eac6b9e","src/macros.rs":"ea6b3a5c117f82ab97d0a410501e7ec250ee11baf3c44b1f207ec404ea682d85","src/mount/bsd.rs":"47477e79ee2862b1d7a5afaf099884036fd81e6384624e60d5d2719a9ddbc112","src/mount/linux.rs":"57ada5949a7a393c427e8076e8556938104f70a73c51452d95ab3d78838f442b","src/mount/mod.rs":"8d8c51f25130e02c860f1d85959d02322b4d9ec748295dfc5a4544e6231725a0","src/mqueue.rs":"0c094b340c918796aff8aa43bc78da566c6203c779a41ce5f490fd41110628f1","src/net/if_.rs":"3d32aceb516606271d8edd2dffd5c710a11868aab54119aebec5a70b35cd963b","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"6d27611db0bc1a64bee80cc74155bb593b1e488092d753fdee102404e7e408ec","src/poll_timeout.rs":"c32412689fcafa561514df9d974206c11bb1276ef79fc10964f11b5416f51a00","src/pty.rs":"d30a7bb587bf727615fc505bc8987d5cae543be0d79d2a8f71a41d9cec2afb6e","src/sched.rs":"542bd9b1d8e1ed132c9a16c3485c70d3d47e30f702c4da1b39906fc64da4c308","src/sys/aio.rs":"b57cc89b70b1052c699264427661c293425536db9577f2fa2c6bdfc805fe06ae","src/sys/epoll.rs":"49ce070f560c8ac7a6f338b4b182f70049303c7d895320a7186fb98b666cafa9","src/sys/event.rs":"3e6e737a880f802644b7c5656a6579d747a66b595ba26ab6cb59df1141ac6eda","src/sys/eventfd.rs":"244ec41689cf90ba0527dd3501ea9f2623873b35cb66577dfc652c35e8492fe4","src/sys/fanotify.rs":"769282c558c7ceb3ea3f9661b6717d507641add46b8b033d4bd200c87df2a66d","src/sys/inotify.rs":"5ce6d83beb2f328c33acf0dd3639a1bdd7b5c2e362745b3cb0fa4c549a641e90","src/sys/ioctl/bsd.rs":"e6affc2babd4fa4539574426e416b330b7e32ba4fd2821899a67417261e7089e","src/sys/ioctl/linux.rs":"8c8bdfc239aa175efb4fc2f666a6ecc799b7d614f85e9143595fff05d37f76f0","src/sys/ioctl/mod.rs":"304a959e9eb24dccfd3fc6153719b417367d9208dc7e6859239fb020c407d103","src/sys/memfd.rs":"a7c2c446143f1dda5537a4342a84b83bb536072215ca973de71f87a33ed8bd37","src/sys/mman.rs":"e75b3ae89c18f541ba8fed01b9147661078f9d035eeb4eaf792ba0e4ff1167fe","src/sys/mod.rs":"30057a1c687859394f27581247ae9e412f5f68d4484bd5196797c1bc1939a6c7","src/sys/personality.rs":"f7fa4e97de0943aa6a969465ca7d2d69ac98015f7c339fdbb88d83ffe26db4ce","src/sys/prctl.rs":"785f97a545e010069d67ef11b22a70ca5000e131ee8ca990a2652a596ade77e5","src/sys/pthread.rs":"258cdf7ff0b61a4afa6d228109e4cb4fb88d859bb8dfe6c959d95130fb010906","src/sys/ptrace/bsd.rs":"54b92e1ffe6455a545f807ed7de9011be05251adfdc71a5823b1965579650939","src/sys/ptrace/linux.rs":"c347075fc8d9afd63d6eaf1acf84afb3a2c956b236eef9f17c19e883a6aaa73d","src/sys/ptrace/mod.rs":"a9aefa2b10cc63c8b40adcd3e7dd612a8f4677bf6f37420cdd09e7129ba02c95","src/sys/quota.rs":"1638e34bddd955c7f98f1814d239eb76647101295c8a1ae40c78dd7dd7638f20","src/sys/reboot.rs":"b748217e4877c94c1870885407b9ab1ab9e059c9fb7d04818a1b29477eac81c6","src/sys/resource.rs":"e701020b893666321f44c08df9e60f8927d00ac1035c89965e967dc0b44c6222","src/sys/select.rs":"9cfcb3a9d15a46b2f209e66cbaf136dab6894c711031313557bc58534ecedc70","src/sys/sendfile.rs":"fc7ac628424eb1132674c73bbe19f0d82a28d6752b0beffbf111965ea3885760","src/sys/signal.rs":"da1720190cdedc854649a525f2cd2556daec1c069d3fe32ad65c4302cca8efd9","src/sys/signalfd.rs":"f0b4d32e642a3a02d349b38d317a805eedc6e60e9e773f650fb0ee4ad7f655a7","src/sys/socket/addr.rs":"75d94b8404711b4ec08b44c3d43c7854f7cd9cf8e17665056dddaf6398d1df2a","src/sys/socket/mod.rs":"12c1a291648553516437bec168602fbebcae3d1ad657a7e55cd86f842db29d50","src/sys/socket/sockopt.rs":"69ab0440767e808c0fe2f2d269eae67653b4657e51b8fe356fab95b7ab26546a","src/sys/stat.rs":"074401a0b0fe74d9516640e0790fe67b7727213115accfdb331a9767ae20064c","src/sys/statfs.rs":"991370ce27196f8721a03a88c3b906cc248f46f147ebd6524d45c61433dc0239","src/sys/statvfs.rs":"526c2e69b640f49331e8ca7a2e59cdb803887c91a53fa41f866364fec93bce24","src/sys/sysinfo.rs":"b4519b1ca091c9dbe94d2a6fd6304944bf3df5626973d2c6884022559706f0d9","src/sys/termios.rs":"dd68b78e4a87786d22334c014d258e43d12f4e9370acda61209eb2c9ed176c86","src/sys/time.rs":"a63f6b5cf67a9323ccc3a225ffec88bb078c5dcf22d0eba78ae071db67aefc53","src/sys/timer.rs":"8c10f0e7cfac857ad00460be30bc68b957909cc9296e70718d3b5d4a0babafde","src/sys/timerfd.rs":"569d662725018427b517ffcfa78d8d03e150a344b8b8533d3f16e3bfd5c762da","src/sys/uio.rs":"d0886bf517e9b21af8ad6a25d332003fe9e132fed43cd642ec61b32d27622bd6","src/sys/utsname.rs":"e1f81d363621445633101800ba34debdb222eaf3a25553f8b486f74d49e4be41","src/sys/wait.rs":"338235d42a2ec29633cf64dada7b9b1d434ed0005776bffdecfd5c69922eed89","src/time.rs":"30038bbe683857469d106631cea13ee1e43f149cb4c947a8353824270ee4267c","src/ucontext.rs":"b8f2e04757a9c2bc38c3b1e259d3a013da8a730fe9bfbe5487637395681b43d3","src/unistd.rs":"5bb3b5ad2984793be4eed6adf653bbc52592c2459b9063009b92edb83ed562cf","test/common/mod.rs":"953155de9a50974fda7a43a66269211154bbb5898791e0abd97dc4184d482f23","test/sys/mod.rs":"f08046850a4b7a9bbf203d8eba0ee3ae9c32b6bd4d9c7bf52ca29efb3eb74f35","test/sys/test_aio.rs":"902ae4abda9286db551e65a7eccf267baee16eeefd1cdddac8399bef2ede0060","test/sys/test_aio_drop.rs":"e9e45333b24381bba99235372d5917a22fbd8692eddfbebcf519697c603de812","test/sys/test_epoll.rs":"c30b08d665a1fe7d7a04fe51d50ec78fc74c2ac707ae0f95f82104d5c76ceaf2","test/sys/test_event.rs":"be4b1b1abd25f87f00b3d115105ef832b2c654fd7028c42f1a304a935935b479","test/sys/test_fanotify.rs":"55b0917f8b85fdc8277e6a796d06251a39398b9f2da88d9eec98a763ff03e918","test/sys/test_inotify.rs":"a141b9a995892547b51ceeb6761a70a6b86d37e8f38d13ea2c497b81b4b0f49f","test/sys/test_ioctl.rs":"07d08a46c4ac84161974b655a0d040e03efc9338e7a7505e0d16826b7653b5c2","test/sys/test_mman.rs":"f129659d6995fcada15e7c923cb943d8dd4c6e4aaa141c6cc5bacfa3257793f5","test/sys/test_prctl.rs":"9c3d0fb16a41c3fd80541b313c2bb63de75634ad4711a71af106e58b0cec9ea8","test/sys/test_pthread.rs":"ace36a2f5587f1874854281b4fd84e4e4d892a1e3c5cc38ced57975739522ad6","test/sys/test_ptrace.rs":"ac4fff669bfc58955e94ed0171e4d47ecf2366fce62509c659e78192f9de7a6d","test/sys/test_resource.rs":"aa58f566efb8132b42ae98be6e50b72fee86ef50c4bcc4a7bf49b275f6762008","test/sys/test_select.rs":"09fe9d020e4f1cdb0951ebd27a6c3f408b23471ce2c51d2f1e4708500fc15261","test/sys/test_signal.rs":"ac6cbd345cbd93b1c9bead56794bd978dc44435beea921bedbdb8a2761e557d5","test/sys/test_signalfd.rs":"8db0c371d0cac7d68208505990291ebc2b2cb8671b0edba16ef22b6b9e56dab2","test/sys/test_socket.rs":"8c6190cbea80d5b2866d0891c6f44fddaba337b655af7e5628dc9537e1cbfab9","test/sys/test_sockopt.rs":"dd1839c495ce37535b2fbf78290dfbb1350f40ed7ed92c7fcedc16a88730ecf1","test/sys/test_stat.rs":"6630a28217fd708bb84cd4f7e7101836b74f2420f9888923fdab664ccc331c1d","test/sys/test_statfs.rs":"a32f6319ea7e989747707de27b06332e7942b07e07ab1602af408be91fae7e73","test/sys/test_statvfs.rs":"05cf8f1bcab0f0cd8fbefe8a2a72f9ac6d95aa760c355ac6d4b6f9c61649bc38","test/sys/test_sysinfo.rs":"ffd49bc96375914a2c4a4a59730cae8072f85771e2c4a80d3403df38d967e272","test/sys/test_termios.rs":"6c6897e0320d063a758f6702228c64ef2b459b4a5affa07ae7e76c1142432f0a","test/sys/test_time.rs":"aff97dd1bfc4aa9b616cc71e9cc11f25fb3ad983f1406c856648736847778c19","test/sys/test_timer.rs":"3ae20d364f075d2811f3ff94eda9886682cc21d8807656007d2464fe36d1e361","test/sys/test_timerfd.rs":"cfed3abf58118611d08f6985251a7739cff67108e11214222a1d2394a3a026ce","test/sys/test_uio.rs":"dda569818e3256ff45aa07b33cffb59828983c83b20266b864cdfa38103cffc9","test/sys/test_utsname.rs":"b8371dca02c9cdfc0c8e93df9b5cf5b5cb8a92b114977966854918abeb01ad73","test/sys/test_wait.rs":"c958e51b10a7d0396d0013e9d637a2848ad9d061d526408b40dfefb850c22beb","test/test.rs":"e1da3bf8ef929a9e4aca354bf72578f6649c80dd5f32400eb124b229bd4506f8","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e6a100685f945b6007312d22575ac5e27363c649f3fed19fb10b18ac5d905449","test/test_errno.rs":"e7a1320e97350c2883368ffe9fc47fd041f4f9ecdee360d21d36254a63a305a3","test/test_fcntl.rs":"4467e1e8698256c982df17108dacd1fcb6ba0eda18044fe198eff25629827e66","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"b4ae25841c2f06f32de9f1acd8230eeccd7095721302ebe78ad454e4e4f9c783","test/test_mount.rs":"9fc453613eab116841a7f2ba57098eebec853fc16ce0e59cb459a203e006115b","test/test_mq.rs":"d8ec2a3f3acad4369851663b3f7fef03177d9f8395b585dee8e2c53f6a2a9b4a","test/test_net.rs":"cfa1d3b4e252193a4b119141f8e93d637e3c32e9029aef72f8bb83e00be6c3b5","test/test_nix_path.rs":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","test/test_nmount.rs":"d6c112547bb80968170b5497cda4b6cbf69dabec6f51d494bd52298995ceff18","test/test_poll.rs":"25b4fa094bbcda5a5317a25d2f292465965dbe3e066374b04a9b27a8d55897ac","test/test_pty.rs":"ec54c5fe096396b5aed5677276acaf80b4c58be7222ee285cfd4eaadf7b34ce0","test/test_sched.rs":"c4579bd376fab8816e63b07fa9ace31dc08e63ebb7c855a2c450698090d1d1e8","test/test_sendfile.rs":"6f82e9f66359a85a7aa819ffd38c7c3326c1bb2384950d681085dc7823fc4a20","test/test_stat.rs":"dae37bd9b5e46e1a76696bed435d8bc4e98ecb91bb3476e7133a6197178d6644","test/test_time.rs":"6eb3536936c67bcfbc80a73a902b4a485943aab5375fc7e3880da6695a4eafce","test/test_unistd.rs":"828a990974b4d843d59f3d134758d4b6a9afa43da3d07dcaf314fcc1615bd732"},"package":"ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"}
\ No newline at end of file
+{"files":{"CHANGELOG.md":"6d533687df51339d3c064c47af7b0d80676c685be27636a4b1f2e18162c9bea1","Cargo.toml":"30a3d3032dda335327557f9b1fca7bccf70c8f46b024221fe842f8a707b6f6cf","LICENSE":"66e3ee1fa7f909ad3c612d556f2a0cdabcd809ad6e66f3b0605015ac64841b70","README.md":"de89eb5b6e00eff6eb3043475da16abf3ae63906cbe3103a450c4bf27cad3f3e","build.rs":"7e47b7c39f11b745b4eb3d30560be80247ebaba1342c9ac62c4a8bfdd463e977","src/dir.rs":"d0926c0804d7d4b9292acd9385674810ab26c78fc15d613f0342ebe267068bdf","src/env.rs":"9d1e7d52c6c5f46d790a8cbc6d5d2ff9097fb7728594c518d51824ebfb70c9b3","src/errno.rs":"204dd49244d461da6827142386a6b491aaeb6c4ca3760bbe9df5fd2f90e9f4ea","src/fcntl.rs":"c697a448eaa83df6d2219f39781b8d41014f1ee418cccb15b41279a780745c5a","src/features.rs":"6edc53dbbadf56a193dc71053f6512b6cf0d09feb5efb8eb991877de1d70c43c","src/ifaddrs.rs":"40ed9c631b5bff403a697889971f44ad87d6fd6bebbd99cb047cf47c190ee87e","src/kmod.rs":"1e77141714fc7da27fcc59caaae0e31b5801f6e164a57f8d6d399a1b4051d5b1","src/lib.rs":"c9bc3d8a2c1b067b15988ee7c0c40a5e62762da910d4f0174f06ed1bc262fe06","src/macros.rs":"ea6b3a5c117f82ab97d0a410501e7ec250ee11baf3c44b1f207ec404ea682d85","src/mount/apple.rs":"bb98335449b95e5135708d33da649472498d305d225564c81cb7f1279ba3b5b9","src/mount/bsd_without_apple.rs":"e79e9b88ceea9476d2b68fcc619e06ebcc9163f954f5d9d5455f3433d3bec97b","src/mount/linux.rs":"83b4716728c54ed1d6db3fd6e2c4499f8bbe77af7e513d29c4e75525ce0d759d","src/mount/mod.rs":"1bfbdf0b8781ac6f8d320a43aedbbdfd72ac7e5d8f2a87e03f4f87cb5857ece3","src/mqueue.rs":"0c094b340c918796aff8aa43bc78da566c6203c779a41ce5f490fd41110628f1","src/net/if_.rs":"ae1c6a38865162ff9b94625055baa50c75906660f9adde840eed3ddea4db639e","src/net/mod.rs":"577f70170e53d4a6de1abb70bf8f1031ec3e65c0e63ef5fcf05c907125e7ac17","src/poll.rs":"6d27611db0bc1a64bee80cc74155bb593b1e488092d753fdee102404e7e408ec","src/poll_timeout.rs":"c32412689fcafa561514df9d974206c11bb1276ef79fc10964f11b5416f51a00","src/pty.rs":"03a50d339350b1942b1038cd6de938b560062ec9fdd9d8d3b1149f91624884f3","src/sched.rs":"542bd9b1d8e1ed132c9a16c3485c70d3d47e30f702c4da1b39906fc64da4c308","src/sys/aio.rs":"e39e5597298a5e9cd282ad27f9ffc7110b97b1b362fe21d5a1dd3b1bff45e1e9","src/sys/epoll.rs":"49ce070f560c8ac7a6f338b4b182f70049303c7d895320a7186fb98b666cafa9","src/sys/event.rs":"3e6e737a880f802644b7c5656a6579d747a66b595ba26ab6cb59df1141ac6eda","src/sys/eventfd.rs":"244ec41689cf90ba0527dd3501ea9f2623873b35cb66577dfc652c35e8492fe4","src/sys/fanotify.rs":"075e0ee9807d28ccfaedd0542fb8ba30a653c81326c41dadf801da359c19d9ca","src/sys/inotify.rs":"5ce6d83beb2f328c33acf0dd3639a1bdd7b5c2e362745b3cb0fa4c549a641e90","src/sys/ioctl/bsd.rs":"e6affc2babd4fa4539574426e416b330b7e32ba4fd2821899a67417261e7089e","src/sys/ioctl/linux.rs":"8c8bdfc239aa175efb4fc2f666a6ecc799b7d614f85e9143595fff05d37f76f0","src/sys/ioctl/mod.rs":"304a959e9eb24dccfd3fc6153719b417367d9208dc7e6859239fb020c407d103","src/sys/memfd.rs":"a7c2c446143f1dda5537a4342a84b83bb536072215ca973de71f87a33ed8bd37","src/sys/mman.rs":"e75b3ae89c18f541ba8fed01b9147661078f9d035eeb4eaf792ba0e4ff1167fe","src/sys/mod.rs":"30057a1c687859394f27581247ae9e412f5f68d4484bd5196797c1bc1939a6c7","src/sys/personality.rs":"f7fa4e97de0943aa6a969465ca7d2d69ac98015f7c339fdbb88d83ffe26db4ce","src/sys/prctl.rs":"c134d3a5c6fc08c028682d39b1765672681caf91a113b0668db1f499e31f9df0","src/sys/pthread.rs":"258cdf7ff0b61a4afa6d228109e4cb4fb88d859bb8dfe6c959d95130fb010906","src/sys/ptrace/bsd.rs":"54b92e1ffe6455a545f807ed7de9011be05251adfdc71a5823b1965579650939","src/sys/ptrace/linux.rs":"f59edb76635fb13925ea33a31eca407926f78b0e644513760b6f875d8d690aef","src/sys/ptrace/mod.rs":"a9aefa2b10cc63c8b40adcd3e7dd612a8f4677bf6f37420cdd09e7129ba02c95","src/sys/quota.rs":"1638e34bddd955c7f98f1814d239eb76647101295c8a1ae40c78dd7dd7638f20","src/sys/reboot.rs":"b748217e4877c94c1870885407b9ab1ab9e059c9fb7d04818a1b29477eac81c6","src/sys/resource.rs":"5353e1991de1347b2ff32d8101af1d3beb9e9d62a6a9dda2e9ead098dfa500b1","src/sys/select.rs":"9cfcb3a9d15a46b2f209e66cbaf136dab6894c711031313557bc58534ecedc70","src/sys/sendfile.rs":"fc7ac628424eb1132674c73bbe19f0d82a28d6752b0beffbf111965ea3885760","src/sys/signal.rs":"fdf50b9d4e271754948d1f76ee0c42c66639e3c6b6d9481b9c1eea3721e29eb2","src/sys/signalfd.rs":"53f03d6298761181b6b6cd2fb402f7bd6acce1e770145d590303ca3e7bf7ffaf","src/sys/socket/addr.rs":"e621f332cb99f8804d458166d522f1691aba6e0a70b06206e64cf9032256648d","src/sys/socket/mod.rs":"d6c83b61abfca1981dfd831a8c0fe7c1b894e0ee63dd6b40acb9f7cc48bc4b70","src/sys/socket/sockopt.rs":"83865578a2b8e18b092216a90e0205f2c58b503f99149aa16cc5e33a412045a1","src/sys/stat.rs":"074401a0b0fe74d9516640e0790fe67b7727213115accfdb331a9767ae20064c","src/sys/statfs.rs":"991370ce27196f8721a03a88c3b906cc248f46f147ebd6524d45c61433dc0239","src/sys/statvfs.rs":"526c2e69b640f49331e8ca7a2e59cdb803887c91a53fa41f866364fec93bce24","src/sys/sysinfo.rs":"93ccfc746128dfcf8fbc2775ceefac6ddcefe154b6e5f7db96de8f29ad869b85","src/sys/termios.rs":"dd68b78e4a87786d22334c014d258e43d12f4e9370acda61209eb2c9ed176c86","src/sys/time.rs":"a63f6b5cf67a9323ccc3a225ffec88bb078c5dcf22d0eba78ae071db67aefc53","src/sys/timer.rs":"8c10f0e7cfac857ad00460be30bc68b957909cc9296e70718d3b5d4a0babafde","src/sys/timerfd.rs":"569d662725018427b517ffcfa78d8d03e150a344b8b8533d3f16e3bfd5c762da","src/sys/uio.rs":"d0886bf517e9b21af8ad6a25d332003fe9e132fed43cd642ec61b32d27622bd6","src/sys/utsname.rs":"e1f81d363621445633101800ba34debdb222eaf3a25553f8b486f74d49e4be41","src/sys/wait.rs":"338235d42a2ec29633cf64dada7b9b1d434ed0005776bffdecfd5c69922eed89","src/time.rs":"30038bbe683857469d106631cea13ee1e43f149cb4c947a8353824270ee4267c","src/ucontext.rs":"b8f2e04757a9c2bc38c3b1e259d3a013da8a730fe9bfbe5487637395681b43d3","src/unistd.rs":"c4cb141128856a133f7ed4cc5babdab9734ce534b118d7c9ffe2ff79aea9d719","test/common/mod.rs":"cb322163f65319b350882fccea8d540216c4ac43f0912f1e35efa7ea0305d23d","test/mount/mod.rs":"4aac842da29f063b6f653fc5ccb02e742283fc683d6281cbcc582f55004b9c0f","test/mount/test_mount.rs":"90820c9378690190bd576e22361d0cb9b932cd7002a099c5034772feefc4f8e6","test/mount/test_mount_apple.rs":"77055902167e85368291284c00ae67b83ec932eca425a17d69ceb867ea5a142d","test/mount/test_nmount.rs":"d6c112547bb80968170b5497cda4b6cbf69dabec6f51d494bd52298995ceff18","test/sys/mod.rs":"f08046850a4b7a9bbf203d8eba0ee3ae9c32b6bd4d9c7bf52ca29efb3eb74f35","test/sys/test_aio.rs":"a0c1315c2924a4eb4d419e08cdb00702061941170c4e3b4e53b383bf3475642d","test/sys/test_aio_drop.rs":"18974ef2ea0072d91e93489d9430725eda32582992f9c6a1f046b4d6be901a8c","test/sys/test_epoll.rs":"c30b08d665a1fe7d7a04fe51d50ec78fc74c2ac707ae0f95f82104d5c76ceaf2","test/sys/test_event.rs":"be4b1b1abd25f87f00b3d115105ef832b2c654fd7028c42f1a304a935935b479","test/sys/test_fanotify.rs":"3719547a2d11f8f7811be7f1a60d4239f0223f70143bbe0f54afbd180e89ae7e","test/sys/test_inotify.rs":"a141b9a995892547b51ceeb6761a70a6b86d37e8f38d13ea2c497b81b4b0f49f","test/sys/test_ioctl.rs":"07d08a46c4ac84161974b655a0d040e03efc9338e7a7505e0d16826b7653b5c2","test/sys/test_mman.rs":"f129659d6995fcada15e7c923cb943d8dd4c6e4aaa141c6cc5bacfa3257793f5","test/sys/test_prctl.rs":"0576ba8aeb6b80a91e6cfcf2d63c54fed32f4d64bf02a1ac584b754f0ba34b4e","test/sys/test_pthread.rs":"ace36a2f5587f1874854281b4fd84e4e4d892a1e3c5cc38ced57975739522ad6","test/sys/test_ptrace.rs":"f3c6fb377de01f0e3ad2c580815de76e84e3224378d5f001169f5e343b3fdbc7","test/sys/test_resource.rs":"aa58f566efb8132b42ae98be6e50b72fee86ef50c4bcc4a7bf49b275f6762008","test/sys/test_select.rs":"09fe9d020e4f1cdb0951ebd27a6c3f408b23471ce2c51d2f1e4708500fc15261","test/sys/test_signal.rs":"a1e4943e459e4bc79ac1e8929bbd4dab3c012935ed8084631fef4e973902a1c0","test/sys/test_signalfd.rs":"348aa82e161d99ffac0b70247441cc5b806ed7e0f23f32ecdfaa87ab2eb6c25c","test/sys/test_socket.rs":"ba1fa797fc8fa617a5283e93bcf1a7f6850c10d5d95353af3ba9e5cc095adc1b","test/sys/test_sockopt.rs":"a5664332c2c310f8c5f48a9fa6012f21c4ab573226307686d8f91b4a432ff831","test/sys/test_stat.rs":"6630a28217fd708bb84cd4f7e7101836b74f2420f9888923fdab664ccc331c1d","test/sys/test_statfs.rs":"90da08a3828b091482ee9be17c7f1aba32ffa598158b25ce3001d468fbc328c5","test/sys/test_statvfs.rs":"05cf8f1bcab0f0cd8fbefe8a2a72f9ac6d95aa760c355ac6d4b6f9c61649bc38","test/sys/test_sysinfo.rs":"ffd49bc96375914a2c4a4a59730cae8072f85771e2c4a80d3403df38d967e272","test/sys/test_termios.rs":"6c6897e0320d063a758f6702228c64ef2b459b4a5affa07ae7e76c1142432f0a","test/sys/test_time.rs":"aff97dd1bfc4aa9b616cc71e9cc11f25fb3ad983f1406c856648736847778c19","test/sys/test_timer.rs":"3ae20d364f075d2811f3ff94eda9886682cc21d8807656007d2464fe36d1e361","test/sys/test_timerfd.rs":"cfed3abf58118611d08f6985251a7739cff67108e11214222a1d2394a3a026ce","test/sys/test_uio.rs":"dda569818e3256ff45aa07b33cffb59828983c83b20266b864cdfa38103cffc9","test/sys/test_utsname.rs":"b8371dca02c9cdfc0c8e93df9b5cf5b5cb8a92b114977966854918abeb01ad73","test/sys/test_wait.rs":"c958e51b10a7d0396d0013e9d637a2848ad9d061d526408b40dfefb850c22beb","test/test.rs":"a4b08951e07e5011bd1809dc01a3ec6edd01cf3ad37ddba4ff06207af3e34c77","test/test_clearenv.rs":"45ca548035b3c20ec87314715feaba2be973709a635d85b8cde46fd1d9f1ecd4","test/test_dir.rs":"e6a100685f945b6007312d22575ac5e27363c649f3fed19fb10b18ac5d905449","test/test_errno.rs":"e7a1320e97350c2883368ffe9fc47fd041f4f9ecdee360d21d36254a63a305a3","test/test_fcntl.rs":"15d5a64f6cffe4fb45796bd6e55126cc77780f66501875614687ec15749face4","test/test_kmod/hello_mod/Makefile":"0219f7bce0603f97d997fb377ca071966c90333ecc665e78a54dfeb97a9c811b","test/test_kmod/hello_mod/hello.c":"bcac6b19c5bd807e1f3878c15e426acc85785a8ade9840c3bb4d068635c9188c","test/test_kmod/mod.rs":"b4ae25841c2f06f32de9f1acd8230eeccd7095721302ebe78ad454e4e4f9c783","test/test_mq.rs":"d8ec2a3f3acad4369851663b3f7fef03177d9f8395b585dee8e2c53f6a2a9b4a","test/test_net.rs":"ababee4623a5afb8548a1618efbdb43efa38e88d606bff8301245db6fa306078","test/test_nix_path.rs":"01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b","test/test_poll.rs":"25b4fa094bbcda5a5317a25d2f292465965dbe3e066374b04a9b27a8d55897ac","test/test_pty.rs":"0fcf37cb5c60167552800447890726d6cb182b5cc2ac3332986155b9641da492","test/test_sched.rs":"c4579bd376fab8816e63b07fa9ace31dc08e63ebb7c855a2c450698090d1d1e8","test/test_sendfile.rs":"6f82e9f66359a85a7aa819ffd38c7c3326c1bb2384950d681085dc7823fc4a20","test/test_stat.rs":"dae37bd9b5e46e1a76696bed435d8bc4e98ecb91bb3476e7133a6197178d6644","test/test_time.rs":"6eb3536936c67bcfbc80a73a902b4a485943aab5375fc7e3880da6695a4eafce","test/test_unistd.rs":"96151e2101fba7cff2fcd125858be50567118e28935be1db76541b9ef0d24ebd"},"package":"71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"}
\ No newline at end of file
diff --git a/crates/nix/Android.bp b/crates/nix/Android.bp
index 0f7e25f..2a9c274 100644
--- a/crates/nix/Android.bp
+++ b/crates/nix/Android.bp
@@ -18,7 +18,7 @@
     host_supported: true,
     crate_name: "nix",
     cargo_env_compat: true,
-    cargo_pkg_version: "0.28.0",
+    cargo_pkg_version: "0.29.0",
     crate_root: "src/lib.rs",
     edition: "2021",
     features: [
diff --git a/crates/nix/CHANGELOG.md b/crates/nix/CHANGELOG.md
index 37e4ab2..b673cac 100644
--- a/crates/nix/CHANGELOG.md
+++ b/crates/nix/CHANGELOG.md
@@ -3,6 +3,98 @@
 
 # Change Log
 
+## [0.29.0] - 2024-05-24
+
+
+### Added
+
+- Add `getregset()/setregset()` for Linux/glibc/x86/x86_64/aarch64/riscv64 and
+  `getregs()/setregs()` for Linux/glibc/aarch64/riscv64
+  ([#2044](https://github.com/nix-rust/nix/pull/2044))
+- Add socket option Ipv6Ttl for apple targets.
+  ([#2287](https://github.com/nix-rust/nix/pull/2287))
+- Add socket option UtunIfname.
+  ([#2325](https://github.com/nix-rust/nix/pull/2325))
+- make SigAction repr(transparent) & can be converted to the libc raw type
+  ([#2326](https://github.com/nix-rust/nix/pull/2326))
+- Add `From` trait implementation for conversions between `sockaddr_in` and
+  `SockaddrIn`, `sockaddr_in6` and `SockaddrIn6`
+  ([#2328](https://github.com/nix-rust/nix/pull/2328))
+- Add socket option ReusePortLb for FreeBSD.
+  ([#2332](https://github.com/nix-rust/nix/pull/2332))
+- Added support for openat2 on linux.
+  ([#2339](https://github.com/nix-rust/nix/pull/2339))
+- Add if_indextoname function.
+  ([#2340](https://github.com/nix-rust/nix/pull/2340))
+- Add `mount` and `unmount` API for apple targets.
+  ([#2347](https://github.com/nix-rust/nix/pull/2347))
+- Added `_PC_MIN_HOLE_SIZE` for `pathconf` and `fpathconf`.
+  ([#2349](https://github.com/nix-rust/nix/pull/2349))
+- Added `impl AsFd for pty::PtyMaster`
+  ([#2355](https://github.com/nix-rust/nix/pull/2355))
+- Add `open` flag `O_SEARCH` to AIX, Empscripten, FreeBSD, Fuchsia, solarish,
+  WASI ([#2374](https://github.com/nix-rust/nix/pull/2374))
+- Add prctl function `prctl_set_vma_anon_name` for Linux/Android.
+  ([#2378](https://github.com/nix-rust/nix/pull/2378))
+- Add `sync(2)` for `apple_targets/solarish/haiku/aix/hurd`, `syncfs(2)` for
+  `hurd` and `fdatasync(2)` for `aix/hurd`
+  ([#2379](https://github.com/nix-rust/nix/pull/2379))
+- Add fdatasync support for Apple targets.
+  ([#2380](https://github.com/nix-rust/nix/pull/2380))
+- Add `fcntl::OFlag::O_PATH` for FreeBSD and Fuchsia
+  ([#2382](https://github.com/nix-rust/nix/pull/2382))
+- Added `PathconfVar::MIN_HOLE_SIZE` for apple_targets.
+  ([#2388](https://github.com/nix-rust/nix/pull/2388))
+- Add `open` flag `O_SEARCH` to apple_targets
+  ([#2391](https://github.com/nix-rust/nix/pull/2391))
+- `O_DSYNC` may now be used with `aio_fsync` and `fcntl` on FreeBSD.
+  ([#2404](https://github.com/nix-rust/nix/pull/2404))
+- Added `Flock::relock` for upgrading and downgrading locks.
+  ([#2407](https://github.com/nix-rust/nix/pull/2407))
+
+### Changed
+
+- Change the `ForkptyResult` type to the following repr so that the
+  uninitialized
+  `master` field won't be accessed in the child process:
+
+  ```rs
+  pub enum ForkptyResult {
+      Parent {
+          child: Pid,
+          master: OwnedFd,
+      },
+      Child,
+  }
+  ``` ([#2315](https://github.com/nix-rust/nix/pull/2315))
+- Updated `cfg_aliases` dependency from version 0.1 to 0.2
+  ([#2322](https://github.com/nix-rust/nix/pull/2322))
+- Change the signature of `ptrace::write` and `ptrace::write_user` to make them
+  safe ([#2324](https://github.com/nix-rust/nix/pull/2324))
+- Allow use of `SignalFd` through shared reference
+
+  Like with many other file descriptors, concurrent use of signalfds is safe.
+  Changing the signal mask of and reading signals from a signalfd can now be
+  done
+  with the `SignalFd` API even if other references to it exist.
+  ([#2367](https://github.com/nix-rust/nix/pull/2367))
+- Changed tee, splice and vmsplice RawFd arguments to AsFd.
+  ([#2387](https://github.com/nix-rust/nix/pull/2387))
+- Added I/O safety to the sys/aio module.  Most functions that previously
+  accepted a `AsRawFd` argument now accept an `AsFd` instead.
+  ([#2401](https://github.com/nix-rust/nix/pull/2401))
+- `RecvMsg::cmsgs()` now returns a `Result`, and checks that cmsgs were not
+  truncated. ([#2413](https://github.com/nix-rust/nix/pull/2413))
+
+### Fixed
+
+- No longer panics when the `fanotify` queue overflows.
+  ([#2399](https://github.com/nix-rust/nix/pull/2399))
+- Fixed ControlMessageOwned::UdpGroSegments wrapped type from u16 to i32 to
+  reflect the used kernel's one.
+  ([#2406](https://github.com/nix-rust/nix/pull/2406))
+
+
 ## [0.28.0] - 2024-02-24
 
 
diff --git a/crates/nix/Cargo.toml b/crates/nix/Cargo.toml
index 34bc897..8b3405d 100644
--- a/crates/nix/Cargo.toml
+++ b/crates/nix/Cargo.toml
@@ -13,7 +13,7 @@
 edition = "2021"
 rust-version = "1.69"
 name = "nix"
-version = "0.28.0"
+version = "0.29.0"
 authors = ["The nix-rust Project Developers"]
 include = [
     "build.rs",
@@ -72,7 +72,7 @@
 version = "1.0"
 
 [dependencies.libc]
-version = "0.2.153"
+version = "0.2.155"
 features = ["extra_traits"]
 
 [dependencies.memoffset]
@@ -99,7 +99,7 @@
 version = "3.7.1"
 
 [build-dependencies.cfg_aliases]
-version = "0.1.1"
+version = "0.2"
 
 [features]
 acct = []
diff --git a/crates/nix/METADATA b/crates/nix/METADATA
index e30d992..b453f1f 100644
--- a/crates/nix/METADATA
+++ b/crates/nix/METADATA
@@ -1,17 +1,17 @@
 name: "nix"
 description: "Rust friendly bindings to *nix APIs"
 third_party {
-  version: "0.28.0"
+  version: "0.29.0"
   license_type: NOTICE
   last_upgrade_date {
-    year: 2024
-    month: 4
-    day: 8
+    year: 2025
+    month: 3
+    day: 5
   }
   homepage: "https://crates.io/crates/nix"
   identifier {
     type: "Archive"
-    value: "https://static.crates.io/crates/nix/nix-0.28.0.crate"
-    version: "0.28.0"
+    value: "https://static.crates.io/crates/nix/nix-0.29.0.crate"
+    version: "0.29.0"
   }
 }
diff --git a/crates/nix/build.rs b/crates/nix/build.rs
index 4535af1..226a32c 100644
--- a/crates/nix/build.rs
+++ b/crates/nix/build.rs
@@ -14,12 +14,27 @@
         solaris: { target_os = "solaris" },
         watchos: { target_os = "watchos" },
         tvos: { target_os = "tvos" },
+        visionos: { target_os = "visionos" },
 
-        apple_targets: { any(ios, macos, watchos, tvos) },
+
+        // cfg aliases we would like to use
+        apple_targets: { any(ios, macos, watchos, tvos, visionos) },
         bsd: { any(freebsd, dragonfly, netbsd, openbsd, apple_targets) },
+        bsd_without_apple: { any(freebsd, dragonfly, netbsd, openbsd) },
         linux_android: { any(android, linux) },
         freebsdlike: { any(dragonfly, freebsd) },
         netbsdlike: { any(netbsd, openbsd) },
         solarish: { any(illumos, solaris) },
     }
+
+    // Below are Nix's custom cfg values that we need to let the compiler know
+    println!("cargo:rustc-check-cfg=cfg(apple_targets)");
+    println!("cargo:rustc-check-cfg=cfg(bsd)");
+    println!("cargo:rustc-check-cfg=cfg(bsd_without_apple)");
+    println!("cargo:rustc-check-cfg=cfg(linux_android)");
+    println!("cargo:rustc-check-cfg=cfg(freebsdlike)");
+    println!("cargo:rustc-check-cfg=cfg(netbsdlike)");
+    println!("cargo:rustc-check-cfg=cfg(solarish)");
+    println!("cargo:rustc-check-cfg=cfg(fbsd14)");
+    println!("cargo:rustc-check-cfg=cfg(qemu)");
 }
diff --git a/crates/nix/src/dir.rs b/crates/nix/src/dir.rs
index ab70f06..20c5593 100644
--- a/crates/nix/src/dir.rs
+++ b/crates/nix/src/dir.rs
@@ -59,7 +59,7 @@
         Dir::from_fd(fd.into_raw_fd())
     }
 
-    /// Converts from a file descriptor, closing it on success or failure.
+    /// Converts from a file descriptor, closing it on failure.
     #[doc(alias("fdopendir"))]
     pub fn from_fd(fd: RawFd) -> Result<Self> {
         let d = ptr::NonNull::new(unsafe { libc::fdopendir(fd) }).ok_or_else(
diff --git a/crates/nix/src/fcntl.rs b/crates/nix/src/fcntl.rs
index ccefe95..cf87926 100644
--- a/crates/nix/src/fcntl.rs
+++ b/crates/nix/src/fcntl.rs
@@ -114,7 +114,7 @@
         /// If the specified path isn't a directory, fail.
         O_DIRECTORY;
         /// Implicitly follow each `write()` with an `fdatasync()`.
-        #[cfg(any(linux_android, apple_targets, netbsdlike))]
+        #[cfg(any(linux_android, apple_targets, target_os = "freebsd", netbsdlike))]
         O_DSYNC;
         /// Error out if a file was not created.
         O_EXCL;
@@ -151,7 +151,7 @@
         /// Obtain a file descriptor for low-level access.
         ///
         /// The file itself is not opened and other file operations will fail.
-        #[cfg(any(linux_android, target_os = "redox"))]
+        #[cfg(any(linux_android, target_os = "redox", target_os = "freebsd", target_os = "fuchsia"))]
         O_PATH;
         /// Only allow reading.
         ///
@@ -164,8 +164,18 @@
         /// Similar to `O_DSYNC` but applies to `read`s instead.
         #[cfg(any(target_os = "linux", netbsdlike))]
         O_RSYNC;
-        /// Skip search permission checks.
-        #[cfg(target_os = "netbsd")]
+        /// Open directory for search only. Skip search permission checks on
+        /// later `openat()` calls using the obtained file descriptor.
+        #[cfg(any(
+            apple_targets,
+            solarish,
+            target_os = "netbsd",
+            target_os = "freebsd",
+            target_os = "fuchsia",
+            target_os = "emscripten",
+            target_os = "aix",
+            target_os = "wasi"
+        ))]
         O_SEARCH;
         /// Open with a shared file lock.
         #[cfg(any(bsd, target_os = "redox"))]
@@ -242,6 +252,119 @@
     Errno::result(fd)
 }
 
+cfg_if::cfg_if! {
+    if #[cfg(target_os = "linux")] {
+        libc_bitflags! {
+            /// Path resolution flags.
+            ///
+            /// See [path resolution(7)](https://man7.org/linux/man-pages/man7/path_resolution.7.html)
+            /// for details of the resolution process.
+            pub struct ResolveFlag: libc::c_ulonglong {
+                /// Do not permit the path resolution to succeed if any component of
+                /// the resolution is not a descendant of the directory indicated by
+                /// dirfd.  This causes absolute symbolic links (and absolute values of
+                /// pathname) to be rejected.
+                RESOLVE_BENEATH;
+
+                /// Treat the directory referred to by dirfd as the root directory
+                /// while resolving pathname.
+                RESOLVE_IN_ROOT;
+
+                /// Disallow all magic-link resolution during path resolution. Magic
+                /// links are symbolic link-like objects that are most notably found
+                /// in proc(5);  examples include `/proc/[pid]/exe` and `/proc/[pid]/fd/*`.
+                ///
+                /// See symlink(7) for more details.
+                RESOLVE_NO_MAGICLINKS;
+
+                /// Disallow resolution of symbolic links during path resolution. This
+                /// option implies RESOLVE_NO_MAGICLINKS.
+                RESOLVE_NO_SYMLINKS;
+
+                /// Disallow traversal of mount points during path resolution (including
+                /// all bind mounts).
+                RESOLVE_NO_XDEV;
+            }
+        }
+
+        /// Specifies how [openat2] should open a pathname.
+        ///
+        /// See <https://man7.org/linux/man-pages/man2/open_how.2type.html>
+        #[repr(transparent)]
+        #[derive(Clone, Copy, Debug)]
+        pub struct OpenHow(libc::open_how);
+
+        impl OpenHow {
+            /// Create a new zero-filled `open_how`.
+            pub fn new() -> Self {
+                // safety: according to the man page, open_how MUST be zero-initialized
+                // on init so that unknown fields are also zeroed.
+                Self(unsafe {
+                    std::mem::MaybeUninit::zeroed().assume_init()
+                })
+            }
+
+            /// Set the open flags used to open a file, completely overwriting any
+            /// existing flags.
+            pub fn flags(mut self, flags: OFlag) -> Self {
+                let flags = flags.bits() as libc::c_ulonglong;
+                self.0.flags = flags;
+                self
+            }
+
+            /// Set the file mode new files will be created with, overwriting any
+            /// existing flags.
+            pub fn mode(mut self, mode: Mode) -> Self {
+                let mode = mode.bits() as libc::c_ulonglong;
+                self.0.mode = mode;
+                self
+            }
+
+            /// Set resolve flags, completely overwriting any existing flags.
+            ///
+            /// See [ResolveFlag] for more detail.
+            pub fn resolve(mut self, resolve: ResolveFlag) -> Self {
+                let resolve = resolve.bits();
+                self.0.resolve = resolve;
+                self
+            }
+        }
+
+        // safety: default isn't derivable because libc::open_how must be zeroed
+        impl Default for OpenHow {
+            fn default() -> Self {
+                Self::new()
+            }
+        }
+
+        /// Open or create a file for reading, writing or executing.
+        ///
+        /// `openat2` is an extension of the [`openat`] function that allows the caller
+        /// to control how path resolution happens.
+        ///
+        /// # See also
+        ///
+        /// [openat2](https://man7.org/linux/man-pages/man2/openat2.2.html)
+        pub fn openat2<P: ?Sized + NixPath>(
+            dirfd: RawFd,
+            path: &P,
+            mut how: OpenHow,
+        ) -> Result<RawFd> {
+            let fd = path.with_nix_path(|cstr| unsafe {
+                libc::syscall(
+                    libc::SYS_openat2,
+                    dirfd,
+                    cstr.as_ptr(),
+                    &mut how as *mut OpenHow,
+                    std::mem::size_of::<libc::open_how>(),
+                )
+            })?;
+
+            Errno::result(fd as RawFd)
+        }
+    }
+}
+
 /// Change the name of a file.
 ///
 /// The `renameat` function is equivalent to `rename` except in the case where either `old_path`
@@ -832,6 +955,30 @@
         std::mem::forget(self);
         Ok(inner)
     }
+
+    /// Relock the file.  This can upgrade or downgrade the lock type.
+    ///
+    /// # Example
+    /// ```
+    /// # use std::fs::File;
+    /// # use nix::fcntl::{Flock, FlockArg};
+    /// # use tempfile::tempfile;
+    /// let f: std::fs::File = tempfile().unwrap();
+    /// let locked_file = Flock::lock(f, FlockArg::LockExclusive).unwrap();
+    /// // Do stuff, then downgrade the lock
+    /// locked_file.relock(FlockArg::LockShared).unwrap();
+    /// ```
+    pub fn relock(&self, arg: FlockArg) -> Result<()> {
+         let flags = match arg {
+            FlockArg::LockShared => libc::LOCK_SH,
+            FlockArg::LockExclusive => libc::LOCK_EX,
+            FlockArg::LockSharedNonblock => libc::LOCK_SH | libc::LOCK_NB,
+            FlockArg::LockExclusiveNonblock => libc::LOCK_EX | libc::LOCK_NB,
+            #[allow(deprecated)]
+            FlockArg::Unlock | FlockArg::UnlockNonblock => return Err(Errno::EINVAL),
+        };
+        Errno::result(unsafe { libc::flock(self.as_raw_fd(), flags) }).map(drop)
+    }
 }
 
 // Safety: `File` is not [std::clone::Clone].
@@ -940,10 +1087,10 @@
 /// # See Also
 /// *[`splice`](https://man7.org/linux/man-pages/man2/splice.2.html)
 #[cfg(linux_android)]
-pub fn splice(
-    fd_in: RawFd,
+pub fn splice<Fd1: AsFd, Fd2: AsFd>(
+    fd_in: Fd1,
     off_in: Option<&mut libc::loff_t>,
-    fd_out: RawFd,
+    fd_out: Fd2,
     off_out: Option<&mut libc::loff_t>,
     len: usize,
     flags: SpliceFFlags,
@@ -956,7 +1103,7 @@
         .unwrap_or(ptr::null_mut());
 
     let ret = unsafe {
-        libc::splice(fd_in, off_in, fd_out, off_out, len, flags.bits())
+        libc::splice(fd_in.as_fd().as_raw_fd(), off_in, fd_out.as_fd().as_raw_fd(), off_out, len, flags.bits())
     };
     Errno::result(ret).map(|r| r as usize)
 }
@@ -966,13 +1113,13 @@
 /// # See Also
 /// *[`tee`](https://man7.org/linux/man-pages/man2/tee.2.html)
 #[cfg(linux_android)]
-pub fn tee(
-    fd_in: RawFd,
-    fd_out: RawFd,
+pub fn tee<Fd1: AsFd, Fd2: AsFd>(
+    fd_in: Fd1,
+    fd_out: Fd2,
     len: usize,
     flags: SpliceFFlags,
 ) -> Result<usize> {
-    let ret = unsafe { libc::tee(fd_in, fd_out, len, flags.bits()) };
+    let ret = unsafe { libc::tee(fd_in.as_fd().as_raw_fd(), fd_out.as_fd().as_raw_fd(), len, flags.bits()) };
     Errno::result(ret).map(|r| r as usize)
 }
 
@@ -981,14 +1128,14 @@
 /// # See Also
 /// *[`vmsplice`](https://man7.org/linux/man-pages/man2/vmsplice.2.html)
 #[cfg(linux_android)]
-pub fn vmsplice(
-    fd: RawFd,
+pub fn vmsplice<F: AsFd>(
+    fd: F,
     iov: &[std::io::IoSlice<'_>],
     flags: SpliceFFlags,
 ) -> Result<usize> {
     let ret = unsafe {
         libc::vmsplice(
-            fd,
+            fd.as_fd().as_raw_fd(),
             iov.as_ptr().cast(),
             iov.len(),
             flags.bits(),
diff --git a/crates/nix/src/lib.rs b/crates/nix/src/lib.rs
index dffac29..c4c0fa5 100644
--- a/crates/nix/src/lib.rs
+++ b/crates/nix/src/lib.rs
@@ -362,3 +362,21 @@
         self.as_os_str().with_nix_path(f)
     }
 }
+
+/// Like `NixPath::with_nix_path()`, but allow the `path` argument to be optional.
+///
+/// A NULL pointer will be provided if `path.is_none()`.
+#[cfg(any(
+    all(apple_targets, feature = "mount"),
+    all(linux_android, any(feature = "mount", feature = "fanotify"))
+))]
+pub(crate) fn with_opt_nix_path<P, T, F>(path: Option<&P>, f: F) -> Result<T>
+where
+    P: ?Sized + NixPath,
+    F: FnOnce(*const libc::c_char) -> T,
+{
+    match path {
+        Some(path) => path.with_nix_path(|p_str| f(p_str.as_ptr())),
+        None => Ok(f(ptr::null())),
+    }
+}
diff --git a/crates/nix/src/mount/apple.rs b/crates/nix/src/mount/apple.rs
new file mode 100644
index 0000000..ce0ab1e
--- /dev/null
+++ b/crates/nix/src/mount/apple.rs
@@ -0,0 +1,111 @@
+use crate::{Errno, NixPath, Result};
+use libc::c_int;
+
+libc_bitflags!(
+    /// Used with [`mount()`] and [`unmount()`].
+    pub struct MntFlags: c_int {
+        /// Do not interpret special files on the filesystem.
+        MNT_NODEV;
+        /// Enable data protection on the filesystem if the filesystem is configured for it.
+        MNT_CPROTECT;
+        /// file system is quarantined
+        MNT_QUARANTINE;
+        /// filesystem is stored locally
+        MNT_LOCAL;
+        /// quotas are enabled on filesystem
+        MNT_QUOTA;
+        /// identifies the root filesystem
+        MNT_ROOTFS;
+        /// file system is not appropriate path to user data
+        MNT_DONTBROWSE;
+        /// VFS will ignore ownership information on filesystem objects
+        MNT_IGNORE_OWNERSHIP;
+        /// filesystem was mounted by automounter
+        MNT_AUTOMOUNTED;
+        /// filesystem is journaled
+        MNT_JOURNALED;
+        /// Don't allow user extended attributes
+        MNT_NOUSERXATTR;
+        /// filesystem should defer writes
+        MNT_DEFWRITE;
+        /// don't block unmount if not responding
+        MNT_NOBLOCK;
+        /// file system is exported
+        MNT_EXPORTED;
+        /// file system written asynchronously
+        MNT_ASYNC;
+        /// Force a read-write mount even if the file system appears to be
+        /// unclean.
+        MNT_FORCE;
+        /// MAC support for objects.
+        MNT_MULTILABEL;
+        /// Do not update access times.
+        MNT_NOATIME;
+        /// Disallow program execution.
+        MNT_NOEXEC;
+        /// Do not honor setuid or setgid bits on files when executing them.
+        MNT_NOSUID;
+        /// Mount read-only.
+        MNT_RDONLY;
+        /// Causes the vfs subsystem to update its data structures pertaining to
+        /// the specified already mounted file system.
+        MNT_RELOAD;
+        /// Create a snapshot of the file system.
+        MNT_SNAPSHOT;
+        /// All I/O to the file system should be done synchronously.
+        MNT_SYNCHRONOUS;
+        /// Union with underlying fs.
+        MNT_UNION;
+        /// Indicates that the mount command is being applied to an already
+        /// mounted file system.
+        MNT_UPDATE;
+    }
+);
+
+/// Mount a file system.
+///
+/// # Arguments
+/// - `source`  -   Specifies the file system.  e.g. `/dev/sd0`.
+/// - `target` -    Specifies the destination.  e.g. `/mnt`.
+/// - `flags` -     Optional flags controlling the mount.
+/// - `data` -      Optional file system specific data.
+///
+/// # see also
+/// [`mount`](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/mount.2.html)
+pub fn mount<
+    P1: ?Sized + NixPath,
+    P2: ?Sized + NixPath,
+    P3: ?Sized + NixPath,
+>(
+    source: &P1,
+    target: &P2,
+    flags: MntFlags,
+    data: Option<&P3>,
+) -> Result<()> {
+    let res = source.with_nix_path(|s| {
+        target.with_nix_path(|t| {
+            crate::with_opt_nix_path(data, |d| unsafe {
+                libc::mount(
+                    s.as_ptr(),
+                    t.as_ptr(),
+                    flags.bits(),
+                    d.cast_mut().cast(),
+                )
+            })
+        })
+    })???;
+
+    Errno::result(res).map(drop)
+}
+
+/// Umount the file system mounted at `target`.
+pub fn unmount<P>(target: &P, flags: MntFlags) -> Result<()>
+where
+    P: ?Sized + NixPath,
+{
+    let res = target.with_nix_path(|cstr| unsafe {
+        libc::unmount(cstr.as_ptr(), flags.bits())
+    })?;
+
+    Errno::result(res).map(drop)
+}
diff --git a/crates/nix/src/mount/bsd.rs b/crates/nix/src/mount/bsd_without_apple.rs
similarity index 98%
rename from crates/nix/src/mount/bsd.rs
rename to crates/nix/src/mount/bsd_without_apple.rs
index 248e0ab..ae9eed7 100644
--- a/crates/nix/src/mount/bsd.rs
+++ b/crates/nix/src/mount/bsd_without_apple.rs
@@ -30,7 +30,7 @@
         #[cfg(target_os = "freebsd")]
         MNT_GJOURNAL;
         /// MAC support for objects.
-        #[cfg(any(apple_targets, target_os = "freebsd"))]
+        #[cfg(target_os = "freebsd")]
         MNT_MULTILABEL;
         /// Disable read clustering.
         #[cfg(freebsdlike)]
@@ -58,7 +58,7 @@
         /// Create a snapshot of the file system.
         ///
         /// See [mksnap_ffs(8)](https://www.freebsd.org/cgi/man.cgi?query=mksnap_ffs)
-        #[cfg(any(apple_targets, target_os = "freebsd"))]
+        #[cfg(target_os = "freebsd")]
         MNT_SNAPSHOT;
         /// Using soft updates.
         #[cfg(any(freebsdlike, netbsdlike))]
@@ -71,7 +71,6 @@
         MNT_SYNCHRONOUS;
         /// Union with underlying fs.
         #[cfg(any(
-                apple_targets,
                 target_os = "freebsd",
                 target_os = "netbsd"
         ))]
diff --git a/crates/nix/src/mount/linux.rs b/crates/nix/src/mount/linux.rs
index aa166bc..3c27150 100644
--- a/crates/nix/src/mount/linux.rs
+++ b/crates/nix/src/mount/linux.rs
@@ -113,21 +113,10 @@
     flags: MsFlags,
     data: Option<&P4>,
 ) -> Result<()> {
-    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| {
+    let res = crate::with_opt_nix_path(source, |s| {
         target.with_nix_path(|t| {
-            with_opt_nix_path(fstype, |ty| {
-                with_opt_nix_path(data, |d| unsafe {
+            crate::with_opt_nix_path(fstype, |ty| {
+                crate::with_opt_nix_path(data, |d| unsafe {
                     libc::mount(
                         s,
                         t.as_ptr(),
diff --git a/crates/nix/src/mount/mod.rs b/crates/nix/src/mount/mod.rs
index 8caf27f..41e7b3e 100644
--- a/crates/nix/src/mount/mod.rs
+++ b/crates/nix/src/mount/mod.rs
@@ -5,8 +5,14 @@
 #[cfg(linux_android)]
 pub use self::linux::*;
 
-#[cfg(bsd)]
-mod bsd;
+#[cfg(bsd_without_apple)]
+mod bsd_without_apple;
 
-#[cfg(bsd)]
-pub use self::bsd::*;
+#[cfg(bsd_without_apple)]
+pub use self::bsd_without_apple::*;
+
+#[cfg(apple_targets)]
+mod apple;
+
+#[cfg(apple_targets)]
+pub use self::apple::*;
diff --git a/crates/nix/src/net/if_.rs b/crates/nix/src/net/if_.rs
index c66b5dc..5b6c2e7 100644
--- a/crates/nix/src/net/if_.rs
+++ b/crates/nix/src/net/if_.rs
@@ -3,9 +3,9 @@
 //! Uses Linux and/or POSIX functions to resolve interface names like "eth0"
 //! or "socan1" into device numbers.
 
-use std::fmt;
-use crate::{Error, NixPath, Result};
-use libc::c_uint;
+use std::{ffi::{CStr, CString}, fmt};
+use crate::{errno::Errno, Error, NixPath, Result};
+use libc::{c_uint, IF_NAMESIZE};
 
 #[cfg(not(solarish))]
 /// type alias for InterfaceFlags
@@ -14,7 +14,7 @@
 /// type alias for InterfaceFlags
 pub type IflagsType = libc::c_longlong;
 
-/// Resolve an interface into a interface number.
+/// Resolve an interface into an 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()) })?;
@@ -26,6 +26,19 @@
     }
 }
 
+/// Resolve an interface number into an interface.
+pub fn if_indextoname(index: c_uint) -> Result<CString> {
+    // We need to allocate this anyway, so doing it directly is faster.
+    let mut buf = vec![0u8; IF_NAMESIZE];
+
+    let return_buf = unsafe {
+        libc::if_indextoname(index, buf.as_mut_ptr().cast())
+    };
+
+    Errno::result(return_buf.cast())?;
+    Ok(CStr::from_bytes_until_nul(buf.as_slice()).unwrap().to_owned())
+}
+
 libc_bitflags!(
     /// Standard interface flags, used by `getifaddrs`
     pub struct InterfaceFlags: IflagsType {
diff --git a/crates/nix/src/pty.rs b/crates/nix/src/pty.rs
index 74f8ecf..171bbfa 100644
--- a/crates/nix/src/pty.rs
+++ b/crates/nix/src/pty.rs
@@ -12,8 +12,6 @@
 use crate::errno::Errno;
 #[cfg(not(target_os = "aix"))]
 use crate::sys::termios::Termios;
-#[cfg(feature = "process")]
-use crate::unistd::ForkResult;
 #[cfg(all(feature = "process", not(target_os = "aix")))]
 use crate::unistd::Pid;
 use crate::{fcntl, unistd, Result};
@@ -31,15 +29,19 @@
 
 feature! {
 #![feature = "process"]
-/// Representation of a master with a forked pty
-///
-/// This is returned by [`forkpty`].
+/// A successful result of [`forkpty()`].
 #[derive(Debug)]
-pub struct ForkptyResult {
-    /// The master port in a virtual pty pair
-    pub master: OwnedFd,
-    /// Metadata about forked process
-    pub fork_result: ForkResult,
+pub enum ForkptyResult {
+    /// This is the parent process of the underlying fork.
+    Parent {
+        /// The PID of the fork's child process
+        child: Pid,
+        /// A file descriptor referring to master side of the pseudoterminal of
+        /// the child process.
+        master: OwnedFd,
+    },
+    /// This is the child process of the underlying fork.
+    Child,
 }
 }
 
@@ -56,6 +58,12 @@
     }
 }
 
+impl AsFd for PtyMaster {
+    fn as_fd(&self) -> BorrowedFd<'_> {
+        self.0.as_fd()
+    }
+}
+
 impl IntoRawFd for PtyMaster {
     fn into_raw_fd(self) -> RawFd {
         let fd = self.0;
@@ -300,9 +308,7 @@
 
 feature! {
 #![feature = "process"]
-/// Create a new pseudoterminal, returning the master file descriptor and forked pid.
-/// in `ForkptyResult`
-/// (see [`forkpty`](https://man7.org/linux/man-pages/man3/forkpty.3.html)).
+/// Create a new process operating in a pseudoterminal.
 ///
 /// 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
@@ -319,6 +325,11 @@
 /// special care must be taken to only invoke code you can control and audit.
 ///
 /// [async-signal-safe]: https://man7.org/linux/man-pages/man7/signal-safety.7.html
+///
+/// # Reference
+///
+/// * [FreeBSD](https://man.freebsd.org/cgi/man.cgi?query=forkpty)
+/// * [Linux](https://man7.org/linux/man-pages/man3/forkpty.3.html)
 #[cfg(not(target_os = "aix"))]
 pub unsafe fn forkpty<'a, 'b, T: Into<Option<&'a Winsize>>, U: Into<Option<&'b Termios>>>(
     winsize: T,
@@ -343,14 +354,23 @@
 
     let res = unsafe { libc::forkpty(master.as_mut_ptr(), ptr::null_mut(), term, win) };
 
-    let fork_result = Errno::result(res).map(|res| match res {
-        0 => ForkResult::Child,
-        res => ForkResult::Parent { child: Pid::from_raw(res) },
-    })?;
+    let success_ret = Errno::result(res)?;
+    let forkpty_result = match success_ret {
+        // In the child process
+        0 => ForkptyResult::Child,
+        // In the parent process
+        child_pid => {
+            // SAFETY:
+            // 1. The master buffer is guaranteed to be initialized in the parent process
+            // 2. OwnedFd::from_raw_fd won't panic as the fd is a valid file descriptor
+            let master = unsafe { OwnedFd::from_raw_fd( master.assume_init() ) };
+            ForkptyResult::Parent {
+                    master,
+                    child: Pid::from_raw(child_pid),
+            }
+        }
+    };
 
-    Ok(ForkptyResult {
-        master: unsafe { OwnedFd::from_raw_fd( master.assume_init() ) },
-        fork_result,
-    })
+    Ok(forkpty_result)
 }
 }
diff --git a/crates/nix/src/sys/aio.rs b/crates/nix/src/sys/aio.rs
index e9213c6..c7ba405 100644
--- a/crates/nix/src/sys/aio.rs
+++ b/crates/nix/src/sys/aio.rs
@@ -30,7 +30,7 @@
     fmt::{self, Debug},
     marker::{PhantomData, PhantomPinned},
     mem,
-    os::unix::io::RawFd,
+    os::unix::io::{AsFd, AsRawFd, BorrowedFd},
     pin::Pin,
     ptr, thread,
 };
@@ -55,6 +55,7 @@
         /// on supported operating systems only, do it like `fdatasync`
         #[cfg(any(apple_targets,
                   target_os = "linux",
+                  target_os = "freebsd",
                   netbsdlike))]
         O_DSYNC
     }
@@ -102,7 +103,7 @@
 // provide polymorphism at the wrong level.  Instead, the best place for
 // polymorphism is at the level of `Futures`.
 #[repr(C)]
-struct AioCb {
+struct AioCb<'a> {
     aiocb: LibcAiocb,
     /// Could this `AioCb` potentially have any in-kernel state?
     // It would be really nice to perform the in-progress check entirely at
@@ -112,9 +113,10 @@
     //   that there's no way to write an AioCb constructor that neither boxes
     //   the object itself, nor moves it during return.
     in_progress: bool,
+    _fd: PhantomData<BorrowedFd<'a>>,
 }
 
-impl AioCb {
+impl<'a> AioCb<'a> {
     pin_utils::unsafe_unpinned!(aiocb: LibcAiocb);
 
     fn aio_return(mut self: Pin<&mut Self>) -> Result<usize> {
@@ -139,18 +141,23 @@
         }
     }
 
-    fn common_init(fd: RawFd, prio: i32, sigev_notify: SigevNotify) -> Self {
+    fn common_init(
+        fd: BorrowedFd<'a>,
+        prio: i32,
+        sigev_notify: SigevNotify,
+    ) -> Self {
         // 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_fildes = fd.as_raw_fd();
         a.aio_reqprio = prio;
         a.aio_sigevent = SigEvent::new(sigev_notify).sigevent();
         AioCb {
             aiocb: LibcAiocb(a),
             in_progress: false,
+            _fd: PhantomData,
         }
     }
 
@@ -186,7 +193,7 @@
     }
 }
 
-impl Debug for AioCb {
+impl<'a> Debug for AioCb<'a> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         fmt.debug_struct("AioCb")
             .field("aiocb", &self.aiocb.0)
@@ -195,7 +202,7 @@
     }
 }
 
-impl Drop for AioCb {
+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) {
@@ -243,11 +250,11 @@
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::{thread, time};
     /// # use std::io::Write;
-    /// # use std::os::unix::io::AsRawFd;
+    /// # use std::os::unix::io::AsFd;
     /// # use tempfile::tempfile;
     /// let wbuf = b"CDEF";
     /// let mut f = tempfile().unwrap();
-    /// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
+    /// let mut aiocb = Box::pin(AioWrite::new(f.as_fd(),
     ///     2,   //offset
     ///     &wbuf[..],
     ///     0,   //priority
@@ -284,11 +291,11 @@
     /// # use nix::sys::aio::*;
     /// # use nix::sys::signal::SigevNotify;
     /// # use std::{thread, time};
-    /// # use std::os::unix::io::AsRawFd;
+    /// # use std::os::unix::io::AsFd;
     /// # use tempfile::tempfile;
     /// const WBUF: &[u8] = b"abcdef123456";
     /// let mut f = tempfile().unwrap();
-    /// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
+    /// let mut aiocb = Box::pin(AioWrite::new(f.as_fd(),
     ///     2,   //offset
     ///     WBUF,
     ///     0,   //priority
@@ -306,7 +313,7 @@
     fn error(self: Pin<&mut Self>) -> Result<()>;
 
     /// Returns the underlying file descriptor associated with the operation.
-    fn fd(&self) -> RawFd;
+    fn fd(&self) -> BorrowedFd;
 
     /// Does this operation currently have any in-kernel state?
     ///
@@ -321,10 +328,10 @@
     /// # use nix::sys::aio::*;
     /// # use nix::sys::signal::SigevNotify::SigevNone;
     /// # use std::{thread, time};
-    /// # use std::os::unix::io::AsRawFd;
+    /// # use std::os::unix::io::AsFd;
     /// # use tempfile::tempfile;
     /// let f = tempfile().unwrap();
-    /// let mut aiof = Box::pin(AioFsync::new(f.as_raw_fd(), AioFsyncMode::O_SYNC,
+    /// let mut aiof = Box::pin(AioFsync::new(f.as_fd(), AioFsyncMode::O_SYNC,
     ///     0, SigevNone));
     /// assert!(!aiof.as_mut().in_progress());
     /// aiof.as_mut().submit().expect("aio_fsync failed early");
@@ -364,8 +371,10 @@
             self.aiocb().error()
         }
 
-        fn fd(&self) -> RawFd {
-            self.aiocb.aiocb.0.aio_fildes
+        fn fd(&self) -> BorrowedFd<'a> {
+            // safe because self's lifetime is the same as the original file
+            // descriptor.
+            unsafe { BorrowedFd::borrow_raw(self.aiocb.aiocb.0.aio_fildes) }
         }
 
         fn in_progress(&self) -> bool {
@@ -413,10 +422,10 @@
 /// # use nix::sys::aio::*;
 /// # use nix::sys::signal::SigevNotify::SigevNone;
 /// # use std::{thread, time};
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// let f = tempfile().unwrap();
-/// let mut aiof = Box::pin(AioFsync::new(f.as_raw_fd(), AioFsyncMode::O_SYNC,
+/// let mut aiof = Box::pin(AioFsync::new(f.as_fd(), AioFsyncMode::O_SYNC,
 ///     0, SigevNone));
 /// aiof.as_mut().submit().expect("aio_fsync failed early");
 /// while (aiof.as_mut().error() == Err(Errno::EINPROGRESS)) {
@@ -426,13 +435,13 @@
 /// ```
 #[derive(Debug)]
 #[repr(transparent)]
-pub struct AioFsync {
-    aiocb: AioCb,
+pub struct AioFsync<'a> {
+    aiocb: AioCb<'a>,
     _pin: PhantomPinned,
 }
 
-impl AioFsync {
-    unsafe_pinned!(aiocb: AioCb);
+impl<'a> AioFsync<'a> {
+    unsafe_pinned!(aiocb: AioCb<'a>);
 
     /// Returns the operation's fsync mode: data and metadata or data only?
     pub fn mode(&self) -> AioFsyncMode {
@@ -451,7 +460,7 @@
     /// * `sigev_notify`: Determines how you will be notified of event
     ///                   completion.
     pub fn new(
-        fd: RawFd,
+        fd: BorrowedFd<'a>,
         mode: AioFsyncMode,
         prio: i32,
         sigev_notify: SigevNotify,
@@ -469,7 +478,7 @@
     }
 }
 
-impl Aio for AioFsync {
+impl<'a> Aio for AioFsync<'a> {
     type Output = ();
 
     aio_methods!();
@@ -490,7 +499,7 @@
 
 // AioFsync does not need AsMut, since it can't be used with lio_listio
 
-impl AsRef<libc::aiocb> for AioFsync {
+impl<'a> AsRef<libc::aiocb> for AioFsync<'a> {
     fn as_ref(&self) -> &libc::aiocb {
         &self.aiocb.aiocb.0
     }
@@ -512,7 +521,7 @@
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
 /// # use std::io::Write;
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// const INITIAL: &[u8] = b"abcdef123456";
 /// const LEN: usize = 4;
@@ -522,7 +531,7 @@
 /// {
 ///     let mut aior = Box::pin(
 ///         AioRead::new(
-///             f.as_raw_fd(),
+///             f.as_fd(),
 ///             2,   //offset
 ///             &mut rbuf,
 ///             0,   //priority
@@ -540,13 +549,13 @@
 #[derive(Debug)]
 #[repr(transparent)]
 pub struct AioRead<'a> {
-    aiocb: AioCb,
+    aiocb: AioCb<'a>,
     _data: PhantomData<&'a [u8]>,
     _pin: PhantomPinned,
 }
 
 impl<'a> AioRead<'a> {
-    unsafe_pinned!(aiocb: AioCb);
+    unsafe_pinned!(aiocb: AioCb<'a>);
 
     /// Returns the requested length of the aio operation in bytes
     ///
@@ -570,7 +579,7 @@
     /// * `sigev_notify`: Determines how you will be notified of event
     ///                   completion.
     pub fn new(
-        fd: RawFd,
+        fd: BorrowedFd<'a>,
         offs: off_t,
         buf: &'a mut [u8],
         prio: i32,
@@ -629,7 +638,7 @@
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
 /// # use std::io::{IoSliceMut, Write};
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// const INITIAL: &[u8] = b"abcdef123456";
 /// let mut rbuf0 = vec![0; 4];
@@ -641,7 +650,7 @@
 /// {
 ///     let mut aior = Box::pin(
 ///         AioReadv::new(
-///             f.as_raw_fd(),
+///             f.as_fd(),
 ///             2,   //offset
 ///             &mut rbufs,
 ///             0,   //priority
@@ -661,14 +670,14 @@
 #[derive(Debug)]
 #[repr(transparent)]
 pub struct AioReadv<'a> {
-    aiocb: AioCb,
+    aiocb: AioCb<'a>,
     _data: PhantomData<&'a [&'a [u8]]>,
     _pin: PhantomPinned,
 }
 
 #[cfg(target_os = "freebsd")]
 impl<'a> AioReadv<'a> {
-    unsafe_pinned!(aiocb: AioCb);
+    unsafe_pinned!(aiocb: AioCb<'a>);
 
     /// Returns the number of buffers the operation will read into.
     pub fn iovlen(&self) -> usize {
@@ -689,7 +698,7 @@
     /// * `sigev_notify`: Determines how you will be notified of event
     ///                   completion.
     pub fn new(
-        fd: RawFd,
+        fd: BorrowedFd<'a>,
         offs: off_t,
         bufs: &mut [IoSliceMut<'a>],
         prio: i32,
@@ -750,13 +759,13 @@
 /// # use nix::sys::aio::*;
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
 /// let mut aiow = Box::pin(
 ///     AioWrite::new(
-///         f.as_raw_fd(),
+///         f.as_fd(),
 ///         2,   //offset
 ///         WBUF,
 ///         0,   //priority
@@ -772,13 +781,13 @@
 #[derive(Debug)]
 #[repr(transparent)]
 pub struct AioWrite<'a> {
-    aiocb: AioCb,
+    aiocb: AioCb<'a>,
     _data: PhantomData<&'a [u8]>,
     _pin: PhantomPinned,
 }
 
 impl<'a> AioWrite<'a> {
-    unsafe_pinned!(aiocb: AioCb);
+    unsafe_pinned!(aiocb: AioCb<'a>);
 
     /// Returns the requested length of the aio operation in bytes
     ///
@@ -802,7 +811,7 @@
     /// * `sigev_notify`: Determines how you will be notified of event
     ///                   completion.
     pub fn new(
-        fd: RawFd,
+        fd: BorrowedFd<'a>,
         offs: off_t,
         buf: &'a [u8],
         prio: i32,
@@ -864,7 +873,7 @@
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
 /// # use std::io::IoSlice;
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// const wbuf0: &[u8] = b"abcdef";
 /// const wbuf1: &[u8] = b"123456";
@@ -873,7 +882,7 @@
 /// let mut f = tempfile().unwrap();
 /// let mut aiow = Box::pin(
 ///     AioWritev::new(
-///         f.as_raw_fd(),
+///         f.as_fd(),
 ///         2,   //offset
 ///         &wbufs,
 ///         0,   //priority
@@ -890,14 +899,14 @@
 #[derive(Debug)]
 #[repr(transparent)]
 pub struct AioWritev<'a> {
-    aiocb: AioCb,
+    aiocb: AioCb<'a>,
     _data: PhantomData<&'a [&'a [u8]]>,
     _pin: PhantomPinned,
 }
 
 #[cfg(target_os = "freebsd")]
 impl<'a> AioWritev<'a> {
-    unsafe_pinned!(aiocb: AioCb);
+    unsafe_pinned!(aiocb: AioCb<'a>);
 
     /// Returns the number of buffers the operation will read into.
     pub fn iovlen(&self) -> usize {
@@ -918,7 +927,7 @@
     /// * `sigev_notify`: Determines how you will be notified of event
     ///                   completion.
     pub fn new(
-        fd: RawFd,
+        fd: BorrowedFd<'a>,
         offs: off_t,
         bufs: &[IoSlice<'a>],
         prio: i32,
@@ -983,17 +992,17 @@
 /// # use nix::sys::signal::SigevNotify;
 /// # use std::{thread, time};
 /// # use std::io::Write;
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// let wbuf = b"CDEF";
 /// let mut f = tempfile().unwrap();
-/// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
+/// let mut aiocb = Box::pin(AioWrite::new(f.as_fd(),
 ///     2,   //offset
 ///     &wbuf[..],
 ///     0,   //priority
 ///     SigevNotify::SigevNone));
 /// aiocb.as_mut().submit().unwrap();
-/// let cs = aio_cancel_all(f.as_raw_fd()).unwrap();
+/// let cs = aio_cancel_all(f.as_fd()).unwrap();
 /// if cs == AioCancelStat::AioNotCanceled {
 ///     while (aiocb.as_mut().error() == Err(Errno::EINPROGRESS)) {
 ///         thread::sleep(time::Duration::from_millis(10));
@@ -1006,8 +1015,8 @@
 /// # References
 ///
 /// [`aio_cancel`](https://pubs.opengroup.org/onlinepubs/9699919799/functions/aio_cancel.html)
-pub fn aio_cancel_all(fd: RawFd) -> Result<AioCancelStat> {
-    match unsafe { libc::aio_cancel(fd, ptr::null_mut()) } {
+pub fn aio_cancel_all<F: AsFd>(fd: F) -> Result<AioCancelStat> {
+    match unsafe { libc::aio_cancel(fd.as_fd().as_raw_fd(), ptr::null_mut()) } {
         libc::AIO_CANCELED => Ok(AioCancelStat::AioCanceled),
         libc::AIO_NOTCANCELED => Ok(AioCancelStat::AioNotCanceled),
         libc::AIO_ALLDONE => Ok(AioCancelStat::AioAllDone),
@@ -1028,18 +1037,18 @@
 /// ```
 /// # use nix::sys::aio::*;
 /// # use nix::sys::signal::SigevNotify;
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use tempfile::tempfile;
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
-/// let mut aiocb = Box::pin(AioWrite::new(f.as_raw_fd(),
+/// let mut aiocb = Box::pin(AioWrite::new(f.as_fd(),
 ///     2,   //offset
 ///     WBUF,
 ///     0,   //priority
 ///     SigevNotify::SigevNone));
 /// aiocb.as_mut().submit().unwrap();
 /// aio_suspend(&[&*aiocb], None).expect("aio_suspend failed");
-/// assert_eq!(aiocb.as_mut().aio_return().unwrap() as usize, WBUF.len());
+/// assert_eq!(aiocb.as_mut().aio_return().unwrap(), WBUF.len());
 /// ```
 /// # References
 ///
@@ -1078,14 +1087,14 @@
 /// This mode is useful for otherwise-synchronous programs that want to execute
 /// a handful of I/O operations in parallel.
 /// ```
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use nix::sys::aio::*;
 /// # use nix::sys::signal::SigevNotify;
 /// # use tempfile::tempfile;
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
 /// let mut aiow = Box::pin(AioWrite::new(
-///     f.as_raw_fd(),
+///     f.as_fd(),
 ///     2,      // offset
 ///     WBUF,
 ///     0,      // priority
@@ -1102,7 +1111,7 @@
 /// technique for reducing overall context-switch overhead, especially when
 /// combined with kqueue.
 /// ```
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use std::thread;
 /// # use std::time;
 /// # use nix::errno::Errno;
@@ -1112,7 +1121,7 @@
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
 /// let mut aiow = Box::pin(AioWrite::new(
-///     f.as_raw_fd(),
+///     f.as_fd(),
 ///     2,      // offset
 ///     WBUF,
 ///     0,      // priority
@@ -1136,7 +1145,7 @@
 /// possibly resubmit some.
 /// ```
 /// # use libc::c_int;
-/// # use std::os::unix::io::AsRawFd;
+/// # use std::os::unix::io::AsFd;
 /// # use std::sync::atomic::{AtomicBool, Ordering};
 /// # use std::thread;
 /// # use std::time;
@@ -1158,7 +1167,7 @@
 /// const WBUF: &[u8] = b"abcdef123456";
 /// let mut f = tempfile().unwrap();
 /// let mut aiow = Box::pin(AioWrite::new(
-///     f.as_raw_fd(),
+///     f.as_fd(),
 ///     2,      // offset
 ///     WBUF,
 ///     0,      // priority
diff --git a/crates/nix/src/sys/fanotify.rs b/crates/nix/src/sys/fanotify.rs
index e217406..e22c527 100644
--- a/crates/nix/src/sys/fanotify.rs
+++ b/crates/nix/src/sys/fanotify.rs
@@ -96,9 +96,22 @@
         /// final data.
         FAN_CLASS_PRE_CONTENT;
 
-        /// Remove the limit of 16384 events for the event queue.
+        /// Remove the limit on the number of events in the event queue.
+        ///
+        /// Prior to Linux kernel 5.13, this limit was hardcoded to 16384. After
+        /// 5.13, one can change it via file `/proc/sys/fs/fanotify/max_queued_events`.
+        ///
+        /// See `fanotify(7)` for details about this limit. Use of this flag
+        /// requires the `CAP_SYS_ADMIN` capability.
         FAN_UNLIMITED_QUEUE;
-        /// Remove the limit of 8192 marks.
+        /// Remove the limit on the number of fanotify marks per user.
+        ///
+        /// Prior to Linux kernel 5.13, this limit was hardcoded to 8192 (per
+        /// group, not per user). After 5.13, one can change it via file
+        /// `/proc/sys/fs/fanotify/max_user_marks`.
+        ///
+        /// See `fanotify(7)` for details about this limit. Use of this flag
+        /// requires the `CAP_SYS_ADMIN` capability.
         FAN_UNLIMITED_MARKS;
 
         /// Make `FanotifyEvent::pid` return pidfd. Since Linux 5.15.
@@ -236,6 +249,9 @@
 
 impl Drop for FanotifyEvent {
     fn drop(&mut self) {
+        if self.0.fd == libc::FAN_NOFD {
+            return;
+        }
         let e = close(self.0.fd);
         if !std::thread::panicking() && e == Err(Errno::EBADF) {
             panic!("Closing an invalid file descriptor!");
@@ -313,18 +329,7 @@
         dirfd: Option<RawFd>,
         path: Option<&P>,
     ) -> Result<()> {
-        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(path, |p| unsafe {
+        let res = crate::with_opt_nix_path(path, |p| unsafe {
             libc::fanotify_mark(
                 self.fd.as_raw_fd(),
                 flags.bits(),
diff --git a/crates/nix/src/sys/prctl.rs b/crates/nix/src/sys/prctl.rs
index 42324be..35b1ce1 100644
--- a/crates/nix/src/sys/prctl.rs
+++ b/crates/nix/src/sys/prctl.rs
@@ -9,9 +9,11 @@
 use crate::sys::signal::Signal;
 use crate::Result;
 
-use libc::{c_int, c_ulong};
+use libc::{c_int, c_ulong, c_void};
 use std::convert::TryFrom;
 use std::ffi::{CStr, CString};
+use std::num::NonZeroUsize;
+use std::ptr::NonNull;
 
 libc_enum! {
     /// The type of hardware memory corruption kill policy for the thread.
@@ -213,3 +215,14 @@
 pub fn get_thp_disable() -> Result<bool> {
     prctl_get_bool(libc::PR_GET_THP_DISABLE)
 }
+
+/// Set an identifier (or reset it) to the address memory range.
+pub fn set_vma_anon_name(addr: NonNull<c_void>, length: NonZeroUsize, name: Option<&CStr>) -> Result<()> {
+    let nameref = match name {
+        Some(n) => n.as_ptr(),
+        _ => std::ptr::null()
+    };
+    let res = unsafe { libc::prctl(libc::PR_SET_VMA, libc::PR_SET_VMA_ANON_NAME, addr.as_ptr(), length, nameref) };
+
+    Errno::result(res).map(drop)
+}
diff --git a/crates/nix/src/sys/ptrace/linux.rs b/crates/nix/src/sys/ptrace/linux.rs
index 26544e1..8abaf4d 100644
--- a/crates/nix/src/sys/ptrace/linux.rs
+++ b/crates/nix/src/sys/ptrace/linux.rs
@@ -17,8 +17,10 @@
             target_arch = "x86_64",
             any(target_env = "gnu", target_env = "musl")
         ),
-        all(target_arch = "x86", target_env = "gnu")
-    )
+        all(target_arch = "x86", target_env = "gnu"),
+        all(target_arch = "aarch64", target_env = "gnu"),
+        all(target_arch = "riscv64", target_env = "gnu"),
+    ),
 ))]
 use libc::user_regs_struct;
 
@@ -170,6 +172,92 @@
     }
 }
 
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+libc_enum! {
+    #[repr(i32)]
+    /// Defines a specific register set, as used in `PTRACE_GETREGSET` and `PTRACE_SETREGSET`.
+    #[non_exhaustive]
+    pub enum RegisterSetValue {
+        NT_PRSTATUS,
+        NT_PRFPREG,
+        NT_PRPSINFO,
+        NT_TASKSTRUCT,
+        NT_AUXV,
+    }
+}
+
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+/// Represents register set areas, such as general-purpose registers or
+/// floating-point registers.
+///
+/// # Safety
+///
+/// This trait is marked unsafe, since implementation of the trait must match
+/// ptrace's request `VALUE` and return data type `Regs`.
+pub unsafe trait RegisterSet {
+    /// Corresponding type of registers in the kernel.
+    const VALUE: RegisterSetValue;
+
+    /// Struct representing the register space.
+    type Regs;
+}
+
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+/// Register sets used in [`getregset`] and [`setregset`]
+pub mod regset {
+    use super::*;
+
+    #[derive(Debug, Clone, Copy)]
+    /// General-purpose registers.
+    pub enum NT_PRSTATUS {}
+
+    unsafe impl RegisterSet for NT_PRSTATUS {
+        const VALUE: RegisterSetValue = RegisterSetValue::NT_PRSTATUS;
+        type Regs = user_regs_struct;
+    }
+
+    #[derive(Debug, Clone, Copy)]
+    /// Floating-point registers.
+    pub enum NT_PRFPREG {}
+
+    unsafe impl RegisterSet for NT_PRFPREG {
+        const VALUE: RegisterSetValue = RegisterSetValue::NT_PRFPREG;
+        #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+        type Regs = libc::user_fpregs_struct;
+        #[cfg(target_arch = "aarch64")]
+        type Regs = libc::user_fpsimd_struct;
+        #[cfg(target_arch = "riscv64")]
+        type Regs = libc::__riscv_mc_d_ext_state;
+    }
+}
+
 libc_bitflags! {
     /// Ptrace options used in conjunction with the PTRACE_SETOPTIONS request.
     /// See `man ptrace` for more details.
@@ -217,6 +305,12 @@
 }
 
 /// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
+///
+/// Note that since `PTRACE_GETREGS` are not available on all platforms (as in [ptrace(2)]),
+/// `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
+/// on aarch64 and riscv64.
+///
+/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
 #[cfg(all(
     target_os = "linux",
     any(
@@ -231,7 +325,58 @@
     ptrace_get_data::<user_regs_struct>(Request::PTRACE_GETREGS, pid)
 }
 
+/// Get user registers, as with `ptrace(PTRACE_GETREGS, ...)`
+///
+/// Note that since `PTRACE_GETREGS` are not available on all platforms (as in [ptrace(2)]),
+/// `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
+/// on aarch64 and riscv64.
+///
+/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(target_arch = "aarch64", target_arch = "riscv64")
+))]
+pub fn getregs(pid: Pid) -> Result<user_regs_struct> {
+    getregset::<regset::NT_PRSTATUS>(pid)
+}
+
+/// Get a particular set of user registers, as with `ptrace(PTRACE_GETREGSET, ...)`
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+pub fn getregset<S: RegisterSet>(pid: Pid) -> Result<S::Regs> {
+    let request = Request::PTRACE_GETREGSET;
+    let mut data = mem::MaybeUninit::<S::Regs>::uninit();
+    let mut iov = libc::iovec {
+        iov_base: data.as_mut_ptr().cast(),
+        iov_len: mem::size_of::<S::Regs>(),
+    };
+    unsafe {
+        ptrace_other(
+            request,
+            pid,
+            S::VALUE as i32 as AddressType,
+            (&mut iov as *mut libc::iovec).cast(),
+        )?;
+    };
+    Ok(unsafe { data.assume_init() })
+}
+
 /// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
+///
+/// Note that since `PTRACE_SETREGS` are not available on all platforms (as in [ptrace(2)]),
+/// `ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
+/// on aarch64 and riscv64.
+///
+/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
 #[cfg(all(
     target_os = "linux",
     any(
@@ -248,12 +393,55 @@
             Request::PTRACE_SETREGS as RequestType,
             libc::pid_t::from(pid),
             ptr::null_mut::<c_void>(),
-            &regs as *const _ as *const c_void,
+            &regs as *const user_regs_struct as *const c_void,
         )
     };
     Errno::result(res).map(drop)
 }
 
+/// Set user registers, as with `ptrace(PTRACE_SETREGS, ...)`
+///
+/// Note that since `PTRACE_SETREGS` are not available on all platforms (as in [ptrace(2)]),
+/// `ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, ...)` is used instead to achieve the same effect
+/// on aarch64 and riscv64.
+///
+/// [ptrace(2)]: https://www.man7.org/linux/man-pages/man2/ptrace.2.html
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(target_arch = "aarch64", target_arch = "riscv64")
+))]
+pub fn setregs(pid: Pid, regs: user_regs_struct) -> Result<()> {
+    setregset::<regset::NT_PRSTATUS>(pid, regs)
+}
+
+/// Set a particular set of user registers, as with `ptrace(PTRACE_SETREGSET, ...)`
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+pub fn setregset<S: RegisterSet>(pid: Pid, mut regs: S::Regs) -> Result<()> {
+    let mut iov = libc::iovec {
+        iov_base: (&mut regs as *mut S::Regs).cast(),
+        iov_len: mem::size_of::<S::Regs>(),
+    };
+    unsafe {
+        ptrace_other(
+            Request::PTRACE_SETREGSET,
+            pid,
+            S::VALUE as i32 as AddressType,
+            (&mut iov as *mut libc::iovec).cast(),
+        )?;
+    }
+    Ok(())
+}
+
 /// 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
@@ -543,17 +731,15 @@
 
 /// Writes a word into the processes memory at the given address, as with
 /// ptrace(PTRACE_POKEDATA, ...)
-///
-/// # 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<()> {
-    unsafe { ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data).map(drop) }
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub fn write(pid: Pid, addr: AddressType, data: c_long) -> Result<()> {
+    unsafe {
+        // Safety(not_unsafe_ptr_arg_deref):
+        // `ptrace_other` is a common abstract
+        // but in `PTRACE_POKEDATA` situation, `data` is exactly what will be wtitten
+        ptrace_other(Request::PTRACE_POKEDATA, pid, addr, data as *mut c_void)
+            .map(drop)
+    }
 }
 
 /// Reads a word from a user area at `offset`, as with ptrace(PTRACE_PEEKUSER, ...).
@@ -564,17 +750,13 @@
 
 /// Writes a word to a user area at `offset`, as with ptrace(PTRACE_POKEUSER, ...).
 /// The user struct definition can be found in `/usr/include/sys/user.h`.
-///
-/// # Safety
-///
-/// The `data` argument is passed directly to `ptrace(2)`.  Read that man page
-/// for guidance.
-pub unsafe fn write_user(
-    pid: Pid,
-    offset: AddressType,
-    data: *mut c_void,
-) -> Result<()> {
+#[allow(clippy::not_unsafe_ptr_arg_deref)]
+pub fn write_user(pid: Pid, offset: AddressType, data: c_long) -> Result<()> {
     unsafe {
-        ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data).map(drop)
+        // Safety(not_unsafe_ptr_arg_deref):
+        // `ptrace_other` is a common abstract
+        // but in `PTRACE_POKEDATA` situation, `data` is exactly what will be wtitten
+        ptrace_other(Request::PTRACE_POKEUSER, pid, offset, data as *mut c_void)
+            .map(drop)
     }
 }
diff --git a/crates/nix/src/sys/resource.rs b/crates/nix/src/sys/resource.rs
index 7131507..73d8a05 100644
--- a/crates/nix/src/sys/resource.rs
+++ b/crates/nix/src/sys/resource.rs
@@ -293,7 +293,9 @@
         TimeVal::from(self.0.ru_stime)
     }
 
-    /// The resident set size at its peak, in kilobytes.
+    /// The resident set size at its peak,
+    #[cfg_attr(apple_targets, doc = " in bytes.")]
+    #[cfg_attr(not(apple_targets), doc = " in kilobytes.")]
     pub fn max_rss(&self) -> c_long {
         self.0.ru_maxrss
     }
diff --git a/crates/nix/src/sys/signal.rs b/crates/nix/src/sys/signal.rs
index c9b593d..921fb28 100644
--- a/crates/nix/src/sys/signal.rs
+++ b/crates/nix/src/sys/signal.rs
@@ -597,7 +597,7 @@
         target_os = "haiku",
         target_os = "hurd",
         target_os = "aix",
-        target_os = "fushsia"
+        target_os = "fuchsia"
     ))]
     #[doc(alias("sigsuspend"))]
     pub fn suspend(&self) -> Result<()> {
@@ -753,11 +753,18 @@
 }
 
 /// Action to take on receipt of a signal. Corresponds to `sigaction`.
+#[repr(transparent)]
 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct SigAction {
     sigaction: libc::sigaction
 }
 
+impl From<SigAction> for libc::sigaction {
+    fn from(value: SigAction) -> libc::sigaction {
+        value.sigaction
+    }
+}
+
 impl SigAction {
     /// Creates a new action.
     ///
diff --git a/crates/nix/src/sys/signalfd.rs b/crates/nix/src/sys/signalfd.rs
index ccba774..4594f4d 100644
--- a/crates/nix/src/sys/signalfd.rs
+++ b/crates/nix/src/sys/signalfd.rs
@@ -105,11 +105,11 @@
         Ok(SignalFd(fd))
     }
 
-    pub fn set_mask(&mut self, mask: &SigSet) -> Result<()> {
+    pub fn set_mask(&self, mask: &SigSet) -> Result<()> {
         self.update(mask, SfdFlags::empty())
     }
 
-    pub fn read_signal(&mut self) -> Result<Option<siginfo>> {
+    pub fn read_signal(&self) -> Result<Option<siginfo>> {
         let mut buffer = mem::MaybeUninit::<siginfo>::uninit();
 
         let size = mem::size_of_val(&buffer);
diff --git a/crates/nix/src/sys/socket/addr.rs b/crates/nix/src/sys/socket/addr.rs
index f6800aa..aa89ba9 100644
--- a/crates/nix/src/sys/socket/addr.rs
+++ b/crates/nix/src/sys/socket/addr.rs
@@ -920,6 +920,19 @@
 }
 
 #[cfg(feature = "net")]
+impl From<SockaddrIn> for libc::sockaddr_in {
+    fn from(sin: SockaddrIn) -> libc::sockaddr_in {
+        sin.0
+    }
+}
+#[cfg(feature = "net")]
+impl From<libc::sockaddr_in> for SockaddrIn {
+    fn from(sin: libc::sockaddr_in) -> SockaddrIn {
+        SockaddrIn(sin)
+    }
+}
+
+#[cfg(feature = "net")]
 impl std::str::FromStr for SockaddrIn {
     type Err = net::AddrParseError;
 
@@ -970,6 +983,20 @@
 }
 
 #[cfg(feature = "net")]
+impl From<SockaddrIn6> for libc::sockaddr_in6 {
+    fn from(sin6: SockaddrIn6) -> libc::sockaddr_in6 {
+        sin6.0
+    }
+}
+
+#[cfg(feature = "net")]
+impl From<libc::sockaddr_in6> for SockaddrIn6 {
+    fn from(sin6: libc::sockaddr_in6) -> SockaddrIn6 {
+        SockaddrIn6(sin6)
+    }
+}
+
+#[cfg(feature = "net")]
 impl private::SockaddrLikePriv for SockaddrIn6 {}
 #[cfg(feature = "net")]
 impl SockaddrLike for SockaddrIn6 {
@@ -2150,9 +2177,8 @@
     }
 
     #[cfg(not(any(target_os = "hurd", target_os = "redox")))]
+    #[allow(clippy::cast_ptr_alignment)]
     mod link {
-        #![allow(clippy::cast_ptr_alignment)]
-
         #[cfg(any(apple_targets, solarish))]
         use super::super::super::socklen_t;
         use super::*;
diff --git a/crates/nix/src/sys/socket/mod.rs b/crates/nix/src/sys/socket/mod.rs
index 3d1651b..1f1869e 100644
--- a/crates/nix/src/sys/socket/mod.rs
+++ b/crates/nix/src/sys/socket/mod.rs
@@ -13,6 +13,7 @@
 #[cfg(all(feature = "uio", not(target_os = "redox")))]
 use libc::{
     c_void, iovec, CMSG_DATA, CMSG_FIRSTHDR, CMSG_LEN, CMSG_NXTHDR, CMSG_SPACE,
+    MSG_CTRUNC,
 };
 #[cfg(not(target_os = "redox"))]
 use std::io::{IoSlice, IoSliceMut};
@@ -599,13 +600,19 @@
 }
 
 impl<'a, S> RecvMsg<'a, '_, S> {
-    /// Iterate over the valid control messages pointed to by this
-    /// msghdr.
-    pub fn cmsgs(&self) -> CmsgIterator {
-        CmsgIterator {
+    /// Iterate over the valid control messages pointed to by this msghdr. If
+    /// allocated space for CMSGs was too small it is not safe to iterate,
+    /// instead return an `Error::ENOBUFS` error.
+    pub fn cmsgs(&self) -> Result<CmsgIterator> {
+
+        if self.mhdr.msg_flags & MSG_CTRUNC == MSG_CTRUNC {
+            return Err(Errno::ENOBUFS);
+        }
+
+        Ok(CmsgIterator {
             cmsghdr: self.cmsghdr,
             mhdr: &self.mhdr
-        }
+        })
     }
 }
 
@@ -700,7 +707,7 @@
     /// let mut iov = [IoSliceMut::new(&mut buffer)];
     /// let r = recvmsg::<SockaddrIn>(in_socket.as_raw_fd(), &mut iov, Some(&mut cmsgspace), flags)
     ///     .unwrap();
-    /// let rtime = match r.cmsgs().next() {
+    /// let rtime = match r.cmsgs().unwrap().next() {
     ///     Some(ControlMessageOwned::ScmTimestamp(rtime)) => rtime,
     ///     Some(_) => panic!("Unexpected control message"),
     ///     None => panic!("No control message")
@@ -773,7 +780,7 @@
     #[cfg(target_os = "linux")]
     #[cfg(feature = "net")]
     #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
-    UdpGroSegments(u16),
+    UdpGroSegments(i32),
 
     /// SO_RXQ_OVFL indicates that an unsigned 32 bit value
     /// ancilliary msg (cmsg) should be attached to recieved
@@ -949,7 +956,7 @@
             #[cfg(target_os = "linux")]
             #[cfg(feature = "net")]
             (libc::SOL_UDP, libc::UDP_GRO) => {
-                let gso_size: u16 = unsafe { ptr::read_unaligned(p as *const _) };
+                let gso_size: i32 = unsafe { ptr::read_unaligned(p as *const _) };
                 ControlMessageOwned::UdpGroSegments(gso_size)
             },
             #[cfg(any(linux_android, target_os = "fuchsia"))]
diff --git a/crates/nix/src/sys/socket/sockopt.rs b/crates/nix/src/sys/socket/sockopt.rs
index 4357695..f66b54e 100644
--- a/crates/nix/src/sys/socket/sockopt.rs
+++ b/crates/nix/src/sys/socket/sockopt.rs
@@ -5,7 +5,7 @@
 use crate::Result;
 use cfg_if::cfg_if;
 use libc::{self, c_int, c_void, socklen_t};
-use std::ffi::{OsStr, OsString};
+use std::ffi::{CStr, CString, OsStr, OsString};
 use std::mem::{self, MaybeUninit};
 use std::os::unix::ffi::OsStrExt;
 use std::os::unix::io::{AsFd, AsRawFd};
@@ -270,6 +270,16 @@
     libc::SO_REUSEPORT,
     bool
 );
+#[cfg(target_os = "freebsd")]
+sockopt_impl!(
+    /// Enables incoming connections to be distributed among N sockets (up to 256)
+    /// via a Load-Balancing hash based algorithm.
+    ReusePortLb,
+    Both,
+    libc::SOL_SOCKET,
+    libc::SO_REUSEPORT_LB,
+    bool
+);
 #[cfg(feature = "net")]
 sockopt_impl!(
     #[cfg_attr(docsrs, doc(cfg(feature = "net")))]
@@ -1026,7 +1036,7 @@
     libc::IP_TTL,
     libc::c_int
 );
-#[cfg(any(linux_android, target_os = "freebsd"))]
+#[cfg(any(apple_targets, linux_android, target_os = "freebsd"))]
 sockopt_impl!(
     /// Set the unicast hop limit for the socket.
     Ipv6Ttl,
@@ -1065,6 +1075,17 @@
     libc::IPV6_DONTFRAG,
     bool
 );
+#[cfg(apple_targets)]
+#[cfg(feature = "net")]
+sockopt_impl!(
+    /// Get the utun interface name.
+    UtunIfname,
+    GetOnly,
+    libc::SYSPROTO_CONTROL,
+    libc::UTUN_OPT_IFNAME,
+    CString,
+    GetCString<[u8; libc::IFNAMSIZ]>
+);
 
 #[allow(missing_docs)]
 // Not documented by Linux!
@@ -1568,3 +1589,32 @@
     }
 }
 
+/// Getter for a `CString` value.
+struct GetCString<T: AsMut<[u8]>> {
+    len: socklen_t,
+    val: MaybeUninit<T>,
+}
+
+impl<T: AsMut<[u8]>> Get<CString> for GetCString<T> {
+    fn uninit() -> Self {
+        GetCString {
+            len: mem::size_of::<T>() as socklen_t,
+            val: MaybeUninit::uninit(),
+        }
+    }
+
+    fn ffi_ptr(&mut self) -> *mut c_void {
+        self.val.as_mut_ptr().cast()
+    }
+
+    fn ffi_len(&mut self) -> *mut socklen_t {
+        &mut self.len
+    }
+
+    unsafe fn assume_init(self) -> CString {
+        let mut v = unsafe { self.val.assume_init() };
+        CStr::from_bytes_until_nul(v.as_mut())
+            .expect("string should be null-terminated")
+            .to_owned()
+    }
+}
diff --git a/crates/nix/src/sys/sysinfo.rs b/crates/nix/src/sys/sysinfo.rs
index e8aa00b..a2bc093 100644
--- a/crates/nix/src/sys/sysinfo.rs
+++ b/crates/nix/src/sys/sysinfo.rs
@@ -1,4 +1,4 @@
-use libc::{self, SI_LOAD_SHIFT};
+use libc::SI_LOAD_SHIFT;
 use std::time::Duration;
 use std::{cmp, mem};
 
diff --git a/crates/nix/src/unistd.rs b/crates/nix/src/unistd.rs
index 4502766..58ede6e 100644
--- a/crates/nix/src/unistd.rs
+++ b/crates/nix/src/unistd.rs
@@ -1377,7 +1377,7 @@
 /// Commit filesystem caches to disk
 ///
 /// See also [sync(2)](https://pubs.opengroup.org/onlinepubs/9699919799/functions/sync.html)
-#[cfg(any(freebsdlike, linux_android, netbsdlike))]
+#[cfg(any(bsd, linux_android, solarish, target_os = "haiku", target_os = "aix", target_os = "hurd"))]
 pub fn sync() {
     unsafe { libc::sync() };
 }
@@ -1386,7 +1386,7 @@
 /// descriptor `fd` to disk
 ///
 /// See also [syncfs(2)](https://man7.org/linux/man-pages/man2/sync.2.html)
-#[cfg(linux_android)]
+#[cfg(any(linux_android, target_os = "hurd"))]
 pub fn syncfs(fd: RawFd) -> Result<()> {
     let res = unsafe { libc::syncfs(fd) };
 
@@ -1411,13 +1411,27 @@
     linux_android,
     solarish,
     netbsdlike,
+    apple_targets,
     target_os = "freebsd",
     target_os = "emscripten",
     target_os = "fuchsia",
+    target_os = "aix",
+    target_os = "hurd",
 ))]
 #[inline]
 pub fn fdatasync(fd: RawFd) -> Result<()> {
-    let res = unsafe { libc::fdatasync(fd) };
+    cfg_if! {
+        // apple libc supports fdatasync too, albeit not being present in its headers
+        // [fdatasync](https://github.com/apple/darwin-xnu/blob/2ff845c2e033bd0ff64b5b6aa6063a1f8f65aa32/bsd/vfs/vfs_syscalls.c#L7728)
+        if #[cfg(apple_targets)] {
+            extern "C" {
+                fn fdatasync(fd: libc::c_int) -> libc::c_int;
+            }
+        } else {
+            use libc::fdatasync as fdatasync;
+        }
+    }
+    let res = unsafe { fdatasync(fd) };
 
     Errno::result(res).map(drop)
 }
@@ -2031,6 +2045,19 @@
     /// 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,
+    #[cfg(any(
+        apple_targets,
+        solarish,
+        freebsdlike,
+        target_os = "netbsd",
+    ))]
+    /// If a file system supports the reporting of holes (see lseek(2)),
+    /// pathconf() and fpathconf() return a positive number that represents the
+    /// minimum hole size returned in bytes.  The offsets of holes returned will
+    /// be aligned to this same value.  A special value of 1 is returned if the
+    /// file system does not specify the minimum hole size but still reports
+    /// holes.
+    MIN_HOLE_SIZE = libc::_PC_MIN_HOLE_SIZE,
     /// Maximum number of bytes in a filename (not including the terminating
     /// null of a filename string).
     NAME_MAX = libc::_PC_NAME_MAX,
diff --git a/crates/nix/test/common/mod.rs b/crates/nix/test/common/mod.rs
index db4aed2..ab0e746 100644
--- a/crates/nix/test/common/mod.rs
+++ b/crates/nix/test/common/mod.rs
@@ -37,8 +37,8 @@
 #[macro_export]
 macro_rules! require_mount {
     ($name:expr) => {
-        use ::sysctl::{CtlValue, Sysctl};
         use nix::unistd::Uid;
+        use sysctl::{CtlValue, Sysctl};
 
         let ctl = ::sysctl::Ctl::new("vfs.usermount").unwrap();
         if !Uid::current().is_root() && CtlValue::Int(0) == ctl.value().unwrap()
@@ -65,7 +65,7 @@
 #[macro_export]
 macro_rules! skip_if_jailed {
     ($name:expr) => {
-        use ::sysctl::{CtlValue, Sysctl};
+        use sysctl::{CtlValue, Sysctl};
 
         let ctl = ::sysctl::Ctl::new("security.jail.jailed").unwrap();
         if let CtlValue::Int(1) = ctl.value().unwrap() {
diff --git a/crates/nix/test/mount/mod.rs b/crates/nix/test/mount/mod.rs
new file mode 100644
index 0000000..2764b83
--- /dev/null
+++ b/crates/nix/test/mount/mod.rs
@@ -0,0 +1,6 @@
+#[cfg(target_os = "linux")]
+mod test_mount;
+#[cfg(apple_targets)]
+mod test_mount_apple;
+#[cfg(target_os = "freebsd")]
+mod test_nmount;
diff --git a/crates/nix/test/test_mount.rs b/crates/nix/test/mount/test_mount.rs
similarity index 94%
rename from crates/nix/test/test_mount.rs
rename to crates/nix/test/mount/test_mount.rs
index a4f0903..9cb7741 100644
--- a/crates/nix/test/test_mount.rs
+++ b/crates/nix/test/mount/test_mount.rs
@@ -53,6 +53,8 @@
         .unwrap_or_else(|e| panic!("read failed: {e}"));
     assert_eq!(buf, SCRIPT_CONTENTS);
 
+    // while forking and unmounting prevent other child processes
+    let _m = FORK_MTX.lock();
     // Verify execute.
     assert_eq!(
         EXPECTED_STATUS,
@@ -129,6 +131,8 @@
         &test_path
     );
 
+    // while forking and unmounting prevent other child processes
+    let _m = FORK_MTX.lock();
     // EACCES: Permission denied
     assert_eq!(
         EACCES,
@@ -168,6 +172,8 @@
             .and_then(|mut f| f.write(SCRIPT_CONTENTS))
             .unwrap_or_else(|e| panic!("write failed: {e}"));
 
+        // wait for child processes to prevent EBUSY
+        let _m = FORK_MTX.lock();
         umount(mount_point.path())
             .unwrap_or_else(|e| panic!("umount failed: {e}"));
     }
diff --git a/crates/nix/test/mount/test_mount_apple.rs b/crates/nix/test/mount/test_mount_apple.rs
new file mode 100644
index 0000000..f286850
--- /dev/null
+++ b/crates/nix/test/mount/test_mount_apple.rs
@@ -0,0 +1,8 @@
+use nix::errno::Errno;
+use nix::mount::{mount, MntFlags};
+
+#[test]
+fn test_mount() {
+    let res = mount::<str, str, str>("", "", MntFlags::empty(), None);
+    assert_eq!(res, Err(Errno::ENOENT));
+}
diff --git a/crates/nix/test/test_nmount.rs b/crates/nix/test/mount/test_nmount.rs
similarity index 100%
rename from crates/nix/test/test_nmount.rs
rename to crates/nix/test/mount/test_nmount.rs
diff --git a/crates/nix/test/sys/test_aio.rs b/crates/nix/test/sys/test_aio.rs
index ba5ad02..2f4494f 100644
--- a/crates/nix/test/sys/test_aio.rs
+++ b/crates/nix/test/sys/test_aio.rs
@@ -1,7 +1,7 @@
 use std::{
     io::{Read, Seek, Write},
     ops::Deref,
-    os::unix::io::AsRawFd,
+    os::unix::io::{AsFd, AsRawFd, BorrowedFd},
     pin::Pin,
     sync::atomic::{AtomicBool, Ordering},
     thread, time,
@@ -45,8 +45,9 @@
 
     #[test]
     fn test_accessors() {
+        let f = tempfile().unwrap();
         let aiocb = AioFsync::new(
-            1001,
+            f.as_fd(),
             AioFsyncMode::O_SYNC,
             42,
             SigevNotify::SigevSignal {
@@ -54,7 +55,7 @@
                 si_value: 99,
             },
         );
-        assert_eq!(1001, aiocb.fd());
+        assert_eq!(f.as_raw_fd(), aiocb.fd().as_raw_fd());
         assert_eq!(AioFsyncMode::O_SYNC, aiocb.mode());
         assert_eq!(42, aiocb.priority());
         let sev = aiocb.sigevent().sigevent();
@@ -67,21 +68,17 @@
     // Skip on Linux, because Linux's AIO implementation can't detect errors
     // synchronously
     #[test]
-    #[cfg(any(target_os = "freebsd", apple_targets))]
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), ignore)]
     fn error() {
         use std::mem;
 
         const INITIAL: &[u8] = b"abcdef123456";
         // Create an invalid AioFsyncMode
-        let mode = unsafe { mem::transmute(666) };
+        let mode = unsafe { mem::transmute::<i32, AioFsyncMode>(666) };
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let mut aiof = Box::pin(AioFsync::new(
-            f.as_raw_fd(),
-            mode,
-            0,
-            SigevNotify::SigevNone,
-        ));
+        let mut aiof =
+            Box::pin(AioFsync::new(f.as_fd(), mode, 0, SigevNotify::SigevNone));
         let err = aiof.as_mut().submit();
         err.expect_err("assertion failed");
     }
@@ -92,9 +89,8 @@
         const INITIAL: &[u8] = b"abcdef123456";
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let fd = f.as_raw_fd();
         let mut aiof = Box::pin(AioFsync::new(
-            fd,
+            f.as_fd(),
             AioFsyncMode::O_SYNC,
             0,
             SigevNotify::SigevNone,
@@ -110,9 +106,10 @@
 
     #[test]
     fn test_accessors() {
+        let f = tempfile().unwrap();
         let mut rbuf = vec![0; 4];
         let aiocb = AioRead::new(
-            1001,
+            f.as_fd(),
             2, //offset
             &mut rbuf,
             42, //priority
@@ -121,7 +118,7 @@
                 si_value: 99,
             },
         );
-        assert_eq!(1001, aiocb.fd());
+        assert_eq!(f.as_raw_fd(), aiocb.fd().as_raw_fd());
         assert_eq!(4, aiocb.nbytes());
         assert_eq!(2, aiocb.offset());
         assert_eq!(42, aiocb.priority());
@@ -140,7 +137,7 @@
         let mut rbuf = vec![0; 4];
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let fd = f.as_raw_fd();
+        let fd = f.as_fd();
         let mut aior =
             Box::pin(AioRead::new(fd, 2, &mut rbuf, 0, SigevNotify::SigevNone));
         aior.as_mut().submit().unwrap();
@@ -164,7 +161,7 @@
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
         let mut aior = Box::pin(AioRead::new(
-            f.as_raw_fd(),
+            f.as_fd(),
             -1, //an invalid offset
             &mut rbuf,
             0, //priority
@@ -184,7 +181,7 @@
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
         {
-            let fd = f.as_raw_fd();
+            let fd = f.as_fd();
             let mut aior = Box::pin(AioRead::new(
                 fd,
                 2,
@@ -211,7 +208,7 @@
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
         {
-            let fd = f.as_raw_fd();
+            let fd = f.as_fd();
             let mut aior =
                 AioRead::new(fd, 2, &mut rbuf, 0, SigevNotify::SigevNone);
             let mut aior = unsafe { Pin::new_unchecked(&mut aior) };
@@ -234,12 +231,13 @@
 
     #[test]
     fn test_accessors() {
+        let f = tempfile().unwrap();
         let mut rbuf0 = vec![0; 4];
         let mut rbuf1 = vec![0; 8];
         let mut rbufs =
             [IoSliceMut::new(&mut rbuf0), IoSliceMut::new(&mut rbuf1)];
         let aiocb = AioReadv::new(
-            1001,
+            f.as_fd(),
             2, //offset
             &mut rbufs,
             42, //priority
@@ -248,7 +246,7 @@
                 si_value: 99,
             },
         );
-        assert_eq!(1001, aiocb.fd());
+        assert_eq!(f.as_raw_fd(), aiocb.fd().as_raw_fd());
         assert_eq!(2, aiocb.iovlen());
         assert_eq!(2, aiocb.offset());
         assert_eq!(42, aiocb.priority());
@@ -270,7 +268,7 @@
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
         {
-            let fd = f.as_raw_fd();
+            let fd = f.as_fd();
             let mut aior = Box::pin(AioReadv::new(
                 fd,
                 2,
@@ -297,9 +295,10 @@
 
     #[test]
     fn test_accessors() {
+        let f = tempfile().unwrap();
         let wbuf = vec![0; 4];
         let aiocb = AioWrite::new(
-            1001,
+            f.as_fd(),
             2, //offset
             &wbuf,
             42, //priority
@@ -308,7 +307,7 @@
                 si_value: 99,
             },
         );
-        assert_eq!(1001, aiocb.fd());
+        assert_eq!(f.as_raw_fd(), aiocb.fd().as_raw_fd());
         assert_eq!(4, aiocb.nbytes());
         assert_eq!(2, aiocb.offset());
         assert_eq!(42, aiocb.priority());
@@ -327,7 +326,7 @@
 
         let f = tempfile().unwrap();
         let mut aiow = Box::pin(AioWrite::new(
-            f.as_raw_fd(),
+            f.as_fd(),
             0,
             wbuf,
             0,
@@ -356,18 +355,20 @@
 
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let mut aiow = Box::pin(AioWrite::new(
-            f.as_raw_fd(),
-            2,
-            &wbuf,
-            0,
-            SigevNotify::SigevNone,
-        ));
-        aiow.as_mut().submit().unwrap();
+        {
+            let mut aiow = Box::pin(AioWrite::new(
+                f.as_fd(),
+                2,
+                &wbuf,
+                0,
+                SigevNotify::SigevNone,
+            ));
+            aiow.as_mut().submit().unwrap();
 
-        let err = poll_aio!(&mut aiow);
-        assert_eq!(err, Ok(()));
-        assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
+            let err = poll_aio!(&mut aiow);
+            assert_eq!(err, Ok(()));
+            assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
+        }
 
         f.rewind().unwrap();
         let len = f.read_to_end(&mut rbuf).unwrap();
@@ -386,19 +387,21 @@
 
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let mut aiow = AioWrite::new(
-            f.as_raw_fd(),
-            2, //offset
-            &wbuf,
-            0, //priority
-            SigevNotify::SigevNone,
-        );
-        let mut aiow = unsafe { Pin::new_unchecked(&mut aiow) };
-        aiow.as_mut().submit().unwrap();
+        {
+            let mut aiow = AioWrite::new(
+                f.as_fd(),
+                2, //offset
+                &wbuf,
+                0, //priority
+                SigevNotify::SigevNone,
+            );
+            let mut aiow = unsafe { Pin::new_unchecked(&mut aiow) };
+            aiow.as_mut().submit().unwrap();
 
-        let err = poll_aio!(&mut aiow);
-        assert_eq!(err, Ok(()));
-        assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
+            let err = poll_aio!(&mut aiow);
+            assert_eq!(err, Ok(()));
+            assert_eq!(aiow.as_mut().aio_return().unwrap(), wbuf.len());
+        }
 
         f.rewind().unwrap();
         let len = f.read_to_end(&mut rbuf).unwrap();
@@ -411,12 +414,14 @@
     // Skip on Linux, because Linux's AIO implementation can't detect errors
     // synchronously
     #[test]
-    #[cfg(any(target_os = "freebsd", apple_targets))]
+    #[cfg_attr(any(target_os = "android", target_os = "linux"), ignore)]
     fn error() {
+        // Not I/O safe!  Deliberately create an invalid fd.
+        let fd = unsafe { BorrowedFd::borrow_raw(666) };
         let wbuf = "CDEF".to_string().into_bytes();
         let mut aiow = Box::pin(AioWrite::new(
-            666, // An invalid file descriptor
-            0,   //offset
+            fd,
+            0, //offset
             &wbuf,
             0, //priority
             SigevNotify::SigevNone,
@@ -435,11 +440,12 @@
 
     #[test]
     fn test_accessors() {
+        let f = tempfile().unwrap();
         let wbuf0 = vec![0; 4];
         let wbuf1 = vec![0; 8];
         let wbufs = [IoSlice::new(&wbuf0), IoSlice::new(&wbuf1)];
         let aiocb = AioWritev::new(
-            1001,
+            f.as_fd(),
             2, //offset
             &wbufs,
             42, //priority
@@ -448,7 +454,7 @@
                 si_value: 99,
             },
         );
-        assert_eq!(1001, aiocb.fd());
+        assert_eq!(f.as_raw_fd(), aiocb.fd().as_raw_fd());
         assert_eq!(2, aiocb.iovlen());
         assert_eq!(2, aiocb.offset());
         assert_eq!(42, aiocb.priority());
@@ -472,18 +478,20 @@
 
         let mut f = tempfile().unwrap();
         f.write_all(INITIAL).unwrap();
-        let mut aiow = Box::pin(AioWritev::new(
-            f.as_raw_fd(),
-            1,
-            &wbufs,
-            0,
-            SigevNotify::SigevNone,
-        ));
-        aiow.as_mut().submit().unwrap();
+        {
+            let mut aiow = Box::pin(AioWritev::new(
+                f.as_fd(),
+                1,
+                &wbufs,
+                0,
+                SigevNotify::SigevNone,
+            ));
+            aiow.as_mut().submit().unwrap();
 
-        let err = poll_aio!(&mut aiow);
-        assert_eq!(err, Ok(()));
-        assert_eq!(aiow.as_mut().aio_return().unwrap(), wlen);
+            let err = poll_aio!(&mut aiow);
+            assert_eq!(err, Ok(()));
+            assert_eq!(aiow.as_mut().aio_return().unwrap(), wlen);
+        }
 
         f.rewind().unwrap();
         let len = f.read_to_end(&mut rbuf).unwrap();
@@ -521,22 +529,25 @@
 
     let mut f = tempfile().unwrap();
     f.write_all(INITIAL).unwrap();
-    let mut aiow = Box::pin(AioWrite::new(
-        f.as_raw_fd(),
-        2, //offset
-        WBUF,
-        0, //priority
-        SigevNotify::SigevSignal {
-            signal: Signal::SIGUSR2,
-            si_value: 0, //TODO: validate in sigfunc
-        },
-    ));
-    aiow.as_mut().submit().unwrap();
-    while !SIGNALED.load(Ordering::Relaxed) {
-        thread::sleep(time::Duration::from_millis(10));
+    {
+        let mut aiow = Box::pin(AioWrite::new(
+            f.as_fd(),
+            2, //offset
+            WBUF,
+            0, //priority
+            SigevNotify::SigevSignal {
+                signal: Signal::SIGUSR2,
+                si_value: 0, //TODO: validate in sigfunc
+            },
+        ));
+        aiow.as_mut().submit().unwrap();
+        while !SIGNALED.load(Ordering::Relaxed) {
+            thread::sleep(time::Duration::from_millis(10));
+        }
+
+        assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
     }
 
-    assert_eq!(aiow.as_mut().aio_return().unwrap(), WBUF.len());
     f.rewind().unwrap();
     let len = f.read_to_end(&mut rbuf).unwrap();
     assert_eq!(len, EXPECT.len());
@@ -551,7 +562,7 @@
 
     let f = tempfile().unwrap();
     let mut aiocb = Box::pin(AioWrite::new(
-        f.as_raw_fd(),
+        f.as_fd(),
         0, //offset
         wbuf,
         0, //priority
@@ -561,7 +572,7 @@
     let err = aiocb.as_mut().error();
     assert!(err == Ok(()) || err == Err(Errno::EINPROGRESS));
 
-    aio_cancel_all(f.as_raw_fd()).unwrap();
+    aio_cancel_all(f.as_fd()).unwrap();
 
     // Wait for aiocb to complete, but don't care whether it succeeded
     let _ = poll_aio!(&mut aiocb);
@@ -579,7 +590,7 @@
     f.write_all(INITIAL).unwrap();
 
     let mut wcb = Box::pin(AioWrite::new(
-        f.as_raw_fd(),
+        f.as_fd(),
         2, //offset
         WBUF,
         0, //priority
@@ -587,7 +598,7 @@
     ));
 
     let mut rcb = Box::pin(AioRead::new(
-        f.as_raw_fd(),
+        f.as_fd(),
         8, //offset
         &mut rbuf,
         0, //priority
@@ -624,21 +635,23 @@
 #[test]
 fn casting() {
     let sev = SigevNotify::SigevNone;
-    let aiof = AioFsync::new(666, AioFsyncMode::O_SYNC, 0, sev);
+    // Only safe because we'll never await the futures
+    let fd = unsafe { BorrowedFd::borrow_raw(666) };
+    let aiof = AioFsync::new(fd, AioFsyncMode::O_SYNC, 0, sev);
     assert_eq!(
         aiof.as_ref() as *const libc::aiocb,
         &aiof as *const AioFsync as *const libc::aiocb
     );
 
     let mut rbuf = [];
-    let aior = AioRead::new(666, 0, &mut rbuf, 0, sev);
+    let aior = AioRead::new(fd, 0, &mut rbuf, 0, sev);
     assert_eq!(
         aior.as_ref() as *const libc::aiocb,
         &aior as *const AioRead as *const libc::aiocb
     );
 
     let wbuf = [];
-    let aiow = AioWrite::new(666, 0, &wbuf, 0, sev);
+    let aiow = AioWrite::new(fd, 0, &wbuf, 0, sev);
     assert_eq!(
         aiow.as_ref() as *const libc::aiocb,
         &aiow as *const AioWrite as *const libc::aiocb
@@ -654,7 +667,9 @@
 
     let mut rbuf = [];
     let mut rbufs = [IoSliceMut::new(&mut rbuf)];
-    let aiorv = AioReadv::new(666, 0, &mut rbufs[..], 0, sev);
+    // Only safe because we'll never await the futures
+    let fd = unsafe { BorrowedFd::borrow_raw(666) };
+    let aiorv = AioReadv::new(fd, 0, &mut rbufs[..], 0, sev);
     assert_eq!(
         aiorv.as_ref() as *const libc::aiocb,
         &aiorv as *const AioReadv as *const libc::aiocb
@@ -662,7 +677,7 @@
 
     let wbuf = [];
     let wbufs = [IoSlice::new(&wbuf)];
-    let aiowv = AioWritev::new(666, 0, &wbufs, 0, sev);
+    let aiowv = AioWritev::new(fd, 0, &wbufs, 0, sev);
     assert_eq!(
         aiowv.as_ref() as *const libc::aiocb,
         &aiowv as *const AioWritev as *const libc::aiocb
diff --git a/crates/nix/test/sys/test_aio_drop.rs b/crates/nix/test/sys/test_aio_drop.rs
index 54106dd..47660cf 100644
--- a/crates/nix/test/sys/test_aio_drop.rs
+++ b/crates/nix/test/sys/test_aio_drop.rs
@@ -16,7 +16,7 @@
 fn test_drop() {
     use nix::sys::aio::*;
     use nix::sys::signal::*;
-    use std::os::unix::io::AsRawFd;
+    use std::os::unix::io::AsFd;
     use tempfile::tempfile;
 
     const WBUF: &[u8] = b"CDEF";
@@ -24,7 +24,7 @@
     let f = tempfile().unwrap();
     f.set_len(6).unwrap();
     let mut aiocb = Box::pin(AioWrite::new(
-        f.as_raw_fd(),
+        f.as_fd(),
         2, //offset
         WBUF,
         0, //priority
diff --git a/crates/nix/test/sys/test_fanotify.rs b/crates/nix/test/sys/test_fanotify.rs
index 20226c2..13ec945 100644
--- a/crates/nix/test/sys/test_fanotify.rs
+++ b/crates/nix/test/sys/test_fanotify.rs
@@ -1,9 +1,10 @@
 use crate::*;
+use nix::errno::Errno;
 use nix::sys::fanotify::{
     EventFFlags, Fanotify, FanotifyResponse, InitFlags, MarkFlags, MaskFlags,
     Response,
 };
-use std::fs::{read_link, File, OpenOptions};
+use std::fs::{read_link, read_to_string, File, OpenOptions};
 use std::io::ErrorKind;
 use std::io::{Read, Write};
 use std::os::fd::AsRawFd;
@@ -16,6 +17,7 @@
 
     test_fanotify_notifications();
     test_fanotify_responses();
+    test_fanotify_overflow();
 }
 
 fn test_fanotify_notifications() {
@@ -147,3 +149,71 @@
 
     file_thread.join().unwrap();
 }
+
+fn test_fanotify_overflow() {
+    let max_events: usize =
+        read_to_string("/proc/sys/fs/fanotify/max_queued_events")
+            .unwrap()
+            .trim()
+            .parse()
+            .unwrap();
+
+    // make sure the kernel is configured with the default value,
+    // just so this test doesn't run forever
+    assert_eq!(max_events, 16384);
+
+    let group = Fanotify::init(
+        InitFlags::FAN_CLASS_NOTIF
+            | InitFlags::FAN_REPORT_TID
+            | InitFlags::FAN_NONBLOCK,
+        EventFFlags::O_RDONLY,
+    )
+    .unwrap();
+    let tempdir = tempfile::tempdir().unwrap();
+    let tempfile = tempdir.path().join("test");
+
+    OpenOptions::new()
+        .write(true)
+        .create_new(true)
+        .open(&tempfile)
+        .unwrap();
+
+    group
+        .mark(
+            MarkFlags::FAN_MARK_ADD,
+            MaskFlags::FAN_OPEN,
+            None,
+            Some(&tempfile),
+        )
+        .unwrap();
+
+    thread::scope(|s| {
+        // perform 10 more events to demonstrate some will be dropped
+        for _ in 0..(max_events + 10) {
+            s.spawn(|| {
+                File::open(&tempfile).unwrap();
+            });
+        }
+    });
+
+    // flush the queue until it's empty
+    let mut n = 0;
+    let mut last_event = None;
+    loop {
+        match group.read_events() {
+            Ok(events) => {
+                n += events.len();
+                if let Some(event) = events.last() {
+                    last_event = Some(event.mask());
+                }
+            }
+            Err(e) if e == Errno::EWOULDBLOCK => break,
+            Err(e) => panic!("{e:?}"),
+        }
+    }
+
+    // make sure we read all we expected.
+    // the +1 is for the overflow event.
+    assert_eq!(n, max_events + 1);
+    assert_eq!(last_event, Some(MaskFlags::FAN_Q_OVERFLOW));
+}
diff --git a/crates/nix/test/sys/test_prctl.rs b/crates/nix/test/sys/test_prctl.rs
index 351213b..b409735 100644
--- a/crates/nix/test/sys/test_prctl.rs
+++ b/crates/nix/test/sys/test_prctl.rs
@@ -122,4 +122,38 @@
 
         prctl::set_thp_disable(original).unwrap();
     }
+
+    #[test]
+    fn test_set_vma_anon_name() {
+        use nix::errno::Errno;
+        use nix::sys::mman;
+        use std::num::NonZeroUsize;
+
+        const ONE_K: libc::size_t = 1024;
+        let sz = NonZeroUsize::new(ONE_K).unwrap();
+        let ptr = unsafe {
+            mman::mmap_anonymous(
+                None,
+                sz,
+                mman::ProtFlags::PROT_READ,
+                mman::MapFlags::MAP_SHARED,
+            )
+            .unwrap()
+        };
+        let err = prctl::set_vma_anon_name(
+            ptr,
+            sz,
+            Some(CStr::from_bytes_with_nul(b"[,$\0").unwrap()),
+        )
+        .unwrap_err();
+        assert_eq!(err, Errno::EINVAL);
+        // `CONFIG_ANON_VMA_NAME` kernel config might not be set
+        prctl::set_vma_anon_name(
+            ptr,
+            sz,
+            Some(CStr::from_bytes_with_nul(b"Nix\0").unwrap()),
+        )
+        .unwrap_or_default();
+        prctl::set_vma_anon_name(ptr, sz, None).unwrap_or_default();
+    }
 }
diff --git a/crates/nix/test/sys/test_ptrace.rs b/crates/nix/test/sys/test_ptrace.rs
index 246b354..c99c676 100644
--- a/crates/nix/test/sys/test_ptrace.rs
+++ b/crates/nix/test/sys/test_ptrace.rs
@@ -1,7 +1,7 @@
 #[cfg(all(
     target_os = "linux",
-    any(target_arch = "x86_64", target_arch = "x86"),
-    target_env = "gnu"
+    target_env = "gnu",
+    any(target_arch = "x86_64", target_arch = "x86")
 ))]
 use memoffset::offset_of;
 use nix::errno::Errno;
@@ -179,8 +179,13 @@
 // 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"
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
 ))]
 #[test]
 fn test_ptrace_syscall() {
@@ -226,12 +231,21 @@
             let get_syscall_id =
                 || ptrace::getregs(child).unwrap().orig_eax as libc::c_long;
 
+            #[cfg(target_arch = "aarch64")]
+            let get_syscall_id =
+                || ptrace::getregs(child).unwrap().regs[8] as libc::c_long;
+
+            #[cfg(target_arch = "riscv64")]
+            let get_syscall_id =
+                || ptrace::getregs(child).unwrap().a7 as libc::c_long;
+
             // this duplicates `get_syscall_id` for the purpose of testing `ptrace::read_user`.
             #[cfg(target_arch = "x86_64")]
             let rax_offset = offset_of!(libc::user_regs_struct, orig_rax);
             #[cfg(target_arch = "x86")]
             let rax_offset = offset_of!(libc::user_regs_struct, orig_eax);
 
+            #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
             let get_syscall_from_user_area = || {
                 // Find the offset of `user.regs.rax` (or `user.regs.eax` for x86)
                 let rax_offset = offset_of!(libc::user, regs) + rax_offset;
@@ -246,6 +260,7 @@
                 Ok(WaitStatus::PtraceSyscall(child))
             );
             assert_eq!(get_syscall_id(), ::libc::SYS_kill);
+            #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
             assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill);
 
             // kill exit
@@ -255,6 +270,7 @@
                 Ok(WaitStatus::PtraceSyscall(child))
             );
             assert_eq!(get_syscall_id(), ::libc::SYS_kill);
+            #[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
             assert_eq!(get_syscall_from_user_area(), ::libc::SYS_kill);
 
             // receive signal
@@ -273,3 +289,85 @@
         }
     }
 }
+
+#[cfg(all(
+    target_os = "linux",
+    target_env = "gnu",
+    any(
+        target_arch = "x86_64",
+        target_arch = "x86",
+        target_arch = "aarch64",
+        target_arch = "riscv64",
+    )
+))]
+#[test]
+fn test_ptrace_regsets() {
+    use nix::sys::ptrace::{self, getregset, regset, setregset};
+    use nix::sys::signal::*;
+    use nix::sys::wait::{waitpid, WaitStatus};
+    use nix::unistd::fork;
+    use nix::unistd::ForkResult::*;
+
+    require_capability!("test_ptrace_regsets", CAP_SYS_PTRACE);
+
+    let _m = crate::FORK_MTX.lock();
+
+    match unsafe { 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))
+            );
+            let mut regstruct =
+                getregset::<regset::NT_PRSTATUS>(child).unwrap();
+            let mut fpregstruct =
+                getregset::<regset::NT_PRFPREG>(child).unwrap();
+
+            #[cfg(target_arch = "x86_64")]
+            let (reg, fpreg) =
+                (&mut regstruct.r15, &mut fpregstruct.st_space[5]);
+            #[cfg(target_arch = "x86")]
+            let (reg, fpreg) =
+                (&mut regstruct.edx, &mut fpregstruct.st_space[5]);
+            #[cfg(target_arch = "aarch64")]
+            let (reg, fpreg) =
+                (&mut regstruct.regs[16], &mut fpregstruct.vregs[5]);
+            #[cfg(target_arch = "riscv64")]
+            let (reg, fpreg) = (&mut regstruct.t1, &mut fpregstruct.__f[5]);
+
+            *reg = 0xdeadbeefu32 as _;
+            *fpreg = 0xfeedfaceu32 as _;
+            let _ = setregset::<regset::NT_PRSTATUS>(child, regstruct);
+            regstruct = getregset::<regset::NT_PRSTATUS>(child).unwrap();
+            let _ = setregset::<regset::NT_PRFPREG>(child, fpregstruct);
+            fpregstruct = getregset::<regset::NT_PRFPREG>(child).unwrap();
+
+            #[cfg(target_arch = "x86_64")]
+            let (reg, fpreg) = (regstruct.r15, fpregstruct.st_space[5]);
+            #[cfg(target_arch = "x86")]
+            let (reg, fpreg) = (regstruct.edx, fpregstruct.st_space[5]);
+            #[cfg(target_arch = "aarch64")]
+            let (reg, fpreg) = (regstruct.regs[16], fpregstruct.vregs[5]);
+            #[cfg(target_arch = "riscv64")]
+            let (reg, fpreg) = (regstruct.t1, fpregstruct.__f[5]);
+            assert_eq!(reg, 0xdeadbeefu32 as _);
+            assert_eq!(fpreg, 0xfeedfaceu32 as _);
+
+            ptrace::cont(child, Some(Signal::SIGKILL)).unwrap();
+            match waitpid(child, None) {
+                Ok(WaitStatus::Signaled(pid, Signal::SIGKILL, _))
+                    if pid == child => {}
+                _ => panic!("The process should have been killed"),
+            }
+        }
+    }
+}
diff --git a/crates/nix/test/sys/test_signal.rs b/crates/nix/test/sys/test_signal.rs
index bf60749..cd4bc3d 100644
--- a/crates/nix/test/sys/test_signal.rs
+++ b/crates/nix/test/sys/test_signal.rs
@@ -283,6 +283,7 @@
 #[test]
 #[cfg(not(target_os = "redox"))]
 fn test_sigaction() {
+    let _m = crate::SIGNAL_MTX.lock();
     thread::spawn(|| {
         extern "C" fn test_sigaction_handler(_: libc::c_int) {}
         extern "C" fn test_sigaction_action(
@@ -349,7 +350,7 @@
     target_os = "haiku",
     target_os = "hurd",
     target_os = "aix",
-    target_os = "fushsia"
+    target_os = "fuchsia"
 ))]
 #[test]
 fn test_sigsuspend() {
diff --git a/crates/nix/test/sys/test_signalfd.rs b/crates/nix/test/sys/test_signalfd.rs
index 4e0971a..d315848 100644
--- a/crates/nix/test/sys/test_signalfd.rs
+++ b/crates/nix/test/sys/test_signalfd.rs
@@ -28,7 +28,7 @@
     };
 
     let mask = SigSet::empty();
-    let mut fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
+    let fd = SignalFd::with_flags(&mask, SfdFlags::SFD_NONBLOCK).unwrap();
 
     let res = fd.read_signal();
     assert!(res.unwrap().is_none());
@@ -47,7 +47,7 @@
     mask.add(signal::SIGUSR1);
     mask.thread_block().unwrap();
 
-    let mut fd = SignalFd::new(&mask).unwrap();
+    let 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
@@ -72,7 +72,7 @@
     // Block the SIGUSR1 signal from automatic processing for this thread
     let mut mask = SigSet::empty();
 
-    let mut fd = SignalFd::new(&mask).unwrap();
+    let fd = SignalFd::new(&mask).unwrap();
 
     mask.add(signal::SIGUSR1);
     mask.thread_block().unwrap();
diff --git a/crates/nix/test/sys/test_socket.rs b/crates/nix/test/sys/test_socket.rs
index 90b8a6f..79c97c8 100644
--- a/crates/nix/test/sys/test_socket.rs
+++ b/crates/nix/test/sys/test_socket.rs
@@ -55,7 +55,7 @@
             .unwrap();
 
     let mut ts = None;
-    for c in recv.cmsgs() {
+    for c in recv.cmsgs().unwrap() {
         if let ControlMessageOwned::ScmTimestampsns(timestamps) = c {
             ts = Some(timestamps.system);
         }
@@ -117,7 +117,7 @@
             .unwrap();
 
     let mut ts = None;
-    for c in recv.cmsgs() {
+    for c in recv.cmsgs().unwrap() {
         if let ControlMessageOwned::ScmRealtime(timeval) = c {
             ts = Some(timeval);
         }
@@ -179,7 +179,7 @@
             .unwrap();
 
     let mut ts = None;
-    for c in recv.cmsgs() {
+    for c in recv.cmsgs().unwrap() {
         if let ControlMessageOwned::ScmMonotonic(timeval) = c {
             ts = Some(timeval);
         }
@@ -889,7 +889,7 @@
         )
         .unwrap();
 
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs().unwrap() {
             if let ControlMessageOwned::ScmRights(fd) = cmsg {
                 assert_eq!(received_r, None);
                 assert_eq!(fd.len(), 1);
@@ -1330,7 +1330,7 @@
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
 
-        let mut cmsgs = msg.cmsgs();
+        let mut cmsgs = msg.cmsgs().unwrap();
         match cmsgs.next() {
             Some(ControlMessageOwned::ScmRights(fds)) => {
                 assert_eq!(
@@ -1399,7 +1399,7 @@
         )
         .unwrap();
 
-        if msg.cmsgs().next().is_some() {
+        if msg.cmsgs().unwrap().next().is_some() {
             panic!("unexpected cmsg");
         }
         assert!(!msg
@@ -1466,7 +1466,7 @@
         .unwrap();
         let mut received_cred = None;
 
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs().unwrap() {
             let cred = match cmsg {
                 #[cfg(linux_android)]
                 ControlMessageOwned::ScmCredentials(cred) => cred,
@@ -1497,7 +1497,7 @@
 #[test]
 fn test_scm_credentials_and_rights() {
     let space = cmsg_space!(libc::ucred, RawFd);
-    test_impl_scm_credentials_and_rights(space);
+    test_impl_scm_credentials_and_rights(space).unwrap();
 }
 
 /// Ensure that passing a an oversized control message buffer to recvmsg
@@ -1509,11 +1509,23 @@
 #[test]
 fn test_too_large_cmsgspace() {
     let space = vec![0u8; 1024];
-    test_impl_scm_credentials_and_rights(space);
+    test_impl_scm_credentials_and_rights(space).unwrap();
 }
 
 #[cfg(linux_android)]
-fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
+#[test]
+fn test_too_small_cmsgspace() {
+    let space = vec![0u8; 4];
+    assert_eq!(
+        test_impl_scm_credentials_and_rights(space),
+        Err(nix::errno::Errno::ENOBUFS)
+    );
+}
+
+#[cfg(linux_android)]
+fn test_impl_scm_credentials_and_rights(
+    mut space: Vec<u8>,
+) -> Result<(), nix::errno::Errno> {
     use libc::ucred;
     use nix::sys::socket::sockopt::PassCred;
     use nix::sys::socket::{
@@ -1573,9 +1585,9 @@
         .unwrap();
         let mut received_cred = None;
 
-        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
+        assert_eq!(msg.cmsgs()?.count(), 2, "expected 2 cmsgs");
 
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs()? {
             match cmsg {
                 ControlMessageOwned::ScmRights(fds) => {
                     assert_eq!(received_r, None, "already received fd");
@@ -1606,6 +1618,8 @@
     read(received_r.as_raw_fd(), &mut buf).unwrap();
     assert_eq!(&buf[..], b"world");
     close(received_r).unwrap();
+
+    Ok(())
 }
 
 // Test creating and using named unix domain sockets
@@ -1837,7 +1851,7 @@
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
 
-        let mut cmsgs = msg.cmsgs();
+        let mut cmsgs = msg.cmsgs().unwrap();
         if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next()
         {
             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
@@ -1929,11 +1943,11 @@
         assert!(!msg
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-        assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
+        assert_eq!(msg.cmsgs().unwrap().count(), 2, "expected 2 cmsgs");
 
         let mut rx_recvif = false;
         let mut rx_recvdstaddr = false;
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs().unwrap() {
             match cmsg {
                 ControlMessageOwned::Ipv4RecvIf(dl) => {
                     rx_recvif = true;
@@ -2027,10 +2041,10 @@
         assert!(!msg
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-        assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs");
+        assert_eq!(msg.cmsgs().unwrap().count(), 1, "expected 1 cmsgs");
 
         let mut rx_recvorigdstaddr = false;
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs().unwrap() {
             match cmsg {
                 ControlMessageOwned::Ipv4OrigDstAddr(addr) => {
                     rx_recvorigdstaddr = true;
@@ -2113,10 +2127,10 @@
         assert!(!msg
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
-        assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs");
+        assert_eq!(msg.cmsgs().unwrap().count(), 1, "expected 1 cmsgs");
 
         let mut rx_recvorigdstaddr = false;
-        for cmsg in msg.cmsgs() {
+        for cmsg in msg.cmsgs().unwrap() {
             match cmsg {
                 ControlMessageOwned::Ipv6OrigDstAddr(addr) => {
                     rx_recvorigdstaddr = true;
@@ -2214,7 +2228,7 @@
             .flags
             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
 
-        let mut cmsgs = msg.cmsgs();
+        let mut cmsgs = msg.cmsgs().unwrap();
         if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next()
         {
             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
@@ -2357,7 +2371,7 @@
         flags,
     )
     .unwrap();
-    let rtime = match r.cmsgs().next() {
+    let rtime = match r.cmsgs().unwrap().next() {
         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
         Some(_) => panic!("Unexpected control message"),
         None => panic!("No control message"),
@@ -2407,7 +2421,7 @@
     // Receive the message
     let mut buffer = vec![0u8; message.len()];
     let cmsgspace = nix::cmsg_space!(TimeSpec);
-    let mut iov = vec![[IoSliceMut::new(&mut buffer)]];
+    let mut iov = [[IoSliceMut::new(&mut buffer)]];
     let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
     let r: Vec<RecvMsg<()>> = recvmmsg(
         in_socket.as_raw_fd(),
@@ -2418,7 +2432,7 @@
     )
     .unwrap()
     .collect();
-    let rtime = match r[0].cmsgs().next() {
+    let rtime = match r[0].cmsgs().unwrap().next() {
         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
         Some(_) => panic!("Unexpected control message"),
         None => panic!("No control message"),
@@ -2508,7 +2522,7 @@
                 MsgFlags::MSG_DONTWAIT,
             ) {
                 Ok(r) => {
-                    drop_counter = match r.cmsgs().next() {
+                    drop_counter = match r.cmsgs().unwrap().next() {
                         Some(ControlMessageOwned::RxqOvfl(drop_counter)) => {
                             drop_counter
                         }
@@ -2687,7 +2701,7 @@
         assert_eq!(msg.address, Some(sock_addr));
 
         // Check for expected control message.
-        let ext_err = match msg.cmsgs().next() {
+        let ext_err = match msg.cmsgs().unwrap().next() {
             Some(cmsg) => testf(&cmsg),
             None => panic!("No control message"),
         };
@@ -2878,7 +2892,7 @@
         #[cfg(not(any(qemu, target_arch = "aarch64")))]
         let mut saw_time = false;
         let mut recvd = 0;
-        for cmsg in rmsg.cmsgs() {
+        for cmsg in rmsg.cmsgs().unwrap() {
             if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
                 let ts = timestamps.system;
 
diff --git a/crates/nix/test/sys/test_sockopt.rs b/crates/nix/test/sys/test_sockopt.rs
index a99d4e3..1da3f6a 100644
--- a/crates/nix/test/sys/test_sockopt.rs
+++ b/crates/nix/test/sys/test_sockopt.rs
@@ -828,3 +828,52 @@
         Err(err) => panic!("{err:?}"),
     }
 }
+
+#[test]
+#[cfg(apple_targets)]
+fn test_utun_ifname() {
+    skip_if_not_root!("test_utun_ifname");
+
+    use nix::sys::socket::connect;
+    use nix::sys::socket::SysControlAddr;
+
+    let fd = socket(
+        AddressFamily::System,
+        SockType::Datagram,
+        SockFlag::empty(),
+        SockProtocol::KextControl,
+    )
+    .unwrap();
+
+    let unit = 123;
+    let addr = SysControlAddr::from_name(
+        fd.as_raw_fd(),
+        "com.apple.net.utun_control",
+        unit,
+    )
+    .unwrap();
+
+    connect(fd.as_raw_fd(), &addr).unwrap();
+
+    let name = getsockopt(&fd, sockopt::UtunIfname)
+        .expect("getting UTUN_OPT_IFNAME on a utun interface should succeed");
+
+    let expected_name = format!("utun{}", unit - 1);
+    assert_eq!(name.into_string(), Ok(expected_name));
+}
+
+#[test]
+#[cfg(target_os = "freebsd")]
+fn test_reuseport_lb() {
+    let fd = socket(
+        AddressFamily::Inet6,
+        SockType::Datagram,
+        SockFlag::empty(),
+        None,
+    )
+    .unwrap();
+    setsockopt(&fd, sockopt::ReusePortLb, &false).unwrap();
+    assert!(!getsockopt(&fd, sockopt::ReusePortLb).unwrap());
+    setsockopt(&fd, sockopt::ReusePortLb, &true).unwrap();
+    assert!(getsockopt(&fd, sockopt::ReusePortLb).unwrap());
+}
diff --git a/crates/nix/test/sys/test_statfs.rs b/crates/nix/test/sys/test_statfs.rs
index 66b3f2c..ca7934e 100644
--- a/crates/nix/test/sys/test_statfs.rs
+++ b/crates/nix/test/sys/test_statfs.rs
@@ -44,7 +44,6 @@
 // The cast is not unnecessary on all platforms.
 #[allow(clippy::unnecessary_cast)]
 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);
 }
diff --git a/crates/nix/test/test.rs b/crates/nix/test/test.rs
index c723142..7401c95 100644
--- a/crates/nix/test/test.rs
+++ b/crates/nix/test/test.rs
@@ -3,7 +3,9 @@
 #[cfg_attr(not(any(target_os = "redox", target_os = "haiku")), macro_use)]
 extern crate nix;
 
+#[macro_use]
 mod common;
+mod mount;
 mod sys;
 #[cfg(not(target_os = "redox"))]
 mod test_dir;
@@ -11,20 +13,11 @@
 mod test_fcntl;
 #[cfg(linux_android)]
 mod test_kmod;
-#[cfg(target_os = "linux")]
-mod test_mount;
-#[cfg(any(
-    freebsdlike,
-    target_os = "fushsia",
-    target_os = "linux",
-    target_os = "netbsd"
-))]
+#[cfg(any(freebsdlike, target_os = "linux", target_os = "netbsd"))]
 mod test_mq;
 #[cfg(not(target_os = "redox"))]
 mod test_net;
 mod test_nix_path;
-#[cfg(target_os = "freebsd")]
-mod test_nmount;
 mod test_poll;
 #[cfg(not(any(
     target_os = "redox",
@@ -59,9 +52,10 @@
     }
 }
 
-/// Any test that creates child processes must grab this mutex, regardless
-/// of what it does with those children.
-pub static FORK_MTX: std::sync::Mutex<()> = std::sync::Mutex::new(());
+/// Any test that creates child processes or can be affected by child processes must grab this mutex, regardless
+/// of what it does with those children. It must hold the mutex until the
+/// child processes are waited upon.
+pub static FORK_MTX: Mutex<()> = Mutex::new(());
 /// 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.
diff --git a/crates/nix/test/test_fcntl.rs b/crates/nix/test/test_fcntl.rs
index 6572e8a..5d32076 100644
--- a/crates/nix/test/test_fcntl.rs
+++ b/crates/nix/test/test_fcntl.rs
@@ -4,12 +4,15 @@
 use nix::fcntl::{open, readlink, OFlag};
 #[cfg(not(target_os = "redox"))]
 use nix::fcntl::{openat, readlinkat, renameat};
+
+#[cfg(target_os = "linux")]
+use nix::fcntl::{openat2, OpenHow, ResolveFlag};
+
 #[cfg(all(
     target_os = "linux",
     target_env = "gnu",
     any(
         target_arch = "x86_64",
-        target_arch = "x32",
         target_arch = "powerpc",
         target_arch = "s390x"
     )
@@ -58,6 +61,64 @@
 }
 
 #[test]
+#[cfg(target_os = "linux")]
+// QEMU does not handle openat well enough to satisfy this test
+// https://gitlab.com/qemu-project/qemu/-/issues/829
+#[cfg_attr(qemu, ignore)]
+fn test_openat2() {
+    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 = openat2(
+        dirfd,
+        tmp.path().file_name().unwrap(),
+        OpenHow::new()
+            .flags(OFlag::O_RDONLY)
+            .mode(Mode::empty())
+            .resolve(ResolveFlag::RESOLVE_BENEATH),
+    )
+    .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]
+#[cfg(target_os = "linux")]
+// QEMU does not handle openat well enough to satisfy this test
+// https://gitlab.com/qemu-project/qemu/-/issues/829
+#[cfg_attr(qemu, ignore)]
+fn test_openat2_forbidden() {
+    let mut tmp = NamedTempFile::new().unwrap();
+    tmp.write_all(b"let me out").unwrap();
+
+    let dirfd =
+        open(tmp.path().parent().unwrap(), OFlag::empty(), Mode::empty())
+            .unwrap();
+
+    let escape_attempt =
+        tmp.path().parent().unwrap().join("../../../hello.txt");
+
+    let res = openat2(
+        dirfd,
+        &escape_attempt,
+        OpenHow::new()
+            .flags(OFlag::O_RDONLY)
+            .resolve(ResolveFlag::RESOLVE_BENEATH),
+    );
+    assert_eq!(Err(Errno::EXDEV), res);
+}
+
+#[test]
 #[cfg(not(target_os = "redox"))]
 fn test_renameat() {
     let old_dir = tempfile::tempdir().unwrap();
@@ -84,7 +145,6 @@
     target_env = "gnu",
     any(
         target_arch = "x86_64",
-        target_arch = "x32",
         target_arch = "powerpc",
         target_arch = "s390x"
     )
@@ -128,7 +188,6 @@
     target_env = "gnu",
     any(
         target_arch = "x86_64",
-        target_arch = "x32",
         target_arch = "powerpc",
         target_arch = "s390x"
     )
@@ -176,7 +235,6 @@
     target_env = "gnu",
     any(
         target_arch = "x86_64",
-        target_arch = "x32",
         target_arch = "powerpc",
         target_arch = "s390x"
     )
@@ -295,15 +353,9 @@
 
         let (rd, wr) = pipe().unwrap();
         let mut offset: loff_t = 5;
-        let res = splice(
-            tmp.as_raw_fd(),
-            Some(&mut offset),
-            wr.as_raw_fd(),
-            None,
-            2,
-            SpliceFFlags::empty(),
-        )
-        .unwrap();
+        let res =
+            splice(tmp, Some(&mut offset), wr, None, 2, SpliceFFlags::empty())
+                .unwrap();
 
         assert_eq!(2, res);
 
@@ -319,9 +371,8 @@
         let (rd2, wr2) = pipe().unwrap();
 
         write(wr1, b"abc").unwrap();
-        let res =
-            tee(rd1.as_raw_fd(), wr2.as_raw_fd(), 2, SpliceFFlags::empty())
-                .unwrap();
+        let res = tee(rd1.try_clone().unwrap(), wr2, 2, SpliceFFlags::empty())
+            .unwrap();
 
         assert_eq!(2, res);
 
@@ -344,8 +395,7 @@
         let buf2 = b"defghi";
         let iovecs = [IoSlice::new(&buf1[0..3]), IoSlice::new(&buf2[0..3])];
 
-        let res = vmsplice(wr.as_raw_fd(), &iovecs[..], SpliceFFlags::empty())
-            .unwrap();
+        let res = vmsplice(wr, &iovecs[..], SpliceFFlags::empty()).unwrap();
 
         assert_eq!(6, res);
 
@@ -636,7 +686,7 @@
 
     /// Verify that `Flock::lock()` correctly obtains a lock, and subsequently unlocks upon drop.
     #[test]
-    fn verify_lock_and_drop() {
+    fn lock_and_drop() {
         // Get 2 `File` handles to same underlying file.
         let file1 = NamedTempFile::new().unwrap();
         let file2 = file1.reopen().unwrap();
@@ -660,9 +710,32 @@
         }
     }
 
+    /// An exclusive lock can be downgraded
+    #[test]
+    fn downgrade() {
+        let file1 = NamedTempFile::new().unwrap();
+        let file2 = file1.reopen().unwrap();
+        let file1 = file1.into_file();
+
+        // Lock first handle
+        let lock1 = Flock::lock(file1, FlockArg::LockExclusive).unwrap();
+
+        // Attempt to lock second handle
+        let file2 = Flock::lock(file2, FlockArg::LockSharedNonblock)
+            .unwrap_err()
+            .0;
+
+        // Downgrade the lock
+        lock1.relock(FlockArg::LockShared).unwrap();
+
+        // Attempt to lock second handle again (but successfully)
+        Flock::lock(file2, FlockArg::LockSharedNonblock)
+            .expect("Expected locking to be successful.");
+    }
+
     /// Verify that `Flock::unlock()` correctly obtains unlocks.
     #[test]
-    fn verify_unlock() {
+    fn unlock() {
         // Get 2 `File` handles to same underlying file.
         let file1 = NamedTempFile::new().unwrap();
         let file2 = file1.reopen().unwrap();
@@ -679,4 +752,29 @@
             panic!("Expected locking to be successful.");
         }
     }
+
+    /// A shared lock can be upgraded
+    #[test]
+    fn upgrade() {
+        let file1 = NamedTempFile::new().unwrap();
+        let file2 = file1.reopen().unwrap();
+        let file3 = file1.reopen().unwrap();
+        let file1 = file1.into_file();
+
+        // Lock first handle
+        let lock1 = Flock::lock(file1, FlockArg::LockShared).unwrap();
+
+        // Attempt to lock second handle
+        {
+            Flock::lock(file2, FlockArg::LockSharedNonblock)
+                .expect("Locking should've succeeded");
+        }
+
+        // Upgrade the lock
+        lock1.relock(FlockArg::LockExclusive).unwrap();
+
+        // Acquiring an additional shared lock should fail
+        Flock::lock(file3, FlockArg::LockSharedNonblock)
+            .expect_err("Should not have been able to lock the file");
+    }
 }
diff --git a/crates/nix/test/test_net.rs b/crates/nix/test/test_net.rs
index faba850..46a3efd 100644
--- a/crates/nix/test/test_net.rs
+++ b/crates/nix/test/test_net.rs
@@ -13,3 +13,14 @@
 fn test_if_nametoindex() {
     if_nametoindex(LOOPBACK).expect("assertion failed");
 }
+
+#[test]
+fn test_if_indextoname() {
+    let loopback_index = if_nametoindex(LOOPBACK).expect("assertion failed");
+    assert_eq!(
+        if_indextoname(loopback_index)
+            .expect("assertion failed")
+            .as_bytes(),
+        LOOPBACK
+    );
+}
diff --git a/crates/nix/test/test_pty.rs b/crates/nix/test/test_pty.rs
index 368ec12..bc618e0 100644
--- a/crates/nix/test/test_pty.rs
+++ b/crates/nix/test/test_pty.rs
@@ -8,6 +8,7 @@
 use nix::pty::*;
 use nix::sys::stat;
 use nix::sys::termios::*;
+use nix::sys::wait::WaitStatus;
 use nix::unistd::{pause, write};
 
 /// Test equivalence of `ptsname` and `ptsname_r`
@@ -16,9 +17,10 @@
 fn test_ptsname_equivalence() {
     let _m = crate::PTSNAME_MTX.lock();
 
-    // Open a new PTTY master
+    // Open a new PTY master
     let master_fd = posix_openpt(OFlag::O_RDWR).unwrap();
     assert!(master_fd.as_raw_fd() > 0);
+    assert!(master_fd.as_fd().as_raw_fd() == master_fd.as_raw_fd());
 
     // Get the name of the slave
     let slave_name = unsafe { ptsname(&master_fd) }.unwrap();
@@ -247,7 +249,6 @@
 fn test_forkpty() {
     use nix::sys::signal::*;
     use nix::sys::wait::wait;
-    use nix::unistd::ForkResult::*;
     // forkpty calls openpty which uses ptname(3) internally.
     let _m0 = crate::PTSNAME_MTX.lock();
     // forkpty spawns a child process
@@ -255,21 +256,22 @@
 
     let string = "naninani\n";
     let echoed_string = "naninani\r\n";
-    let pty = unsafe { forkpty(None, None).unwrap() };
-    match pty.fork_result {
-        Child => {
+    let res = unsafe { forkpty(None, None).unwrap() };
+    match res {
+        ForkptyResult::Child => {
             write(stdout(), string.as_bytes()).unwrap();
             pause(); // we need the child to stay alive until the parent calls read
             unsafe {
                 _exit(0);
             }
         }
-        Parent { child } => {
+        ForkptyResult::Parent { child, master } => {
             let mut buf = [0u8; 10];
             assert!(child.as_raw() > 0);
-            crate::read_exact(&pty.master, &mut buf);
+            crate::read_exact(&master, &mut buf);
             kill(child, SIGTERM).unwrap();
-            wait().unwrap(); // keep other tests using generic wait from getting our child
+            let status = wait().unwrap(); // keep other tests using generic wait from getting our child
+            assert_eq!(status, WaitStatus::Signaled(child, SIGTERM, false));
             assert_eq!(&buf, echoed_string.as_bytes());
         }
     }
diff --git a/crates/nix/test/test_unistd.rs b/crates/nix/test/test_unistd.rs
index aa2e5e5..6ccf59f 100644
--- a/crates/nix/test/test_unistd.rs
+++ b/crates/nix/test/test_unistd.rs
@@ -313,12 +313,15 @@
     // 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();
+    let mut group_list = getgrouplist(&user, group).unwrap();
     assert!(group_list.contains(&group));
 
     initgroups(&user, group).unwrap();
 
-    let new_groups = getgroups().unwrap();
+    let mut new_groups = getgroups().unwrap();
+
+    new_groups.sort_by_key(|gid| gid.as_raw());
+    group_list.sort_by_key(|gid| gid.as_raw());
     assert_eq!(new_groups, group_list);
 
     // Revert back to the old groups
diff --git a/pseudo_crate/Cargo.lock b/pseudo_crate/Cargo.lock
index 11a543d..a5ad1ee 100644
--- a/pseudo_crate/Cargo.lock
+++ b/pseudo_crate/Cargo.lock
@@ -327,7 +327,7 @@
  "mockall_derive",
  "moveit",
  "named-lock",
- "nix 0.28.0",
+ "nix 0.29.0",
  "no-panic",
  "nom",
  "num-bigint",
diff --git a/pseudo_crate/Cargo.toml b/pseudo_crate/Cargo.toml
index e9af4eb..52dc8fe 100644
--- a/pseudo_crate/Cargo.toml
+++ b/pseudo_crate/Cargo.toml
@@ -237,7 +237,7 @@
 mockall_derive = "=0.13.1"
 moveit = "=0.6.0"
 named-lock = "=0.3.0"
-nix = "=0.28.0"
+nix = "=0.29.0"
 no-panic = "=0.1.33"
 nom = "=7.1.3"
 num-bigint = "=0.4.6"