use crate::error::ShredResult;
use rand::{distributions::Alphanumeric, Rng};
use std::fs;
use std::path::{Path, PathBuf};
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
pub struct MetadataHandler;
impl MetadataHandler {
pub fn obfuscate_filename(path: &Path) -> ShredResult<PathBuf> {
let parent = path.parent().unwrap_or_else(|| Path::new("."));
let random_name: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(16)
.map(char::from)
.collect();
let new_path = parent.join(random_name);
fs::rename(path, &new_path)?;
Ok(new_path)
}
pub fn truncate(path: &Path) -> ShredResult<()> {
let file = fs::OpenOptions::new().write(true).open(path)?;
file.set_len(0)?;
file.sync_all()?;
Ok(())
}
pub fn trim(path: &Path) -> ShredResult<()> {
let file = fs::OpenOptions::new().write(true).open(path)?;
let len = file.metadata()?.len();
if len == 0 {
return Ok(());
}
#[cfg(target_os = "linux")]
{
let fd = file.as_raw_fd();
unsafe {
libc::fallocate(fd, 0x01 | 0x02, 0, len as libc::off_t);
}
}
#[cfg(windows)]
{
use std::os::windows::io::AsRawHandle;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::Storage::FileSystem::{
FILE_SET_ZERO_DATA_INFORMATION, FSCTL_SET_ZERO_DATA,
};
use windows_sys::Win32::System::IO::DeviceIoControl;
let handle = file.as_raw_handle() as HANDLE;
let mut info = FILE_SET_ZERO_DATA_INFORMATION {
FileOffset: 0,
BeyondFinalZero: len as i64,
};
let mut bytes_returned = 0;
unsafe {
DeviceIoControl(
handle,
FSCTL_SET_ZERO_DATA,
&mut info as *mut _ as *mut _,
std::mem::size_of::<FILE_SET_ZERO_DATA_INFORMATION>() as u32,
std::ptr::null_mut(),
0,
&mut bytes_returned,
std::ptr::null_mut(),
);
}
}
file.sync_all()?;
Ok(())
}
}