Skip to content

Commit

Permalink
Check fingerprints
Browse files Browse the repository at this point in the history
  • Loading branch information
breard-r committed Nov 20, 2024
1 parent fbda5af commit 4c5d56a
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 56 deletions.
3 changes: 3 additions & 0 deletions locale/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ view_main_open_dir = Open a directory
view_main_open_receipt = Open a notice of receipt
view_main_calc_fingerprints = Checksum calculation
view_main_check_fingerprints = Data integrity check
view_main_check_result_title = Data integrity check result
view_main_check_result_ok_text = Data integrity check passed.
view_main_check_result_err_text = Data integrity check failed.
cpn_file_list_delete = Reset
Expand Down
3 changes: 3 additions & 0 deletions locale/fr-BE.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ view_main_open_dir = Ouvrir un dossier
view_main_open_receipt = Ouvrir un AR
view_main_calc_fingerprints = Calculer les empreintes
view_main_check_fingerprints = Vérifier les empreintes
view_main_check_result_title = Vérification des empreintes
view_main_check_result_ok_text = Les empreintes correspondent.
view_main_check_result_err_text = Échec de la vérification des empreintes.
cpn_file_list_delete = Réinitialiser
Expand Down
3 changes: 3 additions & 0 deletions locale/fr-FR.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ view_main_open_dir = Ouvrir un dossier
view_main_open_receipt = Ouvrir un AR
view_main_calc_fingerprints = Calculer les empreintes
view_main_check_fingerprints = Vérifier les empreintes
view_main_check_result_title = Vérification des empreintes
view_main_check_result_ok_text = Les empreintes correspondent.
view_main_check_result_err_text = Échec de la vérification des empreintes.
cpn_file_list_delete = Réinitialiser
Expand Down
133 changes: 133 additions & 0 deletions src/check.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use crate::files::HashedFile;
use dioxus_logger::tracing::warn;
use std::collections::HashSet;
use std::fmt;
use std::path::PathBuf;

#[derive(Debug, Clone, Copy)]
pub enum CheckType {
ContentFile,
Receipt,
}

#[derive(Debug, Clone, Eq, Hash, PartialEq)]
pub enum CheckResultError {
ContentFileParseError,
ContentFileMissingFile(PathBuf),
ContentFileNonMatchingFile(PathBuf),
ReceiptMissingFile(PathBuf),
ReceiptNonMatchingFile(PathBuf),
}

impl fmt::Display for CheckResultError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let ctn_file_fmt = match &self {
Self::ContentFileParseError => "content file: parse error".to_string(),
Self::ContentFileMissingFile(p) => {
format!("content file: missing file: {}", p.display())
}
Self::ContentFileNonMatchingFile(p) => {
format!("content file: non matching file: {}", p.display())
}
Self::ReceiptMissingFile(p) => format!("receipt: missing file: {}", p.display()),
Self::ReceiptNonMatchingFile(p) => {
format!("receipt: non matching file: {}", p.display())
}
};
write!(f, "{ctn_file_fmt}")
}
}

#[derive(Debug, Clone)]
pub enum CheckResult {
Error(Vec<CheckResultError>),
Ok,
None,
}

impl CheckResult {
pub fn is_err(&self) -> bool {
matches!(self, Self::Error(_))
}

pub fn is_ok(&self) -> bool {
matches!(self, Self::Ok)
}
}

pub fn check(
calculated_set: &Vec<HashedFile>,
reference_set: &Vec<HashedFile>,
t: CheckType,
) -> CheckResult {
let mut errors = HashSet::new();

for ref_file in reference_set {
// Get the canonical absolute path of the reference file.
match ref_file.get_absolute_path() {
Ok(ref_file_abs_path) => {
// We have the canonical absolute path of the reference file.
// Now, let's check if we can find it in the calculated set.
match get_calc_file(calculated_set, ref_file_abs_path) {
Ok(calc_file) => {
if ref_file.get_hash() != calc_file.get_hash() {
// The hashes from both files does not match.
add_non_matching_file(&mut errors, ref_file, t);
}
}
Err(_) => {
// No matching file found in the calculated set.
add_missing_file(&mut errors, ref_file, t);
}
};
}
Err(_) => {
// Unable to get the canonical path: the file does not exists on disk.
add_missing_file(&mut errors, ref_file, t);
}
};
}

// Return the result
if errors.is_empty() {
CheckResult::Ok
} else {
CheckResult::Error(errors.into_iter().collect())
}
}

