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