cap-std-3.4.4/.cargo_vcs_info.json0000644000000001450000000000100123770ustar { "git": { "sha1": "54716a1d87e3141172303a28bdfd23e42e1037cf" }, "path_in_vcs": "cap-std" }cap-std-3.4.4/COPYRIGHT000064400000000000000000000015311046102023000124620ustar 00000000000000Short version for non-lawyers: `cap-std` is triple-licensed under Apache 2.0 with the LLVM Exception, Apache 2.0, and MIT terms. Longer version: Copyrights in the `cap-std` project are retained by their contributors. No copyright assignment is required to contribute to the `cap-std` project. Some files include code derived from Rust's `libstd`; see the comments in the code for details. Except as otherwise noted (below and/or in individual files), `cap-std` is licensed under: - the Apache License, Version 2.0, with the LLVM Exception or - the Apache License, Version 2.0 or , - or the MIT license or , at your option. cap-std-3.4.4/Cargo.lock0000644000000143600000000000100103560ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "ambient-authority" version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" [[package]] name = "arf-strings" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0838b36b21e39005854bd3d7d6cea4ac759e9d7e629bc6c9981e8aa0b567b8b9" dependencies = [ "rustix", ] [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "camino" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" [[package]] name = "cap-primitives" version = "3.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0a1e394ed14f39f8bc26f59d4c0c010dbe7f0a1b9bafff451b1f98b67c8af62a" dependencies = [ "ambient-authority", "fs-set-times", "io-extras", "io-lifetimes", "ipnet", "maybe-owned", "rustix", "rustix-linux-procfs", "windows-sys", "winx", ] [[package]] name = "cap-std" version = "3.4.4" dependencies = [ "arf-strings", "camino", "cap-primitives", "io-extras", "io-lifetimes", "rustix", ] [[package]] name = "errno" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys", ] [[package]] name = "fs-set-times" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", "rustix", "windows-sys", ] [[package]] name = "io-extras" version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2285ddfe3054097ef4b2fe909ef8c3bcd1ea52a8f0d274416caebeef39f04a65" dependencies = [ "io-lifetimes", "windows-sys", ] [[package]] name = "io-lifetimes" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06432fb54d3be7964ecd3649233cddf80db2832f47fec34c01f65b3d9d774983" [[package]] name = "ipnet" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "libc" version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "linux-raw-sys" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "maybe-owned" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "once_cell" version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "rustix" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "rustix-linux-procfs" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", "rustix", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winx" version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d" dependencies = [ "bitflags", "windows-sys", ] cap-std-3.4.4/Cargo.toml0000644000000032120000000000100103730ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "cap-std" version = "3.4.4" authors = [ "Dan Gohman ", "Jakub Konka ", ] build = "build.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Capability-based version of the Rust standard library" readme = "README.md" keywords = [ "std", "api", "network", "file", ] categories = [ "filesystem", "network-programming", ] license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" repository = "https://github.com/bytecodealliance/cap-std" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg=docsrs"] [features] arf_strings = [ "fs_utf8", "arf-strings", ] default = [] fs_utf8 = ["camino"] [lib] name = "cap_std" path = "src/lib.rs" [dependencies.arf-strings] version = "0.7.0" optional = true [dependencies.camino] version = "1.0.5" optional = true [dependencies.cap-primitives] version = "^3.4.4" [dependencies.io-extras] version = "0.18.3" [dependencies.io-lifetimes] version = "2.0.0" default-features = false [target."cfg(not(windows))".dependencies.rustix] version = "1.0.0" features = ["fs"] cap-std-3.4.4/Cargo.toml.orig000064400000000000000000000017241046102023000140620ustar 00000000000000[package] name = "cap-std" version = "3.4.4" description = "Capability-based version of the Rust standard library" authors = [ "Dan Gohman ", "Jakub Konka ", ] license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" keywords = ["std", "api", "network", "file"] categories = ["filesystem", "network-programming"] repository = "https://github.com/bytecodealliance/cap-std" edition = "2021" [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg=docsrs"] [dependencies] arf-strings = { version = "0.7.0", optional = true } cap-primitives = { path = "../cap-primitives", version = "^3.4.4" } io-extras = "0.18.3" io-lifetimes = { version = "2.0.0", default-features = false } camino = { version = "1.0.5", optional = true } [target.'cfg(not(windows))'.dependencies] rustix = { version = "1.0.0", features = ["fs"] } [features] default = [] fs_utf8 = ["camino"] arf_strings = ["fs_utf8", "arf-strings"] cap-std-3.4.4/LICENSE-APACHE000064400000000000000000000251371046102023000131230ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. cap-std-3.4.4/LICENSE-Apache-2.0_WITH_LLVM-exception000064400000000000000000000277231046102023000173440ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --- LLVM Exceptions to the Apache 2.0 License ---- As an exception, if, as a result of your compiling your source code, portions of this Software are embedded into an Object form of such source code, you may redistribute such embedded portions in such Object form without complying with the conditions of Sections 4(a), 4(b) and 4(d) of the License. In addition, if you combine or link compiled forms of this Software with software that is licensed under the GPLv2 ("Combined Software") and if a court of competent jurisdiction determines that the patent provision (Section 3), the indemnity provision (Section 9) or other Section of the License conflicts with the conditions of the GPLv2, you may retroactively and prospectively choose to deem waived or otherwise exclude such Section(s) of the License, but only in their entirety and only with respect to the Combined Software. cap-std-3.4.4/LICENSE-MIT000064400000000000000000000017771046102023000126370ustar 00000000000000Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. cap-std-3.4.4/README.md000064400000000000000000000051741046102023000124550ustar 00000000000000

cap-std

Capability-based version of the Rust standard library

Github Actions CI Status crates.io page docs.rs docs

