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

cap-fs-ext

Extension traits for `Dir`, `File`, etc.

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

The `cap-fs-ext` crate provides extension traits adding extra features to directory types such as [`Dir`], [`File`] and related types. [`Dir`]: https://docs.rs/cap-std/latest/cap_std/fs/struct.Dir.html [`File`]: https://docs.rs/cap-std/latest/cap_std/fs/struct.File.html cap-fs-ext-3.4.1/build.rs000064400000000000000000000050221046102023000132440ustar 00000000000000use std::env::var; use std::io::Write; fn main() { use_feature_or_nothing("windows_by_handle"); // https://github.com/rust-lang/rust/issues/63010 // 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 out_dir = var("OUT_DIR").unwrap(); 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("--out-dir") .arg(out_dir); // Put the output somewhere inconsequential. // If Cargo wants to set RUSTFLAGS, use that. if let Ok(rustflags) = var("CARGO_ENCODED_RUSTFLAGS") { if !rustflags.is_empty() { for arg in rustflags.split('\x1f') { cmd.arg(arg); } } } let mut child = cmd .arg("-") // Read from stdin. .stdin(Stdio::piped()) // Stdin is a pipe. .stderr(Stdio::null()) // Errors from feature detection aren't interesting and can be confusing. .spawn() .unwrap(); writeln!(child.stdin.take().unwrap(), "{}", test.as_ref()).unwrap(); child.wait().unwrap().success() } cap-fs-ext-3.4.1/src/dir_entry_ext.rs000064400000000000000000000047021046102023000156170ustar 00000000000000use cap_primitives::fs::Metadata; #[cfg(windows)] use cap_primitives::fs::_WindowsDirEntryExt; use std::io; /// Extension trait for `DirEntry`. pub trait DirEntryExt { /// Return the full metadata, which on Windows includes the optional /// values. /// /// If the full metadata cannot be computed, this fails rather than /// falling back to partial metadata, even when that might not fail. /// If partial metadata is desired, `std::fs::DirEntry::metadata` can /// be used. fn full_metadata(&self) -> io::Result; } #[cfg(not(windows))] impl DirEntryExt for std::fs::DirEntry { #[inline] fn full_metadata(&self) -> io::Result { self.metadata().map(Metadata::from_just_metadata) } } #[cfg(all(not(windows), feature = "std"))] impl DirEntryExt for cap_std::fs::DirEntry { #[inline] fn full_metadata(&self) -> io::Result { self.metadata() } } #[cfg(all(windows, feature = "std"))] impl DirEntryExt for cap_std::fs::DirEntry { #[inline] fn full_metadata(&self) -> io::Result { _WindowsDirEntryExt::full_metadata(self) } } #[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] fn full_metadata(&self) -> io::Result { self.metadata() } } #[cfg(all(windows, feature = "std", feature = "fs_utf8"))] impl DirEntryExt for cap_std::fs_utf8::DirEntry { #[inline] fn full_metadata(&self) -> io::Result { _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) } } cap-fs-ext-3.4.1/src/dir_ext.rs000064400000000000000000001412351046102023000144010ustar 00000000000000#[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::{ access, open_dir_nofollow, set_symlink_permissions, set_times, set_times_nofollow, FollowSymlinks, Permissions, }; #[cfg(windows)] 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}; /// Extension trait for `Dir`. pub trait DirExt { /// 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 fn set_atime>(&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 fn set_mtime>(&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 fn set_times>( &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 fn set_symlink_times>( &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 fn symlink, Q: AsRef>(&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 fn symlink_file, Q: AsRef>(&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 fn symlink_dir, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()>; /// Similar to `cap_std::fs::Dir::open_dir`, but fails if the path names a /// symlink. fn open_dir_nofollow>(&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. fn remove_file_or_symlink>(&self, path: P) -> io::Result<()>; /// Test for accessibility or existence of a filesystem object. fn access>(&self, path: P, type_: AccessType) -> io::Result<()>; /// Test for accessibility or existence of a filesystem object, without /// following symbolic links. fn access_symlink>(&self, path: P, type_: AccessType) -> io::Result<()>; /// Changes the permissions found on a file or a directory, without following /// symbolic links. fn set_symlink_permissions>(&self, path: P, perm: Permissions) -> 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"))] pub trait DirExtUtf8 { /// 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 fn set_atime>(&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 fn set_mtime>(&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 fn set_times>( &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 fn set_symlink_times>( &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 fn symlink, Q: AsRef>(&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 fn symlink_file, Q: AsRef>( &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 fn symlink_dir, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()>; /// Similar to `cap_std::fs::Dir::open_dir`, but fails if the path names a /// symlink. fn open_dir_nofollow>(&self, path: P) -> io::Result where Self: Sized; /// Removes a file or symlink from a filesystem. /// /// This is similar to [`std::fs::remove_file`], except that it also works /// on symlinks to directories on Windows, similar to how `unlink` works /// on symlinks to directories on Posix-ish platforms. fn remove_file_or_symlink>(&self, path: P) -> io::Result<()>; /// Test for accessibility or existence of a filesystem object. fn access>(&self, path: P, type_: AccessType) -> io::Result<()>; /// Test for accessibility or existence of a filesystem object, without /// following symbolic links. fn access_symlink>(&self, path: P, type_: AccessType) -> io::Result<()>; /// Changes the permissions found on a file or a directory, without following /// symbolic links. fn set_symlink_permissions>( &self, path: P, perm: Permissions, ) -> 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] fn set_atime>(&self, path: P, atime: SystemTimeSpec) -> io::Result<()> { set_times( &self.as_filelike_view::(), path.as_ref(), Some(atime), None, ) } #[inline] fn set_mtime>(&self, path: P, mtime: SystemTimeSpec) -> io::Result<()> { set_times( &self.as_filelike_view::(), path.as_ref(), None, Some(mtime), ) } #[inline] fn set_times>( &self, path: P, atime: Option, mtime: Option, ) -> io::Result<()> { set_times( &self.as_filelike_view::(), path.as_ref(), atime, mtime, ) } #[inline] fn set_symlink_times>( &self, path: P, atime: Option, mtime: Option, ) -> io::Result<()> { set_times_nofollow( &self.as_filelike_view::(), path.as_ref(), atime, mtime, ) } #[cfg(not(windows))] #[inline] fn symlink, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { symlink( src.as_ref(), &self.as_filelike_view::(), dst.as_ref(), ) } #[cfg(not(windows))] #[inline] fn symlink_file, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { self.symlink(src, dst) } #[cfg(not(windows))] #[inline] fn symlink_dir, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { self.symlink(src, dst) } #[cfg(windows)] #[inline] fn symlink, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { if self.metadata(src.as_ref())?.is_dir() { self.symlink_dir(src, dst) } else { self.symlink_file(src, dst) } } #[cfg(windows)] #[inline] fn symlink_file, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { symlink_file( src.as_ref(), &self.as_filelike_view::(), dst.as_ref(), ) } #[cfg(windows)] #[inline] fn symlink_dir, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { symlink_dir( src.as_ref(), &self.as_filelike_view::(), dst.as_ref(), ) } #[inline] fn open_dir_nofollow>(&self, path: P) -> io::Result { match open_dir_nofollow(&self.as_filelike_view::(), path.as_ref()) { Ok(file) => Ok(Self::from_std_file(file)), Err(e) => Err(e), } } #[cfg(not(windows))] #[inline] fn remove_file_or_symlink>(&self, path: P) -> io::Result<()> { self.remove_file(path.as_ref()) } #[cfg(windows)] #[inline] fn remove_file_or_symlink>(&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)?; let meta = file.metadata()?; if meta.file_type().is_symlink() && meta.file_attributes() & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY { self.remove_dir(path)?; } else { self.remove_file(path)?; } // 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. fn access>(&self, path: P, type_: AccessType) -> io::Result<()> { access( &self.as_filelike_view::(), path.as_ref(), type_, FollowSymlinks::Yes, ) } /// Test for accessibility or existence of a filesystem object. fn access_symlink>(&self, path: P, type_: AccessType) -> io::Result<()> { access( &self.as_filelike_view::(), path.as_ref(), type_, FollowSymlinks::No, ) } /// Changes the permissions found on a file or a directory, without following /// symbolic links. fn set_symlink_permissions>( &self, path: P, perm: Permissions, ) -> io::Result<()> { set_symlink_permissions( &self.as_filelike_view::(), path.as_ref(), perm, ) } } #[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] fn set_atime>(&self, path: P, atime: SystemTimeSpec) -> io::Result<()> { let path = from_utf8(path.as_ref())?; set_times( &self.as_filelike_view::(), &path, Some(atime), None, ) } #[inline] fn set_mtime>(&self, path: P, mtime: SystemTimeSpec) -> io::Result<()> { let path = from_utf8(path.as_ref())?; set_times( &self.as_filelike_view::(), &path, None, Some(mtime), ) } #[inline] fn set_times>( &self, path: P, atime: Option, mtime: Option, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; set_times( &self.as_filelike_view::(), &path, atime, mtime, ) } #[inline] fn set_symlink_times>( &self, path: P, atime: Option, mtime: Option, ) -> io::Result<()> { let path = from_utf8(path.as_ref())?; set_times_nofollow( &self.as_filelike_view::(), &path, atime, mtime, ) } #[cfg(not(windows))] #[inline] fn symlink, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { Self::symlink(self, src, dst) } #[cfg(not(windows))] #[inline] fn symlink_file, Q: AsRef>( &self, src: P, dst: Q, ) -> io::Result<()> { Self::symlink(self, src, dst) } #[cfg(not(windows))] #[inline] fn symlink_dir, Q: AsRef>( &self, src: P, dst: Q, ) -> io::Result<()> { Self::symlink(self, src, dst) } #[cfg(windows)] #[inline] fn symlink, Q: AsRef>(&self, src: P, dst: Q) -> io::Result<()> { if self.metadata(src.as_ref())?.is_dir() { Self::symlink_dir(self, src, dst) } else { Self::symlink_file(self, src, dst) } } #[cfg(windows)] #[inline] fn symlink_file, Q: AsRef>( &self, src: P, dst: Q, ) -> io::Result<()> { Self::symlink_file(self, src, dst) } #[cfg(windows)] #[inline] fn symlink_dir, Q: AsRef>( &self, src: P, dst: Q, ) -> io::Result<()> { Self::symlink_dir(self, src, dst) } #[inline] fn open_dir_nofollow>(&self, path: P) -> io::Result { match open_dir_nofollow( &self.as_filelike_view::(), path.as_ref().as_ref(), ) { Ok(file) => Ok(Self::from_std_file(file)), Err(e) => Err(e), } } #[cfg(not(windows))] #[inline] fn remove_file_or_symlink>(&self, path: P) -> io::Result<()> { self.remove_file(path.as_ref()) } #[cfg(windows)] #[inline] fn remove_file_or_symlink>(&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)?; let meta = file.metadata()?; if meta.file_type().is_symlink() && meta.file_attributes() & FILE_ATTRIBUTE_DIRECTORY == FILE_ATTRIBUTE_DIRECTORY { self.remove_dir(path)?; } else { self.remove_file(path)?; } // 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. fn access>(&self, path: P, type_: AccessType) -> io::Result<()> { access( &self.as_filelike_view::(), path.as_ref().as_ref(), type_, FollowSymlinks::Yes, ) } /// Test for accessibility or existence of a filesystem object. fn access_symlink>(&self, path: P, type_: AccessType) -> io::Result<()> { access( &self.as_filelike_view::(), path.as_ref().as_ref(), type_, FollowSymlinks::No, ) } /// Changes the permissions found on a file or a directory, without following /// symbolic links. fn set_symlink_permissions>( &self, path: P, perm: Permissions, ) -> io::Result<()> { set_symlink_permissions( &self.as_filelike_view::(), path.as_ref().as_ref(), perm, ) } } #[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(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(feature = "arf_strings")] fn from_utf8<'a>(path: &'a Utf8Path) -> 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()) } cap-fs-ext-3.4.1/src/file_type_ext.rs000064400000000000000000000064671046102023000156120ustar 00000000000000#[cfg(windows)] use cap_primitives::fs::_WindowsFileTypeExt; /// Extension trait for `FileType`. pub trait FileTypeExt { /// Returns `true` if this file type is a block device. /// /// This corresponds to /// [`std::os::unix::fs::FileTypeExt::is_block_device`], except that it's /// supported on Windows platforms as well. /// /// [`std::os::unix::fs::FileTypeExt::is_block_device`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_block_device fn is_block_device(&self) -> bool; /// Returns `true` if this file type is a char device. /// /// This corresponds to /// [`std::os::unix::fs::FileTypeExt::is_char_device`], except that it's /// supported on Windows platforms as well. /// /// [`std::os::unix::fs::FileTypeExt::is_char_device`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_char_device fn is_char_device(&self) -> bool; /// Returns `true` if this file type is a fifo. /// /// This corresponds to /// [`std::os::unix::fs::FileTypeExt::is_fifo`], except that it's supported /// on Windows platforms as well. /// /// [`std::os::unix::fs::FileTypeExt::is_fifo`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_fifo fn is_fifo(&self) -> bool; /// Returns `true` if this file type is a socket. /// /// This corresponds to /// [`std::os::unix::fs::FileTypeExt::is_socket`], except that it's /// supported on Windows platforms as well. /// /// [`std::os::unix::fs::FileTypeExt::is_socket`]: https://doc.rust-lang.org/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_socket fn is_socket(&self) -> bool; } #[cfg(not(windows))] impl FileTypeExt for std::fs::FileType { #[inline] fn is_block_device(&self) -> bool { std::os::unix::fs::FileTypeExt::is_block_device(self) } #[inline] fn is_char_device(&self) -> bool { std::os::unix::fs::FileTypeExt::is_char_device(self) } #[inline] fn is_fifo(&self) -> bool { std::os::unix::fs::FileTypeExt::is_fifo(self) } #[inline] fn is_socket(&self) -> bool { std::os::unix::fs::FileTypeExt::is_socket(self) } } #[cfg(all(not(windows), any(feature = "std", feature = "async_std")))] impl FileTypeExt for cap_primitives::fs::FileType { #[inline] fn is_block_device(&self) -> bool { cap_primitives::fs::FileTypeExt::is_block_device(self) } #[inline] fn is_char_device(&self) -> bool { cap_primitives::fs::FileTypeExt::is_char_device(self) } #[inline] fn is_fifo(&self) -> bool { cap_primitives::fs::FileTypeExt::is_fifo(self) } #[inline] fn is_socket(&self) -> bool { cap_primitives::fs::FileTypeExt::is_socket(self) } } #[cfg(all(windows, any(feature = "std", feature = "async_std")))] impl FileTypeExt for cap_primitives::fs::FileType { #[inline] fn is_block_device(&self) -> bool { _WindowsFileTypeExt::is_block_device(self) } #[inline] fn is_char_device(&self) -> bool { _WindowsFileTypeExt::is_char_device(self) } #[inline] fn is_fifo(&self) -> bool { _WindowsFileTypeExt::is_fifo(self) } #[inline] fn is_socket(&self) -> bool { _WindowsFileTypeExt::is_socket(self) } } cap-fs-ext-3.4.1/src/is_file_read_write.rs000064400000000000000000000036411046102023000165600ustar 00000000000000use cap_primitives::fs::is_file_read_write; use io_lifetimes::AsFilelike; use std::io; /// A trait for the `is_file_read_write` function for `File` types. /// /// This is only implemented for `File` types; for arbitrary I/O handles, use /// [`system_interface::io::IsReadWrite`] instead. /// /// [`system_interface::io::IsReadWrite`]: https://docs.rs/system-interface/latest/system_interface/io/trait.ReadReady.html pub trait IsFileReadWrite { /// Test whether the given file is readable and/or writable. fn is_file_read_write(&self) -> io::Result<(bool, bool)>; } impl IsFileReadWrite for std::fs::File { #[inline] fn is_file_read_write(&self) -> io::Result<(bool, bool)> { is_file_read_write(self) } } #[cfg(feature = "std")] impl IsFileReadWrite for cap_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 = "std", feature = "fs_utf8"))] impl IsFileReadWrite for cap_std::fs_utf8::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 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::()) } } cap-fs-ext-3.4.1/src/lib.rs000064400000000000000000000030311046102023000135000ustar 00000000000000//! Extension traits for `Dir` #![deny(missing_docs)] #![forbid(unsafe_code)] #![cfg_attr(all(windows, windows_by_handle), feature(windows_by_handle))] #![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" )] mod dir_entry_ext; mod dir_ext; mod file_type_ext; mod is_file_read_write; mod metadata_ext; mod open_options_follow_ext; mod open_options_maybe_dir_ext; 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"))] pub use dir_ext::DirExtUtf8; pub use dir_ext::{AccessType, DirExt, SystemTimeSpec}; pub use file_type_ext::FileTypeExt; pub use is_file_read_write::IsFileReadWrite; pub use metadata_ext::MetadataExt; pub use open_options_follow_ext::OpenOptionsFollowExt; pub use open_options_maybe_dir_ext::OpenOptionsMaybeDirExt; pub use open_options_sync_ext::OpenOptionsSyncExt; pub use reopen::Reopen; /// Re-export these to allow them to be used with `Reuse`. pub use cap_primitives::fs::{ FollowSymlinks, Metadata, MetadataExt as OsMetadataExt, OpenOptions, OpenOptionsExt, }; #[doc(hidden)] pub use cap_primitives::ambient_authority_known_at_compile_time; pub use cap_primitives::{ambient_authority, AmbientAuthority}; cap-fs-ext-3.4.1/src/metadata_ext.rs000064400000000000000000000066001046102023000153770ustar 00000000000000#[cfg(windows)] use cap_primitives::fs::_WindowsByHandle; /// Extension trait for `Metadata`. pub trait MetadataExt { /// Returns the ID of the device containing the file. /// /// This corresponds to [`std::os::unix::fs::MetadataExt::dev`], except /// that it's supported on Windows platforms as well. /// /// [`std::os::unix::fs::MetadataExt::dev`]: https://doc.rust-lang.org/std/os/unix/fs/trait.MetadataExt.html#tymethod.dev fn dev(&self) -> u64; /// Returns the inode number. /// /// This corresponds to [`std::os::unix::fs::MetadataExt::ino`], except /// that it's supported on Windows platforms as well. /// /// FIXME: On Windows' `ReFS`, file identifiers are 128-bit. /// /// [`std::os::unix::fs::MetadataExt::ino`]: https://doc.rust-lang.org/std/os/unix/fs/trait.MetadataExt.html#tymethod.ino fn ino(&self) -> u64; /// Returns the number of hard links pointing to this file. /// /// This corresponds to [`std::os::unix::fs::MetadataExt::nlink`], except /// that it's supported on Windows platforms as well. /// /// [`std::os::unix::fs::MetadataExt::nlink`]: https://doc.rust-lang.org/std/os/unix/fs/trait.MetadataExt.html#tymethod.nlink fn nlink(&self) -> u64; } #[cfg(not(windows))] impl MetadataExt for std::fs::Metadata { #[inline] fn dev(&self) -> u64 { std::os::unix::fs::MetadataExt::dev(self) } #[inline] fn ino(&self) -> u64 { std::os::unix::fs::MetadataExt::ino(self) } #[inline] fn nlink(&self) -> u64 { std::os::unix::fs::MetadataExt::nlink(self) } } #[cfg(all(windows, windows_by_handle))] impl MetadataExt for std::fs::Metadata { #[inline] fn dev(&self) -> u64 { std::os::windows::fs::MetadataExt::volume_serial_number(self) .expect("`dev` depends on a Metadata constructed from an open `File`") .into() } #[inline] fn ino(&self) -> u64 { std::os::windows::fs::MetadataExt::file_index(self) .expect("`ino` depends on a Metadata constructed from an open `File`") } #[inline] fn nlink(&self) -> u64 { std::os::windows::fs::MetadataExt::number_of_links(self) .expect("`nlink` depends on a Metadata constructed from an open `File`") .into() } } #[cfg(all(not(windows), any(feature = "std", feature = "async_std")))] impl MetadataExt for cap_primitives::fs::Metadata { #[inline] fn dev(&self) -> u64 { cap_primitives::fs::MetadataExt::dev(self) } #[inline] fn ino(&self) -> u64 { cap_primitives::fs::MetadataExt::ino(self) } #[inline] fn nlink(&self) -> u64 { cap_primitives::fs::MetadataExt::nlink(self) } } #[cfg(all(windows, any(feature = "std", feature = "async_std")))] impl MetadataExt for cap_primitives::fs::Metadata { fn dev(&self) -> u64 { _WindowsByHandle::volume_serial_number(self) .expect("`dev` depends on a Metadata constructed from an open `File`") .into() } #[inline] fn ino(&self) -> u64 { _WindowsByHandle::file_index(self) .expect("`ino` depends on a Metadata constructed from an open `File`") } #[inline] fn nlink(&self) -> u64 { _WindowsByHandle::number_of_links(self) .expect("`nlink` depends on a Metadata constructed from an open `File`") .into() } } cap-fs-ext-3.4.1/src/open_options_follow_ext.rs000064400000000000000000000020671046102023000177200ustar 00000000000000use crate::FollowSymlinks; /// Extension trait for `cap_primitives::fs::OpenOptions` which adds /// `follow`, a function for controlling whether a symlink in the last /// component of a path is followed. pub trait OpenOptionsFollowExt { /// Sets the option for following symlinks in the last component of a path. /// /// This option, when set to `FollowSymlinks::Yes`, will indicate that a /// symbolic link in the last component of a path will be followed. When /// set to `FollowSymlinks::No`, it will indicate that attempting to /// resolve a path which ends in a symbolic link will fail. fn follow(&mut self, follow: FollowSymlinks) -> &mut Self; } impl OpenOptionsFollowExt for cap_primitives::fs::OpenOptions { #[inline] fn follow(&mut self, follow: FollowSymlinks) -> &mut Self { // `follow` functionality is implemented within `cap_primitives`; we're // just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `follow` isn't in `std`. self._cap_fs_ext_follow(follow) } } cap-fs-ext-3.4.1/src/open_options_maybe_dir_ext.rs000064400000000000000000000020271046102023000203450ustar 00000000000000/// Extension trait for `cap_primitives::fs::OpenOptions` which adds /// `maybe_dir`, a function for controlling whether an open should attempt to /// succeed on a directory. On Posix-ish platforms, opening a directory always /// succeeds, but on Windows, opening a directory needs this option. pub trait OpenOptionsMaybeDirExt { /// Sets the option for disabling an error that might be generated by the /// opened object being a directory. /// /// On some platforms, this may prevent the directory from being deleted /// or renamed while the handle is open. fn maybe_dir(&mut self, maybe_dir: bool) -> &mut Self; } impl OpenOptionsMaybeDirExt for cap_primitives::fs::OpenOptions { #[inline] fn maybe_dir(&mut self, maybe_dir: bool) -> &mut Self { // `maybe_dir` functionality is implemented within `cap_primitives`; // we're just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `maybe_dir` isn't in `std`. self._cap_fs_ext_maybe_dir(maybe_dir) } } cap-fs-ext-3.4.1/src/open_options_sync_ext.rs000064400000000000000000000044421046102023000173710ustar 00000000000000/// Extension trait for `cap_primitives::fs::OpenOptions` which adds /// `sync`, `dsync`, `rsync`, and `nonblock` functions for controlling various /// I/O modes for the opened file. pub trait OpenOptionsSyncExt { /// Requests write operations complete as defined by synchronized I/O file /// integrity completion. fn sync(&mut self, enable: bool) -> &mut Self; /// Requests write operations complete as defined by synchronized I/O data /// integrity completion. fn dsync(&mut self, enable: bool) -> &mut Self; /// Requests read operations complete as defined by the level of integrity /// specified by `sync` and `dsync`. fn rsync(&mut self, enable: bool) -> &mut Self; /// Requests that I/O operations fail with `std::io::ErrorKind::WouldBlock` /// if they would otherwise block. /// /// This option is commonly not implemented for regular files, so blocking /// may still occur. fn nonblock(&mut self, enable: bool) -> &mut Self; } impl OpenOptionsSyncExt for cap_primitives::fs::OpenOptions { #[inline] fn sync(&mut self, enable: bool) -> &mut Self { // `sync` functionality is implemented within `cap_primitives`; // we're just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `sync` isn't in `std`. self._cap_fs_ext_sync(enable) } #[inline] fn dsync(&mut self, enable: bool) -> &mut Self { // `dsync` functionality is implemented within `cap_primitives`; // we're just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `dsync` isn't in `std`. self._cap_fs_ext_dsync(enable) } #[inline] fn rsync(&mut self, enable: bool) -> &mut Self { // `rsync` functionality is implemented within `cap_primitives`; // we're just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `rsync` isn't in `std`. self._cap_fs_ext_rsync(enable) } #[inline] fn nonblock(&mut self, enable: bool) -> &mut Self { // `nonblock` functionality is implemented within `cap_primitives`; // we're just exposing it here since `OpenOptions` is re-exported by // `cap_std` etc. and `nonblock` isn't in `std`. self._cap_fs_ext_nonblock(enable) } } cap-fs-ext-3.4.1/src/reopen.rs000064400000000000000000000057041046102023000142330ustar 00000000000000use cap_primitives::fs::{reopen, OpenOptions}; #[cfg(any(feature = "std", feature = "async_std"))] use io_lifetimes::AsFilelike; #[cfg(feature = "async_std")] use io_lifetimes::FromFilelike; use std::io; /// A trait for the `reopen` function. pub trait Reopen { /// Re-open a file, producing a new independent handle. /// /// This operation isn't supported by all operating systems in all /// circumstances, or in some operating systems in any circumstances, so it /// may return an `io::ErrorKind::Other` error if the file cannot be /// reopened. /// /// For files that aren't deleted, it's supported mostly-reliably on Linux /// and Windows and somewhat-reliably on Darwin. Beyond that, it works /// reliably on terminal device files and (slowly) on directories. It's not /// possible to implement this operation with POSIX APIs alone (short of /// traversing the entire filesystem), so further support will depend on /// operating systems providing OS-specific APIs. /// /// This function takes an `OpenOptions`, however it does not acquire new /// permissions that the original handle lacks. fn reopen(&self, options: &OpenOptions) -> io::Result where Self: Sized; } impl Reopen for std::fs::File { #[inline] fn reopen(&self, options: &OpenOptions) -> io::Result { reopen(self, options) } } #[cfg(feature = "std")] impl Reopen for cap_std::fs::File { #[inline] fn reopen(&self, options: &OpenOptions) -> io::Result { let file = reopen( &AsFilelike::as_filelike_view::(self), options, )?; Ok(Self::from_std(file)) } } #[cfg(all(feature = "std", feature = "fs_utf8"))] impl Reopen for cap_std::fs_utf8::File { #[inline] fn reopen(&self, options: &OpenOptions) -> io::Result { let file = reopen(&self.as_filelike_view::(), options)?; 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)) } }