1 | use crate::fs::asyncify; |
2 | |
3 | use std::io; |
4 | use std::path::Path; |
5 | |
6 | /// A builder for creating directories in various manners. |
7 | /// |
8 | /// This is a specialized version of [`std::fs::DirBuilder`] for usage on |
9 | /// the Tokio runtime. |
10 | #[derive(Debug, Default)] |
11 | pub struct DirBuilder { |
12 | /// Indicates whether to create parent directories if they are missing. |
13 | recursive: bool, |
14 | |
15 | /// Sets the Unix mode for newly created directories. |
16 | #[cfg (unix)] |
17 | pub(super) mode: Option<u32>, |
18 | } |
19 | |
20 | impl DirBuilder { |
21 | /// Creates a new set of options with default mode/security settings for all |
22 | /// platforms and also non-recursive. |
23 | /// |
24 | /// This is an async version of [`std::fs::DirBuilder::new`]. |
25 | /// |
26 | /// # Examples |
27 | /// |
28 | /// ```no_run |
29 | /// use tokio::fs::DirBuilder; |
30 | /// |
31 | /// let builder = DirBuilder::new(); |
32 | /// ``` |
33 | pub fn new() -> Self { |
34 | DirBuilder::default() |
35 | } |
36 | |
37 | /// Indicates whether to create directories recursively (including all parent directories). |
38 | /// Parents that do not exist are created with the same security and permissions settings. |
39 | /// |
40 | /// This option defaults to `false`. |
41 | /// |
42 | /// This is an async version of [`std::fs::DirBuilder::recursive`]. |
43 | /// |
44 | /// # Examples |
45 | /// |
46 | /// ```no_run |
47 | /// use tokio::fs::DirBuilder; |
48 | /// |
49 | /// let mut builder = DirBuilder::new(); |
50 | /// builder.recursive(true); |
51 | /// ``` |
52 | pub fn recursive(&mut self, recursive: bool) -> &mut Self { |
53 | self.recursive = recursive; |
54 | self |
55 | } |
56 | |
57 | /// Creates the specified directory with the configured options. |
58 | /// |
59 | /// It is considered an error if the directory already exists unless |
60 | /// recursive mode is enabled. |
61 | /// |
62 | /// This is an async version of [`std::fs::DirBuilder::create`]. |
63 | /// |
64 | /// # Errors |
65 | /// |
66 | /// An error will be returned under the following circumstances: |
67 | /// |
68 | /// * Path already points to an existing file. |
69 | /// * Path already points to an existing directory and the mode is |
70 | /// non-recursive. |
71 | /// * The calling process doesn't have permissions to create the directory |
72 | /// or its missing parents. |
73 | /// * Other I/O error occurred. |
74 | /// |
75 | /// # Examples |
76 | /// |
77 | /// ```no_run |
78 | /// use tokio::fs::DirBuilder; |
79 | /// use std::io; |
80 | /// |
81 | /// #[tokio::main] |
82 | /// async fn main() -> io::Result<()> { |
83 | /// DirBuilder::new() |
84 | /// .recursive(true) |
85 | /// .create("/tmp/foo/bar/baz" ) |
86 | /// .await?; |
87 | /// |
88 | /// Ok(()) |
89 | /// } |
90 | /// ``` |
91 | pub async fn create(&self, path: impl AsRef<Path>) -> io::Result<()> { |
92 | let path = path.as_ref().to_owned(); |
93 | let mut builder = std::fs::DirBuilder::new(); |
94 | builder.recursive(self.recursive); |
95 | |
96 | #[cfg (unix)] |
97 | { |
98 | if let Some(mode) = self.mode { |
99 | std::os::unix::fs::DirBuilderExt::mode(&mut builder, mode); |
100 | } |
101 | } |
102 | |
103 | asyncify(move || builder.create(path)).await |
104 | } |
105 | } |
106 | |
107 | feature! { |
108 | #![unix] |
109 | |
110 | impl DirBuilder { |
111 | /// Sets the mode to create new directories with. |
112 | /// |
113 | /// This option defaults to 0o777. |
114 | /// |
115 | /// # Examples |
116 | /// |
117 | /// |
118 | /// ```no_run |
119 | /// use tokio::fs::DirBuilder; |
120 | /// |
121 | /// let mut builder = DirBuilder::new(); |
122 | /// builder.mode(0o775); |
123 | /// ``` |
124 | pub fn mode(&mut self, mode: u32) -> &mut Self { |
125 | self.mode = Some(mode); |
126 | self |
127 | } |
128 | } |
129 | } |
130 | |