1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
use std::path::Path;
use crate::core::env::expand_env;
use crate::error::Error;
#[derive(Debug)]
pub struct Options {
pub parents: bool,
pub mode: nc::mode_t,
pub exist_ok: bool,
pub expand_env: bool,
}
impl Options {
pub fn new() -> Options {
Self::default()
}
}
impl Default for Options {
fn default() -> Self {
Options {
parents: false,
mode: 0o755,
exist_ok: false,
expand_env: true,
}
}
}
impl Options {
pub fn with_parents() -> Self {
Self {
parents: true,
..Self::default()
}
}
}
pub fn mkdir<T: AsRef<str>>(directory: T, options: &Options) -> Result<(), Error> {
let exist_ok = if options.parents {
true
} else {
options.parents
};
let directory = if options.expand_env {
expand_env(directory)
} else {
directory.as_ref().to_string()
};
let path = Path::new(&directory);
do_mkdir(path, options.parents, options.mode, exist_ok).map_err(Into::into)
}
fn do_mkdir(p: &Path, recursive: bool, mode: nc::mode_t, exist_ok: bool) -> Result<(), nc::Errno> {
if p.exists() {
if exist_ok {
return Ok(());
} else {
return Err(nc::EEXIST);
}
}
if recursive {
match p.parent() {
Some(parent) => do_mkdir(parent, recursive, mode, true)?,
None => return Err(nc::ENOENT),
}
}
nc::mkdir(p, mode)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mkdir() {
let mut options = Options::new();
options.parents = true;
let ret = mkdir("/tmp/test1/test2", &options);
assert!(ret.is_ok());
}
}