From bb19af73028f254259e14d1c3d41aa9cd97bf712 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Fri, 8 Nov 2019 13:13:39 +0100 Subject: [PATCH] src/client/backup_reader.rs: factor out download_blob() helper --- src/bin/proxmox-backup-client.rs | 42 ++---------------------- src/client/backup_reader.rs | 55 +++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 41 deletions(-) diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index f8bf65748..ee65dfd74 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -8,7 +8,7 @@ use chrono::{Local, Utc, TimeZone}; use std::path::{Path, PathBuf}; use std::collections::{HashSet, HashMap}; use std::ffi::OsStr; -use std::io::{Read, Write, Seek, SeekFrom}; +use std::io::{Write, Seek, SeekFrom}; use std::os::unix::fs::OpenOptionsExt; use proxmox::tools::fs::{file_get_contents, file_get_json, file_set_contents, image_size}; @@ -152,33 +152,6 @@ fn complete_repository(_arg: &str, _param: &HashMap) -> Vec Result<([u8; 32], u64), Error> { - - file.seek(SeekFrom::Start(0))?; - - let mut hasher = openssl::sha::Sha256::new(); - let mut buffer = proxmox::tools::vec::undefined(256*1024); - let mut size: u64 = 0; - - loop { - let count = match file.read(&mut buffer) { - Ok(count) => count, - Err(ref err) if err.kind() == std::io::ErrorKind::Interrupted => { continue; } - Err(err) => return Err(err.into()), - }; - if count == 0 { - break; - } - size += count as u64; - hasher.update(&buffer[..count]); - } - - let csum = hasher.finish(); - - Ok((csum, size)) -} - - async fn backup_directory>( client: &BackupWriter, dir_path: P, @@ -1020,12 +993,6 @@ async fn restore_do(param: Value) -> Result { true, ).await?; - let tmpfile = std::fs::OpenOptions::new() - .write(true) - .read(true) - .custom_flags(libc::O_TMPFILE) - .open("/tmp")?; - let manifest = client.download_manifest().await?; if server_archive_name == MANIFEST_BLOB_NAME { @@ -1040,13 +1007,8 @@ async fn restore_do(param: Value) -> Result { } } else if server_archive_name.ends_with(".blob") { - let mut tmpfile = client.download(&server_archive_name, tmpfile).await?; - let (csum, size) = compute_file_csum(&mut tmpfile)?; - manifest.verify_file(&server_archive_name, &csum, size)?; - - tmpfile.seek(SeekFrom::Start(0))?; - let mut reader = DataBlobReader::new(tmpfile, crypt_config)?; + let mut reader = client.download_blob(&manifest, &server_archive_name).await?; if let Some(target) = target { let mut writer = std::fs::OpenOptions::new() diff --git a/src/client/backup_reader.rs b/src/client/backup_reader.rs index 1eff6459e..2c24ed099 100644 --- a/src/client/backup_reader.rs +++ b/src/client/backup_reader.rs @@ -1,5 +1,6 @@ use failure::*; -use std::io::Write; +use std::io::{Read, Write, Seek, SeekFrom}; +use std::fs::File; use std::sync::Arc; use std::os::unix::fs::OpenOptionsExt; @@ -135,6 +136,32 @@ impl BackupReader { BackupManifest::try_from(json) } + /// Download a .blob file + /// + /// This creates a temorary file in /tmp (using O_TMPFILE). The data is verified using + /// the provided manifest. + pub async fn download_blob( + &self, + manifest: &BackupManifest, + name: &str, + ) -> Result, Error> { + + let tmpfile = std::fs::OpenOptions::new() + .write(true) + .read(true) + .custom_flags(libc::O_TMPFILE) + .open("/tmp")?; + + let mut tmpfile = self.download(name, tmpfile).await?; + + let (csum, size) = compute_file_csum(&mut tmpfile)?; + manifest.verify_file(name, &csum, size)?; + + tmpfile.seek(SeekFrom::Start(0))?; + + DataBlobReader::new(tmpfile, self.crypt_config.clone()) + } + /// Download dynamic index file /// /// This creates a temorary file in /tmp (using O_TMPFILE). The index is verified using @@ -191,3 +218,29 @@ impl BackupReader { Ok(index) } } + +fn compute_file_csum(file: &mut File) -> Result<([u8; 32], u64), Error> { + + file.seek(SeekFrom::Start(0))?; + + let mut hasher = openssl::sha::Sha256::new(); + let mut buffer = proxmox::tools::vec::undefined(256*1024); + let mut size: u64 = 0; + + loop { + let count = match file.read(&mut buffer) { + Ok(count) => count, + Err(ref err) if err.kind() == std::io::ErrorKind::Interrupted => { continue; } + Err(err) => return Err(err.into()), + }; + if count == 0 { + break; + } + size += count as u64; + hasher.update(&buffer[..count]); + } + + let csum = hasher.finish(); + + Ok((csum, size)) +}