fn get_calc_file(
calculated_set: &Vec<HashedFile>,
ref_file_abs_path: PathBuf,
) -> Result<&HashedFile, ()> {
for calc_file in calculated_set {
if let Ok(calc_file_abs_path) = calc_file.get_absolute_path() {
if calc_file_abs_path == ref_file_abs_path {
return Ok(calc_file);
}
}
}
Err(())
}

#[inline]
fn add_missing_file(errors: &mut HashSet<CheckResultError>, file: &HashedFile, t: CheckType) {
let path = file.get_relative_path().to_path_buf();
let e = match t {
CheckType::ContentFile => CheckResultError::ContentFileMissingFile(path),
CheckType::Receipt => CheckResultError::ReceiptMissingFile(path),
};
warn!("{e}");
errors.insert(e);
}

#[inline]
fn add_non_matching_file(errors: &mut HashSet<CheckResultError>, file: &HashedFile, t: CheckType) {
let path = file.get_relative_path().to_path_buf();
let e = match t {
CheckType::ContentFile => CheckResultError::ContentFileNonMatchingFile(path),
CheckType::Receipt => CheckResultError::ReceiptNonMatchingFile(path),
};
warn!("{e}");
errors.insert(e);
}
81 changes: 60 additions & 21 deletions src/files.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::check::{CheckResult, CheckResultError};
use crate::config::Config;
use crate::content_file::ContentFileFormat;
use crate::events::ExternalEventSender;
Expand Down Expand Up @@ -103,8 +104,10 @@ macro_rules! common_lst_impl {
self.base_dir.as_path()
}

