use crate::{Error, Result};
#[derive(Clone, Copy)]
pub(crate) struct FileIdentity {
len: u64,
#[cfg(unix)]
dev: u64,
#[cfg(unix)]
ino: u64,
}
impl FileIdentity {
pub(crate) fn from_metadata(metadata: &std::fs::Metadata) -> Self {
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
Self {
len: metadata.len(),
dev: metadata.dev(),
ino: metadata.ino(),
}
}
#[cfg(not(unix))]
{
Self {
len: metadata.len(),
}
}
}
}
#[cfg(unix)]
fn same_inode(expected: FileIdentity, current: FileIdentity) -> bool {
expected.dev == current.dev && expected.ino == current.ino
}
#[cfg(not(unix))]
fn same_inode(_expected: FileIdentity, _current: FileIdentity) -> bool {
true
}
pub(crate) fn validate_file_identity(
file: &std::fs::File,
expected: FileIdentity,
expected_len: u64,
changed_msg: &'static str,
) -> Result<()> {
let current_metadata = file.metadata().map_err(|source| Error::System {
operation: "metadata(revalidate)",
source,
})?;
let current = FileIdentity::from_metadata(¤t_metadata);
if current.len != expected_len || current.len != expected.len || !same_inode(expected, current) {
return Err(Error::System {
operation: "mmap(revalidate)",
source: std::io::Error::new(std::io::ErrorKind::InvalidData, changed_msg),
});
}
Ok(())
}