src/client/backup_reader.rs: factor out download_blob() helper
This commit is contained in:
		@ -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))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user