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