From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 1206263CA0 for ; Thu, 27 Jan 2022 11:56:39 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6C81A2173C for ; Thu, 27 Jan 2022 11:56:08 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id CFD3B21585 for ; Thu, 27 Jan 2022 11:56:02 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id A204646CC7 for ; Thu, 27 Jan 2022 11:56:02 +0100 (CET) From: Dominik Csapak To: pve-devel@lists.proxmox.com Date: Thu, 27 Jan 2022 11:55:57 +0100 Message-Id: <20220127105601.2741602-5-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20220127105601.2741602-1-d.csapak@proxmox.com> References: <20220127105601.2741602-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.160 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Subject: [pve-devel] [PATCH proxmox-backup 4/5] file-restore: factor out 'list_files' X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 27 Jan 2022 10:56:39 -0000 we'll want to reuse that in a later patch Signed-off-by: Dominik Csapak --- proxmox-file-restore/src/main.rs | 153 +++++++++++++++++-------------- 1 file changed, 85 insertions(+), 68 deletions(-) diff --git a/proxmox-file-restore/src/main.rs b/proxmox-file-restore/src/main.rs index 0ada15e6..cbf79802 100644 --- a/proxmox-file-restore/src/main.rs +++ b/proxmox-file-restore/src/main.rs @@ -25,7 +25,7 @@ use pbs_datastore::catalog::{ArchiveEntry, CatalogReader, DirEntryAttribute}; use pbs_datastore::dynamic_index::{BufferedDynamicReader, LocalDynamicReadAt}; use pbs_datastore::index::IndexFile; use pbs_config::key_config::decrypt_key; -use pbs_client::{BackupReader, RemoteChunkReader}; +use pbs_client::{BackupReader, BackupRepository, RemoteChunkReader}; use pbs_client::pxar::{create_zip, extract_sub_dir, extract_sub_dir_seq}; use pbs_client::tools::{ complete_group_or_snapshot, complete_repository, connect, extract_repository_from_value, @@ -94,6 +94,84 @@ fn keyfile_path(param: &Value) -> Option { None } +async fn list_files( + repo: BackupRepository, + snapshot: BackupDir, + path: ExtractPath, + crypt_config: Option>, + keyfile: Option, + driver: Option, +) -> Result, Error> { + let client = connect(&repo)?; + let client = BackupReader::start( + client, + crypt_config.clone(), + repo.store(), + snapshot.group().backup_type(), + snapshot.group().backup_id(), + snapshot.backup_time(), + true, + ) + .await?; + + let (manifest, _) = client.download_manifest().await?; + manifest.check_fingerprint(crypt_config.as_ref().map(Arc::as_ref))?; + + match path { + ExtractPath::ListArchives => { + let mut entries = vec![]; + for file in manifest.files() { + if !file.filename.ends_with(".pxar.didx") && !file.filename.ends_with(".img.fidx") { + continue; + } + let path = format!("/{}", file.filename); + let attr = if file.filename.ends_with(".pxar.didx") { + // a pxar file is a file archive, so it's root is also a directory root + Some(&DirEntryAttribute::Directory { start: 0 }) + } else { + None + }; + entries.push(ArchiveEntry::new_with_size( + path.as_bytes(), + attr, + Some(file.size), + )); + } + + Ok(entries) + } + ExtractPath::Pxar(file, mut path) => { + let index = client + .download_dynamic_index(&manifest, CATALOG_NAME) + .await?; + let most_used = index.find_most_used_chunks(8); + let file_info = manifest.lookup_file_info(CATALOG_NAME)?; + let chunk_reader = RemoteChunkReader::new( + client.clone(), + crypt_config, + file_info.chunk_crypt_mode(), + most_used, + ); + let reader = BufferedDynamicReader::new(index, chunk_reader); + let mut catalog_reader = CatalogReader::new(reader); + + let mut fullpath = file.into_bytes(); + fullpath.append(&mut path); + + catalog_reader.list_dir_contents(&fullpath) + } + ExtractPath::VM(file, path) => { + let details = SnapRestoreDetails { + manifest, + repo, + snapshot, + keyfile, + }; + data_list(driver, details, file, path).await + } + } +} + #[api( input: { properties: { @@ -170,74 +248,14 @@ async fn list( } }; - let client = connect(&repo)?; - let client = BackupReader::start( - client, - crypt_config.clone(), - repo.store(), - snapshot.group().backup_type(), - snapshot.group().backup_id(), - snapshot.backup_time(), - true, - ) - .await?; - - let (manifest, _) = client.download_manifest().await?; - manifest.check_fingerprint(crypt_config.as_ref().map(Arc::as_ref))?; - - let result = match path { - ExtractPath::ListArchives => { - let mut entries = vec![]; - for file in manifest.files() { - if !file.filename.ends_with(".pxar.didx") && !file.filename.ends_with(".img.fidx") { - continue; - } - let path = format!("/{}", file.filename); - let attr = if file.filename.ends_with(".pxar.didx") { - // a pxar file is a file archive, so it's root is also a directory root - Some(&DirEntryAttribute::Directory { start: 0 }) - } else { - None - }; - entries.push(ArchiveEntry::new_with_size(path.as_bytes(), attr, Some(file.size))); - } - - Ok(entries) - } - ExtractPath::Pxar(file, mut path) => { - let index = client - .download_dynamic_index(&manifest, CATALOG_NAME) - .await?; - let most_used = index.find_most_used_chunks(8); - let file_info = manifest.lookup_file_info(CATALOG_NAME)?; - let chunk_reader = RemoteChunkReader::new( - client.clone(), - crypt_config, - file_info.chunk_crypt_mode(), - most_used, - ); - let reader = BufferedDynamicReader::new(index, chunk_reader); - let mut catalog_reader = CatalogReader::new(reader); + let driver: Option = match param.get("driver") { + Some(drv) => Some(serde_json::from_value(drv.clone())?), + None => None, + }; - let mut fullpath = file.into_bytes(); - fullpath.append(&mut path); + let result = list_files(repo, snapshot, path, crypt_config, keyfile, driver).await?; - catalog_reader.list_dir_contents(&fullpath) - } - ExtractPath::VM(file, path) => { - let details = SnapRestoreDetails { - manifest, - repo, - snapshot, - keyfile, - }; - let driver: Option = match param.get("driver") { - Some(drv) => Some(serde_json::from_value(drv.clone())?), - None => None, - }; - data_list(driver, details, file, path).await - } - }?; + let output_format = get_output_format(¶m); let options = default_table_format_options() .sortby("type", false) @@ -247,7 +265,6 @@ async fn list( .column(ColumnConfig::new("mtime").header("last modified")) .column(ColumnConfig::new("size")); - let output_format = get_output_format(¶m); format_and_print_result_full( &mut json!(result), &API_METHOD_LIST.returns, -- 2.30.2