summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2020-11-28 15:04:38 +0000
committerLars Wirzenius <liw@liw.fi>2020-11-28 15:04:38 +0000
commitd153808d1b7dd3821051c2fc226b401063e7f144 (patch)
tree4e29ec45ff2c7f6e92e38d7be6492ff6bb3391a6
parent59332fdce73badaf665103291a6ee65e52674f25 (diff)
parent074ae1b24cf721ed3d86427795b34a4aefa1290c (diff)
downloadsummain-rs-d153808d1b7dd3821051c2fc226b401063e7f144.tar.gz
Merge branch 'checksum' into 'main'
Checksum See merge request larswirzenius/summain!4
-rw-r--r--Cargo.toml6
-rw-r--r--src/bin/summain.rs4
-rw-r--r--src/lib.rs36
-rw-r--r--subplot/summain.py4
-rw-r--r--summain.md5
5 files changed, 47 insertions, 8 deletions
diff --git a/Cargo.toml b/Cargo.toml
index c634c79..73924e3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,9 +1,9 @@
[package]
name = "summain"
-version = "0.1.0"
+version = "0.2.0"
description = "File manifests"
readme = "README.md"
-license = "GPL-3-or-latergbc"
+license = "GPL-3.0-or-later"
authors = ["Lars Wirzenius <liw@liw.fi>"]
edition = "2018"
@@ -11,7 +11,9 @@ edition = "2018"
[dependencies]
anyhow = "1"
+digest = "0.9"
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8"
+sha2 = "0.9"
structopt = "0.3"
unix_mode = "0.1"
diff --git a/src/bin/summain.rs b/src/bin/summain.rs
index 056bc8b..0abe2f5 100644
--- a/src/bin/summain.rs
+++ b/src/bin/summain.rs
@@ -1,5 +1,4 @@
use anyhow::Context;
-use std::fs::symlink_metadata;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use summain::ManifestEntry;
@@ -20,8 +19,7 @@ struct Opt {
}
fn report(pathname: &Path) -> anyhow::Result<()> {
- let m = symlink_metadata(pathname)?;
- let e = ManifestEntry::new(pathname, m);
+ let e = ManifestEntry::new(pathname)?;
println!("{}", serde_yaml::to_string(&e)?);
Ok(())
}
diff --git a/src/lib.rs b/src/lib.rs
index eacce62..9f46f54 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -32,10 +32,15 @@
//! ~~~
use serde::Serialize;
-use std::fs::Metadata;
+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 {
@@ -57,8 +63,14 @@ impl ManifestEntry {
/// 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 {
+ 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(),
atime_nsec: m.st_atime_nsec(),
@@ -67,8 +79,26 @@ 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 {
diff --git a/subplot/summain.py b/subplot/summain.py
index 3ea6188..98eecf2 100644
--- a/subplot/summain.py
+++ b/subplot/summain.py
@@ -1,3 +1,4 @@
+import logging
import os
@@ -33,4 +34,7 @@ def output_matches_file(ctx, filename=None):
actual = runcmd_get_stdout(ctx)
expected = get_file(filename).decode("UTF-8")
+ logging.debug("output_matches:")
+ logging.debug(f" actual: {actual!r}")
+ logging.debug(f" expect: {expected!r}")
assert_eq(actual, expected)
diff --git a/summain.md b/summain.md
index 7c2c5fa..e6a4d15 100644
--- a/summain.md
+++ b/summain.md
@@ -87,6 +87,7 @@ mtime: 456
mtime_nsec: 0
nlink: 2
size: ~
+sha256: ~
```
## Writeable file
@@ -112,6 +113,7 @@ mtime: 22
mtime_nsec: 0
nlink: 1
size: 0
+sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```
## Read-only file
@@ -136,6 +138,7 @@ mtime: 44
mtime_nsec: 0
nlink: 1
size: 0
+sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```
## Two files sorted
@@ -163,6 +166,7 @@ mtime: 44
mtime_nsec: 0
nlink: 1
size: 0
+sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
---
path: bbb
atime: 33
@@ -172,6 +176,7 @@ mtime: 44
mtime_nsec: 0
nlink: 1
size: 0
+sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
```
---