src/client/backup_reader.rs: factor out download_blob() helper
This commit is contained in:
parent
7205050059
commit
bb19af7302
@ -8,7 +8,7 @@ use chrono::{Local, Utc, TimeZone};
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::io::{Read, Write, Seek, SeekFrom};
|
use std::io::{Write, Seek, SeekFrom};
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
use proxmox::tools::fs::{file_get_contents, file_get_json, file_set_contents, image_size};
|
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<String, String>) -> Vec<Stri
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_file_csum(file: &mut std::fs::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))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async fn backup_directory<P: AsRef<Path>>(
|
async fn backup_directory<P: AsRef<Path>>(
|
||||||
client: &BackupWriter,
|
client: &BackupWriter,
|
||||||
dir_path: P,
|
dir_path: P,
|
||||||
@ -1020,12 +993,6 @@ async fn restore_do(param: Value) -> Result<Value, Error> {
|
|||||||
true,
|
true,
|
||||||
).await?;
|
).await?;
|
||||||
|
|
||||||
let tmpfile = std::fs::OpenOptions::new()
|
|
||||||
.write(true)
|
|
||||||
.read(true)
|
|
||||||
.custom_flags(libc::O_TMPFILE)
|
|
||||||
.open("/tmp")?;
|
|
||||||
|
|
||||||
let manifest = client.download_manifest().await?;
|
let manifest = client.download_manifest().await?;
|
||||||
|
|
||||||
if server_archive_name == MANIFEST_BLOB_NAME {
|
if server_archive_name == MANIFEST_BLOB_NAME {
|
||||||
@ -1040,13 +1007,8 @@ async fn restore_do(param: Value) -> Result<Value, Error> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else if server_archive_name.ends_with(".blob") {
|
} 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)?;
|
let mut reader = client.download_blob(&manifest, &server_archive_name).await?;
|
||||||
manifest.verify_file(&server_archive_name, &csum, size)?;
|
|
||||||
|
|
||||||
tmpfile.seek(SeekFrom::Start(0))?;
|
|
||||||
let mut reader = DataBlobReader::new(tmpfile, crypt_config)?;
|
|
||||||
|
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
let mut writer = std::fs::OpenOptions::new()
|
let mut writer = std::fs::OpenOptions::new()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use failure::*;
|
use failure::*;
|
||||||
use std::io::Write;
|
use std::io::{Read, Write, Seek, SeekFrom};
|
||||||
|
use std::fs::File;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::os::unix::fs::OpenOptionsExt;
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
|
||||||
@ -135,6 +136,32 @@ impl BackupReader {
|
|||||||
BackupManifest::try_from(json)
|
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<DataBlobReader<File>, 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
|
/// Download dynamic index file
|
||||||
///
|
///
|
||||||
/// This creates a temorary file in /tmp (using O_TMPFILE). The index is verified using
|
/// This creates a temorary file in /tmp (using O_TMPFILE). The index is verified using
|
||||||
@ -191,3 +218,29 @@ impl BackupReader {
|
|||||||
Ok(index)
|
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))
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user