1#![deny(unsafe_op_in_unsafe_fn)]
2
3use crate::io;
4use crate::path::{Path, PathBuf};
5
6pub mod common;
7
8cfg_select! {
9 any(target_family = "unix", target_os = "wasi") => {
10 mod unix;
11 use unix as imp;
12 #[cfg(not(target_os = "wasi"))]
13 pub use unix::{chown, fchown, lchown, mkfifo};
14 #[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
15 pub use unix::chroot;
16 #[cfg(not(target_os = "wasi"))]
17 pub(crate) use unix::debug_assert_fd_is_open;
18 #[cfg(any(target_os = "linux", target_os = "android"))]
19 pub(super) use unix::CachedFileMetadata;
20 use crate::sys::common::small_c_string::run_path_with_cstr as with_native_path;
21 }
22 target_os = "windows" => {
23 mod windows;
24 use windows as imp;
25 pub use windows::{symlink_inner, junction_point};
26 use crate::sys::path::with_native_path;
27 }
28 target_os = "hermit" => {
29 mod hermit;
30 use hermit as imp;
31 }
32 target_os = "motor" => {
33 mod motor;
34 use motor as imp;
35 }
36 target_os = "solid_asp3" => {
37 mod solid;
38 use solid as imp;
39 }
40 target_os = "uefi" => {
41 mod uefi;
42 use uefi as imp;
43 }
44 target_os = "vexos" => {
45 mod vexos;
46 use vexos as imp;
47 }
48 _ => {
49 mod unsupported;
50 use unsupported as imp;
51 }
52}
53
54#[cfg(not(any(target_family = "unix", target_os = "windows", target_os = "wasi")))]
56#[inline]
57pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
58 f(path)
59}
60
61pub use imp::{
62 DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
63 ReadDir,
64};
65
66pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
67 imp::readdir(path)
69}
70
71pub fn remove_file(path: &Path) -> io::Result<()> {
72 with_native_path(path, &imp::unlink)
73}
74
75pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
76 with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
77}
78
79pub fn remove_dir(path: &Path) -> io::Result<()> {
80 with_native_path(path, &imp::rmdir)
81}
82
83pub fn remove_dir_all(path: &Path) -> io::Result<()> {
84 #[cfg(not(windows))]
86 return imp::remove_dir_all(path);
87 #[cfg(windows)]
88 with_native_path(path, &imp::remove_dir_all)
89}
90
91pub fn read_link(path: &Path) -> io::Result<PathBuf> {
92 with_native_path(path, &imp::readlink)
93}
94
95pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
96 #[cfg(windows)]
98 return imp::symlink(original, link);
99 #[cfg(not(windows))]
100 with_native_path(original, &|original| {
101 with_native_path(link, &|link| imp::symlink(original, link))
102 })
103}
104
105pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
106 with_native_path(original, &|original| {
107 with_native_path(link, &|link| imp::link(original, link))
108 })
109}
110
111pub fn metadata(path: &Path) -> io::Result<FileAttr> {
112 with_native_path(path, &imp::stat)
113}
114
115pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
116 with_native_path(path, &imp::lstat)
117}
118
119pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
120 with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
121}
122
123#[cfg(all(unix, not(target_os = "vxworks")))]
124pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
125 use crate::fs::OpenOptions;
126
127 let mut options = OpenOptions::new();
128
129 #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
132 {
133 use crate::os::unix::fs::OpenOptionsExt;
134 options.custom_flags(libc::O_NOFOLLOW);
135 }
136
137 options.open(path)?.set_permissions(perm)
138}
139
140#[cfg(any(not(unix), target_os = "vxworks"))]
141pub fn set_permissions_nofollow(_path: &Path, _perm: crate::fs::Permissions) -> io::Result<()> {
142 crate::unimplemented!(
143 "`set_permissions_nofollow` is currently only implemented on Unix platforms"
144 )
145}
146
147pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
148 with_native_path(path, &imp::canonicalize)
149}
150
151pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
152 #[cfg(not(windows))]
154 return imp::copy(from, to);
155 #[cfg(windows)]
156 with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
157}
158
159pub fn exists(path: &Path) -> io::Result<bool> {
160 #[cfg(not(windows))]
162 return imp::exists(path);
163 #[cfg(windows)]
164 with_native_path(path, &imp::exists)
165}
166
167pub fn set_times(path: &Path, times: FileTimes) -> io::Result<()> {
168 with_native_path(path, &|path| imp::set_times(path, times.clone()))
169}
170
171pub fn set_times_nofollow(path: &Path, times: FileTimes) -> io::Result<()> {
172 with_native_path(path, &|path| imp::set_times_nofollow(path, times.clone()))
173}