This crate provides a capability-based version of [`std`], providing sandboxed filesystem, networking, and clock APIs. See the [toplevel README.md] for more information about sandboxing using capability-based security. The filesystem module [`cap_std::fs`], the networking module [`cap_std::net`], and the time module [`cap_std::time`] currently support Linux, macOS, FreeBSD, and Windows. WASI support is in development, though not yet usable. Example usage of [`Dir`] for filesystem access: ```rust use std::io; use cap_std::fs::Dir; /// Open files relative to `dir`. fn dir_example(dir: &Dir) -> io::Result<()> { // This works (assuming symlinks don't lead outside of `dir`). let file = dir.open("the/thing.txt")?; // This fails, since `..` leads outside of `dir`. let hidden = dir.open("../hidden.txt")?; // This fails, as creating symlinks to absolute paths is not permitted. dir.symlink("/hidden.txt", "misdirection.txt")?; // However, even if the symlink had succeeded, or, if there is a // pre-existing symlink to an absolute directory, following a // symlink which would lead outside the sandbox also fails. let secret = dir.open("misdirection.txt")?; Ok(()) } ``` Example usage of [`Pool`] for network access: ```rust use std::io; use cap_std::net::Pool; /// Open network addresses within `pool`. fn pool_example(pool: &Pool) -> io::Result<()> { // Connect to an address. This succeeds only if the given address and // port are present in `pool`. let stream = pool.connect_tcp_stream("localhost:3333")?; Ok(()) } ``` [`std`]: https://doc.rust-lang.org/std/ [toplevel README.md]: https://github.com/bytecodealliance/cap-std/blob/main/README.md [`cap_std::fs`]: https://docs.rs/cap-std/latest/cap_std/fs/index.html [`cap_std::net`]: https://docs.rs/cap-std/latest/cap_std/net/index.html [`cap_std::time`]: https://docs.rs/cap-std/latest/cap_std/time/index.html [`Pool`]: https://docs.rs/cap-std/latest/cap_std/net/struct.Pool.html [`Dir`]: https://docs.rs/cap-std/latest/cap_std/fs/struct.Dir.html cap-std-3.4.4/build.rs000064400000000000000000000054041046102023000126370ustar 00000000000000use std::env::var; use std::io::Write; fn main() { use_feature_or_nothing("can_vector"); // https://github.com/rust-lang/rust/issues/69941 use_feature_or_nothing("write_all_vectored"); // https://github.com/rust-lang/rust/issues/70436 use_feature_or_nothing("windows_file_type_ext"); // Cfgs that users may set. println!("cargo:rustc-check-cfg=cfg(io_lifetimes_use_std)"); // Don't rerun this on changes other than build.rs, as we only depend on // the rustc version. println!("cargo:rerun-if-changed=build.rs"); } fn use_feature_or_nothing(feature: &str) { if has_feature(feature) { use_feature(feature); } println!("cargo:rustc-check-cfg=cfg({})", feature); } fn use_feature(feature: &str) { println!("cargo:rustc-cfg={}", feature); } /// Test whether the rustc at `var("RUSTC")` supports the given feature. fn has_feature(feature: &str) -> bool { can_compile(&format!( "#![allow(stable_features)]\n#![feature({})]", feature )) } /// Test whether the rustc at `var("RUSTC")` can compile the given code. fn can_compile>(test: T) -> bool { use std::process::Stdio; let rustc = var("RUSTC").unwrap(); let target = var("TARGET").unwrap(); // Use `RUSTC_WRAPPER` if it's set, unless it's set to an empty string, // as documented [here]. // [here]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads let wrapper = var("RUSTC_WRAPPER") .ok() .and_then(|w| if w.is_empty() { None } else { Some(w) }); let mut cmd = if let Some(wrapper) = wrapper { let mut cmd = std::process::Command::new(wrapper); // The wrapper's first argument is supposed to be the path to rustc. cmd.arg(rustc); cmd } else { std::process::Command::new(rustc) }; cmd.arg("--crate-type=rlib") // Don't require `main`. .arg("--emit=metadata") // Do as little as possible but still parse. .arg("--target") .arg(target) .arg("-o") .arg("-") .stdout(Stdio::null()); // We don't care about the output (only whether it builds or not) // If Cargo wants to set RUSTFLAGS, use that. if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { if !rustflags.is_empty() { for arg in rustflags.split('\x1f') { cmd.arg(arg); } } } let mut child = cmd .arg("-") // Read from stdin. .stdin(Stdio::piped()) // Stdin is a pipe. .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. .spawn() .unwrap(); writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); child.wait().unwrap().success() } cap-std-3.4.4/src/fs/dir.rs000064400000000000000000000743401046102023000135220ustar 00000000000000#[cfg(target_os = "wasi")] use crate::fs::OpenOptionsExt; use crate::fs::{DirBuilder, File, Metadata, OpenOptions, ReadDir}; #[cfg(feature = "fs_utf8")] use crate::fs_utf8::Dir as DirUtf8; #[cfg(unix)] use crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream}; #[cfg(not(target_os = "wasi"))] use cap_primitives::fs::set_permissions; use cap_primitives::fs::{ canonicalize, copy, create_dir, hard_link, open, open_ambient_dir, open_dir, open_parent_dir, read_base_dir, read_dir, read_link, read_link_contents, remove_dir, remove_dir_all, remove_file, remove_open_dir, remove_open_dir_all, rename, stat, DirOptions, FollowSymlinks, Permissions, }; use cap_primitives::AmbientAuthority; use io_lifetimes::AsFilelike; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; use std::io::{self, Read, Write}; use std::path::{Path, PathBuf}; use std::{fmt, fs}; #[cfg(not(windows))] use { cap_primitives::fs::{symlink, symlink_contents}, io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, }; #[cfg(windows)] use { cap_primitives::fs::{symlink_dir, symlink_file}, io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, }; /// A reference to an open directory on a filesystem. /// /// This does not directly correspond to anything in `std`, however its methods /// correspond to the [functions in `std::fs`] and the constructor methods for /// [`std::fs::File`]. /// /// Unlike `std::fs`, this API's `canonicalize` returns a relative path since /// absolute paths don't interoperate well with the capability model. /// /// [functions in `std::fs`]: https://doc.rust-lang.org/std/fs/index.html#functions pub struct Dir { std_file: fs::File, } impl Dir { /// Constructs a new instance of `Self` from the given [`std::fs::File`]. /// /// To prevent race conditions on Windows, the file must be opened without /// `FILE_SHARE_DELETE`. /// /// This grants access the resources the `std::fs::File` instance already /// has access to. #[inline] pub fn from_std_file(std_file: fs::File) -> Self { Self { std_file } } /// Consumes `self` and returns a [`std::fs::File`]. #[inline] pub fn into_std_file(self) -> fs::File { self.std_file } /// Attempts to open a file in read-only mode. /// /// This corresponds to [`std::fs::File::open`], but only accesses paths /// relative to `self`. #[inline] pub fn open>(&self, path: P) -> io::Result { self.open_with(path, OpenOptions::new().read(true)) } /// Opens a file at `path` with the options specified by `options`. /// /// This corresponds to [`std::fs::OpenOptions::open`]. /// /// Instead of being a method on `OpenOptions`, this is a method on `Dir`, /// and it only accesses paths relative to `self`. #[inline] pub fn open_with>(&self, path: P, options: &OpenOptions) -> io::Result { self._open_with(path.as_ref(), options) } #[cfg(not(target_os = "wasi"))] #[inline] fn _open_with(&self, path: &Path, options: &OpenOptions) -> io::Result { let dir = open(&self.std_file, path, options)?; Ok(File::from_std(dir)) } #[cfg(target_os = "wasi")] #[inline] fn _open_with(&self, path: &Path, options: &OpenOptions) -> io::Result { let dir = options.open_at(&self.std_file, path)?; Ok(File::from_std(dir)) } /// Attempts to open a directory. #[inline] pub fn open_dir>(&self, path: P) -> io::Result { let dir = open_dir(&self.std_file, path.as_ref())?; Ok(Self::from_std_file(dir)) } /// Attempts to open a directory, verifying UTF-8. /// /// This is equivalent to [`crate::fs_utf8::Dir::open_dir`]. #[inline] #[cfg(feature = "fs_utf8")] pub fn open_dir_utf8>(&self, path: P) -> io::Result { let path = crate::fs_utf8::from_utf8(path.as_ref())?; self.open_dir(path).map(DirUtf8::from_cap_std) } /// Creates a new, empty directory at the provided path. /// /// This corresponds to [`std::fs::create_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn create_dir>(&self, path: P) -> io::Result<()> { self._create_dir_one(path.as_ref(), &DirOptions::new()) } /// Recursively create a directory and all of its parent components if they /// are missing. /// /// This corresponds to [`std::fs::create_dir_all`], but only accesses /// paths relative to `self`. #[inline] pub fn create_dir_all>(&self, path: P) -> io::Result<()> { self._create_dir_all(path.as_ref(), &DirOptions::new()) } /// Creates the specified directory with the options configured in this /// builder. /// /// This corresponds to [`std::fs::DirBuilder::create`]. #[cfg(not(target_os = "wasi"))] #[inline] pub fn create_dir_with>( &self, path: P, dir_builder: &DirBuilder, ) -> io::Result<()> { let options = dir_builder.options(); if dir_builder.is_recursive() { self._create_dir_all(path.as_ref(), options) } else { self._create_dir_one(path.as_ref(), options) } } fn _create_dir_one(&self, path: &Path, dir_options: &DirOptions) -> io::Result<()> { create_dir(&self.std_file, path, dir_options) } fn _create_dir_all(&self, path: &Path, dir_options: &DirOptions) -> io::Result<()> { if path == Path::new("") { return Ok(()); } match self._create_dir_one(path, dir_options) { Ok(()) => return Ok(()), Err(ref e) if e.kind() == io::ErrorKind::NotFound => {} Err(_) if self.is_dir(path) => return Ok(()), Err(e) => return Err(e), } match path.parent() { Some(p) => self._create_dir_all(p, dir_options)?, None => { return Err(io::Error::new( io::ErrorKind::Other, "failed to create whole tree", )) } } match self._create_dir_one(path, dir_options) { Ok(()) => Ok(()), Err(_) if self.is_dir(path) => Ok(()), Err(e) => Err(e), } } /// Opens a file in write-only mode. /// /// This corresponds to [`std::fs::File::create`], but only accesses paths /// relative to `self`. #[inline] pub fn create>(&self, path: P) -> io::Result { self.open_with( path, OpenOptions::new().write(true).create(true).truncate(true), ) } /// Returns the canonical form of a path with all intermediate components /// normalized and symbolic links resolved. /// /// This corresponds to [`std::fs::canonicalize`], but instead of returning /// an absolute path, returns a path relative to the directory /// represented by `self`. #[inline] pub fn canonicalize>(&self, path: P) -> io::Result { canonicalize(&self.std_file, path.as_ref()) } /// Copies the contents of one file to another. This function will also /// copy the permission bits of the original file to the destination /// file. /// /// This corresponds to [`std::fs::copy`], but only accesses paths /// relative to `self`. #[inline] pub fn copy, Q: AsRef>( &self, from: P, to_dir: &Self, to: Q, ) -> io::Result { copy(&self.std_file, from.as_ref(), &to_dir.std_file, to.as_ref()) } /// Creates a new hard link on a filesystem. /// /// This corresponds to [`std::fs::hard_link`], but only accesses paths /// relative to `self`. #[inline] pub fn hard_link, Q: AsRef>( &self, src: P, dst_dir: &Self, dst: Q, ) -> io::Result<()> { hard_link( &self.std_file, src.as_ref(), &dst_dir.std_file, dst.as_ref(), ) } /// Given a path, query the file system to get information about a file, /// directory, etc. /// /// This corresponds to [`std::fs::metadata`], but only accesses paths /// relative to `self`. #[inline] pub fn metadata>(&self, path: P) -> io::Result { stat(&self.std_file, path.as_ref(), FollowSymlinks::Yes) } /// Queries metadata about the underlying directory. /// /// This is similar to [`std::fs::File::metadata`], but for `Dir` rather /// than for `File`. #[inline] pub fn dir_metadata(&self) -> io::Result { Metadata::from_file(&self.std_file) } /// Returns an iterator over the entries within `self`. #[inline] pub fn entries(&self) -> io::Result { read_base_dir(&self.std_file).map(|inner| ReadDir { inner }) } /// Returns an iterator over UTF-8 entries within `self`. /// /// Equivalent to [`crate::fs_utf8::Dir::read_dir`]. #[inline] #[cfg(feature = "fs_utf8")] pub fn entries_utf8(&self) -> io::Result { self.entries().map(crate::fs_utf8::ReadDir::from_cap_std) } /// Returns an iterator over the entries within a directory. /// /// This corresponds to [`std::fs::read_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn read_dir>(&self, path: P) -> io::Result { read_dir(&self.std_file, path.as_ref()).map(|inner| ReadDir { inner }) } /// Read the entire contents of a file into a bytes vector. /// /// This corresponds to [`std::fs::read`], but only accesses paths /// relative to `self`. #[inline] pub fn read>(&self, path: P) -> io::Result> { let mut file = self.open(path)?; let mut bytes = Vec::with_capacity(initial_buffer_size(&file)); file.read_to_end(&mut bytes)?; Ok(bytes) } /// Reads a symbolic link, returning the file that the link points to. /// /// This corresponds to [`std::fs::read_link`], but only accesses paths /// relative to `self`. Unlike [`read_link_contents`], this method considers it an error if /// the link's target is an absolute path. #[inline] pub fn read_link>(&self, path: P) -> io::Result { read_link(&self.std_file, path.as_ref()) } /// Reads a symbolic link, returning the file that the link points to. /// /// This corresponds to [`std::fs::read_link`]. but only accesses paths /// relative to `self`. #[inline] pub fn read_link_contents>(&self, path: P) -> io::Result { read_link_contents(&self.std_file, path.as_ref()) } /// Read the entire contents of a file into a string. /// /// This corresponds to [`std::fs::read_to_string`], but only accesses /// paths relative to `self`. #[inline] pub fn read_to_string>(&self, path: P) -> io::Result { let mut s = String::new(); self.open(path)?.read_to_string(&mut s)?; Ok(s) } /// Removes an empty directory. /// /// This corresponds to [`std::fs::remove_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn remove_dir>(&self, path: P) -> io::Result<()> { remove_dir(&self.std_file, path.as_ref()) } /// Removes a directory at this path, after removing all its contents. Use /// carefully! /// /// This corresponds to [`std::fs::remove_dir_all`], but only accesses /// paths relative to `self`. #[inline] pub fn remove_dir_all>(&self, path: P) -> io::Result<()> { remove_dir_all(&self.std_file, path.as_ref()) } /// Remove the directory referenced by `self` and consume `self`. /// /// Even though this implementation works in terms of handles as much as /// possible, removal is not guaranteed to be atomic with respect to a /// concurrent rename of the directory. #[inline] pub fn remove_open_dir(self) -> io::Result<()> { remove_open_dir(self.std_file) } /// Removes the directory referenced by `self`, after removing all its /// contents, and consume `self`. Use carefully! /// /// Even though this implementation works in terms of handles as much as /// possible, removal is not guaranteed to be atomic with respect to a /// concurrent rename of the directory. #[inline] pub fn remove_open_dir_all(self) -> io::Result<()> { remove_open_dir_all(self.std_file) } /// Removes a file from a filesystem. /// /// This corresponds to [`std::fs::remove_file`], but only accesses paths /// relative to `self`. #[inline] pub fn remove_file>(&self, path: P) -> io::Result<()> { remove_file(&self.std_file, path.as_ref()) } /// Rename a file or directory to a new name, replacing the original file /// if to already exists. /// /// This corresponds to [`std::fs::rename`], but only accesses paths /// relative to `self`. #[inline] pub fn rename, Q: AsRef>( &self, from: P, to_dir: &Self, to: Q, ) -> io::Result<()> { rename(&self.std_file, from.as_ref(), &to_dir.std_file, to.as_ref()) } /// Changes the permissions found on a file or a directory. /// /// This corresponds to [`std::fs::set_permissions`], but only accesses /// paths relative to `self`. Also, on some platforms, this function /// may fail if the file or directory cannot be opened for reading or /// writing first. #[cfg(not(target_os = "wasi"))] #[inline] pub fn set_permissions>(&self, path: P, perm: Permissions) -> io::Result<()> { set_permissions(&self.std_file, path.as_ref(), perm) } /// Query the metadata about a file without following symlinks. /// /// This corresponds to [`std::fs::symlink_metadata`], but only accesses /// paths relative to `self`. #[inline] pub fn symlink_metadata>(&self, path: P) -> io::Result { stat(&self.std_file, path.as_ref(), FollowSymlinks::No) } /// Write a slice as the entire contents of a file. /// /// This corresponds to [`std::fs::write`], but only accesses paths /// relative to `self`. #[inline] pub fn write, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> { let mut file = self.create(path)?; file.write_all(contents.as_ref()) } /// Creates a new symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::unix::fs::symlink`], but only accesses /// paths relative to `self`. /// /// Unlike [`symlink_contents`] this method will return an error if `original` is an absolute /// path. /// /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html #[cfg(not(windows))] #[inline] pub fn symlink, Q: AsRef>(&self, original: P, link: Q) -> io::Result<()> { symlink(original.as_ref(), &self.std_file, link.as_ref()) } /// Creates a new symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::unix::fs::symlink`], but only accesses /// paths relative to `self`. /// /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html #[cfg(not(windows))] #[inline] pub fn symlink_contents, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { symlink_contents(original.as_ref(), &self.std_file, link.as_ref()) } /// Creates a new file symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::windows::fs::symlink_file`], but only /// accesses paths relative to `self`. /// /// [`std::os::windows::fs::symlink_file`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html #[cfg(windows)] #[inline] pub fn symlink_file, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { symlink_file(original.as_ref(), &self.std_file, link.as_ref()) } /// Creates a new directory symlink on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::windows::fs::symlink_dir`], but only /// accesses paths relative to `self`. /// /// [`std::os::windows::fs::symlink_dir`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html #[cfg(windows)] #[inline] pub fn symlink_dir, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { symlink_dir(original.as_ref(), &self.std_file, link.as_ref()) } /// Creates a new `UnixListener` bound to the specified socket. /// /// This corresponds to [`std::os::unix::net::UnixListener::bind`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixListener::bind`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.bind #[doc(alias = "bind")] #[cfg(unix)] #[inline] pub fn bind_unix_listener>(&self, path: P) -> io::Result { todo!( "Dir::bind_unix_listener({:?}, {})", self.std_file, path.as_ref().display() ) } /// Connects to the socket named by path. /// /// This corresponds to [`std::os::unix::net::UnixStream::connect`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixStream::connect`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.connect #[doc(alias = "connect")] #[cfg(unix)] #[inline] pub fn connect_unix_stream>(&self, path: P) -> io::Result { todo!( "Dir::connect_unix_stream({:?}, {})", self.std_file, path.as_ref().display() ) } /// Creates a Unix datagram socket bound to the given path. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::bind`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::bind`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.bind #[doc(alias = "bind")] #[cfg(unix)] #[inline] pub fn bind_unix_datagram>(&self, path: P) -> io::Result { todo!( "Dir::bind_unix_datagram({:?}, {})", self.std_file, path.as_ref().display() ) } /// Connects the socket to the specified address. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::connect`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::connect`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.connect #[doc(alias = "connect")] #[cfg(unix)] #[inline] pub fn connect_unix_datagram>( &self, _unix_datagram: &UnixDatagram, path: P, ) -> io::Result<()> { todo!( "Dir::connect_unix_datagram({:?}, {})", self.std_file, path.as_ref().display() ) } /// Sends data on the socket to the specified address. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::send_to`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::send_to`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.send_to #[doc(alias = "send_to")] #[cfg(unix)] #[inline] pub fn send_to_unix_datagram_addr>( &self, _unix_datagram: &UnixDatagram, buf: &[u8], path: P, ) -> io::Result { todo!( "Dir::send_to_unix_datagram_addr({:?}, {:?}, {})", self.std_file, buf, path.as_ref().display() ) } /// Creates a new `Dir` instance that shares the same underlying file /// handle as the existing `Dir` instance. #[inline] pub fn try_clone(&self) -> io::Result { let dir = self.std_file.try_clone()?; Ok(Self::from_std_file(dir)) } /// Returns `true` if the path points at an existing entity. /// /// This corresponds to [`std::path::Path::exists`], but only /// accesses paths relative to `self`. #[inline] pub fn exists>(&self, path: P) -> bool { self.metadata(path).is_ok() } /// Returns `true` if the path points at an existing entity. /// /// This corresponds to [`std::fs::try_exists`], but only /// accesses paths relative to `self`. /// /// # API correspondence with `std` /// /// This API is not yet stable in `std`, but is likely to be. For more /// information, see the [tracker issue](https://github.com/rust-lang/rust/issues/83186). #[inline] pub fn try_exists>(&self, path: P) -> io::Result { match self.metadata(path) { Ok(_) => Ok(true), Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), Err(error) => Err(error), } } /// Returns `true` if the path exists on disk and is pointing at a regular /// file. /// /// This corresponds to [`std::path::Path::is_file`], but only /// accesses paths relative to `self`. #[inline] pub fn is_file>(&self, path: P) -> bool { self.metadata(path).map(|m| m.is_file()).unwrap_or(false) } /// Checks if `path` is a directory. /// /// This is similar to [`std::path::Path::is_dir`] in that it checks if /// `path` relative to `Dir` is a directory. This function will /// traverse symbolic links to query information about the destination /// file. In case of broken symbolic links, this will return `false`. #[inline] pub fn is_dir>(&self, path: P) -> bool { self.metadata(path).map(|m| m.is_dir()).unwrap_or(false) } /// Constructs a new instance of `Self` by opening the given path as a /// directory using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient_dir>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let dir = open_ambient_dir(path.as_ref(), ambient_authority)?; Ok(Self::from_std_file(dir)) } /// Constructs a new instance of `Self` by opening the parent directory /// (aka "..") of `self`, using the host process' ambient authority. /// /// # Ambient Authority /// /// This function accesses a directory outside of the `self` subtree. #[inline] pub fn open_parent_dir(&self, ambient_authority: AmbientAuthority) -> io::Result { let dir = open_parent_dir(&self.std_file, ambient_authority)?; Ok(Self::from_std_file(dir)) } /// Recursively create a directory and all of its parent components if they /// are missing, using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn create_ambient_dir_all>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result<()> { let _ = ambient_authority; fs::create_dir_all(path) } /// Construct a new instance of `Self` from existing directory file /// descriptor. /// /// This can be useful when interacting with other libraries and or C/C++ /// code which has invoked `openat(..., O_DIRECTORY)` external to this /// crate. pub fn reopen_dir(dir: &Filelike) -> io::Result { cap_primitives::fs::open_dir( &dir.as_filelike_view::(), std::path::Component::CurDir.as_ref(), ) .map(Self::from_std_file) } } // Safety: `FilelikeViewType` is implemented for `std::fs::File`. unsafe impl io_lifetimes::views::FilelikeViewType for Dir {} #[cfg(not(windows))] impl FromRawFd for Dir { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std_file(fs::File::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for Dir { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std_file(fs::File::from(fd)) } } #[cfg(windows)] impl FromRawHandle for Dir { /// To prevent race conditions on Windows, the handle must be opened /// without `FILE_SHARE_DELETE`. #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_std_file(fs::File::from_raw_handle(handle)) } } #[cfg(windows)] impl From for Dir { #[inline] fn from(handle: OwnedHandle) -> Self { Self::from_std_file(fs::File::from(handle)) } } #[cfg(not(windows))] impl AsRawFd for Dir { #[inline] fn as_raw_fd(&self) -> RawFd { self.std_file.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for Dir { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std_file.as_fd() } } #[cfg(windows)] impl AsRawHandle for Dir { #[inline] fn as_raw_handle(&self) -> RawHandle { self.std_file.as_raw_handle() } } #[cfg(windows)] impl AsHandle for Dir { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { self.std_file.as_handle() } } #[cfg(windows)] impl AsRawHandleOrSocket for Dir { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.std_file.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for Dir { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.std_file.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for Dir { #[inline] fn into_raw_fd(self) -> RawFd { self.std_file.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(dir: Dir) -> OwnedFd { dir.std_file.into() } } #[cfg(windows)] impl IntoRawHandle for Dir { #[inline] fn into_raw_handle(self) -> RawHandle { self.std_file.into_raw_handle() } } #[cfg(windows)] impl From for OwnedHandle { #[inline] fn from(dir: Dir) -> OwnedHandle { dir.std_file.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for Dir { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.std_file.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(dir: Dir) -> Self { dir.std_file.into() } } /// Indicates how large a buffer to pre-allocate before reading the entire /// file. /// /// Derived from the function of the same name in Rust's library/std/src/fs.rs /// at revision 108e90ca78f052c0c1c49c42a22c85620be19712. fn initial_buffer_size(file: &File) -> usize { // Allocate one extra byte so the buffer doesn't need to grow before the // final `read` call at the end of the file. Don't worry about `usize` // overflow because reading will fail regardless in that case. file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0) } impl fmt::Debug for Dir { // Like libstd's version, but doesn't print the path. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut b = f.debug_struct("Dir"); #[cfg(not(windows))] b.field("fd", &self.std_file.as_raw_fd()); #[cfg(windows)] b.field("handle", &self.std_file.as_raw_handle()); b.finish() } } cap-std-3.4.4/src/fs/dir_entry.rs000064400000000000000000000057441046102023000147450ustar 00000000000000use crate::fs::{Dir, File, FileType, Metadata, OpenOptions}; #[cfg(not(windows))] use rustix::fs::DirEntryExt; use std::ffi::OsString; use std::{fmt, io}; /// Entries returned by the `ReadDir` iterator. /// /// This corresponds to [`std::fs::DirEntry`]. /// /// Unlike `std::fs::DirEntry`, this API has no `DirEntry::path`, because /// absolute paths don't interoperate well with the capability model. /// /// There is a `file_name` function, however there are also `open`, /// `open_with`, `open_dir`, `remove_file`, and `remove_dir` functions for /// opening or removing the entry directly, which can be more efficient and /// convenient. /// /// There is no `from_std` method, as `std::fs::DirEntry` doesn't provide a /// way to construct a `DirEntry` without opening directories by ambient paths. pub struct DirEntry { pub(crate) inner: cap_primitives::fs::DirEntry, } impl DirEntry { /// Open the file for reading. #[inline] pub fn open(&self) -> io::Result { let file = self.inner.open()?; Ok(File::from_std(file)) } /// Open the file with the given options. #[inline] pub fn open_with(&self, options: &OpenOptions) -> io::Result { let file = self.inner.open_with(options)?; Ok(File::from_std(file)) } /// Open the entry as a directory. #[inline] pub fn open_dir(&self) -> io::Result { let dir = self.inner.open_dir()?; Ok(Dir::from_std_file(dir)) } /// Removes the file from its filesystem. #[inline] pub fn remove_file(&self) -> io::Result<()> { self.inner.remove_file() } /// Removes the directory from its filesystem. #[inline] pub fn remove_dir(&self) -> io::Result<()> { self.inner.remove_dir() } /// Returns the metadata for the file that this entry points at. /// /// This corresponds to [`std::fs::DirEntry::metadata`]. #[inline] pub fn metadata(&self) -> io::Result { self.inner.metadata() } /// Returns the file type for the file that this entry points at. /// /// This corresponds to [`std::fs::DirEntry::file_type`]. #[inline] pub fn file_type(&self) -> io::Result { self.inner.file_type() } /// Returns the bare file name of this directory entry without any other /// leading path component. /// /// This corresponds to [`std::fs::DirEntry::file_name`]. #[inline] pub fn file_name(&self) -> OsString { self.inner.file_name() } } #[cfg(not(windows))] impl DirEntryExt for DirEntry { #[inline] fn ino(&self) -> u64 { self.inner.ino() } } #[cfg(windows)] #[doc(hidden)] impl cap_primitives::fs::_WindowsDirEntryExt for DirEntry { #[inline] fn full_metadata(&self) -> io::Result { cap_primitives::fs::_WindowsDirEntryExt::full_metadata(&self.inner) } } impl fmt::Debug for DirEntry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } cap-std-3.4.4/src/fs/file.rs000064400000000000000000000376041046102023000136650ustar 00000000000000use crate::fs::{Metadata, OpenOptions, Permissions}; use cap_primitives::fs::{is_file_read_write, open_ambient}; use cap_primitives::AmbientAuthority; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use std::path::Path; use std::{fmt, fs, process}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, }; /// A reference to an open file on a filesystem. /// /// This corresponds to [`std::fs::File`]. /// /// This `File` has no `open` or `create` methods. To open or create a file, /// first obtain a [`Dir`] containing the path, and then call [`Dir::open`] or /// [`Dir::create`]. /// /// [`Dir`]: crate::fs::Dir /// [`Dir::open`]: crate::fs::Dir::open /// [`Dir::create`]: crate::fs::Dir::create pub struct File { pub(crate) std: fs::File, } impl File { /// Constructs a new instance of `Self` from the given [`std::fs::File`]. /// /// This grants access the resources the `std::fs::File` instance already /// has access to. #[inline] pub fn from_std(std: fs::File) -> Self { Self { std } } /// Consumes `self` and returns a [`std::fs::File`]. #[inline] pub fn into_std(self) -> fs::File { self.std } /// Attempts to sync all OS-internal metadata to disk. /// /// This corresponds to [`std::fs::File::sync_all`]. #[inline] pub fn sync_all(&self) -> io::Result<()> { self.std.sync_all() } /// This function is similar to `sync_all`, except that it may not /// synchronize file metadata to a filesystem. /// /// This corresponds to [`std::fs::File::sync_data`]. #[inline] pub fn sync_data(&self) -> io::Result<()> { self.std.sync_data() } /// Truncates or extends the underlying file, updating the size of this /// file to become size. /// /// This corresponds to [`std::fs::File::set_len`]. #[inline] pub fn set_len(&self, size: u64) -> io::Result<()> { self.std.set_len(size) } /// Queries metadata about the underlying file. /// /// This corresponds to [`std::fs::File::metadata`]. #[inline] pub fn metadata(&self) -> io::Result { metadata_from(&self.std) } /// Creates a new `File` instance that shares the same underlying file /// handle as the existing `File` instance. /// /// This corresponds to [`std::fs::File::try_clone`]. #[inline] pub fn try_clone(&self) -> io::Result { let file = self.std.try_clone()?; Ok(Self::from_std(file)) } /// Changes the permissions on the underlying file. /// /// This corresponds to [`std::fs::File::set_permissions`]. #[inline] pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { self.std .set_permissions(permissions_into_std(&self.std, perm)?) } /// Constructs a new instance of `Self` in read-only mode by opening the /// given path as a file using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let std = open_ambient( path.as_ref(), OpenOptions::new().read(true), ambient_authority, )?; Ok(Self::from_std(std)) } /// Constructs a new instance of `Self` in write-only mode by opening, /// creating or truncating, the given path as a file using the host /// process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn create_ambient>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let std = open_ambient( path.as_ref(), OpenOptions::new().write(true).create(true).truncate(true), ambient_authority, )?; Ok(Self::from_std(std)) } /// Constructs a new instance of `Self` with the options specified by /// `options` by opening the given path as a file using the host process' /// ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient_with>( path: P, options: &OpenOptions, ambient_authority: AmbientAuthority, ) -> io::Result { let std = open_ambient(path.as_ref(), options, ambient_authority)?; Ok(Self::from_std(std)) } /// Returns a new `OpenOptions` object. /// /// This corresponds to [`std::fs::File::options`]. #[must_use] #[inline] pub fn options() -> OpenOptions { OpenOptions::new() } } #[inline] fn metadata_from(file: &fs::File) -> io::Result { Metadata::from_file(file) } #[inline] fn permissions_into_std(file: &fs::File, permissions: Permissions) -> io::Result { permissions.into_std(file) } // Safety: `FilelikeViewType` is implemented for `std::fs::File`. unsafe impl io_lifetimes::views::FilelikeViewType for File {} #[cfg(not(windows))] impl FromRawFd for File { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(fs::File::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for File { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(fs::File::from(fd)) } } #[cfg(windows)] impl FromRawHandle for File { #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_std(fs::File::from_raw_handle(handle)) } } #[cfg(windows)] impl From for File { #[inline] fn from(handle: OwnedHandle) -> Self { Self::from_std(fs::File::from(handle)) } } #[cfg(not(windows))] impl AsRawFd for File { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for File { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } #[cfg(windows)] impl AsRawHandle for File { #[inline] fn as_raw_handle(&self) -> RawHandle { self.std.as_raw_handle() } } #[cfg(windows)] impl AsHandle for File { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { self.std.as_handle() } } #[cfg(windows)] impl AsRawHandleOrSocket for File { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for File { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for File { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(file: File) -> OwnedFd { file.std.into() } } #[cfg(windows)] impl IntoRawHandle for File { #[inline] fn into_raw_handle(self) -> RawHandle { self.std.into_raw_handle() } } #[cfg(windows)] impl From for OwnedHandle { #[inline] fn from(file: File) -> OwnedHandle { file.std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for File { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(file: File) -> Self { file.std.into() } } impl Read for File { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.std.read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { self.std.read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.std.read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.std.read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { self.std.read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Read for &File { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (&mut &self.std).read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { (&mut &self.std).read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (&mut &self.std).read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (&mut &self.std).read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (&mut &self.std).read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Write for File { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.std.write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { self.std.flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { self.std.write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.std.write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { self.std.write_all_vectored(bufs) } } impl Write for &File { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (&mut &self.std).write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { (&mut &self.std).flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { (&mut &self.std).write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (&mut &self.std).write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { (&mut &self.std).write_all_vectored(bufs) } } impl Seek for File { #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { self.std.seek(pos) } #[inline] fn stream_position(&mut self) -> io::Result { self.std.stream_position() } } impl Seek for &File { #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (&mut &self.std).seek(pos) } #[inline] fn stream_position(&mut self) -> io::Result { (&mut &self.std).stream_position() } } impl From for process::Stdio { #[inline] fn from(file: File) -> Self { From::::from(file.std) } } #[cfg(unix)] impl crate::fs::FileExt for File { #[inline] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { std::os::unix::fs::FileExt::read_at(&self.std, buf, offset) } #[inline] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { std::os::unix::fs::FileExt::write_at(&self.std, buf, offset) } #[inline] fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> { std::os::unix::fs::FileExt::read_exact_at(&self.std, buf, offset) } #[inline] fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> { std::os::unix::fs::FileExt::write_all_at(&self.std, buf, offset) } } #[cfg(target_os = "wasi")] impl crate::fs::FileExt for File { #[inline] fn read_at(&self, bufs: &mut [u8], offset: u64) -> io::Result { std::os::wasi::fs::FileExt::read_at(&self.std, bufs, offset) } #[inline] fn write_at(&self, bufs: &[u8], offset: u64) -> io::Result { std::os::wasi::fs::FileExt::write_at(&self.std, bufs, offset) } #[inline] fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result { std::os::wasi::fs::FileExt::read_vectored_at(&self.std, bufs, offset) } #[inline] fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result { std::os::wasi::fs::FileExt::write_vectored_at(&self.std, bufs, offset) } #[inline] fn fdstat_set_flags(&self, flags: u16) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::fdstat_set_flags(&self.std, flags) } #[inline] fn fdstat_set_rights( &self, rights: u64, inheriting: u64, ) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::fdstat_set_rights(&self.std, rights, inheriting) } #[inline] fn advise(&self, offset: u64, len: u64, advice: u8) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::advise(&self.std, offset, len, advice) } #[inline] fn allocate(&self, offset: u64, len: u64) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::allocate(&self.std, offset, len) } #[inline] fn create_directory>(&self, dir: P) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::create_directory(&self.std, dir) } #[inline] fn read_link>( &self, path: P, ) -> std::result::Result { std::os::wasi::fs::FileExt::read_link(&self.std, path) } #[inline] fn metadata_at>( &self, lookup_flags: u32, path: P, ) -> std::result::Result { std::os::wasi::fs::FileExt::metadata_at(&self.std, lookup_flags, path) } #[inline] fn remove_file>(&self, path: P) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::remove_file(&self.std, path) } #[inline] fn remove_directory>(&self, path: P) -> std::result::Result<(), io::Error> { std::os::wasi::fs::FileExt::remove_directory(&self.std, path) } } #[cfg(windows)] impl crate::fs::FileExt for File { #[inline] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { std::os::windows::fs::FileExt::seek_read(&self.std, buf, offset) } #[inline] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { std::os::windows::fs::FileExt::seek_write(&self.std, buf, offset) } } impl fmt::Debug for File { // Like libstd's version, but doesn't print the path. fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut b = f.debug_struct("File"); #[cfg(not(windows))] b.field("fd", &self.std.as_raw_fd()); #[cfg(windows)] b.field("handle", &self.std.as_raw_handle()); if let Ok((read, write)) = is_file_read_write(&self.std) { b.field("read", &read).field("write", &write); } b.finish() } } cap-std-3.4.4/src/fs/mod.rs000064400000000000000000000033731046102023000135210ustar 00000000000000//! A capability-based filesystem API modeled after [`std::fs`]. //! //! This corresponds to [`std::fs`]. //! //! Instead of [`std::fs`'s free functions] and [`std::fs::File`]'s //! constructors which operate on bare paths, this crate has methods on [`Dir`] //! which operate on paths which must be relative to the directory. //! //! Where `std` says "the filesystem", this API says "a filesystem", as //! it doesn't assume that there's a single global filesystem namespace. //! //! Since all functions which expose raw file descriptors are `unsafe`, //! I/O handles in this API are unforgeable (unsafe code notwithstanding). //! This combined with a lack of absolute paths provides a natural //! capability-based interface. //! //! This crate uses the existing `std::path::Path` rather than having its own //! path type, however while `std::path::Path` is mostly just a pure datatype, //! it includes aliases for several `std::fs` functions. To preserve the //! capability-based interface, avoid using `std::path::Path`'s `canonicalize`, //! `read_link`, `read_dir`, `metadata`, and `symlink_metadata` functions. //! //! [`std::fs`'s free functions]: https://doc.rust-lang.org/std/fs/#functions mod dir; mod dir_entry; mod file; mod read_dir; pub use dir::Dir; pub use dir_entry::DirEntry; pub use file::File; pub use read_dir::ReadDir; // Re-export types from `cap_primitives`. pub use cap_primitives::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions}; // Re-export conditional types from `cap_primitives`. #[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))] pub use cap_primitives::fs::FileTypeExt; #[cfg(unix)] pub use cap_primitives::fs::{DirBuilderExt, PermissionsExt}; pub use cap_primitives::fs::{FileExt, MetadataExt, OpenOptionsExt}; cap-std-3.4.4/src/fs/read_dir.rs000064400000000000000000000013461046102023000145110ustar 00000000000000use crate::fs::DirEntry; use std::{fmt, io}; /// Iterator over the entries in a directory. /// /// This corresponds to [`std::fs::ReadDir`]. /// /// There is no `from_std` method, as `std::fs::ReadDir` doesn't provide a way /// to construct a `ReadDir` without opening directories by ambient paths. pub struct ReadDir { pub(crate) inner: cap_primitives::fs::ReadDir, } impl Iterator for ReadDir { type Item = io::Result; #[inline] fn next(&mut self) -> Option { self.inner .next() .map(|inner| inner.map(|inner| DirEntry { inner })) } } impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.inner.fmt(f) } } cap-std-3.4.4/src/fs_utf8/dir.rs000064400000000000000000000677611046102023000145010ustar 00000000000000use crate::fs::{OpenOptions, Permissions}; use crate::fs_utf8::{from_utf8, to_utf8, DirBuilder, File, Metadata, ReadDir}; #[cfg(unix)] use crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream}; use camino::{Utf8Path, Utf8PathBuf}; use cap_primitives::AmbientAuthority; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use io_lifetimes::AsFilelike; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; use std::{fmt, fs, io}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, }; /// A reference to an open directory on a filesystem. /// /// This does not directly correspond to anything in `std`, however its methods /// correspond to the [functions in `std::fs`] and the constructor methods for /// [`std::fs::File`]. /// /// Unlike `std::fs`, this API's `canonicalize` returns a relative path since /// absolute paths don't interoperate well with the capability model. /// /// [functions in `std::fs`]: https://doc.rust-lang.org/std/fs/index.html#functions pub struct Dir { cap_std: crate::fs::Dir, } impl Dir { /// Constructs a new instance of `Self` from the given [`std::fs::File`]. /// /// To prevent race conditions on Windows, the file must be opened without /// `FILE_SHARE_DELETE`. /// /// This grants access the resources the `std::fs::File` instance already /// has access to. #[inline] pub fn from_std_file(std_file: fs::File) -> Self { Self::from_cap_std(crate::fs::Dir::from_std_file(std_file)) } /// Constructs a new instance of `Self` from the given `cap_std::fs::Dir`. #[inline] pub fn from_cap_std(cap_std: crate::fs::Dir) -> Self { Self { cap_std } } /// Return a view of this directory as a [`cap_std::fs::Dir`]. This /// is often useful in order to write shared functions which can operate /// on either type. #[inline] pub fn as_cap_std(&self) -> &crate::fs::Dir { &self.cap_std } /// Attempts to open a file in read-only mode. /// /// This corresponds to [`std::fs::File::open`], but only accesses paths /// relative to `self`. #[inline] pub fn open>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.as_cap_std().open(path).map(File::from_cap_std) } /// Opens a file at `path` with the options specified by `options`. /// /// This corresponds to [`std::fs::OpenOptions::open`]. /// /// Instead of being a method on `OpenOptions`, this is a method on `Dir`, /// and it only accesses paths relative to `self`. #[inline] pub fn open_with>( &self, path: P, options: &OpenOptions, ) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std .open_with(path, options) .map(File::from_cap_std) } /// Attempts to open a directory. #[inline] pub fn open_dir>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.as_ref().open_dir(path).map(Self::from_cap_std) } /// Creates a new, empty directory at the provided path. /// /// This corresponds to [`std::fs::create_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn create_dir>(&self, path: P) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.create_dir(path) } /// Recursively create a directory and all of its parent components if they /// are missing. /// /// This corresponds to [`std::fs::create_dir_all`], but only accesses /// paths relative to `self`. #[inline] pub fn create_dir_all>(&self, path: P) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.create_dir_all(path) } /// Creates the specified directory with the options configured in this /// builder. /// /// This corresponds to [`std::fs::DirBuilder::create`]. #[cfg(not(target_os = "wasi"))] #[inline] pub fn create_dir_with>( &self, path: P, dir_builder: &DirBuilder, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.create_dir_with(path, dir_builder) } /// Opens a file in write-only mode. /// /// This corresponds to [`std::fs::File::create`], but only accesses paths /// relative to `self`. #[inline] pub fn create>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.create(path).map(File::from_cap_std) } /// Returns the canonical form of a path with all intermediate components /// normalized and symbolic links resolved. /// /// This corresponds to [`std::fs::canonicalize`], but instead of returning /// an absolute path, returns a path relative to the directory /// represented by `self`. #[inline] pub fn canonicalize>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.canonicalize(path).and_then(to_utf8) } /// Copies the contents of one file to another. This function will also /// copy the permission bits of the original file to the destination /// file. /// /// This corresponds to [`std::fs::copy`], but only accesses paths /// relative to `self`. #[inline] pub fn copy, Q: AsRef>( &self, from: P, to_dir: &Self, to: Q, ) -> io::Result { let from = from_utf8(from.as_ref())?; let to = from_utf8(to.as_ref())?; self.cap_std.copy(from, &to_dir.cap_std, to) } /// Creates a new hard link on a filesystem. /// /// This corresponds to [`std::fs::hard_link`], but only accesses paths /// relative to `self`. #[inline] pub fn hard_link, Q: AsRef>( &self, src: P, dst_dir: &Self, dst: Q, ) -> io::Result<()> { let src = from_utf8(src.as_ref())?; let dst = from_utf8(dst.as_ref())?; self.cap_std.hard_link(src, &dst_dir.cap_std, dst) } /// Given a path, query the file system to get information about a file, /// directory, etc. /// /// This corresponds to [`std::fs::metadata`], but only accesses paths /// relative to `self`. #[inline] pub fn metadata>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.metadata(path) } /// Queries metadata about the underlying directory. /// /// This is similar to [`std::fs::File::metadata`], but for `Dir` rather /// than for `File`. #[inline] pub fn dir_metadata(&self) -> io::Result { self.cap_std.dir_metadata() } /// Returns an iterator over the entries within `self`. #[inline] pub fn entries(&self) -> io::Result { self.cap_std.entries().map(ReadDir::from_cap_std) } /// Returns an iterator over the entries within a directory. /// /// This corresponds to [`std::fs::read_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn read_dir>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.read_dir(path).map(ReadDir::from_cap_std) } /// Read the entire contents of a file into a bytes vector. /// /// This corresponds to [`std::fs::read`], but only accesses paths /// relative to `self`. #[inline] pub fn read>(&self, path: P) -> io::Result> { let path = from_utf8(path.as_ref())?; self.cap_std.read(path) } /// Reads a symbolic link, returning the file that the link points to. /// /// This corresponds to [`std::fs::read_link`], but only accesses paths /// relative to `self`. Unlike [`read_link_contents`], this method considers it an error if /// the link's target is an absolute path. #[inline] pub fn read_link>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.read_link(path).and_then(to_utf8) } /// Reads a symbolic link, returning the file that the link points to. /// /// This corresponds to [`std::fs::read_link`]. but only accesses paths /// relative to `self`. #[inline] pub fn read_link_contents>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.read_link_contents(path).and_then(to_utf8) } /// Read the entire contents of a file into a string. /// /// This corresponds to [`std::fs::read_to_string`], but only accesses /// paths relative to `self`. #[inline] pub fn read_to_string>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.read_to_string(path) } /// Removes an empty directory. /// /// This corresponds to [`std::fs::remove_dir`], but only accesses paths /// relative to `self`. #[inline] pub fn remove_dir>(&self, path: P) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.remove_dir(path) } /// Removes a directory at this path, after removing all its contents. Use /// carefully! /// /// This corresponds to [`std::fs::remove_dir_all`], but only accesses /// paths relative to `self`. #[inline] pub fn remove_dir_all>(&self, path: P) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.remove_dir_all(path) } /// Remove the directory referenced by `self` and consume `self`. /// /// Even though this implementation works in terms of handles as much as /// possible, removal is not guaranteed to be atomic with respect to a /// concurrent rename of the directory. #[inline] pub fn remove_open_dir(self) -> io::Result<()> { self.cap_std.remove_open_dir() } /// Removes the directory referenced by `self`, after removing all its /// contents, and consume `self`. Use carefully! /// /// Even though this implementation works in terms of handles as much as /// possible, removal is not guaranteed to be atomic with respect to a /// concurrent rename of the directory. #[inline] pub fn remove_open_dir_all(self) -> io::Result<()> { self.cap_std.remove_open_dir_all() } /// Removes a file from a filesystem. /// /// This corresponds to [`std::fs::remove_file`], but only accesses paths /// relative to `self`. #[inline] pub fn remove_file>(&self, path: P) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.remove_file(path) } /// Rename a file or directory to a new name, replacing the original file /// if to already exists. /// /// This corresponds to [`std::fs::rename`], but only accesses paths /// relative to `self`. #[inline] pub fn rename, Q: AsRef>( &self, from: P, to_dir: &Self, to: Q, ) -> io::Result<()> { let from = from_utf8(from.as_ref())?; let to = from_utf8(to.as_ref())?; self.cap_std.rename(from, &to_dir.cap_std, to) } /// Changes the permissions found on a file or a directory. /// /// This corresponds to [`std::fs::set_permissions`], but only accesses /// paths relative to `self`. Also, on some platforms, this function /// may fail if the file or directory cannot be opened for reading or /// writing first. #[cfg(not(target_os = "wasi"))] pub fn set_permissions>( &self, path: P, perm: Permissions, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.set_permissions(path, perm) } /// Query the metadata about a file without following symlinks. /// /// This corresponds to [`std::fs::symlink_metadata`], but only accesses /// paths relative to `self`. #[inline] pub fn symlink_metadata>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.symlink_metadata(path) } /// Write a slice as the entire contents of a file. /// /// This corresponds to [`std::fs::write`], but only accesses paths /// relative to `self`. #[inline] pub fn write, C: AsRef<[u8]>>( &self, path: P, contents: C, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.write(path, contents) } /// Creates a new symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::unix::fs::symlink`], but only accesses /// paths relative to `self`. /// /// Unlike [`symlink_contents`] this method will return an error if `original` is an absolute /// path. /// /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html #[cfg(not(windows))] #[inline] pub fn symlink, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { let original = from_utf8(original.as_ref())?; let link = from_utf8(link.as_ref())?; self.cap_std.symlink(original, link) } /// Creates a new symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::unix::fs::symlink`], but only accesses /// paths relative to `self`. /// /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html #[cfg(not(windows))] #[inline] pub fn symlink_contents, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { let original = from_utf8(original.as_ref())?; let link = from_utf8(link.as_ref())?; self.cap_std.symlink_contents(original, link) } /// Creates a new file symbolic link on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::windows::fs::symlink_file`], but only /// accesses paths relative to `self`. /// /// [`std::os::windows::fs::symlink_file`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html #[cfg(windows)] #[inline] pub fn symlink_file, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { let original = from_utf8(original.as_ref())?; let link = from_utf8(link.as_ref())?; self.cap_std.symlink_file(original, link) } /// Creates a new directory symlink on a filesystem. /// /// The `original` argument provides the target of the symlink. The `link` /// argument provides the name of the created symlink. /// /// Despite the argument ordering, `original` is not resolved relative to /// `self` here. `link` is resolved relative to `self`, and `original` is /// not resolved within this function. /// /// The `link` path is resolved when the symlink is dereferenced, relative /// to the directory that contains it. /// /// This corresponds to [`std::os::windows::fs::symlink_dir`], but only /// accesses paths relative to `self`. /// /// [`std::os::windows::fs::symlink_dir`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html #[cfg(windows)] #[inline] pub fn symlink_dir, Q: AsRef>( &self, original: P, link: Q, ) -> io::Result<()> { let original = from_utf8(original.as_ref())?; let link = from_utf8(link.as_ref())?; self.cap_std.symlink_dir(original, link) } /// Creates a new `UnixListener` bound to the specified socket. /// /// This corresponds to [`std::os::unix::net::UnixListener::bind`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixListener::bind`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.bind #[doc(alias = "bind")] #[cfg(unix)] #[inline] pub fn bind_unix_listener>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.bind_unix_listener(path) } /// Connects to the socket named by path. /// /// This corresponds to [`std::os::unix::net::UnixStream::connect`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixStream::connect`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.connect #[doc(alias = "connect")] #[cfg(unix)] #[inline] pub fn connect_unix_stream>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.connect_unix_stream(path) } /// Creates a Unix datagram socket bound to the given path. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::bind`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::bind`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.bind #[doc(alias = "bind")] #[cfg(unix)] #[inline] pub fn bind_unix_datagram>(&self, path: P) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std.bind_unix_datagram(path) } /// Connects the socket to the specified address. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::connect`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::connect`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.connect #[doc(alias = "connect")] #[cfg(unix)] #[inline] pub fn connect_unix_datagram>( &self, unix_datagram: &UnixDatagram, path: P, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; self.cap_std.connect_unix_datagram(unix_datagram, path) } /// Sends data on the socket to the specified address. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::send_to`], but /// only accesses paths relative to `self`. /// /// XXX: This function is not yet implemented. /// /// [`std::os::unix::net::UnixDatagram::send_to`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.send_to #[doc(alias = "send_to")] #[cfg(unix)] #[inline] pub fn send_to_unix_datagram_addr>( &self, unix_datagram: &UnixDatagram, buf: &[u8], path: P, ) -> io::Result { let path = from_utf8(path.as_ref())?; self.cap_std .send_to_unix_datagram_addr(unix_datagram, buf, path) } /// Creates a new `Dir` instance that shares the same underlying file /// handle as the existing `Dir` instance. #[inline] pub fn try_clone(&self) -> io::Result { Ok(Self { cap_std: self.cap_std.try_clone()?, }) } /// Returns `true` if the path points at an existing entity. /// /// This corresponds to [`std::path::Path::exists`], but only /// accesses paths relative to `self`. #[inline] pub fn exists>(&self, path: P) -> bool { match from_utf8(path.as_ref()) { Ok(path) => self.cap_std.exists(path), Err(_) => false, } } /// Returns `true` if the path points at an existing entity. /// /// This corresponds to [`std::path::Path::exists`], but only /// accesses paths relative to `self`. #[inline] pub fn try_exists>(&self, path: P) -> io::Result { self.cap_std.try_exists(from_utf8(path.as_ref())?) } /// Returns `true` if the path exists on disk and is pointing at a regular /// file. /// /// This corresponds to [`std::path::Path::is_file`], but only /// accesses paths relative to `self`. #[inline] pub fn is_file>(&self, path: P) -> bool { match from_utf8(path.as_ref()) { Ok(path) => self.cap_std.is_file(path), Err(_) => false, } } /// Checks if `path` is a directory. /// /// This is similar to [`std::path::Path::is_dir`] in that it checks if /// `path` relative to `Dir` is a directory. This function will /// traverse symbolic links to query information about the destination /// file. In case of broken symbolic links, this will return `false`. #[inline] pub fn is_dir>(&self, path: P) -> bool { match from_utf8(path.as_ref()) { Ok(path) => self.cap_std.is_dir(path), Err(_) => false, } } /// Constructs a new instance of `Self` by opening the given path as a /// directory using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient_dir>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let path = from_utf8(path.as_ref())?; crate::fs::Dir::open_ambient_dir(path, ambient_authority).map(Self::from_cap_std) } /// Constructs a new instance of `Self` by opening the parent directory /// (aka "..") of `self`, using the host process' ambient authority. /// /// # Ambient Authority /// /// This function accesses a directory outside of the `self` subtree. #[inline] pub fn open_parent_dir(&self, ambient_authority: AmbientAuthority) -> io::Result { self.cap_std .open_parent_dir(ambient_authority) .map(Self::from_cap_std) } /// Recursively create a directory and all of its parent components if they /// are missing, using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn create_ambient_dir_all>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result<()> { let _ = ambient_authority; let path = from_utf8(path.as_ref())?; fs::create_dir_all(path) } /// Construct a new instance of `Self` from existing directory file /// descriptor. /// /// This can be useful when interacting with other libraries and or C/C++ /// code which has invoked `openat(..., O_DIRECTORY)` external to this /// crate. pub fn reopen_dir(dir: &Filelike) -> io::Result { cap_primitives::fs::open_dir( &dir.as_filelike_view::(), std::path::Component::CurDir.as_ref(), ) .map(Self::from_std_file) } } #[cfg(not(windows))] impl FromRawFd for Dir { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std_file(fs::File::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for Dir { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std_file(fs::File::from(fd)) } } #[cfg(windows)] impl FromRawHandle for Dir { /// To prevent race conditions on Windows, the handle must be opened /// without `FILE_SHARE_DELETE`. #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_std_file(fs::File::from_raw_handle(handle)) } } #[cfg(windows)] impl From for Dir { /// To prevent race conditions on Windows, the handle must be opened /// without `FILE_SHARE_DELETE`. #[inline] fn from(handle: OwnedHandle) -> Self { Self::from_std_file(fs::File::from(handle)) } } #[cfg(not(windows))] impl AsRawFd for Dir { #[inline] fn as_raw_fd(&self) -> RawFd { self.cap_std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for Dir { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.cap_std.as_fd() } } // Safety: `FilelikeViewType` is implemented for `std::fs::File`. unsafe impl io_lifetimes::views::FilelikeViewType for Dir {} #[cfg(windows)] impl AsRawHandle for Dir { #[inline] fn as_raw_handle(&self) -> RawHandle { self.cap_std.as_raw_handle() } } #[cfg(windows)] impl AsHandle for Dir { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { self.cap_std.as_handle() } } #[cfg(windows)] impl AsRawHandleOrSocket for Dir { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.cap_std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for Dir { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.cap_std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for Dir { #[inline] fn into_raw_fd(self) -> RawFd { self.cap_std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(dir: Dir) -> OwnedFd { dir.cap_std.into() } } #[cfg(windows)] impl IntoRawHandle for Dir { #[inline] fn into_raw_handle(self) -> RawHandle { self.cap_std.into_raw_handle() } } #[cfg(windows)] impl From for OwnedHandle { #[inline] fn from(dir: Dir) -> OwnedHandle { dir.cap_std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for Dir { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.cap_std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(dir: Dir) -> Self { dir.cap_std.into() } } impl fmt::Debug for Dir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.cap_std.fmt(f) } } impl AsRef for Dir { fn as_ref(&self) -> &crate::fs::Dir { self.as_cap_std() } } cap-std-3.4.4/src/fs_utf8/dir_entry.rs000064400000000000000000000065321046102023000157070ustar 00000000000000use crate::fs::{FileType, Metadata, OpenOptions}; use crate::fs_utf8::{to_utf8, Dir, File}; #[cfg(not(windows))] use rustix::fs::DirEntryExt; use std::{fmt, io}; /// Entries returned by the `ReadDir` iterator. /// /// This corresponds to [`std::fs::DirEntry`]. /// /// Unlike `std::fs::DirEntry`, this API has no `DirEntry::path`, because /// absolute paths don't interoperate well with the capability model. /// /// There is a `file_name` function, however there are also `open`, /// `open_with`, `open_dir`, `remove_file`, and `remove_dir` functions for /// opening or removing the entry directly, which can be more efficient and /// convenient. /// /// There is no `from_std` method, as `std::fs::DirEntry` doesn't provide a way /// to construct a `DirEntry` without opening directories by ambient paths. pub struct DirEntry { cap_std: crate::fs::DirEntry, } impl DirEntry { /// Constructs a new instance of `Self` from the given /// `cap_std::fs::DirEntry`. #[inline] pub fn from_cap_std(cap_std: crate::fs::DirEntry) -> Self { Self { cap_std } } /// Open the file for reading. #[inline] pub fn open(&self) -> io::Result { self.cap_std.open().map(File::from_cap_std) } /// Open the file with the given options. #[inline] pub fn open_with(&self, options: &OpenOptions) -> io::Result { self.cap_std.open_with(options).map(File::from_cap_std) } /// Open the entry as a directory. #[inline] pub fn open_dir(&self) -> io::Result { self.cap_std.open_dir().map(Dir::from_cap_std) } /// Removes the file from its filesystem. #[inline] pub fn remove_file(&self) -> io::Result<()> { self.cap_std.remove_file() } /// Removes the directory from its filesystem. #[inline] pub fn remove_dir(&self) -> io::Result<()> { self.cap_std.remove_dir() } /// Returns the metadata for the file that this entry points at. /// /// This corresponds to [`std::fs::DirEntry::metadata`]. #[inline] pub fn metadata(&self) -> io::Result { self.cap_std.metadata() } /// Returns the file type for the file that this entry points at. /// /// This corresponds to [`std::fs::DirEntry::file_type`]. #[inline] pub fn file_type(&self) -> io::Result { self.cap_std.file_type() } /// Returns the bare file name of this directory entry without any other /// leading path component. /// /// This function returns an `Err` in the case that the file name isn't /// encodable as UTF-8. /// /// If the `arf_strings` feature is enabled, unencodable names are /// translated to UTF-8 using `arf-strings`. /// /// This corresponds to [`std::fs::DirEntry::file_name`]. #[inline] pub fn file_name(&self) -> io::Result { Ok(to_utf8(self.cap_std.file_name())?.into()) } } #[cfg(not(windows))] impl DirEntryExt for DirEntry { #[inline] fn ino(&self) -> u64 { self.cap_std.ino() } } #[cfg(windows)] #[doc(hidden)] impl cap_primitives::fs::_WindowsDirEntryExt for DirEntry { #[inline] fn full_metadata(&self) -> io::Result { self.cap_std.full_metadata() } } impl fmt::Debug for DirEntry { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.cap_std.fmt(f) } } cap-std-3.4.4/src/fs_utf8/file.rs000064400000000000000000000365661046102023000146410ustar 00000000000000use crate::fs::{Metadata, OpenOptions, Permissions}; use crate::fs_utf8::from_utf8; use camino::Utf8Path; use cap_primitives::AmbientAuthority; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; #[cfg(target_os = "wasi")] use std::path::Path; use std::{fmt, fs, process}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, }; /// A reference to an open file on a filesystem. /// /// This corresponds to [`std::fs::File`]. /// /// This `File` has no `open` or `create` methods. To open or create a file, /// first obtain a [`Dir`] containing the path, and then call [`Dir::open`] or /// [`Dir::create`]. /// /// [`Dir`]: crate::fs::Dir /// [`Dir::open`]: crate::fs::Dir::open /// [`Dir::create`]: crate::fs::Dir::create pub struct File { cap_std: crate::fs::File, } impl File { /// Constructs a new instance of `Self` from the given [`std::fs::File`]. /// /// This grants access the resources the `std::fs::File` instance /// already has access to. #[inline] pub fn from_std(std: fs::File) -> Self { Self::from_cap_std(crate::fs::File::from_std(std)) } /// Constructs a new instance of `Self` from the given `cap_std::fs::File`. #[inline] pub fn from_cap_std(cap_std: crate::fs::File) -> Self { Self { cap_std } } /// Consumes `self` and returns a `std::fs::File`. #[inline] pub fn into_std(self) -> fs::File { self.cap_std.into_std() } /// Attempts to sync all OS-internal metadata to disk. /// /// This corresponds to [`std::fs::File::sync_all`]. #[inline] pub fn sync_all(&self) -> io::Result<()> { self.cap_std.sync_all() } /// This function is similar to `sync_all`, except that it may not /// synchronize file metadata to a filesystem. /// /// This corresponds to [`std::fs::File::sync_data`]. #[inline] pub fn sync_data(&self) -> io::Result<()> { self.cap_std.sync_data() } /// Truncates or extends the underlying file, updating the size of this /// file to become size. /// /// This corresponds to [`std::fs::File::set_len`]. #[inline] pub fn set_len(&self, size: u64) -> io::Result<()> { self.cap_std.set_len(size) } /// Queries metadata about the underlying file. /// /// This corresponds to [`std::fs::File::metadata`]. #[inline] pub fn metadata(&self) -> io::Result { self.cap_std.metadata() } /// Creates a new `File` instance that shares the same underlying file /// handle as the existing `File` instance. /// /// This corresponds to [`std::fs::File::try_clone`]. #[inline] pub fn try_clone(&self) -> io::Result { Ok(Self::from_cap_std(self.cap_std.try_clone()?)) } /// Changes the permissions on the underlying file. /// /// This corresponds to [`std::fs::File::set_permissions`]. #[inline] pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> { self.cap_std.set_permissions(perm) } /// Constructs a new instance of `Self` in read-only mode by opening the /// given path as a file using the host process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let path = from_utf8(path.as_ref())?; Ok(Self::from_cap_std(crate::fs::File::open_ambient( path, ambient_authority, )?)) } /// Constructs a new instance of `Self` in write-only mode by opening, /// creating or truncating, the given path as a file using the host /// process' ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn create_ambient>( path: P, ambient_authority: AmbientAuthority, ) -> io::Result { let path = from_utf8(path.as_ref())?; Ok(Self::from_cap_std(crate::fs::File::create_ambient( path, ambient_authority, )?)) } /// Constructs a new instance of `Self` with the options specified by /// `options` by opening the given path as a file using the host process' /// ambient authority. /// /// # Ambient Authority /// /// This function is not sandboxed and may access any path that the host /// process has access to. #[inline] pub fn open_ambient_with>( path: P, options: &OpenOptions, ambient_authority: AmbientAuthority, ) -> io::Result { let path = from_utf8(path.as_ref())?; Ok(Self::from_cap_std(crate::fs::File::open_ambient_with( path, options, ambient_authority, )?)) } /// Returns a new `OpenOptions` object. /// /// This corresponds to [`std::fs::File::options`]. #[must_use] #[inline] pub fn options() -> OpenOptions { OpenOptions::new() } } // Safety: `FilelikeViewType` is implemented for `std::fs::File`. unsafe impl io_lifetimes::views::FilelikeViewType for File {} #[cfg(not(windows))] impl FromRawFd for File { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(fs::File::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for File { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(fs::File::from(fd)) } } #[cfg(windows)] impl FromRawHandle for File { #[inline] unsafe fn from_raw_handle(handle: RawHandle) -> Self { Self::from_std(fs::File::from_raw_handle(handle)) } } #[cfg(windows)] impl From for File { #[inline] fn from(handle: OwnedHandle) -> Self { Self::from_std(fs::File::from(handle)) } } #[cfg(not(windows))] impl AsRawFd for File { #[inline] fn as_raw_fd(&self) -> RawFd { self.cap_std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for File { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.cap_std.as_fd() } } #[cfg(windows)] impl AsRawHandle for File { #[inline] fn as_raw_handle(&self) -> RawHandle { self.cap_std.as_raw_handle() } } #[cfg(windows)] impl AsHandle for File { #[inline] fn as_handle(&self) -> BorrowedHandle<'_> { self.cap_std.as_handle() } } #[cfg(windows)] impl AsRawHandleOrSocket for File { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.cap_std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for File { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.cap_std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for File { #[inline] fn into_raw_fd(self) -> RawFd { self.cap_std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(file: File) -> OwnedFd { file.cap_std.into() } } #[cfg(windows)] impl IntoRawHandle for File { #[inline] fn into_raw_handle(self) -> RawHandle { self.cap_std.into_raw_handle() } } #[cfg(windows)] impl From for OwnedHandle { #[inline] fn from(file: File) -> OwnedHandle { file.cap_std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for File { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.cap_std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(file: File) -> Self { file.cap_std.into() } } impl Read for File { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.cap_std.read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { self.cap_std.read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.cap_std.read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.cap_std.read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { self.cap_std.read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.cap_std.is_read_vectored() } } impl Read for &File { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (&mut &self.cap_std).read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { (&mut &self.cap_std).read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (&mut &self.cap_std).read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (&mut &self.cap_std).read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (&mut &self.cap_std).read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.cap_std.is_read_vectored() } } impl Write for File { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.cap_std.write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { self.cap_std.flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { self.cap_std.write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.cap_std.write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.cap_std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { self.cap_std.write_all_vectored(bufs) } } impl Write for &File { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (&mut &self.cap_std).write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { (&mut &self.cap_std).flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { (&mut &self.cap_std).write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (&mut &self.cap_std).write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.cap_std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { (&mut &self.cap_std).write_all_vectored(bufs) } } impl Seek for File { #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { self.cap_std.seek(pos) } #[inline] fn stream_position(&mut self) -> io::Result { self.cap_std.stream_position() } } impl Seek for &File { #[inline] fn seek(&mut self, pos: SeekFrom) -> io::Result { (&mut &self.cap_std).seek(pos) } #[inline] fn stream_position(&mut self) -> io::Result { (&mut &self.cap_std).stream_position() } } impl From for process::Stdio { #[inline] fn from(file: File) -> Self { From::::from(file.cap_std) } } #[cfg(unix)] impl crate::fs::FileExt for File { #[inline] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.cap_std.read_at(buf, offset) } #[inline] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.cap_std.write_at(buf, offset) } #[inline] fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> { self.cap_std.read_exact_at(buf, offset) } #[inline] fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> { self.cap_std.write_all_at(buf, offset) } } #[cfg(target_os = "wasi")] impl crate::fs::FileExt for File { #[inline] fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.cap_std.read_at(buf, offset) } #[inline] fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.cap_std.write_at(buf, offset) } #[inline] fn read_vectored_at(&self, bufs: &mut [IoSliceMut], offset: u64) -> io::Result { self.cap_std.read_vectored_at(bufs, offset) } #[inline] fn write_vectored_at(&self, bufs: &[IoSlice], offset: u64) -> io::Result { self.cap_std.write_vectored_at(bufs, offset) } #[inline] fn fdstat_set_flags(&self, flags: u16) -> std::result::Result<(), io::Error> { self.cap_std.fdstat_set_flags(flags) } #[inline] fn fdstat_set_rights( &self, rights: u64, inheriting: u64, ) -> std::result::Result<(), io::Error> { self.cap_std.fdstat_set_rights(rights, inheriting) } #[inline] fn advise(&self, offset: u64, len: u64, advice: u8) -> std::result::Result<(), io::Error> { self.cap_std.advise(offset, len, advice) } #[inline] fn allocate(&self, offset: u64, len: u64) -> std::result::Result<(), io::Error> { self.cap_std.allocate(offset, len) } #[inline] fn create_directory>(&self, path: P) -> std::result::Result<(), io::Error> { let path = path.as_ref(); self.cap_std.create_directory(path) } #[inline] fn read_link>( &self, path: P, ) -> std::result::Result { let path = path.as_ref(); self.cap_std.read_link(path) } #[inline] fn metadata_at>( &self, lookup_flags: u32, path: P, ) -> std::result::Result { let path = path.as_ref(); self.cap_std.metadata_at(lookup_flags, path) } #[inline] fn remove_file>(&self, path: P) -> std::result::Result<(), io::Error> { let path = path.as_ref(); self.cap_std.remove_file(path) } #[inline] fn remove_directory>(&self, path: P) -> std::result::Result<(), io::Error> { let path = path.as_ref(); self.cap_std.remove_directory(path) } } #[cfg(windows)] impl crate::fs::FileExt for File { #[inline] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { self.cap_std.seek_read(buf, offset) } #[inline] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { self.cap_std.seek_write(buf, offset) } } impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.cap_std.fmt(f) } } cap-std-3.4.4/src/fs_utf8/mod.rs000064400000000000000000000060341046102023000144640ustar 00000000000000//! A fully UTF-8 filesystem API modeled after [`cap_std::fs`]. //! //! Where `cap_std::fs` would use `Path` and `PathBuf`, this `fs_utf8` module //! uses [`Utf8Path`] and [`Utf8PathBuf`], meaning that all paths are valid //! UTF-8. //! //! To use this module, enable the `fs_utf8` cargo feature. //! //! If you don't want to restrict paths to UTF-8, use the regular //! [`cap_std::fs`] module instead. //! //! [`cap_std::fs`]: ../fs/ mod dir; mod dir_entry; mod file; mod read_dir; pub use dir::Dir; pub use dir_entry::DirEntry; pub use file::File; pub use read_dir::ReadDir; // Re-export things from `cap_std::fs` that we can use as-is. pub use crate::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions}; // Re-export conditional types from `cap_primitives`. #[cfg(any(unix, target_os = "vxworks", all(windows, windows_file_type_ext)))] pub use cap_primitives::fs::FileTypeExt; #[cfg(unix)] pub use cap_primitives::fs::{DirBuilderExt, PermissionsExt}; pub use cap_primitives::fs::{FileExt, MetadataExt, OpenOptionsExt}; // Re-export `camino` to make it easy for users to depend on the same // version we do, because we use its types in our public API. pub use camino; use camino::{Utf8Path, Utf8PathBuf}; #[cfg(not(feature = "arf_strings"))] pub(crate) fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<&'a std::path::Path> { Ok(path.as_std_path()) } #[cfg(feature = "arf_strings")] pub(crate) fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result { #[cfg(not(windows))] let path = { #[cfg(unix)] use std::{ffi::OsString, os::unix::ffi::OsStringExt}; #[cfg(target_os = "wasi")] use std::{ffi::OsString, os::wasi::ffi::OsStringExt}; let string = arf_strings::str_to_host(path.as_str())?; OsString::from_vec(string.into_bytes()) }; #[cfg(windows)] let path = arf_strings::str_to_host(path.as_str())?; Ok(path.into()) } fn to_utf8>(path: P) -> std::io::Result { #[cfg(not(feature = "arf_strings"))] #[cfg(not(windows))] { Ok(Utf8Path::from_path(path.as_ref()) .ok_or(::rustix::io::Errno::ILSEQ)? .to_path_buf()) } #[cfg(not(feature = "arf_strings"))] #[cfg(windows)] { Ok(Utf8Path::from_path(path.as_ref()) .ok_or_else(|| { std::io::Error::new( std::io::ErrorKind::InvalidData, "filesystem path is not valid UTF-8", ) })? .to_path_buf()) } #[cfg(feature = "arf_strings")] { // For now, for WASI use the same logic as other OS's, but // in the future, the idea is we could avoid this. let osstr = path.as_ref().as_os_str(); #[cfg(not(windows))] { arf_strings::host_os_str_to_str(osstr) .map(std::borrow::Cow::into_owned) .map(Into::into) } #[cfg(windows)] { arf_strings::host_to_str(osstr).map(Into::into) } } } cap-std-3.4.4/src/fs_utf8/read_dir.rs000064400000000000000000000016511046102023000154560ustar 00000000000000use crate::fs_utf8::DirEntry; use std::{fmt, io}; /// Iterator over the entries in a directory. /// /// This corresponds to [`std::fs::ReadDir`]. /// /// There is no `from_std` method, as `std::fs::ReadDir` doesn't provide a way /// to construct a `ReadDir` without opening directories by ambient paths. pub struct ReadDir { cap_std: crate::fs::ReadDir, } impl ReadDir { /// Constructs a new instance of `Self` from the given `cap_std::fs::File`. #[inline] pub fn from_cap_std(cap_std: crate::fs::ReadDir) -> Self { Self { cap_std } } } impl Iterator for ReadDir { type Item = io::Result; #[inline] fn next(&mut self) -> Option { self.cap_std .next() .map(|result| result.map(DirEntry::from_cap_std)) } } impl fmt::Debug for ReadDir { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.cap_std.fmt(f) } } cap-std-3.4.4/src/lib.rs000064400000000000000000000040741046102023000130770ustar 00000000000000//! A capability-based API modeled after [`std`]. //! //! This corresponds to [`std`]. //! //! Capability-based APIs represent access to external resources as values //! which can be passed around between different parts of a program. //! //! Two notable features are the [`Dir`] and [`Pool`] types: //! - `Dir` represents an open directory in a filesystem. Instead of opening //! files by absolute paths or paths relative to the current working //! directory, files are opened via paths relative to a `Dir`. The concepts //! of a process-wide "current working directory" and a single global //! filesystem namespace are de-emphasized. //! - `Pool` represents a set of network addresses. Instead of allowing //! applications to request access to any address and then applying //! process-wide filtering rules, filtering rules are built into pools which //! may be passed through the program. //! //! On WASI, use of this library closely reflects the underlying system //! API, so it avoids compatibility layers. //! //! [`Dir`]: fs::Dir //! [`Pool`]: net::Pool #![deny(missing_docs)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] #![cfg_attr(target_os = "wasi", feature(wasi_ext))] #![cfg_attr(can_vector, feature(can_vector))] #![cfg_attr(write_all_vectored, feature(write_all_vectored))] #![doc( html_logo_url = "https://raw.githubusercontent.com/bytecodealliance/cap-std/main/media/cap-std.svg" )] #![doc( html_favicon_url = "https://raw.githubusercontent.com/bytecodealliance/cap-std/main/media/cap-std.ico" )] #![cfg_attr(io_lifetimes_use_std, feature(io_safety))] pub mod fs; #[cfg(feature = "fs_utf8")] pub mod fs_utf8; #[cfg(not(target_os = "wasi"))] // Disable `net` on WASI until it has networking support. pub mod net; pub mod os; pub mod time; // Re-export ambient_authority etc. so that users can use our version. #[doc(hidden)] pub use cap_primitives::ambient_authority_known_at_compile_time; pub use cap_primitives::{ambient_authority, AmbientAuthority}; // And these are also part of our public API pub use cap_primitives::ipnet; pub use io_lifetimes; cap-std-3.4.4/src/net/incoming.rs000064400000000000000000000021531046102023000147160ustar 00000000000000use crate::net::TcpStream; use std::{fmt, io, net}; /// An iterator that infinitely `accept`s connections on a [`TcpListener`]. /// /// This corresponds to [`std::net::Incoming`]. /// /// [`TcpListener`]: struct.TcpListener.html pub struct Incoming<'a> { std: net::Incoming<'a>, } impl<'a> Incoming<'a> { /// Constructs a new instance of `Self` from the given /// `std::net::Incoming`. /// /// This grants access the resources the `std::net::Incoming` instance /// already has access to. #[inline] pub fn from_std(std: net::Incoming<'a>) -> Self { Self { std } } } impl<'a> Iterator for Incoming<'a> { type Item = io::Result; #[inline] fn next(&mut self) -> Option { self.std.next().map(|result| { let tcp_stream = result?; Ok(TcpStream::from_std(tcp_stream)) }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.std.size_hint() } } impl<'a> fmt::Debug for Incoming<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/net/mod.rs000064400000000000000000000014071046102023000136730ustar 00000000000000//! A capability-based network API modeled after [`std::net`]. //! //! This corresponds to [`std::net`]. //! //! Instead of [`std::net`]'s constructor methods which take an address to //! connect to, this crates has methods on [`Pool`] which operate on addresses //! which must be present in the pool. //! //! [`Pool`]: struct.Pool.html mod incoming; mod pool; mod tcp_listener; mod tcp_stream; mod udp_socket; pub use incoming::*; pub use pool::*; pub use tcp_listener::*; pub use tcp_stream::*; pub use udp_socket::*; // Re-export things from `std::net` that we can use as-is. pub use std::net::{ AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs, }; // TODO: re-export experimental Ipv6MulticastScope? cap-std-3.4.4/src/net/pool.rs000064400000000000000000000173671046102023000141010ustar 00000000000000use crate::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; use cap_primitives::net::no_socket_addrs; use cap_primitives::{ipnet, AmbientAuthority}; use std::time::Duration; use std::{io, net}; /// A pool of network addresses. /// /// This does not directly correspond to anything in `std`, however its methods /// correspond to the several functions in [`std::net`]. /// /// `Pool` implements `Clone`, which creates new independent entities that /// carry the full authority of the originals. This means that in a borrow /// of a `Pool`, the scope of the authority is not necessarily limited to /// the scope of the borrow. /// /// Similarly, the [`cap_net_ext::PoolExt`] class allows creating "binder" /// and "connecter" objects which represent capabilities to bind and /// connect to addresses. /// /// [`cap_net_ext::PoolExt`]: https://docs.rs/cap-net-ext/latest/cap_net_ext/trait.PoolExt.html #[derive(Clone, Default)] pub struct Pool { cap: cap_primitives::net::Pool, } impl Pool { /// Construct a new empty pool. pub fn new() -> Self { Self { cap: cap_primitives::net::Pool::new(), } } /// Add addresses to the pool. /// /// # Ambient Authority /// /// This function allows ambient access to any IP address. pub fn insert( &mut self, addrs: A, ambient_authority: AmbientAuthority, ) -> io::Result<()> { self.cap.insert(addrs, ambient_authority) } /// Add a specific [`net::SocketAddr`] to the pool. /// /// # Ambient Authority /// /// This function allows ambient access to any IP address. pub fn insert_socket_addr( &mut self, addr: net::SocketAddr, ambient_authority: AmbientAuthority, ) { self.cap.insert_socket_addr(addr, ambient_authority) } /// Add a range of network addresses, accepting any port, to the pool. /// /// Unlike `insert_ip_net`, this function grants access to any requested /// port. /// /// # Ambient Authority /// /// This function allows ambient access to any IP address. pub fn insert_ip_net_port_any( &mut self, ip_net: ipnet::IpNet, ambient_authority: AmbientAuthority, ) { self.cap.insert_ip_net_port_any(ip_net, ambient_authority) } /// Add a range of network addresses, accepting a range of ports, to the /// pool. /// /// This grants access to the port range starting at `ports_start` and, /// if `ports_end` is provided, ending before `ports_end`. /// /// # Ambient Authority /// /// This function allows ambient access to any IP address. pub fn insert_ip_net_port_range( &mut self, ip_net: ipnet::IpNet, ports_start: u16, ports_end: Option, ambient_authority: AmbientAuthority, ) { self.cap .insert_ip_net_port_range(ip_net, ports_start, ports_end, ambient_authority) } /// Add a range of network addresses with a specific port to the pool. /// /// # Ambient Authority /// /// This function allows ambient access to any IP address. pub fn insert_ip_net( &mut self, ip_net: ipnet::IpNet, port: u16, ambient_authority: AmbientAuthority, ) { self.cap.insert_ip_net(ip_net, port, ambient_authority) } /// Creates a new `TcpListener` which will be bound to the specified /// address. /// /// This corresponds to [`std::net::TcpListener::bind`]. #[doc(alias = "bind")] #[inline] pub fn bind_tcp_listener(&self, addr: A) -> io::Result { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { self.cap.check_addr(&addr)?; // TODO: when compiling for WASI, use WASI-specific methods instead match net::TcpListener::bind(addr) { Ok(tcp_listener) => return Ok(TcpListener::from_std(tcp_listener)), Err(e) => last_err = Some(e), } } match last_err { Some(e) => Err(e), None => Err(no_socket_addrs()), } } /// Opens a TCP connection to a remote host. /// /// This corresponds to [`std::net::TcpStream::connect`]. #[doc(alias = "connect")] #[inline] pub fn connect_tcp_stream(&self, addr: A) -> io::Result { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { self.cap.check_addr(&addr)?; // TODO: when compiling for WASI, use WASI-specific methods instead match net::TcpStream::connect(addr) { Ok(tcp_stream) => return Ok(TcpStream::from_std(tcp_stream)), Err(e) => last_err = Some(e), } } match last_err { Some(e) => Err(e), None => Err(no_socket_addrs()), } } /// Opens a TCP connection to a remote host with a timeout. /// /// This corresponds to [`std::net::TcpStream::connect_timeout`]. #[doc(alias = "connect")] #[inline] pub fn connect_timeout_tcp_stream( &self, addr: &SocketAddr, timeout: Duration, ) -> io::Result { self.cap.check_addr(addr)?; let tcp_stream = net::TcpStream::connect_timeout(addr, timeout)?; Ok(TcpStream::from_std(tcp_stream)) } /// Creates a UDP socket from the given address. /// /// This corresponds to [`std::net::UdpSocket::bind`]. #[doc(alias = "bind")] #[inline] pub fn bind_udp_socket(&self, addr: A) -> io::Result { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { self.cap.check_addr(&addr)?; match net::UdpSocket::bind(addr) { Ok(udp_socket) => return Ok(UdpSocket::from_std(udp_socket)), Err(e) => last_err = Some(e), } } match last_err { Some(e) => Err(e), None => Err(no_socket_addrs()), } } /// Sends data on the socket to the given address. On success, returns the /// number of bytes written. /// /// This corresponds to [`std::net::UdpSocket::send_to`]. #[doc(alias = "send_to")] #[inline] pub fn send_to_udp_socket_addr( &self, udp_socket: &UdpSocket, buf: &[u8], addr: A, ) -> io::Result { let mut addrs = addr.to_socket_addrs()?; // `UdpSocket::send_to` only sends to the first address. let addr = addrs.next().ok_or_else(no_socket_addrs)?; self.cap.check_addr(&addr)?; udp_socket.std.send_to(buf, addr) } /// Connects this UDP socket to a remote address, allowing the `send` and /// `recv` syscalls to be used to send data and also applies filters to /// only receive data from the specified address. /// /// This corresponds to [`std::net::UdpSocket::connect`]. #[doc(alias = "connect")] #[inline] pub fn connect_udp_socket( &self, udp_socket: &UdpSocket, addr: A, ) -> io::Result<()> { let addrs = addr.to_socket_addrs()?; let mut last_err = None; for addr in addrs { self.cap.check_addr(&addr)?; match udp_socket.std.connect(addr) { Ok(()) => return Ok(()), Err(e) => last_err = Some(e), } } match last_err { Some(e) => Err(e), None => Err(no_socket_addrs()), } } /// This is for cap-net-ext. #[doc(hidden)] pub fn _pool(&self) -> &cap_primitives::net::Pool { &self.cap } } cap-std-3.4.4/src/net/tcp_listener.rs000064400000000000000000000145161046102023000156140ustar 00000000000000use crate::net::{Incoming, SocketAddr, TcpStream}; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; use std::{fmt, io, net}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, }; /// A TCP socket server, listening for connections. /// /// This corresponds to [`std::net::TcpListener`]. /// /// This `TcpListener` has no `bind` method. To bind it to a socket address, /// first obtain a [`Pool`] permitting the address, and then call /// [`Pool::bind_tcp_listener`]. /// /// [`Pool`]: struct.Pool.html /// [`Pool::bind_tcp_listener`]: struct.Pool.html#method.bind_tcp_listener pub struct TcpListener { std: net::TcpListener, } impl TcpListener { /// Constructs a new instance of `Self` from the given /// `std::net::TcpListener`. /// /// This grants access the resources the `std::net::TcpListener` instance /// already has access to. #[inline] pub fn from_std(std: net::TcpListener) -> Self { Self { std } } /// Returns the local socket address of this listener. /// /// This corresponds to [`std::net::TcpListener::local_addr`]. #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::net::TcpListener::try_clone`]. #[inline] pub fn try_clone(&self) -> io::Result { let tcp_listener = self.std.try_clone()?; Ok(Self::from_std(tcp_listener)) } /// Accept a new incoming connection from this listener. /// /// This corresponds to [`std::net::TcpListener::accept`]. #[inline] pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { self.std .accept() .map(|(tcp_stream, addr)| (TcpStream::from_std(tcp_stream), addr)) } /// Returns an iterator over the connections being received on this /// listener. /// /// This corresponds to [`std::net::TcpListener::incoming`]. #[inline] pub fn incoming(&self) -> Incoming { let incoming = self.std.incoming(); Incoming::from_std(incoming) } /// Sets the value for the `IP_TTL` option on this socket. /// /// This corresponds to [`std::net::TcpListener::set_ttl`]. #[inline] pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.std.set_ttl(ttl) } /// Gets the value of the `IP_TTL` option for this socket. /// /// This corresponds to [`std::net::TcpListener::ttl`]. #[inline] pub fn ttl(&self) -> io::Result { self.std.ttl() } /// Gets the value of the `SO_ERROR` option on this socket. /// /// This corresponds to [`std::net::TcpListener::take_error`]. #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Moves this TCP stream into or out of nonblocking mode. /// /// This corresponds to [`std::net::TcpListener::set_nonblocking`]. #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } } // Safety: `SocketlikeViewType` is implemented for `std`'s socket types. unsafe impl io_lifetimes::views::SocketlikeViewType for TcpListener {} #[cfg(not(windows))] impl FromRawFd for TcpListener { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(net::TcpListener::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for TcpListener { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(net::TcpListener::from(fd)) } } #[cfg(windows)] impl FromRawSocket for TcpListener { #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { Self::from_std(net::TcpListener::from_raw_socket(socket)) } } #[cfg(windows)] impl From for TcpListener { #[inline] fn from(socket: OwnedSocket) -> Self { Self::from_std(net::TcpListener::from(socket)) } } #[cfg(not(windows))] impl AsRawFd for TcpListener { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for TcpListener { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } #[cfg(windows)] impl AsRawSocket for TcpListener { #[inline] fn as_raw_socket(&self) -> RawSocket { self.std.as_raw_socket() } } #[cfg(windows)] impl AsSocket for TcpListener { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { self.std.as_socket() } } #[cfg(windows)] impl AsRawHandleOrSocket for TcpListener { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for TcpListener { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for TcpListener { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(listener: TcpListener) -> OwnedFd { listener.std.into() } } #[cfg(windows)] impl IntoRawSocket for TcpListener { #[inline] fn into_raw_socket(self) -> RawSocket { self.std.into_raw_socket() } } #[cfg(windows)] impl From for OwnedSocket { #[inline] fn from(listener: TcpListener) -> OwnedSocket { listener.std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for TcpListener { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(listener: TcpListener) -> Self { listener.std.into() } } impl fmt::Debug for TcpListener { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/net/tcp_stream.rs000064400000000000000000000261131046102023000152560ustar 00000000000000use crate::net::{Shutdown, SocketAddr}; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; use std::io::{self, IoSlice, IoSliceMut, Read, Write}; use std::time::Duration; use std::{fmt, net}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, }; /// A TCP stream between a local and a remote socket. /// /// This corresponds to [`std::net::TcpStream`]. /// /// This `TcpStream` has no `connect` method. To create a `TcpStream`, first /// obtain a [`Pool`] permitting the address, and then call /// [`Pool::connect_tcp_stream`]. /// /// [`Pool`]: struct.Pool.html /// [`Pool::connect_tcp_stream`]: struct.Pool.html#method.connect_tcp_stream pub struct TcpStream { std: net::TcpStream, } impl TcpStream { /// Constructs a new instance of `Self` from the given /// `std::net::TcpStream`. /// /// This grants access the resources the `std::net::TcpStream` instance /// already has access to. #[inline] pub fn from_std(std: net::TcpStream) -> Self { Self { std } } /// Returns the socket address of the remote peer of this TCP connection. /// /// This corresponds to [`std::net::TcpStream::peer_addr`]. #[inline] pub fn peer_addr(&self) -> io::Result { self.std.peer_addr() } /// Returns the local socket address of this listener. /// /// This corresponds to [`std::net::TcpStream::local_addr`]. #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Shuts down the read, write, or both halves of this connection. /// /// This corresponds to [`std::net::TcpStream::shutdown`]. #[inline] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.std.shutdown(how) } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::net::TcpStream::try_clone`]. #[inline] pub fn try_clone(&self) -> io::Result { let tcp_stream = self.std.try_clone()?; Ok(Self::from_std(tcp_stream)) } /// Sets the read timeout to the timeout specified. /// /// This corresponds to [`std::net::TcpStream::set_read_timeout`]. #[inline] pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.std.set_read_timeout(dur) } /// Sets the write timeout to the timeout specified. /// /// This corresponds to [`std::net::TcpStream::set_write_timeout`]. #[inline] pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.std.set_write_timeout(dur) } /// Returns the read timeout of this socket. /// /// This corresponds to [`std::net::TcpStream::read_timeout`]. #[inline] pub fn read_timeout(&self) -> io::Result> { self.std.read_timeout() } /// Returns the write timeout of this socket. /// /// This corresponds to [`std::net::TcpStream::write_timeout`]. #[inline] pub fn write_timeout(&self) -> io::Result> { self.std.write_timeout() } /// Receives data on the socket from the remote address to which it is /// connected, without removing that data from the queue. /// /// This corresponds to [`std::net::TcpStream::peek`]. #[inline] pub fn peek(&self, buf: &mut [u8]) -> io::Result { self.std.peek(buf) } /// Sets the value of the `TCP_NODELAY` option on this socket. /// /// This corresponds to [`std::net::TcpStream::set_nodelay`]. #[inline] pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { self.std.set_nodelay(nodelay) } /// Gets the value of the `TCP_NODELAY` option on this socket. /// /// This corresponds to [`std::net::TcpStream::nodelay`]. #[inline] pub fn nodelay(&self) -> io::Result { self.std.nodelay() } /// Sets the value for the `IP_TTL` option on this socket. /// /// This corresponds to [`std::net::TcpStream::set_ttl`]. #[inline] pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.std.set_ttl(ttl) } /// Gets the value of the `IP_TTL` option for this socket. /// /// This corresponds to [`std::net::TcpStream::ttl`]. #[inline] pub fn ttl(&self) -> io::Result { self.std.ttl() } /// Gets the value of the `SO_ERROR` option on this socket. /// /// This corresponds to [`std::net::TcpStream::take_error`]. #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Moves this TCP stream into or out of nonblocking mode. /// /// This corresponds to [`std::net::TcpStream::set_nonblocking`]. #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } } // Safety: `SocketlikeViewType` is implemented for `std`'s socket types. unsafe impl io_lifetimes::views::SocketlikeViewType for TcpStream {} #[cfg(not(windows))] impl FromRawFd for TcpStream { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(net::TcpStream::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for TcpStream { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(net::TcpStream::from(fd)) } } #[cfg(windows)] impl FromRawSocket for TcpStream { #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { Self::from_std(net::TcpStream::from_raw_socket(socket)) } } #[cfg(windows)] impl From for TcpStream { #[inline] fn from(socket: OwnedSocket) -> Self { Self::from_std(net::TcpStream::from(socket)) } } #[cfg(not(windows))] impl AsRawFd for TcpStream { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for TcpStream { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } #[cfg(windows)] impl AsRawSocket for TcpStream { #[inline] fn as_raw_socket(&self) -> RawSocket { self.std.as_raw_socket() } } #[cfg(windows)] impl AsSocket for TcpStream { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { self.std.as_socket() } } #[cfg(windows)] impl AsRawHandleOrSocket for TcpStream { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for TcpStream { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for TcpStream { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(stream: TcpStream) -> OwnedFd { stream.std.into() } } #[cfg(windows)] impl IntoRawSocket for TcpStream { #[inline] fn into_raw_socket(self) -> RawSocket { self.std.into_raw_socket() } } #[cfg(windows)] impl From for OwnedSocket { #[inline] fn from(socket: TcpStream) -> OwnedSocket { socket.std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for TcpStream { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(stream: TcpStream) -> Self { stream.std.into() } } impl Read for TcpStream { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.std.read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { self.std.read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.std.read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.std.read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { self.std.read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Read for &TcpStream { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (&mut &self.std).read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { (&mut &self.std).read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (&mut &self.std).read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (&mut &self.std).read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (&mut &self.std).read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Write for TcpStream { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.std.write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { self.std.flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { self.std.write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.std.write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { self.std.write_all_vectored(bufs) } } impl Write for &TcpStream { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (&mut &self.std).write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { (&mut &self.std).flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { (&mut &self.std).write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (&mut &self.std).write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { (&mut &self.std).write_all_vectored(bufs) } } impl fmt::Debug for TcpStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/net/udp_socket.rs000064400000000000000000000304611046102023000152560ustar 00000000000000use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; #[cfg(not(windows))] use io_extras::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; #[cfg(not(windows))] use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; #[cfg(windows)] use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; use std::time::Duration; use std::{fmt, io, net}; #[cfg(windows)] use { io_extras::os::windows::{ AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, OwnedHandleOrSocket, RawHandleOrSocket, }, std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, }; /// A UDP socket. /// /// This corresponds to [`std::net::UdpSocket`]. /// /// This `UdpSocket` has no `bind`, `connect`, or `send_to` methods. To create /// a `UdpSocket` bound to an address or to send a message to an address, first /// obtain a [`Pool`] permitting the address, and then call /// [`Pool::bind_udp_socket`], or [`Pool::connect_udp_socket`], or /// [`Pool::send_to_udp_socket_addr`]. /// /// [`Pool`]: struct.Pool.html /// [`Pool::bind_udp_socket`]: struct.Pool.html#method.bind_udp_socket /// [`Pool::connect_udp_socket`]: struct.Pool.html#method.connect_udp_socket /// [`Pool::send_to_udp_socket_addr`]: struct.Pool.html#method.send_to_udp_socket_addr pub struct UdpSocket { pub(crate) std: net::UdpSocket, } impl UdpSocket { /// Constructs a new instance of `Self` from the given /// `std::net::UdpSocket`. /// /// This grants access the resources the `std::net::UdpSocket` instance /// already has access to. #[inline] pub fn from_std(std: net::UdpSocket) -> Self { Self { std } } /// Receives a single datagram message on the socket. /// /// This corresponds to [`std::net::UdpSocket::recv_from`]. #[inline] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.std.recv_from(buf) } /// Receives a single datagram message on the socket, without removing it /// from the queue. /// /// This corresponds to [`std::net::UdpSocket::peek_from`]. #[inline] pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.std.peek_from(buf) } /// Returns the socket address of the remote peer this socket was connected /// to. /// /// This corresponds to [`std::net::UdpSocket::peer_addr`]. #[inline] pub fn peer_addr(&self) -> io::Result { self.std.peer_addr() } /// Returns the socket address that this socket was created from. /// /// This corresponds to [`std::net::UdpSocket::local_addr`]. #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::net::UdpSocket::try_clone`]. #[inline] pub fn try_clone(&self) -> io::Result { let udp_socket = self.std.try_clone()?; Ok(Self::from_std(udp_socket)) } /// Sets the read timeout to the timeout specified. /// /// This corresponds to [`std::net::UdpSocket::set_read_timeout`]. #[inline] pub fn set_read_timeout(&self, dur: Option) -> io::Result<()> { self.std.set_read_timeout(dur) } /// Sets the write timeout to the timeout specified. /// /// This corresponds to [`std::net::UdpSocket::set_write_timeout`]. #[inline] pub fn set_write_timeout(&self, dur: Option) -> io::Result<()> { self.std.set_write_timeout(dur) } /// Returns the read timeout of this socket. /// /// This corresponds to [`std::net::UdpSocket::read_timeout`]. #[inline] pub fn read_timeout(&self) -> io::Result> { self.std.read_timeout() } /// Returns the write timeout of this socket. /// /// This corresponds to [`std::net::UdpSocket::write_timeout`]. #[inline] pub fn write_timeout(&self) -> io::Result> { self.std.write_timeout() } /// Sets the value of the `SO_BROADCAST` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::set_broadcast`]. #[inline] pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { self.std.set_broadcast(broadcast) } /// Gets the value of the `SO_BROADCAST` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::broadcast`]. #[inline] pub fn broadcast(&self) -> io::Result { self.std.broadcast() } /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::set_multicast_loop_v4`]. #[inline] pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { self.std.set_multicast_loop_v4(multicast_loop_v4) } /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::multicast_loop_v4`]. #[inline] pub fn multicast_loop_v4(&self) -> io::Result { self.std.multicast_loop_v4() } /// Sets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::set_multicast_ttl_v4`]. #[inline] pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { self.std.set_multicast_ttl_v4(multicast_ttl_v4) } /// Gets the value of the `IP_MULTICAST_TTL` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::multicast_ttl_v4`]. #[inline] pub fn multicast_ttl_v4(&self) -> io::Result { self.std.multicast_ttl_v4() } /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::set_multicast_loop_v6`]. #[inline] pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { self.std.set_multicast_loop_v6(multicast_loop_v6) } /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::multicast_loop_v6`]. #[inline] pub fn multicast_loop_v6(&self) -> io::Result { self.std.multicast_loop_v6() } /// Sets the value for the `IP_TTL` option on this socket. /// /// This corresponds to [`std::net::UdpSocket::set_ttl`]. #[inline] pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { self.std.set_ttl(ttl) } /// Gets the value of the `IP_TTL` option for this socket. /// /// This corresponds to [`std::net::UdpSocket::ttl`]. #[inline] pub fn ttl(&self) -> io::Result { self.std.ttl() } /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. /// /// This corresponds to [`std::net::UdpSocket::join_multicast_v4`]. #[allow(clippy::trivially_copy_pass_by_ref)] #[inline] pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { self.std.join_multicast_v4(multiaddr, interface) } /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type. /// /// This corresponds to [`std::net::UdpSocket::join_multicast_v6`]. #[allow(clippy::trivially_copy_pass_by_ref)] #[inline] pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { self.std.join_multicast_v6(multiaddr, interface) } /// Executes an operation of the `IP_DROP_MEMBERSHIP` type. /// /// This corresponds to [`std::net::UdpSocket::leave_multicast_v4`]. #[allow(clippy::trivially_copy_pass_by_ref)] #[inline] pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { self.std.leave_multicast_v4(multiaddr, interface) } /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type. /// /// This corresponds to [`std::net::UdpSocket::leave_multicast_v6`]. #[allow(clippy::trivially_copy_pass_by_ref)] #[inline] pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { self.std.leave_multicast_v6(multiaddr, interface) } /// Gets the value of the `SO_ERROR` option on this socket. /// /// This corresponds to [`std::net::UdpSocket::take_error`]. #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Sends data on the socket to the remote address to which it is /// connected. /// /// This corresponds to [`std::net::UdpSocket::send`]. #[inline] pub fn send(&self, buf: &[u8]) -> io::Result { self.std.send(buf) } /// Receives a single datagram message on the socket from the remote /// address to which it is connected. /// /// This corresponds to [`std::net::UdpSocket::recv`]. #[inline] pub fn recv(&self, buf: &mut [u8]) -> io::Result { self.std.recv(buf) } /// Receives single datagram on the socket from the remote address to which /// it is connected, without removing the message from input queue. /// /// This corresponds to [`std::net::UdpSocket::peek`]. #[inline] pub fn peek(&self, buf: &mut [u8]) -> io::Result { self.std.peek(buf) } /// Moves this UDP socket into or out of nonblocking mode. /// /// This corresponds to [`std::net::UdpSocket::set_nonblocking`]. #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } } // Safety: `SocketlikeViewType` is implemented for `std`'s socket types. unsafe impl io_lifetimes::views::SocketlikeViewType for UdpSocket {} #[cfg(not(windows))] impl FromRawFd for UdpSocket { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(net::UdpSocket::from_raw_fd(fd)) } } #[cfg(not(windows))] impl From for UdpSocket { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(net::UdpSocket::from(fd)) } } #[cfg(windows)] impl FromRawSocket for UdpSocket { #[inline] unsafe fn from_raw_socket(socket: RawSocket) -> Self { Self::from_std(net::UdpSocket::from_raw_socket(socket)) } } #[cfg(windows)] impl From for UdpSocket { #[inline] fn from(socket: OwnedSocket) -> Self { Self::from_std(net::UdpSocket::from(socket)) } } #[cfg(not(windows))] impl AsRawFd for UdpSocket { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } #[cfg(not(windows))] impl AsFd for UdpSocket { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } #[cfg(windows)] impl AsRawSocket for UdpSocket { #[inline] fn as_raw_socket(&self) -> RawSocket { self.std.as_raw_socket() } } #[cfg(windows)] impl AsSocket for UdpSocket { #[inline] fn as_socket(&self) -> BorrowedSocket<'_> { self.std.as_socket() } } #[cfg(windows)] impl AsRawHandleOrSocket for UdpSocket { #[inline] fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { self.std.as_raw_handle_or_socket() } } #[cfg(windows)] impl AsHandleOrSocket for UdpSocket { #[inline] fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { self.std.as_handle_or_socket() } } #[cfg(not(windows))] impl IntoRawFd for UdpSocket { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } #[cfg(not(windows))] impl From for OwnedFd { #[inline] fn from(socket: UdpSocket) -> OwnedFd { socket.std.into() } } #[cfg(windows)] impl IntoRawSocket for UdpSocket { #[inline] fn into_raw_socket(self) -> RawSocket { self.std.into_raw_socket() } } #[cfg(windows)] impl From for OwnedSocket { #[inline] fn from(socket: UdpSocket) -> OwnedSocket { socket.std.into() } } #[cfg(windows)] impl IntoRawHandleOrSocket for UdpSocket { #[inline] fn into_raw_handle_or_socket(self) -> RawHandleOrSocket { self.std.into_raw_handle_or_socket() } } #[cfg(windows)] impl From for OwnedHandleOrSocket { #[inline] fn from(socket: UdpSocket) -> Self { socket.std.into() } } impl fmt::Debug for UdpSocket { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/os/mod.rs000064400000000000000000000001441046102023000135230ustar 00000000000000//! OS-specific functionality. //! //! This corresponds to [`std::os`]. #[cfg(unix)] pub mod unix; cap-std-3.4.4/src/os/unix/mod.rs000064400000000000000000000002731046102023000145110ustar 00000000000000//! Platform-specific extensions to std for Unix platforms. //! //! This corresponds to [`std::os::unix`]. //! //! [`std::os::unix`]: https://doc.rust-lang.org/std/os/unix/ pub mod net; cap-std-3.4.4/src/os/unix/net/incoming.rs000064400000000000000000000024161046102023000163240ustar 00000000000000use crate::os::unix::net::UnixStream; use std::os::unix; use std::{fmt, io}; /// An iterator over incoming connections to a [`UnixListener`]. /// /// This corresponds to [`std::os::unix::net::Incoming`]. /// /// [`std::os::unix::net::Incoming`]: https://doc.rust-lang.org/std/os/unix/net/struct.Incoming.html /// [`UnixListener`]: struct.UnixListener.html pub struct Incoming<'a> { std: unix::net::Incoming<'a>, } impl<'a> Incoming<'a> { /// Constructs a new instance of `Self` from the given /// `std::os::unix::net::Incoming`. /// /// This grants access the resources the `std::os::unix::net::Incoming` /// instance already has access to. #[inline] pub fn from_std(std: unix::net::Incoming<'a>) -> Self { Self { std } } } impl<'a> Iterator for Incoming<'a> { type Item = io::Result; #[inline] fn next(&mut self) -> Option { self.std.next().map(|result| { let unix_stream = result?; Ok(UnixStream::from_std(unix_stream)) }) } #[inline] fn size_hint(&self) -> (usize, Option) { self.std.size_hint() } } impl<'a> fmt::Debug for Incoming<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/os/unix/net/mod.rs000064400000000000000000000012111046102023000152700ustar 00000000000000//! Unix-specific networking functionality //! //! This corresponds to [`std::os::unix::net`]. //! //! This module is not yet implemented. And it's not easily implementable //! on many platforms. See [this POSIX discussion] which ultimately didn't //! succeed in adding support to POSIX. //! //! [`std::os::unix::net`]: https://doc.rust-lang.org/std/os/unix/net/ //! [this POSIX discussion]: https://www.austingroupbugs.net/view.php?id=980 mod incoming; mod unix_datagram; mod unix_listener; mod unix_stream; pub use incoming::*; pub use unix_datagram::*; pub use unix_listener::*; pub use unix_stream::*; pub use std::os::unix::net::SocketAddr; cap-std-3.4.4/src/os/unix/net/unix_datagram.rs000064400000000000000000000211651046102023000173460ustar 00000000000000use crate::net::Shutdown; use crate::os::unix::net::SocketAddr; use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; use std::os::unix; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::time::Duration; use std::{fmt, io}; /// A Unix datagram socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram`]. /// /// This `UnixDatagram` has no `bind`, `connect`, or `send_to` methods. To /// create a `UnixDatagram`, first obtain a [`Dir`] containing the path, and /// then call [`Dir::bind_unix_datagram`], [`Dir::connect_unix_datagram`], or /// [`Dir::send_to_unix_datagram_addr`]. /// /// [`std::os::unix::net::UnixDatagram`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html /// [`Dir`]: struct.Dir.html /// [`Dir::connect_unix_datagram`]: struct.Dir.html#method.connect_unix_datagram /// [`Dir::bind_unix_datagram`]: struct.Dir.html#method.bind_unix_datagram /// [`Dir::send_to_unix_datagram_addr`]: struct.Dir.html#method.send_to_unix_datagram_addr pub struct UnixDatagram { std: unix::net::UnixDatagram, } impl UnixDatagram { /// Constructs a new instance of `Self` from the given /// `std::os::unix::net::UnixDatagram`. /// /// This grants access the resources the `std::os::unix::net::UnixDatagram` /// instance already has access to. #[inline] pub fn from_std(std: unix::net::UnixDatagram) -> Self { Self { std } } /// Creates a Unix Datagram socket which is not bound to any address. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::unbound`]. /// /// TODO: should this require a capability? /// /// [`std::os::unix::net::UnixDatagram::unbound`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.unbound #[inline] pub fn unbound() -> io::Result { let unix_datagram = unix::net::UnixDatagram::unbound()?; Ok(Self::from_std(unix_datagram)) } /// Creates an unnamed pair of connected sockets. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::pair`]. /// /// TODO: should this require a capability? /// /// [`std::os::unix::net::UnixDatagram::pair`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.pair #[inline] pub fn pair() -> io::Result<(Self, Self)> { unix::net::UnixDatagram::pair().map(|(a, b)| (Self::from_std(a), Self::from_std(b))) } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::try_clone`]. /// /// [`std::os::unix::net::UnixDatagram::try_clone`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.try_clone #[inline] pub fn try_clone(&self) -> io::Result { let unix_datagram = self.std.try_clone()?; Ok(Self::from_std(unix_datagram)) } /// Returns the address of this socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::local_addr`]. /// /// [`std::os::unix::net::UnixDatagram::local_addr`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.local_addr #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Returns the address of this socket's peer. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::peer_addr`]. /// /// [`std::os::unix::net::UnixDatagram::peer_addr`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.peer_addr #[inline] pub fn peer_addr(&self) -> io::Result { self.std.peer_addr() } /// Receives data from the socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::recv_from`]. /// /// [`std::os::unix::net::UnixDatagram::recv_from`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.recv_from #[inline] pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { self.std.recv_from(buf) } /// Receives data from the socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::recv`]. /// /// [`std::os::unix::net::UnixDatagram::recv`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.recv #[inline] pub fn recv(&self, buf: &mut [u8]) -> io::Result { self.std.recv(buf) } /// Sends data on the socket to the socket's peer. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::send`]. /// /// [`std::os::unix::net::UnixDatagram::send`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.send #[inline] pub fn send(&self, buf: &[u8]) -> io::Result { self.std.send(buf) } /// Sets the read timeout for the socket. /// /// This corresponds to /// [`std::os::unix::net::UnixDatagram::set_read_timeout`]. /// /// [`std::os::unix::net::UnixDatagram::set_read_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.set_read_timeout #[inline] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.std.set_read_timeout(timeout) } /// Sets the write timeout for the socket. /// /// This corresponds to /// [`std::os::unix::net::UnixDatagram::set_write_timeout`]. /// /// [`std::os::unix::net::UnixDatagram::set_write_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.set_write_timeout #[inline] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.std.set_write_timeout(timeout) } /// Returns the read timeout of this socket. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::read_timeout`]. /// /// [`std::os::unix::net::UnixDatagram::read_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.read_timeout #[inline] pub fn read_timeout(&self) -> io::Result> { self.std.read_timeout() } /// Returns the write timeout of this socket. /// /// This corresponds to /// [`std::os::unix::net::UnixDatagram::write_timeout`]. /// /// [`std::os::unix::net::UnixDatagram::write_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.write_timeout #[inline] pub fn write_timeout(&self) -> io::Result> { self.std.write_timeout() } /// Moves the socket into or out of nonblocking mode. /// /// This corresponds to /// [`std::os::unix::net::UnixDatagram::set_nonblocking`]. /// /// [`std::os::unix::net::UnixDatagram::set_nonblocking`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.set_nonblocking #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::take_error`]. /// /// [`std::os::unix::net::UnixDatagram::take_error`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.take_error #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Shut down the read, write, or both halves of this connection. /// /// This corresponds to [`std::os::unix::net::UnixDatagram::shutdown`]. /// /// [`std::os::unix::net::UnixDatagram::shutdown`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixDatagram.html#method.shutdown #[inline] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.std.shutdown(how) } } impl FromRawFd for UnixDatagram { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(unix::net::UnixDatagram::from_raw_fd(fd)) } } impl From for UnixDatagram { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(unix::net::UnixDatagram::from(fd)) } } impl AsRawFd for UnixDatagram { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } impl AsFd for UnixDatagram { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } impl IntoRawFd for UnixDatagram { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } impl From for OwnedFd { #[inline] fn from(datagram: UnixDatagram) -> OwnedFd { datagram.std.into() } } impl fmt::Debug for UnixDatagram { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/os/unix/net/unix_listener.rs000064400000000000000000000116431046102023000174130ustar 00000000000000use crate::os::unix::net::{Incoming, SocketAddr, UnixStream}; use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; use std::os::unix; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::{fmt, io}; /// A structure representing a Unix domain socket server. /// /// This corresponds to [`std::os::unix::net::UnixListener`]. /// /// This `UnixListener` has no `bind` method. To bind it to a socket address, /// first obtain a [`Dir`] containing the path, and then call /// [`Dir::bind_unix_listener`]. /// /// [`std::os::unix::net::UnixListener`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html /// [`Dir`]: struct.Dir.html /// [`Dir::bind_unix_listener`]: struct.Dir.html#method.bind_unix_listener pub struct UnixListener { std: unix::net::UnixListener, } impl UnixListener { /// Constructs a new instance of `Self` from the given /// `std::os::unix::net::UnixListener`. /// /// This grants access the resources the `std::os::unix::net::UnixListener` /// instance already has access to. #[inline] pub fn from_std(std: unix::net::UnixListener) -> Self { Self { std } } /// Accepts a new incoming connection to this listener. /// /// This corresponds to [`std::os::unix::net::UnixListener::accept`]. /// /// [`std::os::unix::net::UnixListener::accept`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.accept #[inline] pub fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { self.std .accept() .map(|(unix_stream, addr)| (UnixStream::from_std(unix_stream), addr)) } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::os::unix::net::UnixListener::try_clone`]. /// /// [`std::os::unix::net::UnixListener::try_clone`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.try_clone #[inline] pub fn try_clone(&self) -> io::Result { let unix_listener = self.std.try_clone()?; Ok(Self::from_std(unix_listener)) } /// Returns the local socket address of this listener. /// /// This corresponds to [`std::os::unix::net::UnixListener::local_addr`]. /// /// [`std::os::unix::net::UnixListener::local_addr`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.local_addr #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Moves the socket into or out of nonblocking mode. /// /// This corresponds to /// [`std::os::unix::net::UnixListener::set_nonblocking`]. /// /// [`std::os::unix::net::UnixListener::set_nonblocking`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.set_nonblocking #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. /// /// This corresponds to [`std::os::unix::net::UnixListener::take_error`]. /// /// [`std::os::unix::net::UnixListener::take_error`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.take_error #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Returns an iterator over incoming connections. /// /// This corresponds to [`std::os::unix::net::UnixListener::incoming`]. /// /// [`std::os::unix::net::UnixListener::incoming`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixListener.html#method.incoming #[inline] pub fn incoming(&self) -> Incoming { let incoming = self.std.incoming(); Incoming::from_std(incoming) } } impl FromRawFd for UnixListener { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(unix::net::UnixListener::from_raw_fd(fd)) } } impl From for UnixListener { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(unix::net::UnixListener::from(fd)) } } impl AsRawFd for UnixListener { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } impl AsFd for UnixListener { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } impl IntoRawFd for UnixListener { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } impl From for OwnedFd { #[inline] fn from(listener: UnixListener) -> OwnedFd { listener.std.into() } } impl<'a> IntoIterator for &'a UnixListener { type IntoIter = Incoming<'a>; type Item = io::Result; #[inline] fn into_iter(self) -> Incoming<'a> { let incoming = self.std.into_iter(); Incoming::from_std(incoming) } } impl fmt::Debug for UnixListener { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/os/unix/net/unix_stream.rs000064400000000000000000000234411046102023000170600ustar 00000000000000use crate::net::Shutdown; use crate::os::unix::net::SocketAddr; use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; use std::fmt; use std::io::{self, IoSlice, IoSliceMut, Read, Write}; use std::os::unix; use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::time::Duration; /// A Unix stream socket. /// /// This corresponds to [`std::os::unix::net::UnixStream`]. /// /// This `UnixStream` has no `connect` method. To create a `UnixStream`, first /// obtain a [`Dir`] containing the path, and then call /// [`Dir::connect_unix_stream`]. /// /// [`std::os::unix::net::UnixStream`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html /// [`Dir`]: struct.Dir.html /// [`Dir::connect_unix_stream`]: struct.Dir.html#method.connect_unix_stream pub struct UnixStream { std: unix::net::UnixStream, } impl UnixStream { /// Constructs a new instance of `Self` from the given /// `std::os::unix::net::UnixStream`. /// /// This grants access the resources the `std::os::unix::net::UnixStream` /// instance already has access to. #[inline] pub fn from_std(std: unix::net::UnixStream) -> Self { Self { std } } /// Creates an unnamed pair of connected sockets. /// /// This corresponds to [`std::os::unix::net::UnixStream::pair`]. /// /// TODO: should this require a capability? /// /// [`std::os::unix::net::UnixStream::pair`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.pair #[inline] pub fn pair() -> io::Result<(Self, Self)> { unix::net::UnixStream::pair().map(|(a, b)| (Self::from_std(a), Self::from_std(b))) } /// Creates a new independently owned handle to the underlying socket. /// /// This corresponds to [`std::os::unix::net::UnixStream::try_clone`]. /// /// [`std::os::unix::net::UnixStream::try_clone`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.try_clone #[inline] pub fn try_clone(&self) -> io::Result { let unix_stream = self.std.try_clone()?; Ok(Self::from_std(unix_stream)) } /// Returns the socket address of the local half of this connection. /// /// This corresponds to [`std::os::unix::net::UnixStream::local_addr`]. /// /// [`std::os::unix::net::UnixStream::local_addr`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.local_addr #[inline] pub fn local_addr(&self) -> io::Result { self.std.local_addr() } /// Returns the socket address of the remote half of this connection. /// /// This corresponds to [`std::os::unix::net::UnixStream::peer_addr`]. /// /// [`std::os::unix::net::UnixStream::peer_addr`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.peer_addr #[inline] pub fn peer_addr(&self) -> io::Result { self.std.peer_addr() } /// Sets the read timeout for the socket. /// /// This corresponds to /// [`std::os::unix::net::UnixStream::set_read_timeout`]. /// /// [`std::os::unix::net::UnixStream::set_read_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.set_read_timeout #[inline] pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { self.std.set_read_timeout(timeout) } /// Sets the write timeout for the socket. /// /// This corresponds to /// [`std::os::unix::net::UnixStream::set_write_timeout`]. /// /// [`std::os::unix::net::UnixStream::set_write_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.set_write_timeout #[inline] pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { self.std.set_write_timeout(timeout) } /// Returns the read timeout of this socket. /// /// This corresponds to [`std::os::unix::net::UnixStream::read_timeout`]. /// /// [`std::os::unix::net::UnixStream::read_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.read_timeout #[inline] pub fn read_timeout(&self) -> io::Result> { self.std.read_timeout() } /// Returns the write timeout of this socket. /// /// This corresponds to [`std::os::unix::net::UnixStream::write_timeout`]. /// /// [`std::os::unix::net::UnixStream::write_timeout`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.write_timeout #[inline] pub fn write_timeout(&self) -> io::Result> { self.std.write_timeout() } /// Moves the socket into or out of nonblocking mode. /// /// This corresponds to /// [`std::os::unix::net::UnixStream::set_nonblocking`]. /// /// [`std::os::unix::net::UnixStream::set_nonblocking`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.set_nonblocking #[inline] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { self.std.set_nonblocking(nonblocking) } /// Returns the value of the `SO_ERROR` option. /// /// This corresponds to [`std::os::unix::net::UnixStream::take_error`]. /// /// [`std::os::unix::net::UnixStream::take_error`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.take_error #[inline] pub fn take_error(&self) -> io::Result> { self.std.take_error() } /// Shuts down the read, write, or both halves of this connection. /// /// This corresponds to [`std::os::unix::net::UnixStream::shutdown`]. /// /// [`std::os::unix::net::UnixStream::shutdown`]: https://doc.rust-lang.org/std/os/unix/net/struct.UnixStream.html#method.shutdown #[inline] pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { self.std.shutdown(how) } } impl FromRawFd for UnixStream { #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { Self::from_std(unix::net::UnixStream::from_raw_fd(fd)) } } impl From for UnixStream { #[inline] fn from(fd: OwnedFd) -> Self { Self::from_std(unix::net::UnixStream::from(fd)) } } impl AsRawFd for UnixStream { #[inline] fn as_raw_fd(&self) -> RawFd { self.std.as_raw_fd() } } impl AsFd for UnixStream { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.std.as_fd() } } impl IntoRawFd for UnixStream { #[inline] fn into_raw_fd(self) -> RawFd { self.std.into_raw_fd() } } impl From for OwnedFd { #[inline] fn from(stream: UnixStream) -> OwnedFd { stream.std.into() } } impl Read for UnixStream { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { self.std.read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { self.std.read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.std.read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { self.std.read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { self.std.read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Read for &UnixStream { #[inline] fn read(&mut self, buf: &mut [u8]) -> io::Result { (&mut &self.std).read(buf) } #[inline] fn read_vectored(&mut self, bufs: &mut [IoSliceMut]) -> io::Result { (&mut &self.std).read_vectored(bufs) } #[inline] fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (&mut &self.std).read_exact(buf) } #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { (&mut &self.std).read_to_end(buf) } #[inline] fn read_to_string(&mut self, buf: &mut String) -> io::Result { (&mut &self.std).read_to_string(buf) } #[cfg(can_vector)] #[inline] fn is_read_vectored(&self) -> bool { self.std.is_read_vectored() } } impl Write for UnixStream { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { self.std.write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { self.std.flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { self.std.write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { self.std.write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { self.std.write_all_vectored(bufs) } } impl Write for &UnixStream { #[inline] fn write(&mut self, buf: &[u8]) -> io::Result { (&mut &self.std).write(buf) } #[inline] fn flush(&mut self) -> io::Result<()> { (&mut &self.std).flush() } #[inline] fn write_vectored(&mut self, bufs: &[IoSlice]) -> io::Result { (&mut &self.std).write_vectored(bufs) } #[inline] fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (&mut &self.std).write_all(buf) } #[cfg(can_vector)] #[inline] fn is_write_vectored(&self) -> bool { self.std.is_write_vectored() } #[cfg(write_all_vectored)] #[inline] fn write_all_vectored(&mut self, bufs: &mut [IoSlice]) -> io::Result<()> { (&mut &self.std).write_all_vectored(bufs) } } impl fmt::Debug for UnixStream { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.std.fmt(f) } } cap-std-3.4.4/src/time/mod.rs000064400000000000000000000005561046102023000140470ustar 00000000000000//! A capability-based clock API modeled after [`std::time`]. //! //! This corresponds to [`std::time`]. //! //! Instead of [`std::time`]'s methods which return the current time, this //! crate has methods on [`SystemClock`] and [`MonotonicClock`]. pub use cap_primitives::time::{ Duration, Instant, MonotonicClock, SystemClock, SystemTime, SystemTimeError, };