tokio/fs/
dir_builder.rs

1use crate::fs::asyncify;
2
3use std::io;
4use 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)]
11pub 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
20impl 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
107feature! {
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}