sys_shred/core/
metadata.rs1use crate::error::{ShredError, ShredResult};
7use rand::{distributions::Alphanumeric, Rng};
8use std::fs;
9use std::path::{Path, PathBuf};
10
11#[cfg(unix)]
12use std::os::unix::io::AsRawFd;
13
14pub struct MetadataHandler;
19
20impl MetadataHandler {
21 pub fn obfuscate_filename(path: &Path) -> ShredResult<PathBuf> {
23 let parent = path.parent().unwrap_or_else(|| Path::new("."));
24
25 for _ in 0..5 {
27 let random_name: String = rand::thread_rng()
28 .sample_iter(&Alphanumeric)
29 .take(16)
30 .map(char::from)
31 .collect();
32
33 let new_path = parent.join(random_name);
34 if !new_path.exists() {
35 fs::rename(path, &new_path)?;
36 return Ok(new_path);
37 }
38 }
39
40 Err(ShredError::Obfuscation(
41 "Failed to generate a unique random filename after multiple attempts".to_string(),
42 ))
43 }
44
45 pub fn truncate(path: &Path) -> ShredResult<()> {
47 let file = fs::OpenOptions::new().write(true).open(path)?;
48 file.set_len(0)?;
49 file.sync_all()?;
50 Ok(())
51 }
52
53 pub fn trim(path: &Path) -> ShredResult<()> {
58 let file = fs::OpenOptions::new().write(true).open(path)?;
59 let len = file.metadata()?.len();
60 if len == 0 {
61 return Ok(());
62 }
63
64 #[cfg(target_os = "linux")]
65 {
66 let fd = file.as_raw_fd();
67 let res = unsafe {
68 libc::fallocate(fd, 0x01 | 0x02, 0, len as libc::off_t)
70 };
71 if res != 0 {
72 return Err(ShredError::Io(std::io::Error::last_os_error()));
73 }
74 }
75
76 #[cfg(windows)]
77 {
78 use std::os::windows::io::AsRawHandle;
79 use windows_sys::Win32::Foundation::HANDLE;
80 use windows_sys::Win32::Storage::FileSystem::{
81 FILE_SET_ZERO_DATA_INFORMATION, FSCTL_SET_ZERO_DATA,
82 };
83 use windows_sys::Win32::System::IO::DeviceIoControl;
84
85 let handle = file.as_raw_handle() as HANDLE;
86 let mut info = FILE_SET_ZERO_DATA_INFORMATION {
87 FileOffset: 0,
88 BeyondFinalZero: len as i64,
89 };
90 let mut bytes_returned = 0;
91
92 unsafe {
93 DeviceIoControl(
94 handle,
95 FSCTL_SET_ZERO_DATA,
96 &mut info as *mut _ as *mut _,
97 std::mem::size_of::<FILE_SET_ZERO_DATA_INFORMATION>() as u32,
98 std::ptr::null_mut(),
99 0,
100 &mut bytes_returned,
101 std::ptr::null_mut(),
102 );
103 }
104 }
105
106 file.sync_all()?;
107 Ok(())
108 }
109}