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