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