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),
}
}
unsafe { 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());
}
}