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