use std::fs;
use std::io;
use std::path::{Path, PathBuf};
use super::not_found_or_io;
use crate::error::{Error, Result};
pub fn make_dir(path: impl AsRef<Path>) -> Result<()> {
create_dir(path.as_ref(), None)
}
pub(crate) fn create_dir(path: &Path, mode: Option<u32>) -> Result<()> {
match fs::symlink_metadata(path) {
Ok(meta) if meta.is_dir() => return Ok(()),
Ok(meta) if meta.file_type().is_symlink() => {
return Err(Error::Refused {
path: path.to_path_buf(),
reason: "it is a symbolic link, not a directory",
});
}
Ok(_) => {
return Err(Error::AlreadyExists {
path: path.to_path_buf(),
});
}
Err(e) if e.kind() == io::ErrorKind::NotFound => {}
Err(e) => return Err(Error::io("inspect", path, e)),
}
let mut builder = fs::DirBuilder::new();
let _builder = builder.recursive(true);
apply_mode(&mut builder, mode);
builder
.create(path)
.map_err(|e| Error::io("create directory", path, e))
}
#[cfg(unix)]
pub(super) fn apply_mode(builder: &mut fs::DirBuilder, mode: Option<u32>) {
use std::os::unix::fs::DirBuilderExt;
if let Some(mode) = mode {
let _builder = builder.mode(mode);
}
}
#[cfg(windows)]
pub(super) fn apply_mode(_builder: &mut fs::DirBuilder, _mode: Option<u32>) {}
pub fn make_file(path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref();
if let Some(parent) = path.parent().filter(|p| !p.as_os_str().is_empty()) {
create_dir(parent, None)?;
}
match fs::OpenOptions::new()
.write(true)
.create_new(true)
.open(path)
{
Ok(_file) => Ok(()),
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => Err(Error::AlreadyExists {
path: path.to_path_buf(),
}),
Err(e) => Err(Error::io("create file", path, e)),
}
}
#[must_use]
pub fn exists(path: impl AsRef<Path>) -> bool {
match fs::symlink_metadata(path) {
Ok(_) => true,
Err(e) => e.kind() != io::ErrorKind::NotFound,
}
}
pub fn list(dir: impl AsRef<Path>) -> Result<Vec<PathBuf>> {
let dir = dir.as_ref();
let entries = fs::read_dir(dir).map_err(|e| not_found_or_io("list", dir, e))?;
let mut out = Vec::new();
for entry in entries {
let entry = entry.map_err(|e| Error::io("list", dir, e))?;
out.push(entry.path());
}
out.sort_unstable();
Ok(out)
}