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 /// ``` new() -> Self33 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 /// ``` recursive(&mut self, recursive: bool) -> &mut Self52 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 /// ``` create(&self, path: impl AsRef<Path>) -> io::Result<()>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