pub fn get_files(&self) -> Vec<$file_type> {
self.files.iter().map(|(_, v)| v.clone()).collect()
pub fn get_content_file_absolute_path(&self, config: &Config) -> io::Result<PathBuf> {
let mut path = self.base_dir.clone().canonicalize()?;
path.push(config.get_content_file_name());
Ok(path)
}
}
};
Expand All @@ -122,12 +125,6 @@ pub struct NonHashedFileList {
common_lst_impl!(NonHashedFileList, NonHashedFile);

impl NonHashedFileList {
fn get_content_file_absolute_path(&self, config: &Config) -> io::Result<PathBuf> {
let mut path = self.base_dir.clone().canonicalize()?;
path.push(config.get_content_file_name());
Ok(path)
}

pub fn len(&self) -> usize {
self.files.len()
}
Expand All @@ -136,6 +133,13 @@ impl NonHashedFileList {
self.files.values().fold(0, |acc, f| acc + f.size)
}

pub fn content_file_exists(&self, config: &Config) -> bool {
if let Ok(ctn_file_path) = self.get_content_file_absolute_path(config) {
return ctn_file_path.is_file();
}
false
}

pub async fn from_dir<P: AsRef<Path>>(
dir_path: P,
include_hidden_files: bool,
Expand Down Expand Up @@ -257,6 +261,7 @@ impl NonHashedFileList {
files,
empty_files: self.empty_files.clone(),
duplicated_files,
result: CheckResult::None,
};
hashed_lst
.write_content_file_opt(ctn_file_absolute_path.as_path(), config.content_file_format)?;
Expand All @@ -274,6 +279,7 @@ pub struct HashedFileList {
files: HashMap<FileId, HashedFile>,
empty_files: HashSet<FileId>,
duplicated_files: HashMap<String, HashSet<FileId>>,
result: CheckResult,
}

common_lst_impl!(HashedFileList, HashedFile);
Expand All @@ -286,17 +292,54 @@ impl HashedFileList {
files: HashMap::new(),
empty_files: HashSet::new(),
duplicated_files: HashMap::new(),
result: CheckResult::None,
}
}

pub fn get_files(&self, base_dir: &Path) -> Vec<HashedFile> {
self.files
.values()
.map(|v| {
let mut f = v.clone();
f.base_dir = base_dir.to_path_buf();
f
})
.collect()
}

pub fn get_files_no_base_dir(&self) -> Vec<HashedFile> {
self.get_files(PathBuf::new().as_path())
}

pub fn insert_file(&mut self, file: HashedFile) {
self.files.insert(file.get_id(), file);
}

pub fn set_result_ok(&mut self) {
self.result = CheckResult::Ok;
}

pub fn push_result_error(&mut self, error: CheckResultError) {
match &self.result {
CheckResult::Error(v) => {
let mut v = v.clone();
v.push(error);
self.result = CheckResult::Error(v);
}
_ => {
self.result = CheckResult::Error(vec![error]);
}
}
}

pub fn is_empty(&self) -> bool {
self.files.is_empty()
}

pub fn get_result(&self) -> CheckResult {
self.result.clone()
}

pub fn get_main_hashing_function(&self) -> HashFunc {
let mut occurrences = HashMap::with_capacity(self.files.len());
for file in self.files.values() {
Expand Down Expand Up @@ -345,23 +388,11 @@ macro_rules! common_file_impl {
)
}

pub fn get_base_dir(&self) -> &Path {
self.base_dir.as_path()
}

pub fn get_relative_path(&self) -> &Path {
self.relative_path.as_path()
}

pub fn get_absolute_path(&self) -> io::Result<PathBuf> {
let mut path = self.base_dir.clone();
path.push(self.relative_path.clone());
path.canonicalize()
}

pub fn is_empty(&self) -> bool {
self.size == 0
}
}
};
}
Expand All @@ -378,6 +409,10 @@ pub struct NonHashedFile {
common_file_impl!(NonHashedFile);

impl NonHashedFile {
pub fn is_empty(&self) -> bool {
self.size == 0
}

pub fn new<P: AsRef<Path>>(base_dir: P, path: P) -> io::Result<Self> {
let base_dir = base_dir.as_ref();
let path = path.as_ref();
Expand Down Expand Up @@ -406,7 +441,7 @@ impl NonHashedFile {
}
}

#[derive(Clone, Debug)]
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct HashedFile {
base_dir: PathBuf,
relative_path: PathBuf,
Expand Down Expand Up @@ -443,6 +478,10 @@ impl HashedFile {
pub fn get_hash_func(&self) -> HashFunc {
self.hash_func
}

pub fn get_relative_path(&self) -> &Path {
self.relative_path.as_path()
}
}

#[inline]
Expand Down
1 change: 1 addition & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod analyse_hash;
mod app;
mod assets;
mod check;
mod components;
mod config;
mod content_file;
Expand Down
4 changes: 2 additions & 2 deletions src/receipt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ impl Receipt {
})
}

pub fn get_files(&self) -> Vec<HashedFile> {
self.files.get_files()
pub fn get_files(&self, base_dir: &Path) -> Vec<HashedFile> {
self.files.get_files(base_dir)
}

pub fn get_main_hashing_function(&self) -> HashFunc {
Expand Down
2 changes: 1 addition & 1 deletion src/serializers/ctn_file_cksum_bsd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fs::File;
use std::io::{self, Write};

pub fn ctn_file_cksum_bsd(ctn_file: &mut File, hashed_list: &HashedFileList) -> io::Result<()> {
for file in hashed_list.get_files() {
for file in hashed_list.get_files_no_base_dir() {
let line = format_line(&file);
ctn_file.write_all(line.as_bytes())?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/serializers/ctn_file_cksum_gnu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::fs::File;
use std::io::{self, Write};

pub fn ctn_file_cksum_gnu(ctn_file: &mut File, hashed_list: &HashedFileList) -> io::Result<()> {
for file in hashed_list.get_files() {
for file in hashed_list.get_files_no_base_dir() {
let line = format_line(&file);
ctn_file.write_all(line.as_bytes())?;
}
Expand Down
2 changes: 1 addition & 1 deletion src/serializers/ctn_file_cnil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn ctn_file_cnil(ctn_file: &mut File, hashed_list: &HashedFileList) -> io::R
"Taille (octets)",
hashed_list.get_main_hashing_function()
);
for file in hashed_list.get_files() {
for file in hashed_list.get_files_no_base_dir() {
write_line!(
ctn_file,
file.get_relative_path().display(),
Expand Down
Loading

0 comments on commit 4c5d56a

Please sign in to comment.