You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
95 lines
1.9 KiB
95 lines
1.9 KiB
use std::{
|
|
ops,
|
|
path::{
|
|
PathBuf,
|
|
Path
|
|
},
|
|
fmt,
|
|
};
|
|
use lazy_static::lazy_static;
|
|
|
|
pub mod error;
|
|
|
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
|
pub struct TempFile(PathBuf);
|
|
|
|
const FILENAME_LEN_BYTES: usize = 16;
|
|
const PREFIX: &'static str = "lolistealer-";
|
|
|
|
lazy_static! {
|
|
pub static ref LOCATION: &'static Path = {
|
|
Box::leak(std::env::temp_dir().into_boxed_path())
|
|
};
|
|
}
|
|
|
|
/// Generate a new random byte string for a filename.
|
|
fn generate_filename(mut to: impl fmt::Write) -> Result<(), error::Error>
|
|
{
|
|
let mut buffer = [0u8; FILENAME_LEN_BYTES];
|
|
getrandom::getrandom(&mut buffer[..])?;
|
|
|
|
write!(to, "{}", PREFIX)?;
|
|
for byte in buffer.iter() {
|
|
write!(to, "{:02x}", *byte)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
impl TempFile
|
|
{
|
|
/// Create a new temp file path
|
|
pub fn new() -> Self
|
|
{
|
|
let mut buffer = String::with_capacity((FILENAME_LEN_BYTES*2) + PREFIX.len());
|
|
generate_filename(&mut buffer).expect("tf fatal");
|
|
Self(LOCATION.join(buffer))
|
|
}
|
|
/// Try to create a new temp file path
|
|
pub fn try_new() -> Result<Self, error::Error>
|
|
{
|
|
let mut buffer = String::with_capacity((FILENAME_LEN_BYTES*2) + PREFIX.len());
|
|
generate_filename(&mut buffer)?;
|
|
Ok(Self(LOCATION.join(buffer)))
|
|
}
|
|
|
|
/// Consume the `TempFile` and return the raw path, performing no cleanup.
|
|
pub fn into_pathbuf(mut self) -> PathBuf
|
|
{
|
|
let pb = std::mem::replace(&mut self.0, PathBuf::default());
|
|
std::mem::forget(self);
|
|
pb
|
|
}
|
|
}
|
|
|
|
impl ops::Drop for TempFile
|
|
{
|
|
fn drop(&mut self)
|
|
{
|
|
if self.0.exists() {
|
|
if self.0.is_file() {
|
|
let _ = std::fs::remove_file(&self.0);
|
|
} else {
|
|
let _ = std::fs::remove_dir_all(&self.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl AsRef<Path> for TempFile
|
|
{
|
|
fn as_ref(&self) -> &Path
|
|
{
|
|
self.0.as_ref()
|
|
}
|
|
}
|
|
|
|
impl ops::Deref for TempFile
|
|
{
|
|
type Target = Path;
|
|
fn deref(&self) -> &Self::Target
|
|
{
|
|
self.0.as_ref()
|
|
}
|
|
}
|