1#[cfg(unix)]
2#[path = "unix.rs"]
3mod sys;
4
5#[cfg(windows)]
6#[path = "windows.rs"]
7mod sys;
8
9use std::{io, path::Path};
10
11use compio_buf::{BufResult, IoBuf, buf_try};
12use compio_io::{AsyncReadAtExt, AsyncWriteAtExt};
13
14use crate::{File, metadata};
15
16pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
18 sys::remove_file(path).await
19}
20
21pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
23 sys::remove_dir(path).await
24}
25
26pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
28 DirBuilder::new().create(path).await
29}
30
31pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
34 DirBuilder::new().recursive(true).create(path).await
35}
36
37pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
40 sys::rename(from, to).await
41}
42
43#[cfg(unix)]
45pub async fn symlink(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
46 sys::symlink(original, link).await
47}
48
49#[cfg(windows)]
51pub async fn symlink_file(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
52 sys::symlink_file(original, link).await
53}
54
55#[cfg(windows)]
57pub async fn symlink_dir(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
58 sys::symlink_dir(original, link).await
59}
60
61pub async fn hard_link(original: impl AsRef<Path>, link: impl AsRef<Path>) -> io::Result<()> {
63 sys::hard_link(original, link).await
64}
65
66pub async fn write<P: AsRef<Path>, B: IoBuf>(path: P, buf: B) -> BufResult<(), B> {
71 let (mut file, buf) = buf_try!(File::create(path).await, buf);
72 file.write_all_at(buf, 0).await
73}
74
75pub async fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
77 let file = File::open(path).await?;
78 let BufResult(res, buffer) = file.read_to_end_at(Vec::new(), 0).await;
79 res?;
80 Ok(buffer)
81}
82
83pub struct DirBuilder {
85 inner: sys::DirBuilder,
86 recursive: bool,
87}
88
89impl Default for DirBuilder {
90 fn default() -> Self {
91 Self::new()
92 }
93}
94
95impl DirBuilder {
96 pub fn new() -> Self {
99 Self {
100 inner: sys::DirBuilder::new(),
101 recursive: false,
102 }
103 }
104
105 pub fn recursive(&mut self, recursive: bool) -> &mut Self {
109 self.recursive = recursive;
110 self
111 }
112
113 pub async fn create(&self, path: impl AsRef<Path>) -> io::Result<()> {
116 let path = path.as_ref();
117 if self.recursive {
118 self.create_dir_all(path).await
119 } else {
120 self.inner.create(path).await
121 }
122 }
123
124 async fn create_dir_all(&self, path: &Path) -> io::Result<()> {
125 if path == Path::new("") {
126 return Ok(());
127 }
128
129 match self.inner.create(path).await {
130 Ok(()) => return Ok(()),
131 Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
132 Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => return Ok(()),
133 Err(e) => return Err(e),
134 }
135 match path.parent() {
136 Some(p) => Box::pin(self.create_dir_all(p)).await?,
137 None => {
138 return Err(io::Error::new(
139 io::ErrorKind::Other,
140 "failed to create whole tree",
141 ));
142 }
143 }
144 match self.inner.create(path).await {
145 Ok(()) => Ok(()),
146 Err(_) if metadata(path).await.map(|m| m.is_dir()).unwrap_or_default() => Ok(()),
147 Err(e) => Err(e),
148 }
149 }
150}
151
152#[cfg(unix)]
153impl std::os::unix::fs::DirBuilderExt for DirBuilder {
154 fn mode(&mut self, mode: u32) -> &mut Self {
155 self.inner.mode(mode);
156 self
157 }
158}