src/bin/proxmox-backup-client.rs: implement catalog command
This commit is contained in:
		@ -389,6 +389,55 @@ fn forget_snapshots(
 | 
			
		||||
    Ok(result)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn dump_catalog(
 | 
			
		||||
    param: Value,
 | 
			
		||||
    _info: &ApiMethod,
 | 
			
		||||
    _rpcenv: &mut dyn RpcEnvironment,
 | 
			
		||||
) -> Result<Value, Error> {
 | 
			
		||||
 | 
			
		||||
    let repo = extract_repository_from_value(¶m)?;
 | 
			
		||||
 | 
			
		||||
    let path = tools::required_string_param(¶m, "snapshot")?;
 | 
			
		||||
    let snapshot = BackupDir::parse(path)?;
 | 
			
		||||
 | 
			
		||||
    let keyfile = param["keyfile"].as_str().map(|p| PathBuf::from(p));
 | 
			
		||||
 | 
			
		||||
    let crypt_config = match keyfile {
 | 
			
		||||
        None => None,
 | 
			
		||||
        Some(path) => {
 | 
			
		||||
            let (key, _) = load_and_decrtypt_key(&path, get_encryption_key_password)?;
 | 
			
		||||
            Some(Arc::new(CryptConfig::new(key)?))
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let client = HttpClient::new(repo.host(), repo.user())?;
 | 
			
		||||
 | 
			
		||||
    let client = client.start_backup_reader(
 | 
			
		||||
        repo.store(),
 | 
			
		||||
        &snapshot.group().backup_type(),
 | 
			
		||||
        &snapshot.group().backup_id(),
 | 
			
		||||
        snapshot.backup_time(), true).wait()?;
 | 
			
		||||
 | 
			
		||||
    let writer = Vec::with_capacity(1024*1024);
 | 
			
		||||
    let blob_data = client.download("catalog.blob", writer).wait()?;
 | 
			
		||||
    let blob = DataBlob::from_raw(blob_data)?;
 | 
			
		||||
    blob.verify_crc()?;
 | 
			
		||||
 | 
			
		||||
    let raw_data = match crypt_config {
 | 
			
		||||
        Some(ref crypt_config) => blob.decode(Some(crypt_config))?,
 | 
			
		||||
        None => blob.decode(None)?,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    let slice = &raw_data[..];
 | 
			
		||||
    let mut catalog_reader = pxar::catalog::SimpleCatalogReader::new(slice);
 | 
			
		||||
 | 
			
		||||
    catalog_reader.dump()?;
 | 
			
		||||
 | 
			
		||||
    record_repository(&repo);
 | 
			
		||||
 | 
			
		||||
    Ok(Value::Null)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn list_snapshot_files(
 | 
			
		||||
    param: Value,
 | 
			
		||||
    _info: &ApiMethod,
 | 
			
		||||
@ -616,8 +665,8 @@ fn create_backup(
 | 
			
		||||
            }
 | 
			
		||||
            BackupType::PXAR => {
 | 
			
		||||
                upload_catalog = true;
 | 
			
		||||
                catalog.lock().unwrap().start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
 | 
			
		||||
                println!("Upload directory '{}' to '{:?}' as {}", filename, repo, target);
 | 
			
		||||
                catalog.lock().unwrap().start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
 | 
			
		||||
                let stats = backup_directory(
 | 
			
		||||
                    &client,
 | 
			
		||||
                    &filename,
 | 
			
		||||
@ -1558,6 +1607,17 @@ We do not extraxt '.pxar' archives when writing to stdandard output.
 | 
			
		||||
        .completion_cb("repository", complete_repository)
 | 
			
		||||
        .completion_cb("snapshot", complete_backup_snapshot);
 | 
			
		||||
 | 
			
		||||
    let catalog_cmd_def = CliCommand::new(
 | 
			
		||||
        ApiMethod::new(
 | 
			
		||||
            dump_catalog,
 | 
			
		||||
            ObjectSchema::new("Dump catalog.")
 | 
			
		||||
                .required("snapshot", StringSchema::new("Snapshot path."))
 | 
			
		||||
                .optional("repository", REPO_URL_SCHEMA.clone())
 | 
			
		||||
        ))
 | 
			
		||||
        .arg_param(vec!["snapshot"])
 | 
			
		||||
        .completion_cb("repository", complete_repository)
 | 
			
		||||
        .completion_cb("snapshot", complete_backup_snapshot);
 | 
			
		||||
 | 
			
		||||
    let prune_cmd_def = CliCommand::new(
 | 
			
		||||
        ApiMethod::new(
 | 
			
		||||
            prune,
 | 
			
		||||
@ -1584,6 +1644,7 @@ We do not extraxt '.pxar' archives when writing to stdandard output.
 | 
			
		||||
        .insert("backup".to_owned(), backup_cmd_def.into())
 | 
			
		||||
        .insert("upload-log".to_owned(), upload_log_cmd_def.into())
 | 
			
		||||
        .insert("forget".to_owned(), forget_cmd_def.into())
 | 
			
		||||
        .insert("catalog".to_owned(), catalog_cmd_def.into())
 | 
			
		||||
        .insert("garbage-collect".to_owned(), garbage_collect_cmd_def.into())
 | 
			
		||||
        .insert("list".to_owned(), list_cmd_def.into())
 | 
			
		||||
        .insert("prune".to_owned(), prune_cmd_def.into())
 | 
			
		||||
 | 
			
		||||
@ -5,8 +5,7 @@
 | 
			
		||||
 | 
			
		||||
use failure::*;
 | 
			
		||||
 | 
			
		||||
use std::io::{Read, BufRead, Write, BufReader};
 | 
			
		||||
use std::fs::File;
 | 
			
		||||
use std::io::{Read, BufRead, Write};
 | 
			
		||||
use std::convert::TryFrom;
 | 
			
		||||
 | 
			
		||||
use std::ffi::{CStr, CString};
 | 
			
		||||
@ -139,18 +138,16 @@ impl BackupCatalogWriter for SimpleCatalog {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct SimpleCatalogReader {
 | 
			
		||||
    reader: BufReader<File>,
 | 
			
		||||
pub struct SimpleCatalogReader<R> {
 | 
			
		||||
    reader: R,
 | 
			
		||||
    dir_stack: Vec<CString>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl SimpleCatalogReader {
 | 
			
		||||
impl <R: Read + BufRead> SimpleCatalogReader<R> {
 | 
			
		||||
 | 
			
		||||
    pub fn open<P: AsRef<std::path::Path>>(path: P) -> Result<Self, Error> {
 | 
			
		||||
        let file = std::fs::File::open(path)?;
 | 
			
		||||
        let reader = BufReader::new(file);
 | 
			
		||||
    pub fn new(reader: R) -> Self {
 | 
			
		||||
        let dir_stack = Vec::new();
 | 
			
		||||
        Ok(Self { reader, dir_stack })
 | 
			
		||||
        Self { reader, dir_stack }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn read_filename(&mut self) ->  Result<std::ffi::CString, Error> {
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user