1use std::fs::{Metadata, Permissions};
7use std::io;
8use std::path::{Path, PathBuf};
9
10use crate::io::Handle;
11pub(crate) use crate::rt::blocking::call as blocking;
12
13pub async fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
15 let path = path.as_ref().to_path_buf();
16 blocking(move || std::fs::read(path)).await
17}
18
19pub async fn read_to_string(path: impl AsRef<Path>) -> io::Result<String> {
21 let path = path.as_ref().to_path_buf();
22 blocking(move || std::fs::read_to_string(path)).await
23}
24
25pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()> {
28 let (path, contents) = (path.as_ref().to_path_buf(), contents.as_ref().to_vec());
29 blocking(move || std::fs::write(path, contents)).await
30}
31
32pub async fn metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
34 let path = path.as_ref().to_path_buf();
35 blocking(move || std::fs::metadata(path)).await
36}
37
38pub async fn symlink_metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
40 let path = path.as_ref().to_path_buf();
41 blocking(move || std::fs::symlink_metadata(path)).await
42}
43
44pub async fn try_exists(path: impl AsRef<Path>) -> io::Result<bool> {
47 let path = path.as_ref().to_path_buf();
48 blocking(move || path.try_exists()).await
49}
50
51pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
53 let path = path.as_ref().to_path_buf();
54 blocking(move || std::fs::create_dir(path)).await
55}
56
57pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
59 let path = path.as_ref().to_path_buf();
60 blocking(move || std::fs::create_dir_all(path)).await
61}
62
63pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
65 let path = path.as_ref().to_path_buf();
66 blocking(move || std::fs::remove_file(path)).await
67}
68
69pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
71 let path = path.as_ref().to_path_buf();
72 blocking(move || std::fs::remove_dir(path)).await
73}
74
75pub async fn remove_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
77 let path = path.as_ref().to_path_buf();
78 blocking(move || std::fs::remove_dir_all(path)).await
79}
80
81pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
83 let (from, to) = (from.as_ref().to_path_buf(), to.as_ref().to_path_buf());
84 blocking(move || std::fs::rename(from, to)).await
85}
86
87pub async fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<u64> {
90 let (from, to) = (from.as_ref().to_path_buf(), to.as_ref().to_path_buf());
91 blocking(move || std::fs::copy(from, to)).await
92}
93
94pub async fn hard_link(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
96 let (original, link) = (original.as_ref().to_path_buf(), link.as_ref().to_path_buf());
97 blocking(move || std::fs::hard_link(original, link)).await
98}
99
100#[cfg(unix)]
102pub async fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
103 let (original, link) = (original.as_ref().to_path_buf(), link.as_ref().to_path_buf());
104 blocking(move || std::os::unix::fs::symlink(original, link)).await
105}
106
107#[cfg(windows)]
109pub async fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
110 let (original, link) = (original.as_ref().to_path_buf(), link.as_ref().to_path_buf());
111 blocking(move || std::os::windows::fs::symlink_file(original, link)).await
112}
113
114#[cfg(windows)]
116pub async fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
117 let (original, link) = (original.as_ref().to_path_buf(), link.as_ref().to_path_buf());
118 blocking(move || std::os::windows::fs::symlink_dir(original, link)).await
119}
120
121pub async fn read_link(path: impl AsRef<Path>) -> io::Result<PathBuf> {
123 let path = path.as_ref().to_path_buf();
124 blocking(move || std::fs::read_link(path)).await
125}
126
127pub async fn canonicalize(path: impl AsRef<Path>) -> io::Result<PathBuf> {
129 let path = path.as_ref().to_path_buf();
130 blocking(move || std::fs::canonicalize(path)).await
131}
132
133pub async fn set_permissions(path: impl AsRef<Path>, perm: Permissions) -> io::Result<()> {
135 let path = path.as_ref().to_path_buf();
136 blocking(move || std::fs::set_permissions(path, perm)).await
137}
138
139#[derive(Clone, Debug)]
142pub struct OpenOptions(std::fs::OpenOptions);
143
144impl Default for OpenOptions {
145 fn default() -> Self {
146 Self::new()
147 }
148}
149
150impl OpenOptions {
151 pub fn new() -> Self {
153 Self(std::fs::OpenOptions::new())
154 }
155
156 pub fn read(&mut self, read: bool) -> &mut Self {
158 self.0.read(read);
159 self
160 }
161
162 pub fn write(&mut self, write: bool) -> &mut Self {
164 self.0.write(write);
165 self
166 }
167
168 pub fn append(&mut self, append: bool) -> &mut Self {
170 self.0.append(append);
171 self
172 }
173
174 pub fn truncate(&mut self, truncate: bool) -> &mut Self {
176 self.0.truncate(truncate);
177 self
178 }
179
180 pub fn create(&mut self, create: bool) -> &mut Self {
182 self.0.create(create);
183 self
184 }
185
186 pub fn create_new(&mut self, create_new: bool) -> &mut Self {
188 self.0.create_new(create_new);
189 self
190 }
191
192 #[cfg(unix)]
194 pub fn mode(&mut self, mode: u32) -> &mut Self {
195 std::os::unix::fs::OpenOptionsExt::mode(&mut self.0, mode);
196 self
197 }
198
199 #[cfg(unix)]
201 pub fn custom_flags(&mut self, flags: i32) -> &mut Self {
202 std::os::unix::fs::OpenOptionsExt::custom_flags(&mut self.0, flags);
203 self
204 }
205
206 #[cfg(windows)]
208 pub fn access_mode(&mut self, access: u32) -> &mut Self {
209 std::os::windows::fs::OpenOptionsExt::access_mode(&mut self.0, access);
210 self
211 }
212
213 #[cfg(windows)]
215 pub fn share_mode(&mut self, share: u32) -> &mut Self {
216 std::os::windows::fs::OpenOptionsExt::share_mode(&mut self.0, share);
217 self
218 }
219
220 #[cfg(windows)]
222 pub fn custom_flags(&mut self, flags: u32) -> &mut Self {
223 std::os::windows::fs::OpenOptionsExt::custom_flags(&mut self.0, flags);
224 self
225 }
226
227 #[cfg(windows)]
229 pub fn attributes(&mut self, attributes: u32) -> &mut Self {
230 std::os::windows::fs::OpenOptionsExt::attributes(&mut self.0, attributes);
231 self
232 }
233
234 #[cfg(windows)]
236 pub fn security_qos_flags(&mut self, flags: u32) -> &mut Self {
237 std::os::windows::fs::OpenOptionsExt::security_qos_flags(&mut self.0, flags);
238 self
239 }
240
241 pub async fn open(&self, path: impl AsRef<Path>) -> io::Result<Handle<std::fs::File>> {
243 let (options, path) = (self.0.clone(), path.as_ref().to_path_buf());
244 let file = blocking(move || options.open(path)).await?;
245 Handle::new(file)
246 }
247}
248
249impl From<std::fs::OpenOptions> for OpenOptions {
250 fn from(options: std::fs::OpenOptions) -> Self {
251 Self(options)
252 }
253}
254
255#[derive(Debug, Default)]
257pub struct DirBuilder {
258 recursive: bool,
259 #[cfg(unix)]
260 mode: Option<u32>,
261}
262
263impl DirBuilder {
264 pub fn new() -> Self {
266 Self::default()
267 }
268
269 pub fn recursive(&mut self, recursive: bool) -> &mut Self {
271 self.recursive = recursive;
272 self
273 }
274
275 #[cfg(unix)]
277 pub fn mode(&mut self, mode: u32) -> &mut Self {
278 self.mode = Some(mode);
279 self
280 }
281
282 pub async fn create(&self, path: impl AsRef<Path>) -> io::Result<()> {
284 let mut builder = std::fs::DirBuilder::new();
285 builder.recursive(self.recursive);
286 #[cfg(unix)]
287 if let Some(mode) = self.mode {
288 std::os::unix::fs::DirBuilderExt::mode(&mut builder, mode);
289 }
290 let path = path.as_ref().to_path_buf();
291 blocking(move || builder.create(path)).await
292 }
293}