use log::{error, debug};
use libc;
use std::os::unix;
use std::time;
use std::fs;
use std::io;
use std::error::Error;
use chrono;
pub fn update_access(fd: unix::io::RawFd, mtime: time::SystemTime)
-> Result<(), time::SystemTimeError> {
let mtime = mtime.duration_since(time::UNIX_EPOCH)?;
let now;
unsafe {
now = libc::time(std::ptr::null_mut());
}
let times: [libc::timeval; 2] = [
libc::timeval{ // atime
tv_sec: now,
tv_usec: 0,
},
libc::timeval{ // mtime
tv_sec: mtime.as_secs() as i64,
tv_usec: mtime.subsec_micros() as i64,
},
];
unsafe {
if libc::futimes(fd as libc::c_int, times.as_ptr()) < 0 {
let cstr = std::ffi::CString::new("update_access: futimes").unwrap();
libc::perror(cstr.as_ptr());
}
};
Ok(())
}
fn do_purge_file(ent: &fs::DirEntry, old_time: time::SystemTime, now: time::SystemTime)
-> Result<(), Box<dyn Error>> {
let meta = ent.metadata()?;
let atime = meta.accessed()?;
if atime < old_time {
// First remove; don't want stupid printing errors to prevent a remove_file
fs::remove_file(&ent.path())?;
let file_age = chrono::Duration::from_std(now.duration_since(atime)?)?;
let file_access_time = chrono::DateTime::<chrono::offset::Utc>::from(atime);
debug!("Deleting '{}' (last accessed at {}; {}d{}h old)",
ent.file_name().to_string_lossy(),
file_access_time.format("%Y-%m-%d %H:%M"),
file_age.num_days(),
file_age.num_hours() - (file_age.num_days() * 24));
}
Ok(())
}
fn do_purge(dir: &str, old_time: time::SystemTime, now: time::SystemTime)
-> Result<(), io::Error> {
let readdir = fs::read_dir(dir)?;
for ent in readdir {
let ent = match ent {
Err(err) => {
error!("Purge: Readdir error: {}", err);
continue;
},
Ok(ent) => ent,
};
if let Err(err) = do_purge_file(&ent, old_time, now) {
error!("Purge: {}: {}", ent.file_name().to_string_lossy(), err);
continue;
}
}
Ok(())
}
pub fn purge(dir: &str, expiration: time::Duration) {
let now = time::SystemTime::now();
let old_time = match now.checked_sub(expiration) {
None => {
error!("Purge failed: now.checked_sub(old) returned None.");
return;
},
Some(t) => t,
};
if let Err(err) = do_purge(dir, old_time, now) {
error!("Purge failed: {}", err);
}
}