diff --git a/Cargo.toml b/Cargo.toml index 650d8e9e..68e05c05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,7 @@ exclude = ["/.*"] rust-version = "1.63" [dev-dependencies] -async-std = { version = "1.13.0", features = ["attributes", "io_safety"] } anyhow = "1.0.37" -cap-async-std = { path = "cap-async-std", version = "3.4.5" } cap-fs-ext = { path = "cap-fs-ext", version = "3.4.5" } cap-net-ext = { path = "cap-net-ext", version = "3.4.5" } cap-directories = { path = "cap-directories", version = "3.4.5" } @@ -56,23 +54,14 @@ fs_utf8 = [ "cap-fs-ext/fs_utf8", "cap-tempfile/fs_utf8", ] -async_std_fs_utf8 = [ - "cap-async-std/fs_utf8", - "cap-fs-ext/async_std_fs_utf8" -] arf_strings = [ "cap-std/arf_strings", "cap-fs-ext/arf_strings", "cap-tempfile/arf_strings", ] -async_std_arf_strings = [ - "cap-async-std/arf_strings", - "cap-fs-ext/async_std_arf_strings" -] [workspace] members = [ - "cap-async-std", "cap-fs-ext", "cap-net-ext", "cap-directories", diff --git a/README.md b/README.md index 941694a4..832558e9 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ The `cap-std` project is organized around the eponymous [`cap-std`] crate, and develops libraries to make it easy to write capability-based code, including: - [`cap-std`] itself, which provides capability-based versions of `std` APIs - - [`cap-async-std`], which is to [`async-std`] what `cap-std` is to `std` - [`cap-directories`] which provides capability-based access to [standard application directories] - [`cap-tempfile`], which provides capability-based access to @@ -45,7 +44,6 @@ Linux. [CWE-22]: https://cwe.mitre.org/data/definitions/22.html [2021 CWE Top 25 Most Dangerous Software Weaknesses]: https://cwe.mitre.org/top25/archive/2021/2021_cwe_top25.html [`cap-std`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-std/README.md -[`cap-async-std`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-async-std/README.md [`cap-directories`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-directories/README.md [`cap-tempfile`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-tempfile/README.md [`cap-fs-ext`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-fs-ext/README.md @@ -53,7 +51,6 @@ Linux. [`cap-rand`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-rand/README.md [`cap-net-ext`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-net-ext/README.md [`cap_std::fs`]: https://docs.rs/cap-std/latest/cap_std/fs/index.html -[`async-std`]: https://docs.rs/async-std/ [standard application directories]: https://docs.rs/directories-next/ [temporary directories]: https://docs.rs/tempfile/ [random number generators]: https://docs.rs/rand/ diff --git a/cap-async-std/COPYRIGHT b/cap-async-std/COPYRIGHT deleted file mode 100644 index 6081f98c..00000000 --- a/cap-async-std/COPYRIGHT +++ /dev/null @@ -1,29 +0,0 @@ -Short version for non-lawyers: - -`cap-async-std` is triple-licensed under Apache 2.0 with the LLVM Exception, -Apache 2.0, and MIT terms. - - -Longer version: - -Copyrights in the `cap-async-std` project are retained by their contributors. -No copyright assignment is required to contribute to the `cap-async-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-async-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. diff --git a/cap-async-std/Cargo.toml b/cap-async-std/Cargo.toml deleted file mode 100644 index c202e649..00000000 --- a/cap-async-std/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "cap-async-std" -version = "3.4.5" -description = "Capability-based version of async-std" -authors = [ - "Dan Gohman ", - "Jakub Konka ", -] -license = "Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT" -keywords = ["network", "file", "async", "future", "await"] -categories = ["filesystem", "network-programming", "asynchronous", "concurrency"] -repository = "https://github.com/bytecodealliance/cap-std" -edition = "2021" - -[dependencies] -arf-strings = { version = "0.7.0", optional = true } -async-std = { version = "1.13.0", features = ["attributes", "io_safety"] } -cap-primitives = { path = "../cap-primitives", version = "^3.4.5" } -io-lifetimes = { version = "2.0.0", default-features = false, features = ["async-std"] } -io-extras = { version = "0.18.3", features = ["use_async_std"] } -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"] -tokio1 = ["async-std/tokio1"] diff --git a/cap-async-std/LICENSE-APACHE b/cap-async-std/LICENSE-APACHE deleted file mode 100644 index 16fe87b0..00000000 --- a/cap-async-std/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - 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. diff --git a/cap-async-std/LICENSE-Apache-2.0_WITH_LLVM-exception b/cap-async-std/LICENSE-Apache-2.0_WITH_LLVM-exception deleted file mode 100644 index f9d81955..00000000 --- a/cap-async-std/LICENSE-Apache-2.0_WITH_LLVM-exception +++ /dev/null @@ -1,220 +0,0 @@ - - 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. - diff --git a/cap-async-std/LICENSE-MIT b/cap-async-std/LICENSE-MIT deleted file mode 100644 index 31aa7938..00000000 --- a/cap-async-std/LICENSE-MIT +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/cap-async-std/README.md b/cap-async-std/README.md deleted file mode 100644 index 22cf075b..00000000 --- a/cap-async-std/README.md +++ /dev/null @@ -1,19 +0,0 @@ -
-

cap-async-std

- -

- Capability-based version of `async-std` -

- -

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

-
- -This crate provides a capability-based version of [`async-std`]. See the -[toplevel README.md] for more information about capability-based security. - -[`async-std`]: https://crates.io/crates/async-std -[toplevel README.md]: https://github.com/bytecodealliance/cap-std/blob/main/README.md diff --git a/cap-async-std/build.rs b/cap-async-std/build.rs deleted file mode 100644 index 434559ec..00000000 --- a/cap-async-std/build.rs +++ /dev/null @@ -1,84 +0,0 @@ -use std::env::var; -use std::io::Write; - -fn main() { - 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() -} diff --git a/cap-async-std/src/fs/dir.rs b/cap-async-std/src/fs/dir.rs deleted file mode 100644 index 692443f1..00000000 --- a/cap-async-std/src/fs/dir.rs +++ /dev/null @@ -1,1075 +0,0 @@ -use crate::fs::{DirBuilder, File, Metadata, OpenOptions, ReadDir}; -#[cfg(target_os = "wasi")] -use async_std::os::wasi::{ - fs::OpenOptionsExt, - io::{AsRawFd, IntoRawFd}, -}; -use async_std::path::{Path, PathBuf}; -use async_std::task::spawn_blocking; -use async_std::{fs, io}; -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, remove_dir, remove_dir_all, remove_file, remove_open_dir, - remove_open_dir_all, rename, set_permissions, stat, DirOptions, FollowSymlinks, Permissions, -}; -use cap_primitives::AmbientAuthority; -use io_lifetimes::raw::{AsRawFilelike, FromRawFilelike}; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -use io_lifetimes::{AsFilelike, FromFilelike}; -#[cfg(windows)] -use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; -use std::fmt; -use std::mem::ManuallyDrop; -#[cfg(unix)] -use { - crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream}, - async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, - cap_primitives::fs::symlink, -}; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, - cap_primitives::fs::{symlink_dir, symlink_file}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A reference to an open directory on a filesystem. -/// -/// This does not directly correspond to anything in `async_std`, however its -/// methods correspond to the [functions in `async_std::fs`] and the -/// constructor methods for [`async_std::fs::File`]. -/// -/// Unlike `async_std::fs`, this API's `canonicalize` returns a relative path -/// since absolute paths don't interoperate well with the capability model. -/// -/// [functions in `async_std::fs`]: https://docs.rs/async-std/latest/async_std/fs/index.html#functions -#[derive(Clone)] -pub struct Dir { - std_file: fs::File, -} - -impl Dir { - /// Constructs a new instance of `Self` from the given - /// `async_std::fs::File`. - /// - /// To prevent race conditions on Windows, the file must be opened without - /// `FILE_SHARE_DELETE`. - /// - /// This grants access the resources the `async_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 an `async_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 [`async_std::fs::File::open`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn open>(&self, path: P) -> io::Result { - self.open_with(path, OpenOptions::new().read(true)).await - } - - /// Opens a file at `path` with the options specified by `options`. - /// - /// This corresponds to [`async_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 async fn open_with>( - &self, - path: P, - options: &OpenOptions, - ) -> io::Result { - self._open_with(path.as_ref(), options).await - } - - #[cfg(not(target_os = "wasi"))] - async fn _open_with(&self, path: &Path, options: &OpenOptions) -> io::Result { - let path = path.to_path_buf(); - let clone = self.clone(); - let options = options.clone(); - let file = spawn_blocking(move || { - open( - &*clone.as_filelike_view::(), - path.as_ref(), - &options, - ) - }) - .await? - .into(); - Ok(File::from_std(file)) - } - - #[cfg(target_os = "wasi")] - async fn _open_with( - file: &std::fs::File, - path: &Path, - options: &OpenOptions, - ) -> io::Result { - let file = options.open_at(&self.std_file, path)?.into(); - Ok(File::from_std(file)) - } - - /// Attempts to open a directory. - #[inline] - pub async fn open_dir>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - let dir = spawn_blocking(move || { - open_dir(&clone.as_filelike_view::(), path.as_ref()) - }) - .await? - .into(); - Ok(Self::from_std_file(dir)) - } - - /// Creates a new, empty directory at the provided path. - /// - /// This corresponds to [`async_std::fs::create_dir`], but only accesses - /// paths relative to `self`. - /// - /// TODO: async: fix this when we fix - #[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 [`async_std::fs::create_dir_all`], but only - /// accesses paths relative to `self`. - /// - /// TODO: async: fix this when we fix - #[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 [`async_std::fs::DirBuilder::create`]. - /// - /// TODO: async: fix this when we fix - #[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) - } - } - - #[inline] - fn _create_dir_one(&self, path: &Path, dir_options: &DirOptions) -> io::Result<()> { - create_dir( - &self.as_filelike_view::(), - path.as_ref(), - 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_blocking(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_blocking(path) => Ok(()), - Err(e) => Err(e), - } - } - - /// Opens a file in write-only mode. - /// - /// This corresponds to [`async_std::fs::File::create`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn create>(&self, path: P) -> io::Result { - self.open_with( - path, - OpenOptions::new().write(true).create(true).truncate(true), - ) - .await - } - - /// Returns the canonical form of a path with all intermediate components - /// normalized and symbolic links resolved. - /// - /// This corresponds to [`async_std::fs::canonicalize`], but instead of - /// returning an absolute path, returns a path relative to the - /// directory represented by `self`. - #[inline] - pub async fn canonicalize>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - canonicalize(&clone.as_filelike_view::(), path.as_ref()) - }) - .await - .map(PathBuf::from) - } - - /// 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 [`async_std::fs::copy`], but only accesses paths - /// relative to `self`. - #[inline] - pub async fn copy, Q: AsRef>( - &self, - from: P, - to_dir: &Self, - to: Q, - ) -> io::Result { - let from = from.as_ref().to_path_buf(); - let to = to.as_ref().to_path_buf(); - let from_clone = self.clone(); - let to_clone = to_dir.clone(); - spawn_blocking(move || { - copy( - &from_clone.as_filelike_view::(), - from.as_ref(), - &to_clone.as_filelike_view::(), - to.as_ref(), - ) - }) - .await - } - - /// Creates a new hard link on a filesystem. - /// - /// This corresponds to [`async_std::fs::hard_link`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn hard_link, Q: AsRef>( - &self, - src: P, - dst_dir: &Self, - dst: Q, - ) -> io::Result<()> { - let dst = dst.as_ref().to_path_buf(); - let src = src.as_ref().to_path_buf(); - let src_clone = self.clone(); - let dst_clone = dst_dir.clone(); - spawn_blocking(move || { - hard_link( - &src_clone.as_filelike_view::(), - src.as_ref(), - &dst_clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - /// Given a path, query the file system to get information about a file, - /// directory, etc. - /// - /// This corresponds to [`async_std::fs::metadata`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn metadata>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - stat( - &clone.as_filelike_view::(), - path.as_ref(), - FollowSymlinks::Yes, - ) - }) - .await - } - - /// TODO: Remove this once `create_dir` and friends are async. - #[inline] - fn metadata_blocking>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - stat( - &self.as_filelike_view::(), - 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 async fn dir_metadata(&self) -> io::Result { - let clone = self.clone(); - spawn_blocking(move || metadata_from(&*clone.as_filelike_view::())).await - } - - /// Returns an iterator over the entries within `self`. - #[inline] - pub async fn entries(&self) -> io::Result { - let clone = self.clone(); - spawn_blocking(move || read_base_dir(&clone.as_filelike_view::())) - .await - .map(|inner| ReadDir { inner }) - } - - /// Returns an iterator over the entries within a directory. - /// - /// This corresponds to [`async_std::fs::read_dir`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn read_dir>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || read_dir(&clone.as_filelike_view::(), path.as_ref())) - .await - .map(|inner| ReadDir { inner }) - } - - /// Read the entire contents of a file into a bytes vector. - /// - /// This corresponds to [`async_std::fs::read`], but only accesses paths - /// relative to `self`. - #[inline] - pub async fn read>(&self, path: P) -> io::Result> { - use async_std::prelude::*; - let mut file = self.open(path).await?; - let mut bytes = Vec::with_capacity(initial_buffer_size(&file).await); - file.read_to_end(&mut bytes).await?; - Ok(bytes) - } - - /// Reads a symbolic link, returning the file that the link points to. - /// - /// This corresponds to [`async_std::fs::read_link`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn read_link>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || read_link(&clone.as_filelike_view::(), path.as_ref())) - .await - .map(PathBuf::from) - } - - /// Read the entire contents of a file into a string. - /// - /// This corresponds to [`async_std::fs::read_to_string`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn read_to_string>(&self, path: P) -> io::Result { - use async_std::prelude::*; - let mut s = String::new(); - self.open(path).await?.read_to_string(&mut s).await?; - Ok(s) - } - - /// Removes an empty directory. - /// - /// This corresponds to [`async_std::fs::remove_dir`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn remove_dir>(&self, path: P) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - remove_dir(&clone.as_filelike_view::(), path.as_ref()) - }) - .await - } - - /// Removes a directory at this path, after removing all its contents. Use - /// carefully! - /// - /// This corresponds to [`async_std::fs::remove_dir_all`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn remove_dir_all>(&self, path: P) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - remove_dir_all(&clone.as_filelike_view::(), path.as_ref()) - }) - .await - } - - /// 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 async fn remove_open_dir(self) -> io::Result<()> { - let file = std::fs::File::from_into_filelike(self.std_file); - spawn_blocking(move || remove_open_dir(file)).await - } - - /// 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 async fn remove_open_dir_all(self) -> io::Result<()> { - let file = std::fs::File::from_into_filelike(self.std_file); - spawn_blocking(move || remove_open_dir_all(file)).await - } - - /// Removes a file from a filesystem. - /// - /// This corresponds to [`async_std::fs::remove_file`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn remove_file>(&self, path: P) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - remove_file(&clone.as_filelike_view::(), path.as_ref()) - }) - .await - } - - /// Rename a file or directory to a new name, replacing the original file - /// if to already exists. - /// - /// This corresponds to [`async_std::fs::rename`], but only accesses paths - /// relative to `self`. - #[inline] - pub async fn rename, Q: AsRef>( - &self, - from: P, - to_dir: &Self, - to: Q, - ) -> io::Result<()> { - let from = from.as_ref().to_path_buf(); - let to = to.as_ref().to_path_buf(); - let clone = self.clone(); - let to_clone = to_dir.clone(); - spawn_blocking(move || { - rename( - &clone.as_filelike_view::(), - from.as_ref(), - &to_clone.as_filelike_view::(), - to.as_ref(), - ) - }) - .await - } - - /// Changes the permissions found on a file or a directory. - /// - /// This corresponds to [`async_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. - pub async fn set_permissions>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_permissions( - &clone.as_filelike_view::(), - path.as_ref(), - perm, - ) - }) - .await - } - - /// Query the metadata about a file without following symlinks. - /// - /// This corresponds to [`async_std::fs::symlink_metadata`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn symlink_metadata>(&self, path: P) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - stat( - &clone.as_filelike_view::(), - path.as_ref(), - FollowSymlinks::No, - ) - }) - .await - } - - /// Write a slice as the entire contents of a file. - /// - /// This corresponds to [`async_std::fs::write`], but only accesses paths - /// relative to `self`. - #[inline] - pub async fn write, C: AsRef<[u8]>>( - &self, - path: P, - contents: C, - ) -> io::Result<()> { - use async_std::prelude::*; - let mut file = self.create(path).await?; - file.write_all(contents.as_ref()).await - } - - /// 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 [`async_std::os::unix::fs::symlink`], but only - /// accesses paths relative to `self`. - /// - /// [`async_std::os::unix::fs::symlink`]: https://docs.rs/async-std/latest/async_std/os/unix/fs/fn.symlink.html - #[cfg(not(windows))] - #[inline] - pub async fn symlink, Q: AsRef>( - &self, - original: P, - link: Q, - ) -> io::Result<()> { - let original = original.as_ref().to_path_buf(); - let link = link.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink( - original.as_ref(), - &clone.as_filelike_view::(), - link.as_ref(), - ) - }) - .await - } - - /// 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 [`async_std::os::windows::fs::symlink_file`], but - /// only accesses paths relative to `self`. - /// - /// [`async_std::os::windows::fs::symlink_file`]: https://docs.rs/async-std/latest/async_std/os/windows/fs/fn.symlink_file.html - #[cfg(windows)] - #[inline] - pub async fn symlink_file, Q: AsRef>( - &self, - original: P, - link: Q, - ) -> io::Result<()> { - let original = original.as_ref().to_path_buf(); - let link = link.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink_file( - original.as_ref(), - &clone.as_filelike_view::(), - link.as_ref(), - ) - }) - .await - } - - /// 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 [`async_std::os::windows::fs::symlink_dir`], but - /// only accesses paths relative to `self`. - /// - /// [`async_std::os::windows::fs::symlink_dir`]: https://docs.rs/async-std/latest/async_std/os/windows/fs/fn.symlink_dir.html - #[cfg(windows)] - #[inline] - pub async fn symlink_dir, Q: AsRef>( - &self, - original: P, - link: Q, - ) -> io::Result<()> { - let original = original.as_ref().to_path_buf(); - let link = link.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink_dir( - original.as_ref(), - &clone.as_filelike_view::(), - link.as_ref(), - ) - }) - .await - } - - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// This corresponds to [`async_std::os::unix::net::UnixListener::bind`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixListener::bind`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixListener.html#method.bind - #[doc(alias = "bind")] - #[cfg(unix)] - #[inline] - pub async 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 [`async_std::os::unix::net::UnixStream::connect`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixStream::connect`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixStream.html#method.connect - #[doc(alias = "connect")] - #[cfg(unix)] - #[inline] - pub async 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 [`async_std::os::unix::net::UnixDatagram::bind`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::bind`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.bind - #[doc(alias = "bind")] - #[cfg(unix)] - #[inline] - pub async 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 - /// [`async_std::os::unix::net::UnixDatagram::connect`], but only - /// accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::connect`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.connect - #[doc(alias = "connect")] - #[cfg(unix)] - #[inline] - pub async 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 - /// [`async_std::os::unix::net::UnixDatagram::send_to`], but only - /// accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::send_to`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.send_to - #[doc(alias = "send_to")] - #[cfg(unix)] - #[inline] - pub async 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() - ) - } - - // async_std doesn't have `try_clone`. - - /// Returns `true` if the path points at an existing entity. - /// - /// This corresponds to [`async_std::path::Path::exists`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn exists>(&self, path: P) -> bool { - self.metadata(path).await.is_ok() - } - - /// Returns `true` if the path points at an existing entity. - /// - /// This is an asynchronous version of [`std::fs::try_exists`], and also - /// only accesses paths relative to `self`. - /// - /// NOTE: This API is not yet part of `async_std`. - #[inline] - pub async fn try_exists>(&self, path: P) -> io::Result { - match self.metadata(path.as_ref()).await { - Ok(_) => Ok(true), - Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false), - Err(e) => Err(e), - } - } - - /// Returns `true` if the path exists on disk and is pointing at a regular - /// file. - /// - /// This corresponds to [`async_std::path::Path::is_file`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn is_file>(&self, path: P) -> bool { - self.metadata(path) - .await - .map(|m| m.is_file()) - .unwrap_or(false) - } - - /// Checks if `path` is a directory. - /// - /// This is similar to [`async_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 async fn is_dir>(&self, path: P) -> bool { - self.metadata(path) - .await - .map(|m| m.is_dir()) - .unwrap_or(false) - } - - /// TODO: Remove this once `create_dir` and friends are async. - #[inline] - fn is_dir_blocking>(&self, path: P) -> bool { - self.metadata_blocking(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 async fn open_ambient_dir>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = path.as_ref().to_path_buf(); - spawn_blocking(move || open_ambient_dir(path.as_ref(), ambient_authority)) - .await - .map(|f| Self::from_std_file(f.into())) - } - - /// 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 async fn open_parent_dir(&self, ambient_authority: AmbientAuthority) -> io::Result { - let clone = self.clone(); - let dir = spawn_blocking(move || { - open_parent_dir( - &*clone.as_filelike_view::(), - ambient_authority, - ) - }) - .await? - .into(); - 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 async fn create_ambient_dir_all>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result<()> { - let _ = ambient_authority; - let path = path.as_ref().to_path_buf(); - fs::create_dir_all(path).await - } - - /// 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 async fn reopen_dir(dir: &Filelike) -> io::Result { - // Our public API has a `&Filelike` here, which prevents us from doing - // a `clone` as we usually do. So instead, we use the raw filelike, which - // we can clone and depend on it remaining open until we return. - let raw_filelike = dir.as_filelike_view::().as_raw_filelike(); - // SAFETY: `raw_filelike` remains open for the duration of the - // `reopen_dir` call. - let file = ManuallyDrop::new(unsafe { std::fs::File::from_raw_filelike(raw_filelike) }); - let dir = spawn_blocking(move || { - cap_primitives::fs::open_dir(&*file, std::path::Component::CurDir.as_ref()) - }) - .await? - .into(); - Ok(Self::from_std_file(dir)) - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -fn metadata_from(file: &std::fs::File) -> io::Result { - Metadata::from_file(file) -} - -#[cfg(target_os = "wasi")] -#[inline] -fn metadata_from(file: &std::fs::File) -> io::Result { - file.metadata() -} - -// 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. -async 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() - .await - .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() - } -} diff --git a/cap-async-std/src/fs/dir_entry.rs b/cap-async-std/src/fs/dir_entry.rs deleted file mode 100644 index 0731af48..00000000 --- a/cap-async-std/src/fs/dir_entry.rs +++ /dev/null @@ -1,114 +0,0 @@ -use crate::fs::{Dir, File, FileType, Metadata, OpenOptions}; -use async_std::io; -#[cfg(unix)] -use async_std::os::unix::fs::DirEntryExt; -#[cfg(target_os = "wasi")] -use async_std::os::wasi::fs::DirEntryExt; -use std::ffi::OsString; -use std::fmt; - -/// Entries returned by the `ReadDir` iterator. -/// -/// This corresponds to [`async_std::fs::DirEntry`]. -/// -/// Unlike `async_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 `async_std::fs::DirEntry` doesn't provide -/// a way to construct a `DirEntry` without opening directories by ambient -/// paths. -/// -/// TODO: async -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()?.into(); - 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)?.into(); - Ok(File::from_std(file)) - } - - /// Open the entry as a directory. - #[inline] - pub fn open_dir(&self) -> io::Result { - let file = self.inner.open_dir()?.into(); - Ok(Dir::from_std_file(file)) - } - - /// 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 [`async_std::fs::DirEntry::metadata`]. - #[inline] - pub fn metadata(&self) -> io::Result { - // TODO: Make this async. - self.inner.metadata() - } - - /// Returns the file type for the file that this entry points at. - /// - /// This corresponds to [`async_std::fs::DirEntry::file_type`]. - #[inline] - pub async fn file_type(&self) -> io::Result { - // TODO: Make this actually async. - self.inner.file_type() - } - - /// Returns the bare file name of this directory entry without any other - /// leading path component. - /// - /// This corresponds to [`async_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 { - self.inner.full_metadata() - } -} - -impl fmt::Debug for DirEntry { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/cap-async-std/src/fs/file.rs b/cap-async-std/src/fs/file.rs deleted file mode 100644 index adee6427..00000000 --- a/cap-async-std/src/fs/file.rs +++ /dev/null @@ -1,498 +0,0 @@ -use crate::fs::{Metadata, OpenOptions, Permissions}; -use async_std::fs; -use async_std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; -#[cfg(unix)] -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg(target_os = "wasi")] -use async_std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::task::{spawn_blocking, Context, Poll}; -use cap_primitives::fs::{is_file_read_write, open_ambient}; -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::fmt; -use std::path::Path; -use std::pin::Pin; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A reference to an open file on a filesystem. -/// -/// This corresponds to [`async_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 -#[derive(Clone)] -pub struct File { - pub(crate) std: fs::File, -} - -impl File { - /// Constructs a new instance of `Self` from the given - /// `async_std::fs::File`. - /// - /// This grants access the resources the `async_std::fs::File` instance - /// already has access to. - #[inline] - pub fn from_std(std: fs::File) -> Self { - Self { std } - } - - /// Consumes `self` and returns an `async_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 [`async_std::fs::File::sync_all`]. - #[inline] - pub async fn sync_all(&self) -> io::Result<()> { - self.std.sync_all().await - } - - /// This function is similar to `sync_all`, except that it may not - /// synchronize file metadata to a filesystem. - /// - /// This corresponds to [`async_std::fs::File::sync_data`]. - #[inline] - pub async fn sync_data(&self) -> io::Result<()> { - self.std.sync_data().await - } - - /// Truncates or extends the underlying file, updating the size of this - /// file to become size. - /// - /// This corresponds to [`async_std::fs::File::set_len`]. - #[inline] - pub async fn set_len(&self, size: u64) -> io::Result<()> { - self.std.set_len(size).await - } - - /// Queries metadata about the underlying file. - /// - /// This corresponds to [`async_std::fs::File::metadata`]. - #[inline] - pub async fn metadata(&self) -> io::Result { - let clone = self.clone(); - spawn_blocking(move || metadata_from(&*clone.std.as_filelike_view::())).await - } - - // async_std doesn't have `try_clone`. - - /// Changes the permissions on the underlying file. - /// - /// This corresponds to [`async_std::fs::File::set_permissions`]. - #[inline] - pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> { - let sync = self.std.as_filelike_view::(); - self.std - .set_permissions(permissions_into_std(&sync, perm)?) - .await - } - - /// 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 async fn open_ambient>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = path.as_ref().to_path_buf(); - spawn_blocking(move || { - open_ambient( - path.as_ref(), - OpenOptions::new().read(true), - ambient_authority, - ) - }) - .await - .map(|f| Self::from_std(f.into())) - } - - /// 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 async fn create_ambient>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = path.as_ref().to_path_buf(); - spawn_blocking(move || { - open_ambient( - path.as_ref(), - OpenOptions::new().write(true).create(true).truncate(true), - ambient_authority, - ) - }) - .await - .map(|f| Self::from_std(f.into())) - } - - /// 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 async fn open_ambient_with>( - path: P, - options: &OpenOptions, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = path.as_ref().to_path_buf(); - let options = options.clone(); - spawn_blocking(move || open_ambient(path.as_ref(), &options, ambient_authority)) - .await - .map(|f| Self::from_std(f.into())) - } - - /// Returns a new `OpenOptions` object. - /// - /// This corresponds to [`async_std::fs::File::options`]. - #[must_use] - #[inline] - pub fn options() -> OpenOptions { - OpenOptions::new() - } -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -fn metadata_from(file: &std::fs::File) -> io::Result { - Metadata::from_file(file) -} - -#[cfg(target_os = "wasi")] -#[inline] -fn metadata_from(file: &std::fs::File) -> io::Result { - file.metadata() -} - -#[cfg(not(target_os = "wasi"))] -#[inline] -fn permissions_into_std( - file: &std::fs::File, - permissions: Permissions, -) -> io::Result { - permissions.into_std(file) -} - -#[cfg(target_os = "wasi")] -#[inline] -fn permissions_into_std( - _file: &std::fs::File, - permissions: Permissions, -) -> io::Result { - permissions -} - -// 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 poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Read for &File { - #[inline] - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Write for File { - #[inline] - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &[u8], - ) -> Poll> { - Write::poll_write(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Write for &File { - #[inline] - fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { - Write::poll_write(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Seek for File { - #[inline] - fn poll_seek( - mut self: Pin<&mut Self>, - cx: &mut Context, - pos: SeekFrom, - ) -> Poll> { - Seek::poll_seek(Pin::new(&mut self.std), cx, pos) - } -} - -impl Seek for &File { - #[inline] - fn poll_seek(self: Pin<&mut Self>, cx: &mut Context, pos: SeekFrom) -> Poll> { - Seek::poll_seek(Pin::new(&mut &self.std), cx, pos) - } -} - -// TODO: Can async_std implement `From` for `process::Stdio`? - -// async_std doesn't have `FileExt`. - -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"); - let file = self.std.as_filelike_view::(); - #[cfg(not(windows))] - b.field("fd", &file.as_raw_fd()); - #[cfg(windows)] - b.field("handle", &file.as_raw_handle()); - if let Ok((read, write)) = is_file_read_write(&file) { - b.field("read", &read).field("write", &write); - } - b.finish() - } -} diff --git a/cap-async-std/src/fs/mod.rs b/cap-async-std/src/fs/mod.rs deleted file mode 100644 index 7fccbaf0..00000000 --- a/cap-async-std/src/fs/mod.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! A capability-based filesystem API modeled after [`async_std::fs`]. -//! -//! This corresponds to [`async_std::fs`]. -//! -//! Instead of [`async_std::fs`'s free functions] and [`async_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 `async_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 `async_std::path::Path` rather than having its -//! own path type, however while `async_std::path::Path` is mostly just a pure -//! datatype, it includes aliases for several `async_std::fs` functions. To -//! preserve the capability-based interface, avoid using -//! `async_std::path::Path`'s `canonicalize`, `read_link`, `read_dir`, -//! `metadata`, and `symlink_metadata` functions. -//! -//! [`async_std::fs`'s free functions]: https://docs.rs/async-std/latest/async_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 things from `cap_primitives` that we can use as-is. -#[cfg(not(target_os = "wasi"))] -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}; - -// Re-export things from `async_std` that we can use as-is. -#[cfg(target_os = "wasi")] -pub use async_std::fs::{DirBuilder, FileType, Metadata, OpenOptions, Permissions}; diff --git a/cap-async-std/src/fs/read_dir.rs b/cap-async-std/src/fs/read_dir.rs deleted file mode 100644 index a8010e68..00000000 --- a/cap-async-std/src/fs/read_dir.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::fs::DirEntry; -use async_std::io; -use std::fmt; - -/// Iterator over the entries in a directory. -/// -/// This corresponds to [`async_std::fs::ReadDir`]. -/// -/// There is no `from_std` method, as `async_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) - } -} diff --git a/cap-async-std/src/fs_utf8/dir.rs b/cap-async-std/src/fs_utf8/dir.rs deleted file mode 100644 index 86da21a5..00000000 --- a/cap-async-std/src/fs_utf8/dir.rs +++ /dev/null @@ -1,811 +0,0 @@ -use crate::fs::{OpenOptions, Permissions}; -use crate::fs_utf8::{from_utf8, to_utf8, DirBuilder, File, Metadata, ReadDir}; -use async_std::{fs, io}; -use camino::{Utf8Path, Utf8PathBuf}; -use cap_primitives::AmbientAuthority; -use io_lifetimes::raw::{AsRawFilelike, FromRawFilelike}; -use io_lifetimes::AsFilelike; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -#[cfg(windows)] -use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; -use std::fmt; -use std::mem::ManuallyDrop; -#[cfg(unix)] -use { - crate::os::unix::net::{UnixDatagram, UnixListener, UnixStream}, - async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}, -}; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A reference to an open directory on a filesystem. -/// -/// This does not directly correspond to anything in `async_std`, however its -/// methods correspond to the [functions in `async_std::fs`] and the -/// constructor methods for [`async_std::fs::File`]. -/// -/// Unlike `async_std::fs`, this API's `canonicalize` returns a relative path -/// since absolute paths don't interoperate well with the capability model. -/// -/// [functions in `async_std::fs`]: https://docs.rs/async-std/latest/async_std/fs/index.html#functions -#[derive(Clone)] -pub struct Dir { - cap_std: crate::fs::Dir, -} - -impl Dir { - /// Constructs a new instance of `Self` from the given - /// `async_std::fs::File`. - /// - /// To prevent race conditions on Windows, the file must be opened without - /// `FILE_SHARE_DELETE`. - /// - /// This grants access the resources the `async_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 } - } - - /// Attempts to open a file in read-only mode. - /// - /// This corresponds to [`async_std::fs::File::open`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn open>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.open(path).await.map(File::from_cap_std) - } - - /// Opens a file at `path` with the options specified by `options`. - /// - /// This corresponds to [`async_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 async fn open_with>( - &self, - path: P, - options: &OpenOptions, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std - .open_with(path, options) - .await - .map(File::from_cap_std) - } - - /// Attempts to open a directory. - #[inline] - pub async fn open_dir>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.open_dir(path).await.map(Self::from_cap_std) - } - - /// Creates a new, empty directory at the provided path. - /// - /// This corresponds to [`async_std::fs::create_dir`], but only accesses - /// paths relative to `self`. - /// - /// TODO: async: fix this when we fix https://github.com/bytecodealliance/cap-std/issues/51 - #[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 [`async_std::fs::create_dir_all`], but only - /// accesses paths relative to `self`. - /// - /// TODO: async: fix this when we fix https://github.com/bytecodealliance/cap-std/issues/51 - #[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 [`async_std::fs::DirBuilder::create`]. - /// - /// TODO: async: fix this when we fix https://github.com/bytecodealliance/cap-std/issues/51 - #[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 [`async_std::fs::File::create`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn create>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.create(path).await.map(File::from_cap_std) - } - - /// Returns the canonical form of a path with all intermediate components - /// normalized and symbolic links resolved. - /// - /// This corresponds to [`async_std::fs::canonicalize`], but instead of - /// returning an absolute path, returns a path relative to the - /// directory represented by `self`. - #[inline] - pub async fn canonicalize>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.canonicalize(path).await.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 [`async_std::fs::copy`], but only accesses paths - /// relative to `self`. - #[inline] - pub async 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).await - } - - /// Creates a new hard link on a filesystem. - /// - /// This corresponds to [`async_std::fs::hard_link`], but only accesses - /// paths relative to `self`. - #[inline] - pub async 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).await - } - - /// Given a path, query the file system to get information about a file, - /// directory, etc. - /// - /// This corresponds to [`async_std::fs::metadata`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn metadata>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.metadata(path).await - } - - /// Queries metadata about the underlying directory. - /// - /// This is similar to [`std::fs::File::metadata`], but for `Dir` rather - /// than for `File`. - #[inline] - pub async fn dir_metadata(&self) -> io::Result { - self.cap_std.dir_metadata().await - } - - /// Returns an iterator over the entries within `self`. - #[inline] - pub async fn entries(&self) -> io::Result { - self.cap_std.entries().await.map(ReadDir::from_cap_std) - } - - /// Returns an iterator over the entries within a directory. - /// - /// This corresponds to [`async_std::fs::read_dir`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn read_dir>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.read_dir(path).await.map(ReadDir::from_cap_std) - } - - /// Read the entire contents of a file into a bytes vector. - /// - /// This corresponds to [`async_std::fs::read`], but only accesses paths - /// relative to `self`. - #[inline] - pub async fn read>(&self, path: P) -> io::Result> { - let path = from_utf8(path.as_ref())?; - self.cap_std.read(path).await - } - - /// Reads a symbolic link, returning the file that the link points to. - /// - /// This corresponds to [`async_std::fs::read_link`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn read_link>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.read_link(path).await.and_then(to_utf8) - } - - /// Read the entire contents of a file into a string. - /// - /// This corresponds to [`async_std::fs::read_to_string`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn read_to_string>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.read_to_string(path).await - } - - /// Removes an empty directory. - /// - /// This corresponds to [`async_std::fs::remove_dir`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn remove_dir>(&self, path: P) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - self.cap_std.remove_dir(path).await - } - - /// Removes a directory at this path, after removing all its contents. Use - /// carefully! - /// - /// This corresponds to [`async_std::fs::remove_dir_all`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn remove_dir_all>(&self, path: P) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - self.cap_std.remove_dir_all(path).await - } - - /// 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 async fn remove_open_dir(self) -> io::Result<()> { - self.cap_std.remove_open_dir().await - } - - /// 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 async fn remove_open_dir_all(self) -> io::Result<()> { - self.cap_std.remove_open_dir_all().await - } - - /// Removes a file from a filesystem. - /// - /// This corresponds to [`async_std::fs::remove_file`], but only accesses - /// paths relative to `self`. - #[inline] - pub async fn remove_file>(&self, path: P) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - self.cap_std.remove_file(path).await - } - - /// Rename a file or directory to a new name, replacing the original file - /// if to already exists. - /// - /// This corresponds to [`async_std::fs::rename`], but only accesses paths - /// relative to `self`. - #[inline] - pub async 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).await - } - - /// Changes the permissions found on a file or a directory. - /// - /// This corresponds to [`async_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. - pub async fn set_permissions>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - self.cap_std.set_permissions(path, perm).await - } - - /// Query the metadata about a file without following symlinks. - /// - /// This corresponds to [`async_std::fs::symlink_metadata`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn symlink_metadata>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.symlink_metadata(path).await - } - - /// Write a slice as the entire contents of a file. - /// - /// This corresponds to [`async_std::fs::write`], but only accesses paths - /// relative to `self`. - #[inline] - pub async 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).await - } - - /// 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 [`async_std::os::unix::fs::symlink`], but only - /// accesses paths relative to `self`. - /// - /// [`async_std::os::unix::fs::symlink`]: https://docs.rs/async-std/latest/async_std/os/unix/fs/fn.symlink.html - #[cfg(not(windows))] - #[inline] - pub async 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).await - } - - /// 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 [`async_std::os::windows::fs::symlink_file`], but - /// only accesses paths relative to `self`. - /// - /// [`async_std::os::windows::fs::symlink_file`]: https://docs.rs/async-std/latest/async_std/os/windows/fs/fn.symlink_file.html - #[cfg(windows)] - #[inline] - pub async 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).await - } - - /// 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 [`async_std::os::windows::fs::symlink_dir`], but - /// only accesses paths relative to `self`. - /// - /// [`async_std::os::windows::fs::symlink_dir`]: https://docs.rs/async-std/latest/async_std/os/windows/fs/fn.symlink_dir.html - #[cfg(windows)] - #[inline] - pub async 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).await - } - - /// Creates a new `UnixListener` bound to the specified socket. - /// - /// This corresponds to [`async_std::os::unix::net::UnixListener::bind`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixListener::bind`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixListener.html#method.bind - #[doc(alias = "bind")] - #[cfg(unix)] - #[inline] - pub async fn bind_unix_listener>( - &self, - path: P, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.bind_unix_listener(path).await - } - - /// Connects to the socket named by path. - /// - /// This corresponds to [`async_std::os::unix::net::UnixStream::connect`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixStream::connect`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixStream.html#method.connect - #[doc(alias = "connect")] - #[cfg(unix)] - #[inline] - pub async fn connect_unix_stream>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.connect_unix_stream(path).await - } - - /// Creates a Unix datagram socket bound to the given path. - /// - /// This corresponds to [`async_std::os::unix::net::UnixDatagram::bind`], - /// but only accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::bind`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.bind - #[doc(alias = "bind")] - #[cfg(unix)] - #[inline] - pub async fn bind_unix_datagram>( - &self, - path: P, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - self.cap_std.bind_unix_datagram(path).await - } - - /// Connects the socket to the specified address. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixDatagram::connect`], but only - /// accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::connect`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.connect - #[doc(alias = "connect")] - #[cfg(unix)] - #[inline] - pub async 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) - .await - } - - /// Sends data on the socket to the specified address. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixDatagram::send_to`], but only - /// accesses paths relative to `self`. - /// - /// XXX: This function is not yet implemented. - /// - /// [`async_std::os::unix::net::UnixDatagram::send_to`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.send_to - #[doc(alias = "send_to")] - #[cfg(unix)] - #[inline] - pub async 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) - .await - } - - // async_std doesn't have `try_clone`. - - /// Returns `true` if the path points at an existing entity. - /// - /// This corresponds to [`async_std::path::Path::exists`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn exists>(&self, path: P) -> bool { - match from_utf8(path.as_ref()) { - Ok(path) => self.cap_std.exists(path).await, - Err(_) => false, - } - } - - /// Returns `true` if the path points at an existing entity. - /// - /// This corresponds to [`async_std::path::Path::exists`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn try_exists>(&self, path: P) -> io::Result { - self.cap_std.try_exists(from_utf8(path.as_ref())?).await - } - - /// Returns `true` if the path exists on disk and is pointing at a regular - /// file. - /// - /// This corresponds to [`async_std::path::Path::is_file`], but only - /// accesses paths relative to `self`. - #[inline] - pub async fn is_file>(&self, path: P) -> bool { - match from_utf8(path.as_ref()) { - Ok(path) => self.cap_std.is_file(path).await, - Err(_) => false, - } - } - - /// Checks if `path` is a directory. - /// - /// This is similar to [`async_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 async fn is_dir>(&self, path: P) -> bool { - match from_utf8(path.as_ref()) { - Ok(path) => self.cap_std.is_dir(path).await, - 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 async 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) - .await - .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 async fn open_parent_dir(&self, ambient_authority: AmbientAuthority) -> io::Result { - self.cap_std - .open_parent_dir(ambient_authority) - .await - .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 async 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).await - } - - /// 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 async fn reopen_dir(dir: &Filelike) -> io::Result { - // Our public API has a `&Filelike` here, which prevents us from doing - // a `clone` as we usually do. So instead, we use the raw fd, which we - // can clone and depend on it remaining open until we return. - let raw_filelike = dir.as_filelike_view::().as_raw_filelike(); - // SAFETY: `raw_filelike` remains open for the duration of the `reopen_dir` - // call. - let file = ManuallyDrop::new(unsafe { std::fs::File::from_raw_filelike(raw_filelike) }); - crate::fs::Dir::reopen_dir(&*file) - .await - .map(Self::from_cap_std) - } -} - -// 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.cap_std.as_raw_fd() - } -} - -#[cfg(not(windows))] -impl AsFd for Dir { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - self.cap_std.as_fd() - } -} - -#[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 AsHandleOrSocket for Dir { - #[inline] - fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> { - self.cap_std.as_handle_or_socket() - } -} - -#[cfg(windows)] -impl AsRawHandleOrSocket for Dir { - #[inline] - fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket { - self.cap_std.as_raw_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) - } -} diff --git a/cap-async-std/src/fs_utf8/dir_entry.rs b/cap-async-std/src/fs_utf8/dir_entry.rs deleted file mode 100644 index cabfcb8c..00000000 --- a/cap-async-std/src/fs_utf8/dir_entry.rs +++ /dev/null @@ -1,119 +0,0 @@ -use 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 [`async_std::fs::DirEntry`]. -/// -/// Unlike `async_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 `async_std::fs::DirEntry` doesn't provide -/// a way to construct a `DirEntry` without opening directories by ambient -/// paths. -/// -/// TODO: async -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 [`async_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 [`async_std::fs::DirEntry::file_type`]. - #[inline] - pub async fn file_type(&self) -> io::Result { - self.cap_std.file_type().await - } - - /// 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 [`async_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) - } -} diff --git a/cap-async-std/src/fs_utf8/file.rs b/cap-async-std/src/fs_utf8/file.rs deleted file mode 100644 index 5bbc5aa6..00000000 --- a/cap-async-std/src/fs_utf8/file.rs +++ /dev/null @@ -1,449 +0,0 @@ -use crate::fs::{Metadata, OpenOptions, Permissions}; -use crate::fs_utf8::from_utf8; -use async_std::fs; -use async_std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; -#[cfg(unix)] -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg(target_os = "wasi")] -use async_std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::task::{Context, Poll}; -use camino::Utf8Path; -use cap_primitives::AmbientAuthority; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -#[cfg(windows)] -use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle}; -use std::fmt; -use std::pin::Pin; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A reference to an open file on a filesystem. -/// -/// This corresponds to [`async_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 - /// `async_std::fs::File`. - /// - /// This grants access the resources the `async_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 an `async_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 [`async_std::fs::File::sync_all`]. - #[inline] - pub async fn sync_all(&self) -> io::Result<()> { - self.cap_std.sync_all().await - } - - /// This function is similar to `sync_all`, except that it may not - /// synchronize file metadata to a filesystem. - /// - /// This corresponds to [`async_std::fs::File::sync_data`]. - #[inline] - pub async fn sync_data(&self) -> io::Result<()> { - self.cap_std.sync_data().await - } - - /// Truncates or extends the underlying file, updating the size of this - /// file to become size. - /// - /// This corresponds to [`async_std::fs::File::set_len`]. - #[inline] - pub async fn set_len(&self, size: u64) -> io::Result<()> { - self.cap_std.set_len(size).await - } - - /// Queries metadata about the underlying file. - /// - /// This corresponds to [`async_std::fs::File::metadata`]. - #[inline] - pub async fn metadata(&self) -> io::Result { - self.cap_std.metadata().await - } - - // async_std doesn't have `try_clone`. - - /// Changes the permissions on the underlying file. - /// - /// This corresponds to [`async_std::fs::File::set_permissions`]. - #[inline] - pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> { - self.cap_std.set_permissions(perm).await - } - - /// 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 async fn open_ambient>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - crate::fs::File::open_ambient(path, ambient_authority) - .await - .map(Self::from_cap_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 async fn create_ambient>( - path: P, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - crate::fs::File::create_ambient(path, ambient_authority) - .await - .map(Self::from_cap_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 async fn open_ambient_with>( - path: P, - options: &OpenOptions, - ambient_authority: AmbientAuthority, - ) -> io::Result { - let path = from_utf8(path.as_ref())?; - crate::fs::File::open_ambient_with(path, options, ambient_authority) - .await - .map(Self::from_cap_std) - } - - /// Returns a new `OpenOptions` object. - /// - /// This corresponds to [`async_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 poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut self.cap_std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut self.cap_std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Read for &File { - #[inline] - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut &self.cap_std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut &self.cap_std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Write for File { - #[inline] - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &[u8], - ) -> Poll> { - Write::poll_write(Pin::new(&mut self.cap_std), cx, buf) - } - - #[inline] - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut self.cap_std), cx) - } - - #[inline] - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut self.cap_std), cx) - } - - #[inline] - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut self.cap_std), cx, bufs) - } - - // async_std doesn't have `can_vector`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Write for &File { - #[inline] - fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { - Write::poll_write(Pin::new(&mut &self.cap_std), cx, buf) - } - - #[inline] - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut &self.cap_std), cx) - } - - #[inline] - fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut &self.cap_std), cx) - } - - #[inline] - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut &self.cap_std), cx, bufs) - } - - // async_std doesn't have `can_vector`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Seek for File { - #[inline] - fn poll_seek( - mut self: Pin<&mut Self>, - cx: &mut Context, - pos: SeekFrom, - ) -> Poll> { - Seek::poll_seek(Pin::new(&mut self.cap_std), cx, pos) - } - - // async_std doesn't have `stream_position`. -} - -impl Seek for &File { - #[inline] - fn poll_seek(self: Pin<&mut Self>, cx: &mut Context, pos: SeekFrom) -> Poll> { - Seek::poll_seek(Pin::new(&mut &self.cap_std), cx, pos) - } - - // async_std doesn't have `stream_position`. -} - -// TODO: Can async_std implement `From` for `process::Stdio`? - -// async_std doesn't have `FileExt`. - -impl fmt::Debug for File { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.cap_std.fmt(f) - } -} diff --git a/cap-async-std/src/fs_utf8/mod.rs b/cap-async-std/src/fs_utf8/mod.rs deleted file mode 100644 index 3002a862..00000000 --- a/cap-async-std/src/fs_utf8/mod.rs +++ /dev/null @@ -1,102 +0,0 @@ -//! A fully UTF-8 filesystem API modeled after [`cap_async_std::fs`]. -//! -//! Where `cap_async_std::fs` would use `Path` and `PathBuf`, this `fs_utf8` -//! module uses [`Utf8Path`] and [`Utf8PathBuf`], meaning that all paths are -//! valid UTF-8. -//! -//! If you don't want this, use the regular [`cap_async_std::fs`] module -//! instead. -//! -//! [`cap_async_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"))] -fn from_utf8<'a>(path: &'a Utf8Path) -> std::io::Result<&'a async_std::path::Path> { - Ok(path.as_std_path().into()) -} - -#[cfg(feature = "arf_strings")] -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().into()) - .ok_or_else(|| ::rustix::io::Errno::ILSEQ)? - .to_path_buf()) - } - - #[cfg(not(feature = "arf_strings"))] - #[cfg(windows)] - { - Ok(Utf8Path::from_path(path.as_ref().into()) - .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) - } - } -} diff --git a/cap-async-std/src/fs_utf8/read_dir.rs b/cap-async-std/src/fs_utf8/read_dir.rs deleted file mode 100644 index 2e143e06..00000000 --- a/cap-async-std/src/fs_utf8/read_dir.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::fs_utf8::DirEntry; -use std::{fmt, io}; - -/// Iterator over the entries in a directory. -/// -/// This corresponds to [`async_std::fs::ReadDir`]. -/// -/// There is no `from_std` method, as `async_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) - } -} diff --git a/cap-async-std/src/lib.rs b/cap-async-std/src/lib.rs deleted file mode 100644 index 2397ba31..00000000 --- a/cap-async-std/src/lib.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! A capability-based API modeled after [`async_std`]. -//! -//! This corresponds to [`async_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(target_os = "wasi", feature(wasi_ext))] -// async_std doesn't have "can_vector". -// async_std doesn't have "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; -#[doc(hidden)] -pub use cap_primitives::ambient_authority_known_at_compile_time; -pub use cap_primitives::{ambient_authority, AmbientAuthority}; - -// Re-export `async_std` 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 async_std; -// And these are also part of our public API -pub use cap_primitives::ipnet; -pub use io_lifetimes; diff --git a/cap-async-std/src/net/incoming.rs b/cap-async-std/src/net/incoming.rs deleted file mode 100644 index 84d7ca41..00000000 --- a/cap-async-std/src/net/incoming.rs +++ /dev/null @@ -1,52 +0,0 @@ -use crate::net::TcpStream; -use async_std::stream::Stream; -use async_std::task::{Context, Poll}; -use async_std::{io, net}; -use std::fmt; -use std::pin::Pin; - -/// An iterator that infinitely `accept`s connections on a [`TcpListener`]. -/// -/// This corresponds to [`async_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 - /// `async_std::net::Incoming`. - /// - /// This grants access the resources the `async_std::net::Incoming` - /// instance already has access to. - #[inline] - pub fn from_std(std: net::Incoming<'a>) -> Self { - Self { std } - } -} - -impl<'a> Stream for Incoming<'a> { - type Item = io::Result; - - #[inline] - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Stream::poll_next(Pin::new(&mut self.std), cx).map(|poll| { - poll.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) - } -} diff --git a/cap-async-std/src/net/mod.rs b/cap-async-std/src/net/mod.rs deleted file mode 100644 index 24b2e5ae..00000000 --- a/cap-async-std/src/net/mod.rs +++ /dev/null @@ -1,29 +0,0 @@ -//! A capability-based network API modeled after [`async_std::net`]. -//! -//! This corresponds to [`async_std::net`]. -//! -//! Instead of [`async_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 `async_std::net` that we can use as-is. -pub use async_std::net::{ - AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, - ToSocketAddrs, -}; - -// TODO: re-export experimental Ipv6MulticastScope? diff --git a/cap-async-std/src/net/pool.rs b/cap-async-std/src/net/pool.rs deleted file mode 100644 index 2da1cc5e..00000000 --- a/cap-async-std/src/net/pool.rs +++ /dev/null @@ -1,231 +0,0 @@ -use crate::net::{TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; -use async_std::{io, net}; -use cap_primitives::net::no_socket_addrs; -use cap_primitives::{ipnet, AmbientAuthority}; - -/// A pool of network addresses. -/// -/// This does not directly correspond to anything in `async_std`, however its -/// methods correspond to the several functions in [`async_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 async fn insert( - &mut self, - addrs: A, - ambient_authority: AmbientAuthority, - ) -> io::Result<()> { - for addr in addrs.to_socket_addrs().await? { - self.cap.insert(addr, ambient_authority)?; - } - Ok(()) - } - - /// 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 [`async_std::net::TcpListener::bind`]. - #[doc(alias = "bind")] - #[inline] - pub async fn bind_tcp_listener(&self, addr: A) -> io::Result { - let addrs = addr.to_socket_addrs().await?; - - 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).await { - 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()), - } - } - - /// Creates a new TCP stream connected to the specified address. - /// - /// This corresponds to [`async_std::net::TcpStream::connect`]. - #[doc(alias = "connect")] - #[inline] - pub async fn connect_tcp_stream(&self, addr: A) -> io::Result { - let addrs = addr.to_socket_addrs().await?; - - 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).await { - 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()), - } - } - - // async_std doesn't have `connect_timeout`. - - /// Creates a UDP socket from the given address. - /// - /// This corresponds to [`async_std::net::UdpSocket::bind`]. - #[doc(alias = "bind")] - #[inline] - pub async fn bind_udp_socket(&self, addr: A) -> io::Result { - let addrs = addr.to_socket_addrs().await?; - - let mut last_err = None; - for addr in addrs { - self.cap.check_addr(&addr)?; - match net::UdpSocket::bind(addr).await { - 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. - /// - /// This corresponds to [`async_std::net::UdpSocket::send_to`]. - #[doc(alias = "send_to")] - #[inline] - pub async fn send_to_udp_socket_addr( - &self, - udp_socket: &UdpSocket, - buf: &[u8], - addr: A, - ) -> io::Result { - let mut addrs = addr.to_socket_addrs().await?; - - // `UdpSocket::send_to` only sends to the first address. - let addr = match addrs.next() { - None => return Err(no_socket_addrs()), - Some(addr) => addr, - }; - self.cap.check_addr(&addr)?; - udp_socket.std.send_to(buf, addr).await - } - - /// Connects the UDP socket to a remote address. - /// - /// This corresponds to [`async_std::net::UdpSocket::connect`]. - #[doc(alias = "connect")] - #[inline] - pub async fn connect_udp_socket( - &self, - udp_socket: &UdpSocket, - addr: A, - ) -> io::Result<()> { - let addrs = addr.to_socket_addrs().await?; - - let mut last_err = None; - for addr in addrs { - self.cap.check_addr(&addr)?; - match udp_socket.std.connect(addr).await { - Ok(()) => return Ok(()), - Err(e) => last_err = Some(e), - } - } - match last_err { - Some(e) => Err(e), - None => Err(no_socket_addrs()), - } - } -} diff --git a/cap-async-std/src/net/tcp_listener.rs b/cap-async-std/src/net/tcp_listener.rs deleted file mode 100644 index b097ad68..00000000 --- a/cap-async-std/src/net/tcp_listener.rs +++ /dev/null @@ -1,219 +0,0 @@ -use crate::net::{Incoming, SocketAddr, TcpStream}; -#[cfg(unix)] -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::{io, net}; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -#[cfg(windows)] -use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; -use std::fmt; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A TCP socket server, listening for connections. -/// -/// This corresponds to [`async_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 - /// `async_std::net::TcpListener`. - /// - /// This grants access the resources the `async_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 [`async_std::net::TcpListener::local_addr`]. - #[inline] - pub fn local_addr(&self) -> io::Result { - self.std.local_addr() - } - - // async_std doesn't have `try_clone`. - - /// Accept a new incoming connection from this listener. - /// - /// This corresponds to [`async_std::net::TcpListener::accept`]. - #[inline] - pub async fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> { - self.std - .accept() - .await - .map(|(tcp_stream, addr)| (TcpStream::from_std(tcp_stream), addr)) - } - - /// Returns an iterator over the connections being received on this - /// listener. - /// - /// This corresponds to [`async_std::net::TcpListener::incoming`]. - #[inline] - pub fn incoming(&self) -> Incoming<'_> { - let incoming = self.std.incoming(); - Incoming::from_std(incoming) - } - - // async_std doesn't have `TcpListener::set_ttl`. - - // async_std doesn't have `TcpListener::ttl`. - - // async_std doesn't have `TcpListener::take_error`. - - // async_std doesn't have `TcpListener::set_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) - } -} diff --git a/cap-async-std/src/net/tcp_stream.rs b/cap-async-std/src/net/tcp_stream.rs deleted file mode 100644 index 48d56cf3..00000000 --- a/cap-async-std/src/net/tcp_stream.rs +++ /dev/null @@ -1,375 +0,0 @@ -use crate::net::{Shutdown, SocketAddr}; -use async_std::io::{self, IoSlice, IoSliceMut, Read, Write}; -use async_std::net; -#[cfg(unix)] -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::task::{Context, Poll}; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -#[cfg(windows)] -use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; -use std::fmt; -use std::pin::Pin; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A TCP stream between a local and a remote socket. -/// -/// This corresponds to [`async_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 -#[derive(Clone)] -pub struct TcpStream { - std: net::TcpStream, -} - -impl TcpStream { - /// Constructs a new instance of `Self` from the given - /// `async_std::net::TcpStream`. - /// - /// This grants access the resources the `async_std::net::TcpStream` - /// instance already has access to. - #[inline] - pub fn from_std(std: net::TcpStream) -> Self { - Self { std } - } - - /// Returns the remote address that this stream is connected to. - /// - /// This corresponds to [`async_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 [`async_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 [`async_std::net::TcpStream::shutdown`]. - #[inline] - pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { - self.std.shutdown(how) - } - - // async_std doesn't have `try_clone`. - - // async_std doesn't have `set_read_timeout`. - - // async_std doesn't have `set_write_timeout`. - - // async_std doesn't have `read_timeout`. - - // async_std doesn't have `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 [`async_std::net::TcpStream::peek`]. - #[inline] - pub async fn peek(&self, buf: &mut [u8]) -> io::Result { - self.std.peek(buf).await - } - - /// Sets the value of the `TCP_NODELAY` option on this socket. - /// - /// This corresponds to [`async_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 [`async_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 [`async_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 [`async_std::net::TcpStream::ttl`]. - #[inline] - pub fn ttl(&self) -> io::Result { - self.std.ttl() - } - - // async_std doesn't have `take_error`. - - // async_std doesn't have `set_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(stream: TcpStream) -> OwnedSocket { - stream.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 poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Read for &TcpStream { - #[inline] - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Write for TcpStream { - #[inline] - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &[u8], - ) -> Poll> { - Write::poll_write(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Write for &TcpStream { - #[inline] - fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { - Write::poll_write(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl fmt::Debug for TcpStream { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.std.fmt(f) - } -} diff --git a/cap-async-std/src/net/udp_socket.rs b/cap-async-std/src/net/udp_socket.rs deleted file mode 100644 index 6cb418c3..00000000 --- a/cap-async-std/src/net/udp_socket.rs +++ /dev/null @@ -1,364 +0,0 @@ -use crate::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; -#[cfg(unix)] -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::{io, net}; -#[cfg(not(windows))] -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -#[cfg(windows)] -use io_lifetimes::{AsSocket, BorrowedSocket, OwnedSocket}; -use std::fmt; -#[cfg(windows)] -use { - async_std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}, - io_extras::os::windows::{ - AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, IntoRawHandleOrSocket, - OwnedHandleOrSocket, RawHandleOrSocket, - }, -}; - -/// A UDP socket. -/// -/// This corresponds to [`async_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 - /// `async_std::net::UdpSocket`. - /// - /// This grants access the resources the `async_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 [`async_std::net::UdpSocket::recv_from`]. - #[inline] - pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.std.recv_from(buf).await - } - - // async_std doesn't have `peek_from`. - - /// Returns the socket address of the remote peer this socket was connected - /// to. - /// - /// This corresponds to [`async_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 [`async_std::net::UdpSocket::local_addr`]. - #[inline] - pub fn local_addr(&self) -> io::Result { - self.std.local_addr() - } - - // async_std doesn't have `try_clone`. - - // async_std doesn't have `set_read_timeout`. - - // async_std doesn't have `set_write_timeout`. - - // async_std doesn't have `read_timeout`. - - // async_std doesn't have `write_timeout`. - - /// Sets the value of the `SO_BROADCAST` option for this socket. - /// - /// This corresponds to [`async_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 [`async_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 - /// [`async_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 [`async_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 - /// [`async_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 [`async_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 - /// [`async_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 [`async_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 [`async_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 [`async_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 [`async_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 [`async_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 [`async_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 [`async_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) - } - - // async_std doesn't have `take_error`. - - /// Sends data on the socket to the remote address to which it is - /// connected. - /// - /// This corresponds to [`async_std::net::UdpSocket::send`]. - #[inline] - pub async fn send(&self, buf: &[u8]) -> io::Result { - self.std.send(buf).await - } - - /// Receives a single datagram message on the socket from the remote - /// address to which it is connected. - /// - /// This corresponds to [`async_std::net::UdpSocket::recv`]. - #[inline] - pub async fn recv(&self, buf: &mut [u8]) -> io::Result { - self.std.recv(buf).await - } - - // async_std doesn't have `UdpSocket::peek`. - - // async_std doesn't have `set_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) - } -} diff --git a/cap-async-std/src/os/mod.rs b/cap-async-std/src/os/mod.rs deleted file mode 100644 index b328c15c..00000000 --- a/cap-async-std/src/os/mod.rs +++ /dev/null @@ -1,6 +0,0 @@ -//! OS-specific extensions. -//! -//! This corresponds to [`async_std::os`]. - -#[cfg(unix)] -pub mod unix; diff --git a/cap-async-std/src/os/unix/mod.rs b/cap-async-std/src/os/unix/mod.rs deleted file mode 100644 index 75aa605c..00000000 --- a/cap-async-std/src/os/unix/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Platform-specific extensions for Unix platforms. -//! -//! This corresponds to [`async_std::os::unix`]. -//! -//! [`async_std::os::unix`]: https://docs.rs/async-std/latest/async_std/os/unix/ - -pub mod net; diff --git a/cap-async-std/src/os/unix/net/incoming.rs b/cap-async-std/src/os/unix/net/incoming.rs deleted file mode 100644 index bfa6882b..00000000 --- a/cap-async-std/src/os/unix/net/incoming.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::os::unix::net::UnixStream; -use async_std::io; -use async_std::os::unix; -use async_std::stream::Stream; -use async_std::task::{Context, Poll}; -use std::fmt; -use std::pin::Pin; - -/// An iterator over incoming connections to a [`UnixListener`]. -/// -/// This corresponds to [`async_std::os::unix::net::Incoming`]. -/// -/// [`async_std::os::unix::net::Incoming`]: https://docs.rs/async-std/latest/async_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 - /// `async_std::os::unix::net::Incoming`. - /// - /// This grants access the resources the - /// `async_std::os::unix::net::Incoming` instance already has access to, - /// without any sandboxing. - #[inline] - pub fn from_std(std: unix::net::Incoming<'a>) -> Self { - Self { std } - } -} - -impl<'a> Stream for Incoming<'a> { - type Item = io::Result; - - #[inline] - fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Stream::poll_next(Pin::new(&mut self.std), cx).map(|poll| { - poll.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) - } -} diff --git a/cap-async-std/src/os/unix/net/mod.rs b/cap-async-std/src/os/unix/net/mod.rs deleted file mode 100644 index 800611ed..00000000 --- a/cap-async-std/src/os/unix/net/mod.rs +++ /dev/null @@ -1,17 +0,0 @@ -//! Unix-specific networking functionality -//! -//! This corresponds to [`async_std::os::unix::net`]. -//! -//! [`async_std::os::unix::net`]: https://docs.rs/async-std/latest/async_std/os/unix/net/ - -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 async_std::os::unix::net::SocketAddr; diff --git a/cap-async-std/src/os/unix/net/unix_datagram.rs b/cap-async-std/src/os/unix/net/unix_datagram.rs deleted file mode 100644 index ac487203..00000000 --- a/cap-async-std/src/os/unix/net/unix_datagram.rs +++ /dev/null @@ -1,190 +0,0 @@ -use crate::net::Shutdown; -use crate::os::unix::net::SocketAddr; -use async_std::io; -use async_std::os::unix; -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -use std::fmt; - -/// A Unix datagram socket. -/// -/// This corresponds to [`async_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`]. -/// -/// [`async_std::os::unix::net::UnixDatagram`]: https://docs.rs/async-std/latest/async_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 - /// `async_std::os::unix::net::UnixDatagram`. - /// - /// This grants access the resources the - /// `async_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 - /// [`async_std::os::unix::net::UnixDatagram::unbound`]. - /// - /// TODO: should this require a capability? - /// - /// [`async_std::os::unix::net::UnixDatagram::unbound`]: https://docs.rs/async-std/latest/async_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 [`async_std::os::unix::net::UnixDatagram::pair`]. - /// - /// TODO: should this require a capability? - /// - /// [`async_std::os::unix::net::UnixDatagram::pair`]: https://docs.rs/async-std/latest/async_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))) - } - - // async_std doesn't have `try_clone`. - - /// Returns the address of this socket. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixDatagram::local_addr`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::local_addr`]: https://docs.rs/async-std/latest/async_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 - /// [`async_std::os::unix::net::UnixDatagram::peer_addr`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::peer_addr`]: https://docs.rs/async-std/latest/async_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 - /// [`async_std::os::unix::net::UnixDatagram::recv_from`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::recv_from`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.recv_from - #[inline] - pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { - self.std.recv_from(buf).await - } - - /// Receives data from the socket. - /// - /// This corresponds to [`async_std::os::unix::net::UnixDatagram::recv`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::recv`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.recv - #[inline] - pub async fn recv(&self, buf: &mut [u8]) -> io::Result { - self.std.recv(buf).await - } - - /// Sends data on the socket to the socket's peer. - /// - /// This corresponds to [`async_std::os::unix::net::UnixDatagram::send`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::send`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixDatagram.html#method.send - #[inline] - pub async fn send(&self, buf: &[u8]) -> io::Result { - self.std.send(buf).await - } - - // async_std doesn't have `set_read_timeout`. - - // async_std doesn't have `set_write_timeout`. - - // async_std doesn't have `read_timeout`. - - // async_std doesn't have `write_timeout`. - - // async_std doesn't have `set_nonblocking`. - - // async_std doesn't have `take_error`. - - /// Shut down the read, write, or both halves of this connection. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixDatagram::shutdown`]. - /// - /// [`async_std::os::unix::net::UnixDatagram::shutdown`]: https://docs.rs/async-std/latest/async_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) - } -} diff --git a/cap-async-std/src/os/unix/net/unix_listener.rs b/cap-async-std/src/os/unix/net/unix_listener.rs deleted file mode 100644 index bc00e0b6..00000000 --- a/cap-async-std/src/os/unix/net/unix_listener.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::os::unix::net::{Incoming, SocketAddr, UnixStream}; -use async_std::io; -use async_std::os::unix; -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -use std::fmt; - -/// A structure representing a Unix domain socket server. -/// -/// This corresponds to [`async_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`]. -/// -/// [`async_std::os::unix::net::UnixListener`]: https://docs.rs/async-std/latest/async_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 - /// `async_std::os::unix::net::UnixListener`. - /// - /// This grants access the resources the - /// `async_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 [`async_std::os::unix::net::UnixListener::accept`]. - /// - /// [`async_std::os::unix::net::UnixListener::accept`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixListener.html#method.accept - #[inline] - pub async fn accept(&self) -> io::Result<(UnixStream, SocketAddr)> { - self.std - .accept() - .await - .map(|(unix_stream, addr)| (UnixStream::from_std(unix_stream), addr)) - } - - // async_std doesn't have `try_clone`. - - /// Returns the local socket address of this listener. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixListener::local_addr`]. - /// - /// [`async_std::os::unix::net::UnixListener::local_addr`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixListener.html#method.local_addr - #[inline] - pub fn local_addr(&self) -> io::Result { - self.std.local_addr() - } - - // async_std doesn't have `set_nonblocking`. - - // async_std doesn't have `take_error`. - - /// Returns an iterator over incoming connections. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixListener::incoming`]. - /// - /// [`async_std::os::unix::net::UnixListener::incoming`]: https://docs.rs/async-std/latest/async_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() - } -} - -// async_std's `IntoStream` is unstable. - -impl fmt::Debug for UnixListener { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.std.fmt(f) - } -} diff --git a/cap-async-std/src/os/unix/net/unix_stream.rs b/cap-async-std/src/os/unix/net/unix_stream.rs deleted file mode 100644 index 79162d21..00000000 --- a/cap-async-std/src/os/unix/net/unix_stream.rs +++ /dev/null @@ -1,256 +0,0 @@ -use crate::net::Shutdown; -use crate::os::unix::net::SocketAddr; -use async_std::io::{self, IoSlice, IoSliceMut, Read, Write}; -use async_std::os::unix; -use async_std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -use async_std::task::{Context, Poll}; -use io_lifetimes::{AsFd, BorrowedFd, OwnedFd}; -use std::fmt; -use std::pin::Pin; - -/// A Unix stream socket. -/// -/// This corresponds to [`async_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`]. -/// -/// [`async_std::os::unix::net::UnixStream`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixStream.html -/// [`Dir`]: struct.Dir.html -/// [`Dir::connect_unix_stream`]: struct.Dir.html#method.connect_unix_stream -#[derive(Clone)] -pub struct UnixStream { - std: unix::net::UnixStream, -} - -impl UnixStream { - /// Constructs a new instance of `Self` from the given - /// `async_std::os::unix::net::UnixStream`. - /// - /// This grants access the resources the - /// `async_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 [`async_std::os::unix::net::UnixStream::pair`]. - /// - /// TODO: should this require a capability? - /// - /// [`async_std::os::unix::net::UnixStream::pair`]: https://docs.rs/async-std/latest/async_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))) - } - - // async_std doesn't have `try_clone`. - - /// Returns the socket address of the local half of this connection. - /// - /// This corresponds to - /// [`async_std::os::unix::net::UnixStream::local_addr`]. - /// - /// [`async_std::os::unix::net::UnixStream::local_addr`]: https://docs.rs/async-std/latest/async_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 - /// [`async_std::os::unix::net::UnixStream::peer_addr`]. - /// - /// [`async_std::os::unix::net::UnixStream::peer_addr`]: https://docs.rs/async-std/latest/async_std/os/unix/net/struct.UnixStream.html#method.peer_addr - #[inline] - pub fn peer_addr(&self) -> io::Result { - self.std.peer_addr() - } - - // async_std doesn't have `set_read_timeout`. - - // async_std doesn't have `set_write_timeout`. - - // async_std doesn't have `read_timeout`. - - // async_std doesn't have `write_timeout`. - - // async_std doesn't have `set_nonblocking`. - - // async_std doesn't have `take_error`. - - /// Shuts down the read, write, or both halves of this connection. - /// - /// This corresponds to [`async_std::os::unix::net::UnixStream::shutdown`]. - /// - /// [`async_std::os::unix::net::UnixStream::shutdown`]: https://docs.rs/async-std/latest/async_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 poll_read( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Read for &UnixStream { - #[inline] - fn poll_read( - self: Pin<&mut Self>, - cx: &mut Context, - buf: &mut [u8], - ) -> Poll> { - Read::poll_read(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_read_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &mut [IoSliceMut], - ) -> Poll> { - Read::poll_read_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_read_vectored`. - - // async_std doesn't have `initializer`. -} - -impl Write for UnixStream { - #[inline] - fn poll_write( - mut self: Pin<&mut Self>, - cx: &mut Context, - buf: &[u8], - ) -> Poll> { - Write::poll_write(Pin::new(&mut self.std), cx, buf) - } - - #[inline] - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut self.std), cx) - } - - #[inline] - fn poll_write_vectored( - mut self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl Write for &UnixStream { - #[inline] - fn poll_write(self: Pin<&mut Self>, cx: &mut Context, buf: &[u8]) -> Poll> { - Write::poll_write(Pin::new(&mut &self.std), cx, buf) - } - - #[inline] - fn poll_flush(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_flush(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_close(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { - Write::poll_close(Pin::new(&mut &self.std), cx) - } - - #[inline] - fn poll_write_vectored( - self: Pin<&mut Self>, - cx: &mut Context, - bufs: &[IoSlice], - ) -> Poll> { - Write::poll_write_vectored(Pin::new(&mut &self.std), cx, bufs) - } - - // async_std doesn't have `is_write_vectored`. - - // async_std doesn't have `write_all_vectored`. -} - -impl fmt::Debug for UnixStream { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.std.fmt(f) - } -} diff --git a/cap-async-std/src/time/mod.rs b/cap-async-std/src/time/mod.rs deleted file mode 100644 index ff5d788d..00000000 --- a/cap-async-std/src/time/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -//! 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, -}; diff --git a/cap-fs-ext/Cargo.toml b/cap-fs-ext/Cargo.toml index c5b9df26..fc1a396f 100644 --- a/cap-fs-ext/Cargo.toml +++ b/cap-fs-ext/Cargo.toml @@ -14,12 +14,9 @@ edition = "2021" [dependencies] arf-strings = { version = "0.7.0", optional = true } -cap-async-std = { path = "../cap-async-std", optional = true, version = "3.4.5" } cap-std = { path = "../cap-std", optional = true, version = "3.4.5" } cap-primitives = { path = "../cap-primitives", version = "3.4.5" } io-lifetimes = { version = "2.0.0", default-features = false } -async-std = { version = "1.13.0", features = ["io_safety", "attributes"], optional = true } -async-trait = { version = "0.1.42", optional = true } camino = { version = "1.0.5", optional = true } [features] @@ -27,9 +24,6 @@ default = ["std"] fs_utf8 = ["cap-std/fs_utf8", "camino"] arf_strings = ["cap-std/arf_strings", "fs_utf8", "arf-strings"] std = ["cap-std"] -async_std = ["cap-async-std", "async-std", "io-lifetimes/async-std", "async-trait"] -async_std_fs_utf8 = ["cap-async-std/fs_utf8", "camino"] -async_std_arf_strings = ["cap-async-std/arf_strings", "async_std_fs_utf8", "arf-strings"] [target.'cfg(windows)'.dependencies.windows-sys] version = ">=0.52, <=0.59" diff --git a/cap-fs-ext/src/dir_entry_ext.rs b/cap-fs-ext/src/dir_entry_ext.rs index b71b1310..59abf6fb 100644 --- a/cap-fs-ext/src/dir_entry_ext.rs +++ b/cap-fs-ext/src/dir_entry_ext.rs @@ -39,22 +39,6 @@ impl DirEntryExt for cap_std::fs::DirEntry { } } -#[cfg(all(not(windows), feature = "async_std"))] -impl DirEntryExt for cap_async_std::fs::DirEntry { - #[inline] - fn full_metadata(&self) -> io::Result { - self.metadata() - } -} - -#[cfg(all(windows, feature = "async_std"))] -impl DirEntryExt for cap_async_std::fs::DirEntry { - #[inline] - fn full_metadata(&self) -> io::Result { - _WindowsDirEntryExt::full_metadata(self) - } -} - #[cfg(all(not(windows), feature = "std", feature = "fs_utf8"))] impl DirEntryExt for cap_std::fs_utf8::DirEntry { #[inline] @@ -70,19 +54,3 @@ impl DirEntryExt for cap_std::fs_utf8::DirEntry { _WindowsDirEntryExt::full_metadata(self) } } - -#[cfg(all(not(windows), feature = "async_std", feature = "fs_utf8"))] -impl DirEntryExt for cap_async_std::fs_utf8::DirEntry { - #[inline] - fn full_metadata(&self) -> io::Result { - self.metadata() - } -} - -#[cfg(all(windows, feature = "async_std", feature = "fs_utf8"))] -impl DirEntryExt for cap_async_std::fs_utf8::DirEntry { - #[inline] - fn full_metadata(&self) -> io::Result { - _WindowsDirEntryExt::full_metadata(self) - } -} diff --git a/cap-fs-ext/src/dir_ext.rs b/cap-fs-ext/src/dir_ext.rs index 71124a6c..afc31385 100644 --- a/cap-fs-ext/src/dir_ext.rs +++ b/cap-fs-ext/src/dir_ext.rs @@ -1,7 +1,5 @@ #[cfg(feature = "fs_utf8")] use camino::Utf8Path; -#[cfg(all(windows, feature = "async_std", feature = "fs_utf8"))] -use cap_primitives::fs::stat; #[cfg(not(windows))] use cap_primitives::fs::symlink; use cap_primitives::fs::{ @@ -13,8 +11,6 @@ use cap_primitives::fs::{symlink_dir, symlink_file}; use io_lifetimes::AsFilelike; use std::io; use std::path::Path; -#[cfg(feature = "async_std")] -use {async_std::task::spawn_blocking, async_trait::async_trait}; pub use cap_primitives::fs::{AccessType, SystemTimeSpec}; @@ -112,152 +108,8 @@ pub trait DirExt { -> io::Result<()>; } -/// Extension trait for `Dir`, async. -/// -/// The path parameters include `Send` for the `async_trait` macro. -#[cfg(feature = "async_std")] -#[async_trait] -pub trait AsyncDirExt { - /// Set the last access time for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_atime`]. - /// - /// [`filetime::set_file_atime`]: https://docs.rs/filetime/latest/filetime/fn.set_file_atime.html - async fn set_atime + Send>( - &self, - path: P, - atime: SystemTimeSpec, - ) -> io::Result<()>; - - /// Set the last modification time for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_mtime`]. - /// - /// [`filetime::set_file_mtime`]: https://docs.rs/filetime/latest/filetime/fn.set_file_mtime.html - async fn set_mtime + Send>( - &self, - path: P, - mtime: SystemTimeSpec, - ) -> io::Result<()>; - - /// Set the last access and modification times for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_times`]. - /// - /// [`filetime::set_file_times`]: https://docs.rs/filetime/latest/filetime/fn.set_file_times.html - async fn set_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()>; - - /// Set the last access and modification times for a file on a filesystem. - /// This function does not follow symlink. - /// - /// This corresponds to [`filetime::set_symlink_file_times`]. - /// - /// [`filetime::set_symlink_file_times`]: https://docs.rs/filetime/latest/filetime/fn.set_symlink_file_times.html - async fn set_symlink_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()>; - - /// Creates a new symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::unix::fs::symlink`], except that - /// it's supported on non-Unix platforms as well, and it's not guaranteed - /// to be atomic. - /// - /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html - async fn symlink< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Creates a new file symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::windows::fs::symlink_file`], except that - /// it's supported on non-Windows platforms as well, and it's not - /// guaranteed to fail if the target is not a file. - /// - /// [`std::os::windows::fs::symlink_file`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html - async fn symlink_file< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Creates a new directory symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::windows::fs::symlink_dir`], except that - /// it's supported on non-Windows platforms as well, and it's not - /// guaranteed to fail if the target is not a directory. - /// - /// [`std::os::windows::fs::symlink_dir`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html - async fn symlink_dir< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Similar to `cap_std::fs::Dir::open_dir`, but fails if the path names a - /// symlink. - async fn open_dir_nofollow + Send>( - &self, - path: P, - ) -> io::Result - where - Self: Sized; - - /// Removes a file or symlink from a filesystem. - /// - /// Removal of symlinks has different behavior under Windows - if a symlink - /// points to a directory, it cannot be removed with the `remove_file` - /// operation. This method will remove files and all symlinks. - async fn remove_file_or_symlink + Send>( - &self, - path: P, - ) -> io::Result<()>; - - /// Test for accessibility or existence of a filesystem object. - async fn access + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()>; - - /// Test for accessibility or existence of a filesystem object, without - /// following symbolic links. - async fn access_symlink + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()>; - - /// Changes the permissions found on a file or a directory, without following - /// symbolic links. - async fn set_symlink_permissions + Send>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()>; -} - /// `fs_utf8` version of `DirExt`. -#[cfg(all(any(feature = "std", feature = "async_std"), feature = "fs_utf8"))] +#[cfg(all(feature = "std", feature = "fs_utf8"))] pub trait DirExtUtf8 { /// Set the last access time for a file on a filesystem. /// @@ -359,132 +211,6 @@ pub trait DirExtUtf8 { ) -> io::Result<()>; } -/// `fs_utf8` version of `DirExt`. -/// -/// The path parameters include `Send` for the `async_trait` macro. -#[cfg(all(feature = "async_std", feature = "fs_utf8"))] -#[async_trait] -pub trait AsyncDirExtUtf8 { - /// Set the last access time for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_atime`]. - /// - /// [`filetime::set_file_atime`]: https://docs.rs/filetime/latest/filetime/fn.set_file_atime.html - async fn set_atime + Send>( - &self, - path: P, - atime: SystemTimeSpec, - ) -> io::Result<()>; - - /// Set the last modification time for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_mtime`]. - /// - /// [`filetime::set_file_mtime`]: https://docs.rs/filetime/latest/filetime/fn.set_file_mtime.html - async fn set_mtime + Send>( - &self, - path: P, - mtime: SystemTimeSpec, - ) -> io::Result<()>; - - /// Set the last access and modification times for a file on a filesystem. - /// - /// This corresponds to [`filetime::set_file_times`]. - /// - /// [`filetime::set_file_times`]: https://docs.rs/filetime/latest/filetime/fn.set_file_times.html - async fn set_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()>; - - /// Set the last access and modification times for a file on a filesystem. - /// This function does not follow symlink. - /// - /// This corresponds to [`filetime::set_symlink_file_times`]. - /// - /// [`filetime::set_symlink_file_times`]: https://docs.rs/filetime/latest/filetime/fn.set_symlink_file_times.html - async fn set_symlink_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()>; - - /// Creates a new symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::unix::fs::symlink`], except that - /// it's supported on non-Unix platforms as well, and it's not guaranteed - /// to be atomic. - /// - /// [`std::os::unix::fs::symlink`]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html - async fn symlink + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Creates a new file symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::windows::fs::symlink_file`], except that - /// it's supported on non-Windows platforms as well, and it's not - /// guaranteed to fail if the target is not a file. - /// - /// [`std::os::windows::fs::symlink_file`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html - async fn symlink_file + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Creates a new directory symbolic link on a filesystem. - /// - /// This corresponds to [`std::os::windows::fs::symlink_dir`], except that - /// it's supported on non-Windows platforms as well, and it's not - /// guaranteed to fail if the target is not a directory. - /// - /// [`std::os::windows::fs::symlink_dir`]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html - async fn symlink_dir + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()>; - - /// Similar to `cap_std::fs::Dir::open_dir`, but fails if the path names a - /// symlink. - async fn open_dir_nofollow + Send>(&self, path: P) -> io::Result - where - Self: Sized; - - /// Removes a file or symlink from a filesystem. - /// - /// Removal of symlinks has different behavior under Windows - if a symlink - /// points to a directory, it cannot be removed with the `remove_file` - /// operation. This method will remove files and all symlinks. - async fn remove_file_or_symlink + Send>(&self, path: P) -> io::Result<()>; - - /// Test for accessibility or existence of a filesystem object. - async fn access + Send>(&self, path: P, type_: AccessType) - -> io::Result<()>; - - /// Test for accessibility or existence of a filesystem object, without - /// following symbolic links. - async fn access_symlink + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()>; - - /// Changes the permissions found on a file or a directory, without following - /// symbolic links. - async fn set_symlink_permissions + Send>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()>; -} - #[cfg(feature = "std")] impl DirExt for cap_std::fs::Dir { #[inline] @@ -674,359 +400,6 @@ impl DirExt for cap_std::fs::Dir { } } -#[cfg(feature = "async_std")] -#[async_trait] -impl AsyncDirExt for cap_async_std::fs::Dir { - #[inline] - async fn set_atime + Send>( - &self, - path: P, - atime: SystemTimeSpec, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - path.as_ref(), - Some(atime), - None, - ) - }) - .await - } - - #[inline] - async fn set_mtime + Send>( - &self, - path: P, - mtime: SystemTimeSpec, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - path.as_ref(), - None, - Some(mtime), - ) - }) - .await - } - - #[inline] - async fn set_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - path.as_ref(), - atime, - mtime, - ) - }) - .await - } - - #[inline] - async fn set_symlink_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_times_nofollow( - &clone.as_filelike_view::(), - path.as_ref(), - atime, - mtime, - ) - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink_file< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink_dir< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - #[cfg(windows)] - #[inline] - async fn symlink< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - if self.metadata(&src).await?.is_dir() { - spawn_blocking(move || { - symlink_dir( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } else { - spawn_blocking(move || { - symlink_file( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - } - - #[cfg(windows)] - #[inline] - async fn symlink_file< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink_file( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - #[cfg(windows)] - #[inline] - async fn symlink_dir< - P: AsRef + Send, - Q: AsRef + Send, - >( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = src.as_ref().to_path_buf(); - let dst = dst.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - symlink_dir( - src.as_ref(), - &clone.as_filelike_view::(), - dst.as_ref(), - ) - }) - .await - } - - #[inline] - async fn open_dir_nofollow + Send>( - &self, - path: P, - ) -> io::Result { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - match open_dir_nofollow(&clone.as_filelike_view::(), path.as_ref()) { - Ok(file) => Ok(Self::from_std_file(file.into())), - Err(e) => Err(e), - } - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn remove_file_or_symlink + Send>( - &self, - path: P, - ) -> io::Result<()> { - self.remove_file(path).await - } - - #[cfg(windows)] - #[inline] - async fn remove_file_or_symlink + Send>( - &self, - path: P, - ) -> io::Result<()> { - use crate::OpenOptionsFollowExt; - use cap_primitives::fs::_WindowsByHandle; - use cap_std::fs::{OpenOptions, OpenOptionsExt}; - use windows_sys::Win32::Storage::FileSystem::{ - DELETE, FILE_ATTRIBUTE_DIRECTORY, FILE_FLAG_BACKUP_SEMANTICS, - FILE_FLAG_OPEN_REPARSE_POINT, - }; - let path = path.as_ref(); - - let mut opts = OpenOptions::new(); - opts.access_mode(DELETE); - opts.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); - opts.follow(FollowSymlinks::No); - let file = self.open_with(path, &opts).await?; - - let meta = file.metadata().await?; - if meta.file_type().is_symlink() - && meta.file_attributes() & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY - { - self.remove_dir(path).await?; - } else { - self.remove_file(path).await?; - } - - // Drop the file after calling `remove_file` or `remove_dir`, since - // Windows doesn't actually remove the file until after the last open - // handle is closed, and this protects us from race conditions where - // other processes replace the file out from underneath us. - drop(file); - - Ok(()) - } - - /// Test for accessibility or existence of a filesystem object. - async fn access + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - access( - &clone.as_filelike_view::(), - path.as_ref(), - type_, - FollowSymlinks::Yes, - ) - }) - .await - } - - /// Test for accessibility or existence of a filesystem object, without - /// following symbolic links. - async fn access_symlink + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - access( - &clone.as_filelike_view::(), - path.as_ref(), - type_, - FollowSymlinks::No, - ) - }) - .await - } - - /// Changes the permissions found on a file or a directory, without following - /// symbolic links. - async fn set_symlink_permissions + Send>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()> { - let path = path.as_ref().to_path_buf(); - let clone = self.clone(); - spawn_blocking(move || { - set_symlink_permissions( - &clone.as_filelike_view::(), - path.as_ref(), - perm, - ) - }) - .await - } -} - #[cfg(all(feature = "std", feature = "fs_utf8"))] impl DirExtUtf8 for cap_std::fs_utf8::Dir { #[inline] @@ -1227,301 +600,13 @@ impl DirExtUtf8 for cap_std::fs_utf8::Dir { } } -#[cfg(all(feature = "async_std", feature = "fs_utf8"))] -#[async_trait] -impl AsyncDirExtUtf8 for cap_async_std::fs_utf8::Dir { - #[inline] - async fn set_atime + Send>( - &self, - path: P, - atime: SystemTimeSpec, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - &path, - Some(atime), - None, - ) - }) - .await - } - - #[inline] - async fn set_mtime + Send>( - &self, - path: P, - mtime: SystemTimeSpec, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - &path, - None, - Some(mtime), - ) - }) - .await - } - - #[inline] - async fn set_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - set_times( - &clone.as_filelike_view::(), - &path, - atime, - mtime, - ) - }) - .await - } - - #[inline] - async fn set_symlink_times + Send>( - &self, - path: P, - atime: Option, - mtime: Option, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - set_times_nofollow( - &clone.as_filelike_view::(), - &path, - atime, - mtime, - ) - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = from_utf8(src.as_ref())?; - let dst = from_utf8(dst.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || symlink(&src, &clone.as_filelike_view::(), &dst)) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink_file + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - self.symlink(src, dst).await - } - - #[cfg(not(windows))] - #[inline] - async fn symlink_dir + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - self.symlink(src, dst).await - } - - #[cfg(windows)] - #[inline] - async fn symlink + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = from_utf8(src.as_ref())?; - let src_ = src.clone(); - let dst = from_utf8(dst.as_ref())?; - let clone = self.clone(); - // Call `stat` directly to avoid `async_trait` capturing `self`. - let metadata = spawn_blocking(move || { - stat( - &clone.as_filelike_view::(), - &src_, - FollowSymlinks::Yes, - ) - }) - .await?; - let clone = self.clone(); - if metadata.is_dir() { - spawn_blocking(move || { - symlink_dir(&src, &clone.as_filelike_view::(), &dst) - }) - .await - } else { - spawn_blocking(move || { - symlink_file(&src, &clone.as_filelike_view::(), &dst) - }) - .await - } - } - - #[cfg(windows)] - #[inline] - async fn symlink_file + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = from_utf8(src.as_ref())?; - let dst = from_utf8(dst.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || symlink_file(&src, &clone.as_filelike_view::(), &dst)) - .await - } - - #[cfg(windows)] - #[inline] - async fn symlink_dir + Send, Q: AsRef + Send>( - &self, - src: P, - dst: Q, - ) -> io::Result<()> { - let src = from_utf8(src.as_ref())?; - let dst = from_utf8(dst.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || symlink_dir(&src, &clone.as_filelike_view::(), &dst)) - .await - } - - #[inline] - async fn open_dir_nofollow + Send>(&self, path: P) -> io::Result { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - match open_dir_nofollow(&clone.as_filelike_view::(), path.as_ref()) { - Ok(file) => Ok(Self::from_std_file(file.into())), - Err(e) => Err(e), - } - }) - .await - } - - #[cfg(not(windows))] - #[inline] - async fn remove_file_or_symlink + Send>(&self, path: P) -> io::Result<()> { - self.remove_file(path).await - } - - #[cfg(windows)] - #[inline] - async fn remove_file_or_symlink + Send>(&self, path: P) -> io::Result<()> { - use crate::{FollowSymlinks, OpenOptionsFollowExt}; - use cap_primitives::fs::_WindowsByHandle; - use cap_std::fs::{OpenOptions, OpenOptionsExt}; - use windows_sys::Win32::Storage::FileSystem::{ - DELETE, FILE_ATTRIBUTE_DIRECTORY, FILE_FLAG_BACKUP_SEMANTICS, - FILE_FLAG_OPEN_REPARSE_POINT, - }; - let path = path.as_ref(); - - let mut opts = OpenOptions::new(); - opts.access_mode(DELETE); - opts.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS); - opts.follow(FollowSymlinks::No); - let file = self.open_with(path, &opts).await?; - - let meta = file.metadata().await?; - if meta.file_type().is_symlink() - && meta.file_attributes() & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY - { - self.remove_dir(path).await?; - } else { - self.remove_file(path).await?; - } - - // Drop the file after calling `remove_file` or `remove_dir`, since - // Windows doesn't actually remove the file until after the last open - // handle is closed, and this protects us from race conditions where - // other processes replace the file out from underneath us. - drop(file); - - Ok(()) - } - - async fn access + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - access( - &clone.as_filelike_view::(), - path.as_ref(), - type_, - FollowSymlinks::Yes, - ) - }) - .await - } - - async fn access_symlink + Send>( - &self, - path: P, - type_: AccessType, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - access( - &clone.as_filelike_view::(), - path.as_ref(), - type_, - FollowSymlinks::No, - ) - }) - .await - } - - /// Changes the permissions found on a file or a directory, without following - /// symbolic links. - async fn set_symlink_permissions + Send>( - &self, - path: P, - perm: Permissions, - ) -> io::Result<()> { - let path = from_utf8(path.as_ref())?; - let clone = self.clone(); - spawn_blocking(move || { - set_symlink_permissions( - &clone.as_filelike_view::(), - path.as_ref(), - perm, - ) - }) - .await - } -} - -#[cfg(all(any(feature = "std", feature = "async_std"), feature = "fs_utf8"))] +#[cfg(all(feature = "std", feature = "fs_utf8"))] #[cfg(not(feature = "arf_strings"))] fn from_utf8<'a>(path: &'a Utf8Path) -> io::Result<&'a std::path::Path> { Ok(path.as_std_path()) } -#[cfg(all(any(feature = "std", feature = "async_std"), feature = "fs_utf8"))] +#[cfg(all(feature = "std", feature = "fs_utf8"))] #[cfg(feature = "arf_strings")] fn from_utf8<'a>(path: &'a Utf8Path) -> io::Result { #[cfg(not(windows))] diff --git a/cap-fs-ext/src/file_type_ext.rs b/cap-fs-ext/src/file_type_ext.rs index 7598944d..0a23569f 100644 --- a/cap-fs-ext/src/file_type_ext.rs +++ b/cap-fs-ext/src/file_type_ext.rs @@ -63,7 +63,7 @@ impl FileTypeExt for std::fs::FileType { } } -#[cfg(all(not(windows), any(feature = "std", feature = "async_std")))] +#[cfg(all(not(windows), feature = "std"))] impl FileTypeExt for cap_primitives::fs::FileType { #[inline] fn is_block_device(&self) -> bool { @@ -86,7 +86,7 @@ impl FileTypeExt for cap_primitives::fs::FileType { } } -#[cfg(all(windows, any(feature = "std", feature = "async_std")))] +#[cfg(all(windows, feature = "std"))] impl FileTypeExt for cap_primitives::fs::FileType { #[inline] fn is_block_device(&self) -> bool { diff --git a/cap-fs-ext/src/is_file_read_write.rs b/cap-fs-ext/src/is_file_read_write.rs index 949a58db..15381acd 100644 --- a/cap-fs-ext/src/is_file_read_write.rs +++ b/cap-fs-ext/src/is_file_read_write.rs @@ -35,27 +35,3 @@ impl IsFileReadWrite for cap_std::fs_utf8::File { is_file_read_write(&self.as_filelike_view::()) } } - -#[cfg(feature = "async_std")] -impl IsFileReadWrite for async_std::fs::File { - #[inline] - fn is_file_read_write(&self) -> io::Result<(bool, bool)> { - is_file_read_write(&self.as_filelike_view::()) - } -} - -#[cfg(feature = "async_std")] -impl IsFileReadWrite for cap_async_std::fs::File { - #[inline] - fn is_file_read_write(&self) -> io::Result<(bool, bool)> { - is_file_read_write(&self.as_filelike_view::()) - } -} - -#[cfg(all(feature = "async_std", feature = "fs_utf8"))] -impl IsFileReadWrite for cap_async_std::fs_utf8::File { - #[inline] - fn is_file_read_write(&self) -> io::Result<(bool, bool)> { - is_file_read_write(&self.as_filelike_view::()) - } -} diff --git a/cap-fs-ext/src/lib.rs b/cap-fs-ext/src/lib.rs index 22ea2b1e..2ed80ee7 100644 --- a/cap-fs-ext/src/lib.rs +++ b/cap-fs-ext/src/lib.rs @@ -21,11 +21,7 @@ mod open_options_sync_ext; mod reopen; pub use dir_entry_ext::DirEntryExt; -#[cfg(feature = "async_std")] -pub use dir_ext::AsyncDirExt; -#[cfg(all(feature = "async_std", feature = "fs_utf8"))] -pub use dir_ext::AsyncDirExtUtf8; -#[cfg(all(any(feature = "std", feature = "async_std"), feature = "fs_utf8"))] +#[cfg(all(feature = "std", feature = "fs_utf8"))] pub use dir_ext::DirExtUtf8; pub use dir_ext::{AccessType, DirExt, SystemTimeSpec}; pub use file_type_ext::FileTypeExt; diff --git a/cap-fs-ext/src/metadata_ext.rs b/cap-fs-ext/src/metadata_ext.rs index fbacfcf7..f06791c6 100644 --- a/cap-fs-ext/src/metadata_ext.rs +++ b/cap-fs-ext/src/metadata_ext.rs @@ -71,7 +71,7 @@ impl MetadataExt for std::fs::Metadata { } } -#[cfg(all(not(windows), any(feature = "std", feature = "async_std")))] +#[cfg(all(not(windows), feature = "std"))] impl MetadataExt for cap_primitives::fs::Metadata { #[inline] fn dev(&self) -> u64 { @@ -89,7 +89,7 @@ impl MetadataExt for cap_primitives::fs::Metadata { } } -#[cfg(all(windows, any(feature = "std", feature = "async_std")))] +#[cfg(all(windows, feature = "std"))] impl MetadataExt for cap_primitives::fs::Metadata { fn dev(&self) -> u64 { _WindowsByHandle::volume_serial_number(self) diff --git a/cap-fs-ext/src/reopen.rs b/cap-fs-ext/src/reopen.rs index 28deaafd..32f3acc2 100644 --- a/cap-fs-ext/src/reopen.rs +++ b/cap-fs-ext/src/reopen.rs @@ -1,8 +1,6 @@ use cap_primitives::fs::{reopen, OpenOptions}; -#[cfg(any(feature = "std", feature = "async_std"))] +#[cfg(feature = "std")] use io_lifetimes::AsFilelike; -#[cfg(feature = "async_std")] -use io_lifetimes::FromFilelike; use std::io; /// A trait for the `reopen` function. @@ -55,32 +53,3 @@ impl Reopen for cap_std::fs_utf8::File { Ok(Self::from_std(file)) } } - -#[cfg(feature = "async_std")] -impl Reopen for async_std::fs::File { - #[inline] - fn reopen(&self, options: &OpenOptions) -> io::Result { - let file = reopen(&self.as_filelike_view::(), options)?; - Ok(async_std::fs::File::from_into_filelike(file)) - } -} - -#[cfg(feature = "async_std")] -impl Reopen for cap_async_std::fs::File { - #[inline] - fn reopen(&self, options: &OpenOptions) -> io::Result { - let file = reopen(&self.as_filelike_view::(), options)?; - let std = async_std::fs::File::from_into_filelike(file); - Ok(Self::from_std(std)) - } -} - -#[cfg(all(feature = "async_std", feature = "fs_utf8"))] -impl Reopen for cap_async_std::fs_utf8::File { - #[inline] - fn reopen(&self, options: &OpenOptions) -> io::Result { - let file = reopen(&self.as_filelike_view::(), options)?; - let std = async_std::fs::File::from_into_filelike(file); - Ok(Self::from_std(std)) - } -} diff --git a/cap-primitives/README.md b/cap-primitives/README.md index b5ef9fb7..014ea021 100644 --- a/cap-primitives/README.md +++ b/cap-primitives/README.md @@ -13,7 +13,7 @@ The `cap-primitives` crate provides primitive sandboxing operations that -[`cap-std`] and [`cap-async-std`] are built on. +[`cap-std`] is built on. The filesystem module [`cap_primitives::fs`], the networking module [`cap_primitives::net`], and time module [`cap_primitives::time`] currently @@ -21,7 +21,6 @@ support Linux, macOS, FreeBSD, and Windows. WASI support is in development, though not yet usable. [`cap-std`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-std/README.md -[`cap-async-std`]: https://github.com/bytecodealliance/cap-std/blob/main/cap-async-std/README.md [`cap_primitives::fs`]: https://docs.rs/cap-primitives/latest/cap_primitives/fs/index.html [`cap_primitives::net`]: https://docs.rs/cap-primitives/latest/cap_primitives/net/index.html [`cap_primitives::time`]: https://docs.rs/cap-primitives/latest/cap_primitives/time/index.html diff --git a/examples/async_std_fs_misc.rs b/examples/async_std_fs_misc.rs deleted file mode 100644 index cfd9a5c0..00000000 --- a/examples/async_std_fs_misc.rs +++ /dev/null @@ -1,113 +0,0 @@ -// Copied from https://doc.rust-lang.org/rust-by-example/std_misc/fs.html and -// adapted to use this crate instead. - -use async_std::io; -use async_std::io::prelude::*; -use cap_async_std::ambient_authority; -use cap_async_std::fs::{Dir, OpenOptions}; -//use async_std::os::unix; -use std::path::Path; - -// A simple implementation of `% cat path` -async fn cat(dir: &mut Dir, path: &Path) -> io::Result { - let mut f = dir.open(path).await?; - let mut s = String::new(); - match f.read_to_string(&mut s).await { - Ok(_) => Ok(s), - Err(e) => Err(e), - } -} - -// A simple implementation of `% echo s > path` -async fn echo(s: &str, dir: &mut Dir, path: &Path) -> io::Result<()> { - let mut f = dir.create(path).await?; - - f.write_all(s.as_bytes()).await -} - -// A simple implementation of `% touch path` (ignores existing files) -async fn touch(dir: &mut Dir, path: &Path) -> io::Result<()> { - match dir - .open_with(path, OpenOptions::new().create(true).write(true)) - .await - { - Ok(_) => Ok(()), - Err(e) => Err(e), - } -} - -#[async_std::main] -async fn main() { - let mut cwd = Dir::open_ambient_dir(".", ambient_authority()) - .await - .expect("!"); - - println!("`mkdir a`"); - - // Create a directory, returns `io::Result<()>` - match cwd.create_dir("a") { - Err(why) => println!("! {:?}", why.kind()), - Ok(_) => {} - } - - println!("`echo hello > a/b.txt`"); - // The previous match can be simplified using the `unwrap_or_else` method - echo("hello", &mut cwd, &Path::new("a/b.txt")) - .await - .unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); - - println!("`mkdir -p a/c/d`"); - // Recursively create a directory, returns `io::Result<()>` - cwd.create_dir_all("a/c/d").unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); - - println!("`touch a/c/e.txt`"); - touch(&mut cwd, &Path::new("a/c/e.txt")) - .await - .unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); - - #[cfg(target_family = "unix")] - { - println!("`ln -s ../b.txt a/c/b.txt`"); - // Create a symbolic link, returns `io::Result<()>` - cwd.symlink("../b.txt", "a/c/b.txt") - .await - .unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); - } - - println!("`cat a/c/b.txt`"); - match cat(&mut cwd, &Path::new("a/c/b.txt")).await { - Err(why) => println!("! {:?}", why.kind()), - Ok(s) => println!("> {}", s), - } - - println!("`ls a`"); - // Read the contents of a directory, returns `io::Result>` - match cwd.read_dir("a").await { - Err(why) => println!("! {:?}", why.kind()), - Ok(paths) => { - for path in paths { - println!("! {:?}", path.unwrap().file_name()); - } - } - } - - println!("`rm a/c/e.txt`"); - // Remove a file, returns `io::Result<()>` - cwd.remove_file("a/c/e.txt").await.unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); - - println!("`rmdir a/c/d`"); - // Remove an empty directory, returns `io::Result<()>` - cwd.remove_dir("a/c/d").await.unwrap_or_else(|why| { - println!("! {:?}", why.kind()); - }); -}