use std::{
io,
path::{Path, PathBuf},
};
pub const MAX_TEMP_PREFIX_BYTES: usize = 128;
#[derive(Debug)]
pub struct TemporaryDirectory {
inner: tempfile::TempDir,
}
impl TemporaryDirectory {
pub fn new() -> io::Result<Self> {
Self::in_directory(&std::env::temp_dir(), "kernal-")
}
pub fn in_directory(parent: &Path, prefix: &str) -> io::Result<Self> {
if prefix.len() > MAX_TEMP_PREFIX_BYTES
|| matches!(prefix, "." | "..")
|| prefix
.chars()
.any(|ch| ch.is_control() || "\\/<>:\"|?*".contains(ch))
{
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"invalid temporary-directory prefix",
));
}
let mut builder = tempfile::Builder::new();
builder.prefix(prefix).rand_bytes(16);
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
builder.permissions(std::fs::Permissions::from_mode(0o700));
}
let inner = builder.tempdir_in(parent)?;
Ok(Self { inner })
}
pub fn path(&self) -> &Path {
self.inner.path()
}
#[must_use]
pub fn persist(self) -> PathBuf {
self.inner.keep()
}
pub fn close(self) -> io::Result<()> {
self.inner.close()
}
}
impl AsRef<Path> for TemporaryDirectory {
fn as_ref(&self) -> &Path {
self.path()
}
}