• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::collections::VecDeque;
15 use std::ffi::OsString;
16 use std::fs::{FileType, Metadata, Permissions};
17 use std::future::Future;
18 use std::io;
19 use std::iter::Fuse;
20 use std::path::{Path, PathBuf};
21 use std::pin::Pin;
22 use std::sync::Arc;
23 use std::task::Poll::Ready;
24 use std::task::{Context, Poll};
25 
26 use crate::fs::{async_op, poll_ready};
27 use crate::futures::poll_fn;
28 use crate::spawn::spawn_blocking;
29 use crate::{JoinHandle, TaskBuilder};
30 
31 const BLOCK_SIZE: usize = 32;
32 
33 /// Creates a new directory at the given path.
34 ///
35 /// The async version of [`std::fs::create_dir`]
36 ///
37 /// # Errors
38 ///
39 /// In the following situations, the function will return an error, but is not
40 /// limited to just these cases:
41 ///
42 /// * The path has already been used.
43 /// * No permission to create directory at the given path.
44 /// * A parent directory in the path does not exist. In this case, use
45 ///   [`create_dir_all`] to create the missing parent directory and the target
46 ///   directory at the same time.
47 ///
48 /// # Examples
49 ///
50 /// ```no_run
51 /// use std::io;
52 ///
53 /// use ylong_runtime::fs;
54 /// async fn fs_func() -> io::Result<()> {
55 ///     fs::create_dir("/parent/dir").await?;
56 ///     Ok(())
57 /// }
58 /// ```
create_dir<P: AsRef<Path>>(path: P) -> io::Result<()>59 pub async fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
60     let path = path.as_ref().to_owned();
61     async_op(move || std::fs::create_dir(path)).await
62 }
63 
64 /// Creates a new directory and all of its missing parent directories.
65 ///
66 /// The async version of [`std::fs::create_dir_all`]
67 ///
68 /// # Errors
69 ///
70 /// In the following situations, the function will return an error, but is not
71 /// limited to just these cases:
72 ///
73 /// * The path has already been used.
74 /// * No permission to create directory at the given path.
75 /// * The missing parent directories can't not be created.
76 ///
77 /// # Examples
78 ///
79 /// ```no_run
80 /// use std::io;
81 ///
82 /// use ylong_runtime::fs;
83 /// async fn fs_func() -> io::Result<()> {
84 ///     fs::create_dir_all("/parent/dir").await?;
85 ///     Ok(())
86 /// }
87 /// ```
create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()>88 pub async fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
89     let path = path.as_ref().to_owned();
90     async_op(move || std::fs::create_dir_all(path)).await
91 }
92 
93 /// Removes an empty directory.
94 ///
95 /// The async version of [`std::fs::remove_dir`]
96 ///
97 /// # Errors
98 ///
99 /// In the following situations, the function will return an error, but is not
100 /// limited to just these cases:
101 ///
102 /// * The directory does not exist.
103 /// * The given path is not a directory.
104 /// * No permission to remove directory at the given path.
105 /// * The directory isn't empty.
106 ///
107 /// # Examples
108 ///
109 /// ```no_run
110 /// use std::io;
111 ///
112 /// use ylong_runtime::fs;
113 /// async fn fs_func() -> io::Result<()> {
114 ///     fs::remove_dir("/parent/dir").await?;
115 ///     Ok(())
116 /// }
117 /// ```
remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()>118 pub async fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
119     let path = path.as_ref().to_owned();
120     async_op(move || std::fs::remove_dir(path)).await
121 }
122 
123 /// Removes a directory and all its contents at the given path.
124 ///
125 /// The async version of [`std::fs::remove_dir_all`]
126 ///
127 /// # Errors
128 ///
129 /// * The directory does not exist.
130 /// * The given path is not a directory.
131 /// * No permission to remove directory or its contents at the given path.
132 ///
133 /// # Examples
134 ///
135 /// ```no_run
136 /// use std::io;
137 ///
138 /// use ylong_runtime::fs;
139 /// async fn fs_func() -> io::Result<()> {
140 ///     fs::remove_dir_all("/parent/dir").await?;
141 ///     Ok(())
142 /// }
143 /// ```
remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()>144 pub async fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
145     let path = path.as_ref().to_owned();
146     async_op(move || std::fs::remove_dir_all(path)).await
147 }
148 
149 /// Returns an iterator over the entries within a directory.
150 ///
151 /// The async version of [`std::fs::read_dir`]
152 ///
153 /// # Errors
154 ///
155 /// * The directory does not exist.
156 /// * The given path is not a directory.
157 /// * No permission to view the contents at the given path.
158 ///
159 /// # Examples
160 ///
161 /// ```no_run
162 /// use std::io;
163 ///
164 /// use ylong_runtime::fs;
165 /// async fn fs_func() -> io::Result<()> {
166 ///     let mut dir = fs::read_dir("/parent/dir").await?;
167 ///     assert!(dir.next().await.is_ok());
168 ///     Ok(())
169 /// }
170 /// ```
read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir>171 pub async fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
172     let path = path.as_ref().to_owned();
173     async_op(|| {
174         let mut std_dir = std::fs::read_dir(path)?.fuse();
175         let mut block = VecDeque::with_capacity(BLOCK_SIZE);
176         ReadDir::fill_block(&mut std_dir, &mut block);
177         Ok(ReadDir::new(std_dir, block))
178     })
179     .await
180 }
181 
182 /// Removes a file from the filesystem.
183 ///
184 /// The async version of [`std::fs::remove_file`]
185 ///
186 /// # Errors
187 ///
188 /// This function will return an error in the following situations, but is not
189 /// limited to just these cases:
190 ///
191 /// * Path points to a directory.
192 /// * The file doesn't exist.
193 /// * The user lacks permissions to remove the file.
194 ///
195 /// # Examples
196 ///
197 /// ```no_run
198 /// use std::io;
199 ///
200 /// use ylong_runtime::fs;
201 /// async fn fs_func() -> io::Result<()> {
202 ///     fs::remove_file("file.txt").await?;
203 ///     Ok(())
204 /// }
205 /// ```
remove_file<P: AsRef<Path>>(path: P) -> io::Result<()>206 pub async fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
207     let path = path.as_ref().to_owned();
208     async_op(move || std::fs::remove_file(path)).await
209 }
210 
211 /// Rename a file or directory to a new name, replacing the original file if to
212 /// already exists. This will not work if the new name is on a different mount
213 /// point.
214 ///
215 /// The async version of [`std::fs::rename`]
216 ///
217 /// # Errors
218 ///
219 /// This function will return an error in the following situations, but is not
220 /// limited to just these cases:
221 ///
222 /// * from does not exist.
223 /// * The user lacks permissions to view contents.
224 /// * from and to are on separate filesystems.
225 ///
226 /// # Examples
227 ///
228 /// ```no_run
229 /// use std::io;
230 ///
231 /// use ylong_runtime::fs;
232 /// async fn fs_func() -> io::Result<()> {
233 ///     fs::rename("file.txt", "new_file.txt").await?;
234 ///     Ok(())
235 /// }
236 /// ```
rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>237 pub async fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
238     let from = from.as_ref().to_owned();
239     let to = to.as_ref().to_owned();
240     async_op(move || std::fs::rename(from, to)).await
241 }
242 
243 /// Copies the contents of one file to another. This function will also copy the
244 /// permission bits of the original file to the destination file. This function
245 /// will overwrite the contents of to. Note that if from and to both point to
246 /// the same file, then the file will likely get truncated by this operation. On
247 /// success, the total number of bytes copied is returned and it is equal to the
248 /// length of the to file as reported by metadata.
249 ///
250 /// The async version of [`std::fs::copy`]
251 ///
252 /// # Errors
253 ///
254 /// This function will return an error in the following situations, but is not
255 /// limited to just these cases:
256 ///
257 /// * from is neither a regular file nor a symlink to a regular file.
258 /// * from does not exist.
259 /// * The current process does not have the permission rights to read from or
260 ///   write to.
261 ///
262 /// # Examples
263 ///
264 /// ```no_run
265 /// use std::io;
266 ///
267 /// use ylong_runtime::fs;
268 /// async fn fs_func() -> io::Result<()> {
269 ///     fs::copy("file.txt", "new_file.txt").await?;
270 ///     Ok(())
271 /// }
272 /// ```
copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64>273 pub async fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
274     let from = from.as_ref().to_owned();
275     let to = to.as_ref().to_owned();
276     async_op(move || std::fs::copy(from, to)).await
277 }
278 
279 /// Reads the entire contents of a file into a string.
280 ///
281 /// The async version of [`std::fs::read_to_string`]
282 ///
283 /// # Errors
284 ///
285 /// This function will return an error if path does not already exist.
286 ///
287 /// # Examples
288 ///
289 /// ```no_run
290 /// use std::io;
291 ///
292 /// use ylong_runtime::fs;
293 /// async fn read_to_string() -> io::Result<()> {
294 ///     let foo = fs::read_to_string("file.txt").await?;
295 ///     Ok(())
296 /// }
297 /// ```
read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String>298 pub async fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
299     let path = path.as_ref().to_owned();
300     async_op(move || std::fs::read_to_string(path)).await
301 }
302 
303 /// Reads the entire contents of a file into a bytes vector.
304 ///
305 /// The async version of [`std::fs::read`]
306 ///
307 /// # Errors
308 ///
309 /// This function will return an error if path does not already exist.
310 ///
311 /// # Examples
312 ///
313 /// ```no_run
314 /// use std::io;
315 ///
316 /// use ylong_runtime::fs;
317 /// async fn read() -> io::Result<()> {
318 ///     let foo = fs::read("file.txt").await?;
319 ///     Ok(())
320 /// }
321 /// ```
read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>>322 pub async fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
323     let path = path.as_ref().to_owned();
324     async_op(move || std::fs::read(path)).await
325 }
326 
327 /// Writes a slice as the entire contents of a file.
328 /// This function will create a file if it does not exist, and will entirely
329 /// replace its contents if it does.
330 ///
331 /// The async version of [`std::fs::write`]
332 ///
333 /// # Examples
334 ///
335 /// ```no_run
336 /// use std::io;
337 ///
338 /// use ylong_runtime::fs;
339 /// async fn write() -> io::Result<()> {
340 ///     fs::write("file.txt", b"Hello world").await?;
341 ///     Ok(())
342 /// }
343 /// ```
write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()>344 pub async fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
345     let path = path.as_ref().to_owned();
346     let contents = contents.as_ref().to_owned();
347 
348     async_op(move || std::fs::write(path, contents)).await
349 }
350 
351 /// Reads a symbolic link, returning the file that the link points to.
352 ///
353 /// The async version of [`std::fs::read_link`]
354 ///
355 /// # Errors
356 ///
357 /// This function will return an error in the following situations, but is not
358 /// limited to just these cases:
359 ///
360 /// * path is not a symbolic link.
361 /// * path does not exist.
362 ///
363 /// # Examples
364 ///
365 /// ```no_run
366 /// use std::io;
367 ///
368 /// use ylong_runtime::fs;
369 /// async fn read_link() -> io::Result<()> {
370 ///     fs::read_link("file.txt").await?;
371 ///     Ok(())
372 /// }
373 /// ```
read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf>374 pub async fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
375     let path = path.as_ref().to_owned();
376     async_op(move || std::fs::read_link(path)).await
377 }
378 
379 /// Creates a new hard link on the filesystem.
380 ///
381 /// The async version of [`std::fs::hard_link`]
382 ///
383 /// # Errors
384 ///
385 /// This function will return an error in the following situations, but is not
386 /// limited to just these cases:
387 ///
388 /// * The original path is not a file or doesn't exist.
389 ///
390 /// # Examples
391 ///
392 /// ```no_run
393 /// use std::io;
394 ///
395 /// use ylong_runtime::fs;
396 /// async fn hard_link() -> io::Result<()> {
397 ///     fs::hard_link("file1.txt", "file2.txt").await?;
398 ///     Ok(())
399 /// }
400 /// ```
hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()>401 pub async fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
402     let original = original.as_ref().to_owned();
403     let link = link.as_ref().to_owned();
404     async_op(move || std::fs::hard_link(original, link)).await
405 }
406 
407 /// Given a path, query the file system to get information about a file,
408 /// directory, etc. This function will traverse symbolic links to query
409 /// information about the destination file.
410 ///
411 /// The async version of [`std::fs::metadata`]
412 ///
413 /// # Errors
414 ///
415 /// This function will return an error in the following situations, but is not
416 /// limited to just these cases:
417 ///
418 /// * The original path is not a file or doesn't exist.
419 ///
420 /// # Examples
421 ///
422 /// ```no_run
423 /// use std::io;
424 ///
425 /// use ylong_runtime::fs;
426 /// async fn metadata() -> io::Result<()> {
427 ///     let data = fs::metadata("/path/file.txt").await?;
428 ///     Ok(())
429 /// }
430 /// ```
metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata>431 pub async fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
432     let path = path.as_ref().to_owned();
433     async_op(move || std::fs::metadata(path)).await
434 }
435 
436 /// Queries the metadata about a file without following symlinks.
437 ///
438 /// The async version of [`std::fs::symlink_metadata`]
439 ///
440 /// # Errors
441 ///
442 /// This function will return an error in the following situations, but is not
443 /// limited to just these cases:
444 ///
445 /// * The user lacks permissions to perform metadata call on path.
446 /// * path does not exist.
447 ///
448 /// # Examples
449 ///
450 /// ```no_run
451 /// use std::io;
452 ///
453 /// use ylong_runtime::fs;
454 /// async fn symlink_metadata() -> io::Result<()> {
455 ///     fs::symlink_metadata("/path/file.txt").await?;
456 ///     Ok(())
457 /// }
458 /// ```
symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata>459 pub async fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
460     let path = path.as_ref().to_owned();
461     async_op(move || std::fs::symlink_metadata(path)).await
462 }
463 
464 /// Returns the canonical, absolute form of a path with all intermediate
465 /// components normalized and symbolic links resolved.
466 ///
467 /// The async version of [`std::fs::canonicalize`]
468 ///
469 /// # Errors
470 ///
471 /// This function will return an error in the following situations, but is not
472 /// limited to just these cases:
473 ///
474 /// * path does not exist.
475 /// * A non-final component in path is not a directory.
476 ///
477 /// # Examples
478 ///
479 /// ```no_run
480 /// use std::io;
481 ///
482 /// use ylong_runtime::fs;
483 /// async fn canonicalize() -> io::Result<()> {
484 ///     fs::canonicalize("../path/../file.txt").await?;
485 ///     Ok(())
486 /// }
487 /// ```
canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf>488 pub async fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
489     let path = path.as_ref().to_owned();
490     async_op(move || std::fs::canonicalize(path)).await
491 }
492 
493 /// Changes the permissions found on a file or a directory.
494 ///
495 /// The async version of [`std::fs::set_permissions`]
496 ///
497 /// # Errors
498 ///
499 /// This function will return an error in the following situations, but is not
500 /// limited to just these cases:
501 ///
502 /// * path does not exist.
503 /// * The user lacks the permission to change attributes of the file.
504 ///
505 /// # Examples
506 ///
507 /// ```no_run
508 /// use std::{fs, io};
509 /// async fn set_permissions() -> io::Result<()> {
510 ///     let mut perms = ylong_runtime::fs::metadata("file.txt").await?.permissions();
511 ///     perms.set_readonly(true);
512 ///     ylong_runtime::fs::set_permissions("file.txt", perms).await?;
513 ///     Ok(())
514 /// }
515 /// ```
set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()>516 pub async fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
517     let path = path.as_ref().to_owned();
518     async_op(move || std::fs::set_permissions(path, perm)).await
519 }
520 
521 type Entries = (Fuse<std::fs::ReadDir>, VecDeque<io::Result<DirEntry>>);
522 
523 enum State {
524     Available(Box<Option<Entries>>),
525     Empty(JoinHandle<Entries>),
526 }
527 /// Directory for reading file entries.
528 ///
529 /// Returned from the [`read_dir`] function of this module and
530 /// will yield instances of [`io::Result`]<[`DirEntry`]>. A [`DirEntry`]
531 /// contains information like the entry's path and possibly other metadata.
532 ///
533 /// # Errors
534 ///
535 /// Returns [`Err`] if an IO error occurs during iteration.
536 pub struct ReadDir(State);
537 
538 impl ReadDir {
new(std_dir: Fuse<std::fs::ReadDir>, block: VecDeque<io::Result<DirEntry>>) -> ReadDir539     fn new(std_dir: Fuse<std::fs::ReadDir>, block: VecDeque<io::Result<DirEntry>>) -> ReadDir {
540         ReadDir(State::Available(Box::new(Some((std_dir, block)))))
541     }
542 
fill_block( std_dir: &mut Fuse<std::fs::ReadDir>, block: &mut VecDeque<io::Result<DirEntry>>, )543     fn fill_block(
544         std_dir: &mut Fuse<std::fs::ReadDir>,
545         block: &mut VecDeque<io::Result<DirEntry>>,
546     ) {
547         for res in std_dir.by_ref().take(BLOCK_SIZE) {
548             match res {
549                 Ok(entry) => block.push_back(Ok(DirEntry(Arc::new(entry)))),
550                 Err(e) => block.push_back(Err(e)),
551             }
552         }
553     }
554 
poll_next(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>>555     fn poll_next(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<Option<DirEntry>>> {
556         loop {
557             match self.0 {
558                 State::Available(ref mut dir) => {
559                     let (mut std_dir, mut block) = dir.take().unwrap();
560                     match block.pop_front() {
561                         Some(Ok(entry)) => {
562                             self.0 = State::Available(Box::new(Some((std_dir, block))));
563                             return Ready(Ok(Some(entry)));
564                         }
565                         Some(Err(e)) => {
566                             self.0 = State::Available(Box::new(Some((std_dir, block))));
567                             return Ready(Err(e));
568                         }
569                         None => {}
570                     }
571 
572                     self.0 = State::Empty(spawn_blocking(&TaskBuilder::new(), move || {
573                         ReadDir::fill_block(&mut std_dir, &mut block);
574                         (std_dir, block)
575                     }));
576                 }
577                 State::Empty(ref mut handle) => {
578                     let (std_dir, mut block) = poll_ready!(Pin::new(handle).poll(cx))?;
579                     let res = match block.pop_front() {
580                         Some(Ok(entry)) => Ok(Some(entry)),
581                         Some(Err(e)) => Err(e),
582                         None => Ok(None),
583                     };
584                     self.0 = State::Available(Box::new(Some((std_dir, block))));
585                     return Ready(res);
586                 }
587             }
588         }
589     }
590 
591     /// Returns the next entry in the directory.
592     ///
593     /// # Return value
594     /// The function returns:
595     /// * `Ok(Some(entry))` entry is an entry in the directory.
596     /// * `Ok(None)` if there is no more entries in the directory.
597     /// * `Err(e)` if an IO error occurred.
598     ///
599     /// # Examples
600     ///
601     /// ```no_run
602     /// use std::io;
603     ///
604     /// use ylong_runtime::fs;
605     /// async fn fs_func() -> io::Result<()> {
606     ///     let mut dir = fs::read_dir("/parent/dir").await?;
607     ///     assert!(dir.next().await.is_ok());
608     ///     Ok(())
609     /// }
610     /// ```
next(&mut self) -> io::Result<Option<DirEntry>>611     pub async fn next(&mut self) -> io::Result<Option<DirEntry>> {
612         poll_fn(|cx| self.poll_next(cx)).await
613     }
614 }
615 
616 /// Entries returned by the [`ReadDir::next_entry`].
617 ///
618 /// Represents an entry inside of a directory on the filesystem.
619 /// Each entry can be inspected via methods to learn about the full path
620 /// or possibly other metadata through per-platform extension traits.
621 pub struct DirEntry(Arc<std::fs::DirEntry>);
622 
623 impl DirEntry {
624     /// Returns the full path to the file represented by this entry.
625     ///
626     /// # Examples
627     ///
628     /// ```no_run
629     /// use std::io;
630     ///
631     /// use ylong_runtime::fs;
632     ///
633     /// async fn fs_func() -> io::Result<()> {
634     ///     let mut dir = fs::read_dir("/parent/dir").await?;
635     ///     while let Some(entry) = dir.next().await? {
636     ///         println!("{:?}", entry.path());
637     ///     }
638     ///     Ok(())
639     /// }
640     /// ```
641     ///
642     /// This prints output like:
643     ///
644     /// ```text
645     /// "/parent/dir/some.txt"
646     /// "/parent/dir/rust.rs"
647     /// ```
path(&self) -> PathBuf648     pub fn path(&self) -> PathBuf {
649         self.0.path()
650     }
651 
652     /// Returns the name of the file represented by this entry.
653     ///
654     /// # Examples
655     ///
656     /// ```no_run
657     /// use std::io;
658     ///
659     /// use ylong_runtime::fs;
660     ///
661     /// async fn fs_func() -> io::Result<()> {
662     ///     let mut dir = fs::read_dir("/parent/dir").await?;
663     ///     while let Some(entry) = dir.next().await? {
664     ///         println!("{:?}", entry.file_name());
665     ///     }
666     ///     Ok(())
667     /// }
668     /// ```
file_name(&self) -> OsString669     pub fn file_name(&self) -> OsString {
670         self.0.file_name()
671     }
672 
673     /// Returns the metadata for the file represented by this entry.
674     ///
675     /// This function won't traverse symlinks if this entry points
676     /// at a symlink.
677     ///
678     /// # Examples
679     ///
680     /// ```no_run
681     /// use std::io;
682     ///
683     /// use ylong_runtime::fs;
684     ///
685     /// async fn fs_func() -> io::Result<()> {
686     ///     let mut dir = fs::read_dir("/parent/dir").await?;
687     ///     while let Some(entry) = dir.next().await? {
688     ///         if let Ok(metadata) = entry.metadata().await {
689     ///             println!("{:?}", metadata.permissions());
690     ///         }
691     ///     }
692     ///     Ok(())
693     /// }
694     /// ```
metadata(&self) -> io::Result<Metadata>695     pub async fn metadata(&self) -> io::Result<Metadata> {
696         let entry = self.0.clone();
697         async_op(move || entry.metadata()).await
698     }
699 
700     /// Returns the file type for the file represented by this entry.
701     ///
702     /// This function won't traverse symlinks if this entry points
703     /// at a symlink.
704     ///
705     /// # Examples
706     ///
707     /// ```no_run
708     /// use std::io;
709     ///
710     /// use ylong_runtime::fs;
711     ///
712     /// async fn fs_func() -> io::Result<()> {
713     ///     let mut dir = fs::read_dir("/parent/dir").await?;
714     ///     while let Some(entry) = dir.next().await? {
715     ///         if let Ok(file_type) = entry.file_type().await {
716     ///             println!("{:?}", file_type);
717     ///         }
718     ///     }
719     ///     Ok(())
720     /// }
721     /// ```
file_type(&self) -> io::Result<FileType>722     pub async fn file_type(&self) -> io::Result<FileType> {
723         let entry = self.0.clone();
724         async_op(move || entry.file_type()).await
725     }
726 }
727 
728 #[cfg(test)]
729 mod test {
730     use crate::fs::{
731         canonicalize, copy, hard_link, metadata, read, read_link, read_to_string, remove_file,
732         rename, set_permissions, symlink_metadata, write, File,
733     };
734 
735     /// UT test for `remove_file`
736     ///
737     /// # Brief
738     ///
739     /// 1. Create a new file.
740     /// 2. Remove the file with `remove_file()`, check result is Ok(()).
741     #[test]
ut_fs_create_remove_file()742     fn ut_fs_create_remove_file() {
743         crate::block_on(async {
744             let file_path = "file0.txt";
745 
746             File::create(file_path).await.unwrap();
747             let res = remove_file(file_path).await;
748 
749             assert!(res.is_ok());
750         });
751     }
752 
753     /// UT test for `rename`
754     ///
755     /// # Brief
756     ///
757     /// 1. Create a new file.
758     /// 2. Rename the file with `rename()`.
759     /// 3. Delete the new file.
760     #[test]
ut_fs_rename()761     fn ut_fs_rename() {
762         crate::block_on(async {
763             let file_path = "file1.txt";
764 
765             File::create(file_path).await.unwrap();
766             let res = rename(file_path, "new_file1.txt").await;
767             assert!(res.is_ok());
768 
769             let res = remove_file("new_file1.txt").await;
770             assert!(res.is_ok());
771         });
772     }
773 
774     /// UT test for `write()` and `read_to_string()`
775     ///
776     /// # Brief
777     ///
778     /// 1. Create a new file.
779     /// 2. Write the file with `write()`.
780     /// 3. Read the file with `read_to_string()`, check whether it's correct.
781     /// 4. Delete the file.
782     #[test]
ut_fs_write_and_read_to_string()783     fn ut_fs_write_and_read_to_string() {
784         crate::block_on(async {
785             let input = "Hello world";
786             let file_path = "file2.txt";
787 
788             File::create(file_path).await.unwrap();
789 
790             let res = write(file_path, input.as_bytes()).await;
791             assert!(res.is_ok());
792             let s = read_to_string(file_path).await.unwrap();
793             assert_eq!(s, input);
794 
795             let res = remove_file(file_path).await;
796             assert!(res.is_ok());
797         });
798     }
799 
800     /// UT test for `read()` and `write()`
801     ///
802     /// # Brief
803     ///
804     /// 1. Create a new file.
805     /// 2. Write the file with `write()`.
806     /// 3. Read the file with `read()`, check whether it's correct.
807     /// 4. Delete the file.
808     #[test]
ut_fs_write_and_read()809     fn ut_fs_write_and_read() {
810         crate::block_on(async {
811             let input = "Hello world";
812             let file_path = "file3.txt";
813 
814             File::create(file_path).await.unwrap();
815 
816             let res = write(file_path, input.as_bytes()).await;
817             assert!(res.is_ok());
818             let buf = read(file_path).await.unwrap();
819             let s = String::from_utf8(buf).expect("Found invalid UTF-8");
820             assert_eq!(s, input);
821 
822             let res = remove_file(file_path).await;
823             assert!(res.is_ok());
824         });
825     }
826 
827     /// UT test for `read_link()`
828     ///
829     /// # Brief
830     ///
831     /// 1. Read a symbolic link with read_link().
832     /// 2. Check whether the result is correct.
833     #[test]
ut_fs_read_link()834     fn ut_fs_read_link() {
835         crate::block_on(async {
836             let file_path = "file4.txt";
837 
838             let res = read_link(file_path).await;
839             assert!(res.is_err());
840         });
841     }
842 
843     /// UT test for `copy()`
844     ///
845     /// # Brief
846     ///
847     /// 1. Create a new file.
848     /// 2. Copy the file with `copy()`.
849     /// 3. Check whether the result is correct.
850     /// 4. Delete two files.
851     #[test]
ut_fs_copy()852     fn ut_fs_copy() {
853         crate::block_on(async {
854             let file_path = "file5.txt";
855 
856             File::create(file_path).await.unwrap();
857 
858             let res = copy(file_path, "new_file5.txt").await;
859             assert!(res.is_ok());
860 
861             let res = remove_file(file_path).await;
862             assert!(res.is_ok());
863             let res = remove_file("new_file5.txt").await;
864             assert!(res.is_ok());
865         });
866     }
867 
868     /// UT test for `hard_link()`
869     ///
870     /// # Brief
871     ///
872     /// 1. Create a new file.
873     /// 2. Create a new hard link on the filesystem with `hard_link()`.
874     /// 3. Check whether the result is correct.
875     /// 4. Delete two files.
876     #[test]
ut_fs_hard_link()877     fn ut_fs_hard_link() {
878         crate::block_on(async {
879             let file_path = "file6.txt";
880 
881             File::create(file_path).await.unwrap();
882 
883             let res = hard_link(file_path, "new_file6.txt").await;
884             assert!(res.is_ok());
885 
886             let res = remove_file(file_path).await;
887             assert!(res.is_ok());
888             let res = remove_file("new_file6.txt").await;
889             assert!(res.is_ok());
890         });
891     }
892 
893     /// UT test for `metadata()`
894     ///
895     /// # Brief
896     ///
897     /// 1. Create a new file.
898     /// 2. Get information about this file with `metadata()`.
899     /// 3. Check whether the result is correct.
900     /// 4. Delete the file.
901     #[test]
ut_fs_metadata()902     fn ut_fs_metadata() {
903         crate::block_on(async {
904             let file_path = "file7.txt";
905 
906             File::create(file_path).await.unwrap();
907 
908             let res = metadata(file_path).await;
909             assert!(res.is_ok());
910 
911             let res = remove_file(file_path).await;
912             assert!(res.is_ok());
913         });
914     }
915 
916     /// UT test for `canonicalize()`
917     ///
918     /// # Brief
919     ///
920     /// 1. Create a new file.
921     /// 2. Get the canonical, absolute form of a path with all intermediate
922     ///    components normalized and symbolic links resolved with
923     ///    `canonicalize()`.
924     /// 3. Check whether the result is correct.
925     /// 4. Delete the file.
926     #[test]
ut_fs_canonicalize()927     fn ut_fs_canonicalize() {
928         crate::block_on(async {
929             let file_path = "file8.txt";
930             File::create(file_path).await.unwrap();
931 
932             let res = canonicalize(file_path).await;
933             assert!(res.is_ok());
934 
935             let res = remove_file(file_path).await;
936             assert!(res.is_ok());
937         });
938     }
939 
940     /// UT test for `symlink_metadata()`
941     ///
942     /// # Brief
943     ///
944     /// 1. Create a new file.
945     /// 2. Query the metadata about a file without following symlinks with
946     ///    `symlink_metadata()`.
947     /// 3. Check whether the result is correct.
948     /// 4. Delete the file.
949     #[test]
ut_fs_symlink_metadata()950     fn ut_fs_symlink_metadata() {
951         crate::block_on(async {
952             let file_path = "file9.txt";
953             File::create(file_path).await.unwrap();
954 
955             let res = symlink_metadata(file_path).await;
956             assert!(res.is_ok());
957 
958             let res = remove_file(file_path).await;
959             assert!(res.is_ok());
960         });
961     }
962 
963     /// UT test for `set_permissions()`
964     ///
965     /// # Brief
966     ///
967     /// 1. Create a new file.
968     /// 2. Set file as readonly with `set_permissions()`.
969     /// 3. Check whether the result is correct.
970     /// 4. Delete the file.
971     #[test]
ut_fs_set_permissions()972     fn ut_fs_set_permissions() {
973         crate::block_on(async {
974             let file_path = "file10.txt";
975             File::create(file_path).await.unwrap();
976 
977             let mut perms = metadata(file_path).await.unwrap().permissions();
978             perms.set_readonly(true);
979             let res = set_permissions(file_path, perms).await;
980             assert!(res.is_ok());
981 
982             let mut perms = metadata(file_path).await.unwrap().permissions();
983             #[allow(clippy::permissions_set_readonly_false)]
984             perms.set_readonly(false);
985             let res = set_permissions(file_path, perms).await;
986             assert!(res.is_ok());
987 
988             let res = remove_file(file_path).await;
989             assert!(res.is_ok());
990         });
991     }
992 }
993