summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs29
1 files changed, 29 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
index ccd652f..9f46f54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,10 +32,15 @@
//! ~~~
use serde::Serialize;
+use sha2::{Digest, Sha256};
use std::fs::symlink_metadata;
+use std::fs::File;
+use std::io::{BufReader, Read};
use std::os::linux::fs::MetadataExt;
use std::path::{Path, PathBuf};
+const BUF_SIZE: usize = 1024 * 1024;
+
/// An entry in a file manifest.
#[derive(Serialize, Debug)]
pub struct ManifestEntry {
@@ -48,6 +53,7 @@ pub struct ManifestEntry {
mtime_nsec: i64,
nlink: u64,
size: Option<u64>,
+ sha256: Option<String>,
}
impl ManifestEntry {
@@ -59,6 +65,11 @@ impl ManifestEntry {
/// The structure can be serialized using serde.
pub fn new(path: &Path) -> std::io::Result<Self> {
let m = symlink_metadata(path)?;
+ let hash = if m.is_file() {
+ Some(file_checksum(path)?)
+ } else {
+ None
+ };
Ok(Self {
path: path.to_path_buf(),
atime: m.st_atime(),
@@ -68,10 +79,28 @@ impl ManifestEntry {
mtime_nsec: m.st_mtime_nsec(),
nlink: m.st_nlink(),
size: if m.is_dir() { None } else { Some(m.st_size()) },
+ sha256: hash,
})
}
}
+fn file_checksum(path: &Path) -> std::io::Result<String> {
+ let mut hasher = Sha256::new();
+
+ let file = File::open(path)?;
+ let mut reader = BufReader::new(file);
+ let mut buf = vec![0; BUF_SIZE];
+ loop {
+ let n = reader.read(&mut buf)?;
+ if n == 0 {
+ break;
+ }
+ hasher.update(&buf[..n]);
+ }
+ let hash = hasher.finalize();
+ Ok(format!("{:x}", hash))
+}
+
mod mode {
use serde::{self, Serializer};