std/sys/fs/
mod.rs

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// FIXME: Replace this with platform-specific path conversion functions.
55#[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    // FIXME: use with_native_path on all platforms
68    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    // FIXME: use with_native_path on all platforms
85    #[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    // FIXME: use with_native_path on all platforms
97    #[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    // ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
130    // Their filesystems do not have symbolic links, so no special handling is required.
131    #[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    // FIXME: use with_native_path on all platforms
153    #[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    // FIXME: use with_native_path on all platforms
161    #[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}