[pbs-devel] [PATCH v9 proxmox-backup 38/58] client: pxar: allow to restore prelude to optional path

Christian Ebner c.ebner at proxmox.com
Wed Jun 5 12:53:56 CEST 2024


Pxar archives allow to store additional information in a prelude
entry since pxar format version 2.

Add an optional parameter to `pxar` and `proxmox-backup-client` to
specify the path to restore the prelude to and pass this to the
archive extraction by extending the `PxarExtractOptions` by a
corresponding field. If none is given, the prelude is simply skipped
during restore.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
changes since version 8:
- add missing file completion

 pbs-client/src/pxar/extract.rs    | 23 +++++++++++++++++++++--
 proxmox-backup-client/src/main.rs | 15 +++++++++++++--
 pxar-bin/src/main.rs              |  9 ++++++++-
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/pbs-client/src/pxar/extract.rs b/pbs-client/src/pxar/extract.rs
index e22390606..99c0d0e10 100644
--- a/pbs-client/src/pxar/extract.rs
+++ b/pbs-client/src/pxar/extract.rs
@@ -2,7 +2,8 @@
 
 use std::collections::HashMap;
 use std::ffi::{CStr, CString, OsStr, OsString};
-use std::io;
+use std::fs::OpenOptions;
+use std::io::{self, Write};
 use std::os::unix::ffi::OsStrExt;
 use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
 use std::path::{Path, PathBuf};
@@ -37,6 +38,7 @@ pub struct PxarExtractOptions<'a> {
     pub allow_existing_dirs: bool,
     pub overwrite_flags: OverwriteFlags,
     pub on_error: Option<ErrorHandler>,
+    pub prelude_path: Option<PathBuf>,
 }
 
 bitflags! {
@@ -125,9 +127,26 @@ where
         // we use this to keep track of our directory-traversal
         decoder.enable_goodbye_entries(true);
 
-        let (root, _) = handle_root_with_optional_format_version_prelude(&mut decoder)
+        let (root, prelude) = handle_root_with_optional_format_version_prelude(&mut decoder)
             .context("error reading pxar archive")?;
 
+        if let Some(ref path) = options.prelude_path {
+            if let Some(entry) = prelude {
+                let mut prelude_file = OpenOptions::new()
+                    .create(true)
+                    .write(true)
+                    .open(path)
+                    .with_context(|| format!("error creating prelude file '{path:?}'"))?;
+                if let pxar::EntryKind::Prelude(ref prelude) = entry.kind() {
+                    prelude_file.write_all(prelude.as_os_str().as_bytes())?;
+                } else {
+                    log::info!("unexpected entry kind for prelude");
+                }
+            } else {
+                log::info!("No prelude entry found, skip prelude restore.");
+            }
+        }
+
         if !root.is_dir() {
             bail!("pxar archive does not start with a directory entry!");
         }
diff --git a/proxmox-backup-client/src/main.rs b/proxmox-backup-client/src/main.rs
index 37412b154..b4d01ed3f 100644
--- a/proxmox-backup-client/src/main.rs
+++ b/proxmox-backup-client/src/main.rs
@@ -1441,7 +1441,12 @@ We do not extract '.pxar' archives when writing to standard output.
                 description: "ignore errors that occur during device node extraction",
                 optional: true,
                 default: false,
-            }
+            },
+            "prelude-target": {
+                description: "Path to restore prelude to, (pxar v2 archives only).",
+                type: String,
+                optional: true,
+            },
         }
     }
 )]
@@ -1603,12 +1608,17 @@ async fn restore(
             overwrite_flags.insert(pbs_client::pxar::OverwriteFlags::all());
         }
 
+        let prelude_path = param["prelude-target"]
+            .as_str()
+            .map(|path| PathBuf::from(path));
+
         let options = pbs_client::pxar::PxarExtractOptions {
             match_list: &[],
             extract_match_default: true,
             allow_existing_dirs,
             overwrite_flags,
             on_error,
+            prelude_path,
         };
 
         let mut feature_flags = pbs_client::pxar::Flags::DEFAULT;
@@ -1936,7 +1946,8 @@ fn main() {
         .completion_cb("ns", complete_namespace)
         .completion_cb("snapshot", complete_group_or_snapshot)
         .completion_cb("archive-name", complete_archive_name)
-        .completion_cb("target", complete_file_name);
+        .completion_cb("target", complete_file_name)
+        .completion_cb("prelude-target", complete_file_name);
 
     let prune_cmd_def = CliCommand::new(&API_METHOD_PRUNE)
         .arg_param(&["group"])
diff --git a/pxar-bin/src/main.rs b/pxar-bin/src/main.rs
index ecb617d65..bb57cf374 100644
--- a/pxar-bin/src/main.rs
+++ b/pxar-bin/src/main.rs
@@ -130,6 +130,10 @@ fn extract_archive_from_reader<R: std::io::Read>(
                 description: "'ppxar' payload input data file to restore split archive.",
                 optional: true,
             },
+            "prelude-target": {
+                description: "Path to restore pxar archive prelude to.",
+                optional: true,
+            },
         },
     },
 )]
@@ -153,6 +157,7 @@ fn extract_archive(
     no_sockets: bool,
     strict: bool,
     payload_input: Option<String>,
+    prelude_target: Option<String>,
 ) -> Result<(), Error> {
     let mut feature_flags = Flags::DEFAULT;
     if no_xattrs {
@@ -226,6 +231,7 @@ fn extract_archive(
         overwrite_flags,
         extract_match_default,
         on_error,
+        prelude_path: prelude_target.map(|path| PathBuf::from(path)),
     };
 
     if archive == "-" {
@@ -507,7 +513,8 @@ fn main() {
                 .completion_cb("archive", complete_file_name)
                 .completion_cb("target", complete_file_name)
                 .completion_cb("files-from", complete_file_name)
-                .completion_cb("payload-input", complete_file_name),
+                .completion_cb("payload-input", complete_file_name)
+                .completion_cb("prelude-target", complete_file_name),
         )
         .insert(
             "mount",
-- 
2.39.2





More information about the pbs-devel mailing list