-use anyhow::{bail, Error};
+use anyhow::{bail, format_err, Error};
use std::convert::TryInto;
use proxmox::tools::io::{ReadExt, WriteExt};
/// we always compute the correct one.
pub struct DataChunkBuilder<'a, 'b> {
config: Option<&'b CryptConfig>,
+ crypt_mode: CryptMode,
orig_data: &'a [u8],
digest_computed: bool,
digest: [u8; 32],
Self {
orig_data,
config: None,
+ crypt_mode: CryptMode::None,
digest_computed: false,
digest: [0u8; 32],
compress: true,
/// Set encryption Configuration
///
- /// If set, chunks are encrypted.
- pub fn crypt_config(mut self, value: &'b CryptConfig) -> Self {
+ /// If set, chunks are encrypted or signed
+ pub fn crypt_config(mut self, value: &'b CryptConfig, crypt_mode: CryptMode) -> Self {
if self.digest_computed {
panic!("unable to set crypt_config after compute_digest().");
}
- self.config = Some(value);
+ if crypt_mode == CryptMode::None {
+ self.config = None;
+ } else {
+ self.config = Some(value);
+ }
+
+ self.crypt_mode = crypt_mode;
self
}
self.compute_digest();
}
- let chunk = DataBlob::encode(
- self.orig_data,
- self.config,
- self.compress,
- )?;
+ let chunk = match self.crypt_mode {
+ CryptMode::None | CryptMode::Encrypt => {
+ DataBlob::encode(self.orig_data, self.config, self.compress)?
+ }
+ CryptMode::SignOnly => DataBlob::create_signed(
+ self.orig_data,
+ self.config
+ .ok_or_else(|| format_err!("cannot sign without crypt config"))?,
+ self.compress,
+ )?,
+ };
Ok((chunk, self.digest))
}
/// Create a chunk filled with zeroes
pub fn build_zero_chunk(
crypt_config: Option<&CryptConfig>,
+ crypt_mode: CryptMode,
chunk_size: usize,
compress: bool,
) -> Result<(DataBlob, [u8; 32]), Error> {
zero_bytes.resize(chunk_size, 0u8);
let mut chunk_builder = DataChunkBuilder::new(&zero_bytes).compress(compress);
if let Some(ref crypt_config) = crypt_config {
- chunk_builder = chunk_builder.crypt_config(crypt_config);
+ chunk_builder = chunk_builder.crypt_config(crypt_config, crypt_mode);
}
chunk_builder.build()
async fn backup_directory<P: AsRef<Path>>(
client: &BackupWriter,
+ crypt_mode: CryptMode,
previous_manifest: Option<Arc<BackupManifest>>,
dir_path: P,
archive_name: &str,
});
let stats = client
- .upload_stream(previous_manifest, archive_name, stream, "dynamic", None)
+ .upload_stream(crypt_mode, previous_manifest, archive_name, stream, "dynamic", None)
.await?;
Ok(stats)
async fn backup_image<P: AsRef<Path>>(
client: &BackupWriter,
+ crypt_mode: CryptMode,
previous_manifest: Option<Arc<BackupManifest>>,
image_path: P,
archive_name: &str,
let stream = FixedChunkStream::new(stream, chunk_size.unwrap_or(4*1024*1024));
let stats = client
- .upload_stream(previous_manifest, archive_name, stream, "fixed", Some(image_size))
+ .upload_stream(crypt_mode, previous_manifest, archive_name, stream, "fixed", Some(image_size))
.await?;
Ok(stats)
}
fn spawn_catalog_upload(
- client: Arc<BackupWriter>
+ client: Arc<BackupWriter>,
+ crypt_mode: CryptMode,
) -> Result<
(
Arc<Mutex<CatalogWriter<crate::tools::StdChannelWriter>>>,
tokio::spawn(async move {
let catalog_upload_result = client
- .upload_stream(None, CATALOG_NAME, catalog_chunk_stream, "dynamic", None)
+ .upload_stream(crypt_mode, None, CATALOG_NAME, catalog_chunk_stream, "dynamic", None)
.await;
if let Err(ref err) = catalog_upload_result {
BackupSpecificationType::PXAR => {
// start catalog upload on first use
if catalog.is_none() {
- let (cat, res) = spawn_catalog_upload(client.clone())?;
+ let (cat, res) = spawn_catalog_upload(client.clone(), crypt_mode)?;
catalog = Some(cat);
catalog_result_tx = Some(res);
}
catalog.lock().unwrap().start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
let stats = backup_directory(
&client,
+ crypt_mode,
previous_manifest.clone(),
&filename,
&target,
println!("Upload image '{}' to '{:?}' as {}", filename, repo, target);
let stats = backup_image(
&client,
+ crypt_mode,
previous_manifest.clone(),
&filename,
&target,
pub async fn upload_stream(
&self,
+ crypt_mode: CryptMode,
previous_manifest: Option<Arc<BackupManifest>>,
archive_name: &str,
stream: impl Stream<Item = Result<bytes::BytesMut, Error>>,
&prefix,
known_chunks.clone(),
self.crypt_config.clone(),
+ crypt_mode,
self.verbose,
)
.await?;
prefix: &str,
known_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
crypt_config: Option<Arc<CryptConfig>>,
+ crypt_mode: CryptMode,
verbose: bool,
) -> impl Future<Output = Result<(usize, usize, std::time::Duration, usize, [u8; 32]), Error>> {
.compress(true);
if let Some(ref crypt_config) = crypt_config {
- chunk_builder = chunk_builder.crypt_config(crypt_config);
+ chunk_builder = chunk_builder.crypt_config(crypt_config, crypt_mode);
}
let mut known_chunks = known_chunks.lock().unwrap();