1 //! Tokio-specific wrappers that use `fs_err` error messages.
2
3 use crate::errors::{Error, ErrorKind, SourceDestError, SourceDestErrorKind};
4 use std::fs::{Metadata, Permissions};
5 use std::path::{Path, PathBuf};
6 use tokio::io;
7 mod dir_builder;
8 mod file;
9 mod open_options;
10 mod read_dir;
11
12 pub use self::open_options::OpenOptions;
13 pub use self::read_dir::{read_dir, DirEntry, ReadDir};
14 pub use dir_builder::DirBuilder;
15 pub use file::File;
16
17 /// Returns the canonical, absolute form of a path with all intermediate
18 /// components normalized and symbolic links resolved.
19 ///
20 /// Wrapper for [`tokio::fs::canonicalize`].
21 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
canonicalize(path: impl AsRef<Path>) -> io::Result<PathBuf>22 pub async fn canonicalize(path: impl AsRef<Path>) -> io::Result<PathBuf> {
23 let path = path.as_ref();
24 tokio::fs::canonicalize(path)
25 .await
26 .map_err(|err| Error::build(err, ErrorKind::Canonicalize, path))
27 }
28
29 /// Copies the contents of one file to another. This function will also copy the permission bits
30 /// of the original file to the destination file.
31 /// This function will overwrite the contents of to.
32 ///
33 /// Wrapper for [`tokio::fs::copy`].
34 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64, io::Error>35 pub async fn copy(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<u64, io::Error> {
36 let (from, to) = (from.as_ref(), to.as_ref());
37 tokio::fs::copy(from, to)
38 .await
39 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Copy, from, to))
40 }
41
42 /// Creates a new, empty directory at the provided path.
43 ///
44 /// Wrapper for [`tokio::fs::create_dir`].
45 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
create_dir(path: impl AsRef<Path>) -> io::Result<()>46 pub async fn create_dir(path: impl AsRef<Path>) -> io::Result<()> {
47 let path = path.as_ref();
48 tokio::fs::create_dir(path)
49 .await
50 .map_err(|err| Error::build(err, ErrorKind::CreateDir, path))
51 }
52
53 /// Recursively creates a directory and all of its parent components if they
54 /// are missing.
55 ///
56 /// Wrapper for [`tokio::fs::create_dir_all`].
57 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
create_dir_all(path: impl AsRef<Path>) -> io::Result<()>58 pub async fn create_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
59 let path = path.as_ref();
60 tokio::fs::create_dir_all(path)
61 .await
62 .map_err(|err| Error::build(err, ErrorKind::CreateDir, path))
63 }
64
65 /// Creates a new hard link on the filesystem.
66 ///
67 /// Wrapper for [`tokio::fs::hard_link`].
68 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()>69 pub async fn hard_link(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
70 let (src, dst) = (src.as_ref(), dst.as_ref());
71 tokio::fs::hard_link(src, dst)
72 .await
73 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::HardLink, src, dst))
74 }
75
76 /// Given a path, queries the file system to get information about a file,
77 /// directory, etc.
78 ///
79 /// Wrapper for [`tokio::fs::metadata`].
80 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
metadata(path: impl AsRef<Path>) -> io::Result<Metadata>81 pub async fn metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
82 let path = path.as_ref();
83 tokio::fs::metadata(path)
84 .await
85 .map_err(|err| Error::build(err, ErrorKind::Metadata, path))
86 }
87
88 /// Reads the entire contents of a file into a bytes vector.
89 ///
90 /// Wrapper for [`tokio::fs::read`].
91 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
read(path: impl AsRef<Path>) -> io::Result<Vec<u8>>92 pub async fn read(path: impl AsRef<Path>) -> io::Result<Vec<u8>> {
93 let path = path.as_ref();
94 tokio::fs::read(path)
95 .await
96 .map_err(|err| Error::build(err, ErrorKind::Read, path))
97 }
98
99 /// Reads a symbolic link, returning the file that the link points to.
100 ///
101 /// Wrapper for [`tokio::fs::read_link`].
102 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
read_link(path: impl AsRef<Path>) -> io::Result<PathBuf>103 pub async fn read_link(path: impl AsRef<Path>) -> io::Result<PathBuf> {
104 let path = path.as_ref();
105 tokio::fs::read_link(path)
106 .await
107 .map_err(|err| Error::build(err, ErrorKind::ReadLink, path))
108 }
109
110 /// Creates a future which will open a file for reading and read the entire
111 /// contents into a string and return said string.
112 ///
113 /// Wrapper for [`tokio::fs::read_to_string`].
114 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
read_to_string(path: impl AsRef<Path>) -> io::Result<String>115 pub async fn read_to_string(path: impl AsRef<Path>) -> io::Result<String> {
116 let path = path.as_ref();
117 tokio::fs::read_to_string(path)
118 .await
119 .map_err(|err| Error::build(err, ErrorKind::Read, path))
120 }
121
122 /// Removes an existing, empty directory.
123 ///
124 /// Wrapper for [`tokio::fs::remove_dir`].
125 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
remove_dir(path: impl AsRef<Path>) -> io::Result<()>126 pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
127 let path = path.as_ref();
128 tokio::fs::remove_dir(path)
129 .await
130 .map_err(|err| Error::build(err, ErrorKind::RemoveDir, path))
131 }
132
133 /// Removes a directory at this path, after removing all its contents. Use carefully!
134 ///
135 /// Wrapper for [`tokio::fs::remove_dir_all`].
136 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
remove_dir_all(path: impl AsRef<Path>) -> io::Result<()>137 pub async fn remove_dir_all(path: impl AsRef<Path>) -> io::Result<()> {
138 let path = path.as_ref();
139 tokio::fs::remove_dir_all(path)
140 .await
141 .map_err(|err| Error::build(err, ErrorKind::RemoveDir, path))
142 }
143
144 /// Removes a file from the filesystem.
145 ///
146 /// Wrapper for [`tokio::fs::remove_file`].
147 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
remove_file(path: impl AsRef<Path>) -> io::Result<()>148 pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
149 let path = path.as_ref();
150 tokio::fs::remove_file(path)
151 .await
152 .map_err(|err| Error::build(err, ErrorKind::RemoveFile, path))
153 }
154
155 /// Renames a file or directory to a new name, replacing the original file if
156 /// `to` already exists.
157 ///
158 /// Wrapper for [`tokio::fs::rename`].
159 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()>160 pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
161 let (from, to) = (from.as_ref(), to.as_ref());
162 tokio::fs::rename(from, to)
163 .await
164 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Rename, from, to))
165 }
166
167 /// Changes the permissions found on a file or a directory.
168 ///
169 /// Wrapper for [`tokio::fs::set_permissions`].
170 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
set_permissions(path: impl AsRef<Path>, perm: Permissions) -> io::Result<()>171 pub async fn set_permissions(path: impl AsRef<Path>, perm: Permissions) -> io::Result<()> {
172 let path = path.as_ref();
173 tokio::fs::set_permissions(path, perm)
174 .await
175 .map_err(|err| Error::build(err, ErrorKind::SetPermissions, path))
176 }
177
178 /// Queries the file system metadata for a path.
179 ///
180 /// Wrapper for [`tokio::fs::symlink_metadata`].
181 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
symlink_metadata(path: impl AsRef<Path>) -> io::Result<Metadata>182 pub async fn symlink_metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
183 let path = path.as_ref();
184 tokio::fs::symlink_metadata(path)
185 .await
186 .map_err(|err| Error::build(err, ErrorKind::SymlinkMetadata, path))
187 }
188
189 /// Creates a new symbolic link on the filesystem.
190 ///
191 /// Wrapper for [`tokio::fs::symlink`].
192 #[cfg(unix)]
193 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()>194 pub async fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
195 let (src, dst) = (src.as_ref(), dst.as_ref());
196 tokio::fs::symlink(src, dst)
197 .await
198 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::Symlink, src, dst))
199 }
200
201 /// Creates a new directory symlink on the filesystem.
202 ///
203 /// Wrapper for [`tokio::fs::symlink_dir`].
204 #[cfg(windows)]
205 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
206 #[deprecated = "use fs_err::tokio::symlink_dir instead"]
symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()>207 pub async fn symlink(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
208 symlink_dir(src, dst).await
209 }
210
211 /// Creates a new directory symlink on the filesystem.
212 ///
213 /// Wrapper for [`tokio::fs::symlink_dir`].
214 #[cfg(windows)]
215 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()>216 pub async fn symlink_dir(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
217 let (src, dst) = (src.as_ref(), dst.as_ref());
218 tokio::fs::symlink_dir(src, dst)
219 .await
220 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::SymlinkDir, src, dst))
221 }
222
223 /// Creates a new file symbolic link on the filesystem.
224 ///
225 /// Wrapper for [`tokio::fs::symlink_file`].
226 #[cfg(windows)]
227 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()>228 pub async fn symlink_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
229 let (src, dst) = (src.as_ref(), dst.as_ref());
230 tokio::fs::symlink_file(src, dst)
231 .await
232 .map_err(|err| SourceDestError::build(err, SourceDestErrorKind::SymlinkFile, src, dst))
233 }
234
235 /// Creates a future that will open a file for writing and write the entire
236 /// contents of `contents` to it.
237 ///
238 /// Wrapper for [`tokio::fs::write`].
239 #[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()>240 pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> io::Result<()> {
241 let (path, contents) = (path.as_ref(), contents.as_ref());
242 tokio::fs::write(path, contents)
243 .await
244 .map_err(|err| Error::build(err, ErrorKind::Write, path))
245 }
246