Newer
Older
use crate::{
aead::encrypt_file_buffered, errors::CvfsErrors, errors::CvfsResult, secure_file::ActiveFile,
};
Stefan Schindler
committed
use multi_key_manager::{file::File, LiveKeyMaterial, LiveKeys, MutableNonce, OpeningNonce};
use ring::aead::{BoundKey, SealingKey, UnboundKey};
use std::{cell::RefCell, collections::HashMap, fmt::Debug, io::Write, rc::Rc};
impl Metadata {
/// creates a new empty index
pub fn empty() -> Self {
Self {
files: HashMap::new(),
}
pub fn restore_from_slice(input: &[u8]) -> CvfsResult<Self> {
let files = rmp_serde::from_slice(input)?;
Ok(Self { files })
Stefan Schindler
committed
pub(crate) fn store_to_disk(
&mut self,
mut output: File,
key_material: &mut LiveKeys,
) -> CvfsResult<()> {
// flush all the open files
for active in self
.files
.values_mut()
.filter(|element| element.active.is_some())
{
let algorithm = &ring::aead::CHACHA20_POLY1305;
let unbound = UnboundKey::new(
algorithm,
key_material.unsafe_insecure_borrow_i_know_what_i_am_doing(),
)?;
let shared_nonce = Rc::new(RefCell::new(active.nonce));
{
let nonce = MutableNonce::new(Rc::clone(&shared_nonce));
let mut key = SealingKey::new(unbound, nonce);
active
.active
.as_mut()
.expect("already filtered")
.try_flush(&mut key)?;
}
active.nonce = *shared_nonce.borrow();
}
// flush the index
let buf = rmp_serde::to_vec_named(&self.files)?;
//println!("Metadata serialised buffer len: {}", buf.len());
Stefan Schindler
committed
assert!(buf.len() > 0, "unable to serialise files");
let mut key = key_material.get_sealing_master_key();
encrypt_file_buffered(&mut output, &buf, &mut key)?;
Stefan Schindler
committed
output.flush()?;
println!("Metadata::store_to_disk flush ok");
Ok(())
}
pub fn find_active_file(&mut self, id: &FileTag) -> CvfsResult<&mut ActiveFile> {
.filter_map(|element| match &mut element.active {
Some(active) if active.id == *id => Some(active),
_ => None,
.ok_or_else(|| CvfsErrors::FileHandlerNotFound(id.clone()))
Stefan Schindler
committed
impl Debug for Metadata {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Metadata")
.field("files", &format_args!("{:#?}", &self.files))
//f.debug_list()
// .entries(self.files.entries())
.finish()
}
}
/// Information stored per file, except the path in the virtual file sytem
#[derive(Serialize, Deserialize)]
/// this exists if the file is already open
#[serde(skip)]
pub(crate) active: Option<ActiveFile>,
Stefan Schindler
committed
/// Don't store the full path so the archive stays protable
pub(crate) real_block_name: String,
/// keep this as private as possible
nonce: u128,
Stefan Schindler
committed
pub fn new(real_block_name: String) -> Self {
Stefan Schindler
committed
real_block_name,
pub fn get_opening_nonce(&self) -> OpeningNonce {
OpeningNonce::new(self.nonce.clone())
}
}
impl core::fmt::Debug for FileInfo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("FileInfo")
Stefan Schindler
committed
.field("active", &self.active)
"/{}{}",
Stefan Schindler
committed
crate::BLOCK_PATH,
self.real_block_name //self.real_path.file_name().unwrap_or_default()
Stefan Schindler
committed
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct FileTag(pub(crate) u64);
impl FileTag {
pub fn next(file_tag_counter: &mut u64) -> Self {
//FileTag(file_tag_counter.fetch_add(1, Ordering::SeqCst))
let id = file_tag_counter.clone();
*file_tag_counter += 1;
FileTag(id)
}
}
/*
#[cfg(test)]
mod tests {
use super::*;