89 lines
2.8 KiB
Rust
89 lines
2.8 KiB
Rust
use std::{
|
|
fs,
|
|
time::{Duration, SystemTime, UNIX_EPOCH},
|
|
};
|
|
|
|
use std::os::unix::fs::{MetadataExt, PermissionsExt};
|
|
|
|
/// Owned, `Clone`-able snapshot of the file attributes that musicfs needs to
|
|
/// serve FUSE `getattr` and to compute the per-item identity hash.
|
|
///
|
|
/// Decoupled from `std::fs::Metadata` so that non-disk origins (e.g. a future
|
|
/// `NetworkOrigin` reading a server manifest) can construct equivalent
|
|
/// attributes without a real inode on disk. The on-disk origin builds this
|
|
/// via `From<&fs::Metadata>`; other origins build it from their own metadata
|
|
/// source using the same field types.
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct FileAttrs {
|
|
pub size: u64,
|
|
pub blocks: u64,
|
|
pub atime: SystemTime,
|
|
pub mtime: SystemTime,
|
|
pub ctime: SystemTime,
|
|
pub crtime: SystemTime,
|
|
pub perm: u16,
|
|
pub nlink: u32,
|
|
pub uid: u32,
|
|
pub gid: u32,
|
|
pub rdev: u32,
|
|
pub blksize: u32,
|
|
}
|
|
|
|
impl From<&fs::Metadata> for FileAttrs {
|
|
fn from(metadata: &fs::Metadata) -> Self {
|
|
return FileAttrs {
|
|
size: metadata.size(),
|
|
blocks: metadata.blocks(),
|
|
atime: metadata.accessed().unwrap_or(UNIX_EPOCH),
|
|
mtime: metadata.modified().unwrap_or(UNIX_EPOCH),
|
|
ctime: UNIX_EPOCH + Duration::from_secs(metadata.ctime() as u64),
|
|
crtime: metadata.created().unwrap_or(UNIX_EPOCH),
|
|
perm: metadata.permissions().mode() as u16,
|
|
nlink: metadata.nlink() as u32,
|
|
uid: metadata.uid(),
|
|
gid: metadata.gid(),
|
|
rdev: metadata.rdev() as u32,
|
|
blksize: metadata.blksize() as u32,
|
|
};
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn file_attrs_from_metadata_copies_size_and_block_fields() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let metadata = fs::metadata(tmp.path()).unwrap();
|
|
|
|
let attrs = FileAttrs::from(&metadata);
|
|
|
|
assert_eq!(attrs.size, metadata.size());
|
|
assert_eq!(attrs.blocks, metadata.blocks());
|
|
assert_eq!(attrs.blksize, metadata.blksize() as u32);
|
|
}
|
|
|
|
#[test]
|
|
fn file_attrs_from_metadata_copies_unix_ownership() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let metadata = fs::metadata(tmp.path()).unwrap();
|
|
|
|
let attrs = FileAttrs::from(&metadata);
|
|
|
|
assert_eq!(attrs.uid, metadata.uid());
|
|
assert_eq!(attrs.gid, metadata.gid());
|
|
assert_eq!(attrs.perm, metadata.permissions().mode() as u16);
|
|
}
|
|
|
|
#[test]
|
|
fn file_attrs_from_metadata_preserves_mtime() {
|
|
let tmp = tempfile::tempdir().unwrap();
|
|
let metadata = fs::metadata(tmp.path()).unwrap();
|
|
|
|
let attrs = FileAttrs::from(&metadata);
|
|
|
|
assert_eq!(attrs.mtime, metadata.modified().unwrap_or(UNIX_EPOCH));
|
|
}
|
|
}
|