mirror of https://github.com/dswd/zvault
Encrypted bundle info
This commit is contained in:
parent
014c456fd0
commit
883c4c1c24
|
@ -103,10 +103,6 @@ Recommended: Brotli/2-7
|
|||
- File attributes
|
||||
- xattrs https://crates.io/crates/xattr
|
||||
|
||||
### Formats
|
||||
- Bundles
|
||||
- Encrypted bundle header
|
||||
|
||||
### CLI functionality
|
||||
- list --tree
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ pub fn bundle_path(bundle: &BundleId, mut folder: PathBuf, mut count: usize) ->
|
|||
(folder, file.into())
|
||||
}
|
||||
|
||||
pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, StoredBundle>) -> Result<(Vec<StoredBundle>, Vec<StoredBundle>), BundleDbError> {
|
||||
pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, StoredBundle>, crypto: Arc<Mutex<Crypto>>) -> Result<(Vec<StoredBundle>, Vec<StoredBundle>), BundleDbError> {
|
||||
let mut paths = vec![path.as_ref().to_path_buf()];
|
||||
let mut bundle_paths = HashSet::new();
|
||||
while let Some(path) = paths.pop() {
|
||||
|
@ -91,7 +91,7 @@ pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, Sto
|
|||
let mut new = vec![];
|
||||
for path in bundle_paths {
|
||||
let bundle = StoredBundle {
|
||||
info: try!(BundleReader::load_info(&path)),
|
||||
info: try!(BundleReader::load_info(&path, crypto.clone())),
|
||||
path: path
|
||||
};
|
||||
let id = bundle.info.id.clone();
|
||||
|
@ -149,12 +149,12 @@ impl BundleDb {
|
|||
self.remote_bundles.insert(bundle.id(), bundle);
|
||||
}
|
||||
}
|
||||
let (new, gone) = try!(load_bundles(&self.local_bundles_path, &mut self.local_bundles));
|
||||
let (new, gone) = try!(load_bundles(&self.local_bundles_path, &mut self.local_bundles, self.crypto.clone()));
|
||||
if !new.is_empty() || !gone.is_empty() {
|
||||
let bundles: Vec<_> = self.local_bundles.values().cloned().collect();
|
||||
try!(StoredBundle::save_list_to(&bundles, &local_cache_path));
|
||||
}
|
||||
let (new, gone) = try!(load_bundles(&self.remote_path, &mut self.remote_bundles));
|
||||
let (new, gone) = try!(load_bundles(&self.remote_path, &mut self.remote_bundles, self.crypto.clone()));
|
||||
if !new.is_empty() || !gone.is_empty() {
|
||||
let bundles: Vec<_> = self.remote_bundles.values().cloned().collect();
|
||||
try!(StoredBundle::save_list_to(&bundles, &remote_cache_path));
|
||||
|
|
|
@ -71,6 +71,17 @@ serde_impl!(BundleMode(u8) {
|
|||
});
|
||||
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct BundleHeader {
|
||||
pub encryption: Option<Encryption>,
|
||||
pub info_size: usize
|
||||
}
|
||||
serde_impl!(BundleHeader(u8) {
|
||||
encryption: Option<Encryption> => 0,
|
||||
info_size: usize => 1
|
||||
});
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BundleInfo {
|
||||
pub id: BundleId,
|
||||
|
@ -87,7 +98,7 @@ serde_impl!(BundleInfo(u64?) {
|
|||
id: BundleId => 0,
|
||||
mode: BundleMode => 1,
|
||||
compression: Option<Compression> => 2,
|
||||
encryption: Option<Encryption> => 3,
|
||||
//encryption: already in the header
|
||||
hash_method: HashMethod => 4,
|
||||
raw_size: usize => 6,
|
||||
encoded_size: usize => 7,
|
||||
|
|
|
@ -84,7 +84,7 @@ impl BundleReader {
|
|||
self.info.id.clone()
|
||||
}
|
||||
|
||||
fn load_header<P: AsRef<Path>>(path: P) -> Result<(BundleInfo, u8, usize), BundleReaderError> {
|
||||
fn load_header<P: AsRef<Path>>(path: P, crypto: Arc<Mutex<Crypto>>) -> Result<(BundleInfo, u8, usize), BundleReaderError> {
|
||||
let path = path.as_ref();
|
||||
let mut file = BufReader::new(try!(File::open(path).context(path)));
|
||||
let mut header = [0u8; 8];
|
||||
|
@ -96,20 +96,28 @@ impl BundleReader {
|
|||
if version != HEADER_VERSION {
|
||||
return Err(BundleReaderError::UnsupportedVersion(path.to_path_buf(), version))
|
||||
}
|
||||
let header: BundleInfo = try!(msgpack::decode_from_stream(&mut file).context(path));
|
||||
debug!("Load bundle {}", header.id);
|
||||
let content_start = file.seek(SeekFrom::Current(0)).unwrap() as usize + header.chunk_info_size;
|
||||
Ok((header, version, content_start))
|
||||
let header: BundleHeader = try!(msgpack::decode_from_stream(&mut file).context(path));
|
||||
let mut info_data = Vec::with_capacity(header.info_size);
|
||||
info_data.resize(header.info_size, 0);
|
||||
try!(file.read_exact(&mut info_data).context(path));
|
||||
if let Some(ref encryption) = header.encryption {
|
||||
info_data = try!(crypto.lock().unwrap().decrypt(&encryption, &info_data).context(path));
|
||||
}
|
||||
let mut info: BundleInfo = try!(msgpack::decode(&info_data).context(path));
|
||||
info.encryption = header.encryption;
|
||||
debug!("Load bundle {}", info.id);
|
||||
let content_start = file.seek(SeekFrom::Current(0)).unwrap() as usize + info.chunk_info_size;
|
||||
Ok((info, version, content_start))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn load_info<P: AsRef<Path>>(path: P) -> Result<BundleInfo, BundleReaderError> {
|
||||
Self::load_header(path).map(|b| b.0)
|
||||
pub fn load_info<P: AsRef<Path>>(path: P, crypto: Arc<Mutex<Crypto>>) -> Result<BundleInfo, BundleReaderError> {
|
||||
Self::load_header(path, crypto).map(|b| b.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn load(path: PathBuf, crypto: Arc<Mutex<Crypto>>) -> Result<Self, BundleReaderError> {
|
||||
let (header, version, content_start) = try!(Self::load_header(&path));
|
||||
let (header, version, content_start) = try!(Self::load_header(&path, crypto.clone()));
|
||||
Ok(BundleReader::new(path, version, content_start, crypto, header))
|
||||
}
|
||||
|
||||
|
|
|
@ -105,21 +105,30 @@ impl BundleWriter {
|
|||
let mut file = BufWriter::new(try!(File::create(&path).context(&path as &Path)));
|
||||
try!(file.write_all(&HEADER_STRING).context(&path as &Path));
|
||||
try!(file.write_all(&[HEADER_VERSION]).context(&path as &Path));
|
||||
let header = BundleInfo {
|
||||
let info = BundleInfo {
|
||||
mode: self.mode,
|
||||
hash_method: self.hash_method,
|
||||
compression: self.compression,
|
||||
encryption: self.encryption,
|
||||
encryption: self.encryption.clone(),
|
||||
chunk_count: self.chunk_count,
|
||||
id: id.clone(),
|
||||
raw_size: self.raw_size,
|
||||
encoded_size: encoded_size,
|
||||
chunk_info_size: chunk_data.len()
|
||||
};
|
||||
let mut info_data = try!(msgpack::encode(&info).context(&path as &Path));
|
||||
if let Some(ref encryption) = self.encryption {
|
||||
info_data = try!(self.crypto.lock().unwrap().encrypt(&encryption, &info_data));
|
||||
}
|
||||
let header = BundleHeader {
|
||||
encryption: self.encryption,
|
||||
info_size: info_data.len()
|
||||
};
|
||||
try!(msgpack::encode_to_stream(&header, &mut file).context(&path as &Path));
|
||||
try!(file.write_all(&info_data).context(&path as &Path));
|
||||
try!(file.write_all(&chunk_data).context(&path as &Path));
|
||||
try!(file.write_all(&self.data).context(&path as &Path));
|
||||
Ok(StoredBundle { path: path, info: header })
|
||||
Ok(StoredBundle { path: path, info: info })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
Loading…
Reference in New Issue