diff --git a/database/src/fs.rs b/database/src/fs.rs index 676144e..f5dc2f6 100644 --- a/database/src/fs.rs +++ b/database/src/fs.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{collections::HashMap, io::{BufRead, BufReader}}; use std::convert::TryFrom; use std::fs::{OpenOptions, File, create_dir_all, read_link, remove_file, rename, set_permissions, Permissions}; use std::io::Write; @@ -22,6 +22,8 @@ use tempfile::NamedTempFile; use openpgp::Cert; use openpgp_utils::POLICY; +use crate::updates::Epoch; + pub struct Filesystem { tmp_dir: PathBuf, @@ -401,6 +403,35 @@ impl Database for Filesystem { Ok(()) } + fn read_log_epoch(&self, epoch: Epoch) -> Result>> { + if epoch >= Epoch::current().expect("before end of time") { + Err(anyhow!("Epoch must be in the past to read"))?; + } + + let path = self.keys_dir_log.join(epoch.to_string()); + let file = match std::fs::File::open(&path) { + Ok(file) => file, + Err(_) => return Ok(None), + }; + let mut result: Vec = Vec::new(); + for (i, line) in BufReader::new(file).lines().enumerate() { + let line = line?; + let mut fields = line.split_whitespace(); + // timestamp field - ignore + fields.next() + .ok_or_else(|| anyhow!("Malformed line {:?}:{}: {:?}", path, i + 1, line))?; + // fingerprint field + let field = fields.next() + .ok_or_else(|| anyhow!("Malformed line {:?}:{}: {:?}", path, i + 1, line))?; + // parse only the prefix + let prefix = u32::from_str_radix(&field[0..8], 16) + .map_err(|_| anyhow!("Malformed fingerprint in line {:?}:{}", path, i + 1))?; + result.push(prefix); + } + result.sort(); + Ok(Some(result)) + } + fn move_tmp_to_full(&self, file: NamedTempFile, fpr: &Fingerprint) -> Result<()> { if self.dry_run { return Ok(()); diff --git a/database/src/lib.rs b/database/src/lib.rs index d1babb7..8df32d1 100644 --- a/database/src/lib.rs +++ b/database/src/lib.rs @@ -178,6 +178,8 @@ pub trait Database: Sync + Send { fn by_email(&self, email: &Email) -> Option; fn by_email_wkd(&self, email: &Email) -> Option>; + fn read_log_epoch(&self, epoch: Epoch) -> Result>>; + /// Complex operation that updates a Cert in the database. /// /// 1. Merge new Cert with old, full Cert