[pbs-devel] [PATCH v7 proxmox-backup 24/69] client: restore: read payload from dedicated index

Christian Ebner c.ebner at proxmox.com
Mon May 27 16:32:38 CEST 2024


Whenever a split pxar archive is encountered, instantiate and attach
the required dedicated reader instance to the decoder instance on
restore.

Piping the output to stdout is not possible for these, as this would
require a decoder instance which can decode the input stream, while
maintaining the pxar stream format as output.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
changes since version 6:
- adapt to PxarVariant pxar interface
- use newly introduced has_pxar_filename_extension
- allow for pxar -> mpxar mapping

 proxmox-backup-client/src/main.rs | 45 ++++++++++++++++++++-----------
 1 file changed, 29 insertions(+), 16 deletions(-)

diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index db0fb6324..ef481743f 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -35,7 +35,7 @@ use pbs_client::tools::{
     complete_archive_name, complete_auth_id, complete_backup_group, complete_backup_snapshot,
     complete_backup_source, complete_chunk_size, complete_group_or_snapshot,
     complete_img_archive_name, complete_namespace, complete_pxar_archive_name, complete_repository,
-    connect, connect_rate_limited, extract_repository_from_value,
+    connect, connect_rate_limited, extract_repository_from_value, has_pxar_filename_extension,
     key_source::{
         crypto_parameters, format_key_source, get_encryption_key_password, KEYFD_SCHEMA,
         KEYFILE_SCHEMA, MASTER_PUBKEY_FD_SCHEMA, MASTER_PUBKEY_FILE_SCHEMA,
@@ -1216,7 +1216,7 @@ async fn dump_image<W: Write>(
 fn parse_archive_type(name: &str) -> (String, ArchiveType) {
     if name.ends_with(".didx") || name.ends_with(".fidx") || name.ends_with(".blob") {
         (name.into(), archive_type(name).unwrap())
-    } else if name.ends_with(".pxar") {
+    } else if has_pxar_filename_extension(name, false) {
         (format!("{}.didx", name), ArchiveType::DynamicIndex)
     } else if name.ends_with(".img") {
         (format!("{}.fidx", name), ArchiveType::FixedIndex)
@@ -1400,6 +1400,9 @@ async fn restore(
 
     let (manifest, backup_index_data) = client.download_manifest().await?;
 
+    let (archive_name, payload_archive_name) =
+        helper::get_pxar_archive_names(&archive_name, &manifest);
+
     if archive_name == ENCRYPTED_KEY_BLOB_NAME && crypt_config.is_none() {
         log::info!("Restoring encrypted key blob without original key - skipping manifest fingerprint check!")
     } else {
@@ -1450,20 +1453,13 @@ async fn restore(
                 .map_err(|err| format_err!("unable to pipe data - {}", err))?;
         }
     } else if archive_type == ArchiveType::DynamicIndex {
-        let index = client
-            .download_dynamic_index(&manifest, &archive_name)
-            .await?;
-
-        let most_used = index.find_most_used_chunks(8);
-
-        let chunk_reader = RemoteChunkReader::new(
+        let mut reader = get_buffered_pxar_reader(
+            &archive_name,
             client.clone(),
-            crypt_config,
-            file_info.chunk_crypt_mode(),
-            most_used,
-        );
-
-        let mut reader = BufferedDynamicReader::new(index, chunk_reader);
+            &manifest,
+            crypt_config.clone(),
+        )
+        .await?;
 
         let on_error = if ignore_extract_device_errors {
             let handler: PxarErrorHandler = Box::new(move |err: Error| {
@@ -1518,8 +1514,22 @@ async fn restore(
         }
 
         if let Some(target) = target {
+            let reader = if let Some(payload_archive_name) = payload_archive_name {
+                let payload_reader = get_buffered_pxar_reader(
+                    &payload_archive_name,
+                    client.clone(),
+                    &manifest,
+                    crypt_config.clone(),
+                )
+                .await?;
+                pxar::PxarVariant::Split(reader, payload_reader)
+            } else {
+                pxar::PxarVariant::Unified(reader)
+            };
+            let decoder = pxar::decoder::Decoder::from_std(reader)?;
+
             pbs_client::pxar::extract_archive(
-                pxar::decoder::Decoder::from_std(pxar::PxarVariant::Unified(reader))?,
+                decoder,
                 Path::new(target),
                 feature_flags,
                 |path| {
@@ -1529,6 +1539,9 @@ async fn restore(
             )
             .map_err(|err| format_err!("error extracting archive - {:#}", err))?;
         } else {
+            if archive_name.ends_with(".mpxar.didx") || archive_name.ends_with(".ppxar.didx") {
+                bail!("unable to pipe split archive");
+            }
             let mut writer = std::fs::OpenOptions::new()
                 .write(true)
                 .open("/dev/stdout")
-- 
2.39.2





More information about the pbs-devel mailing list