//! File manifests. //! //! This crate defines the [`ManifestEntry`] struct to represent an //! entry in a file manifest. The entry contains data about each file. //! A manifest can be produced of some data, and later, a new manifest //! can be produced and compared with the original. If the manifests //! have changed, the data has changed. If they haven't changed, the //! data has probably not changed. //! //! Such manifests can be used, for example, to verify that data that //! has been restored from a backup is the same as what was backed up. //! //! This crate uses Linux metadata of files. //! //! ~~~ //! let m = std::fs::metadata(".").unwrap(); //! let e = summain::ManifestEntry(m); //! println!("{}", serde_yaml::to_string(e).unwrap()); //! ~~~ //! //! The output is something like: //! //! ~~~yaml //! path: "." //! atime: 1606565868 //! atime_nsec: 824368155 //! mode: drwxrwxr-x //! mtime: 1606565867 //! mtime_nsec: 500355545 //! nlink: 6 //! size: ~ //! ~~~ use serde::Serialize; use std::fs::Metadata; use std::os::linux::fs::MetadataExt; use std::path::{Path, PathBuf}; /// An entry in a file manifest. #[derive(Serialize, Debug)] pub struct ManifestEntry { path: PathBuf, atime: i64, atime_nsec: i64, #[serde(with = "mode")] mode: u32, mtime: i64, mtime_nsec: i64, nlink: u64, size: Option, } impl ManifestEntry { /// Create a new manifest entry. /// /// The pathname of the file and the metadata are passed in by the /// caller. This function doesn't query the system for it. /// /// The structure can be serialized using serde. pub fn new(path: &Path, m: Metadata) -> Self { Self { path: path.to_path_buf(), atime: m.st_atime(), atime_nsec: m.st_atime_nsec(), mode: m.st_mode(), mtime: m.st_mtime(), mtime_nsec: m.st_mtime_nsec(), nlink: m.st_nlink(), size: if m.is_dir() { None } else { Some(m.st_size()) }, } } } mod mode { use serde::{self, Serializer}; pub fn serialize(mode: &u32, serializer: S) -> Result where S: Serializer, { let s = unix_mode::to_string(*mode); serializer.serialize_str(&s) } }