[pbs-devel] [PATCH v6 proxmox-backup 25/29] pxar-bin: implement listing for appendix entries

Christian Ebner c.ebner at proxmox.com
Thu Jan 25 14:26:04 CET 2024


Fix the output of pxar list <archive.pxar> by also dumping the
entries referenced in the appendix section.

Signed-off-by: Christian Ebner <c.ebner at proxmox.com>
---
Changes since v5:
- not present in previous version

 pxar-bin/src/main.rs | 57 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/pxar-bin/src/main.rs b/pxar-bin/src/main.rs
index 6d365115..066b6212 100644
--- a/pxar-bin/src/main.rs
+++ b/pxar-bin/src/main.rs
@@ -1,6 +1,7 @@
-use std::collections::{HashSet, VecDeque};
-use std::ffi::OsStr;
+use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::ffi::{CString, OsStr};
 use std::fs::OpenOptions;
+use std::os::unix::ffi::OsStrExt;
 use std::os::unix::fs::OpenOptionsExt;
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
@@ -15,6 +16,7 @@ use pathpatterns::{MatchEntry, MatchType, PatternFlag};
 use pbs_client::pxar::{
     format_single_line_entry, Flags, OverwriteFlags, PxarExtractOptions, ENCODER_MAX_ENTRIES,
 };
+use pxar::EntryKind;
 
 use proxmox_router::cli::*;
 use proxmox_schema::api;
@@ -438,15 +440,60 @@ async fn mount_archive(archive: String, mountpoint: String, verbose: bool) -> Re
 )]
 /// List the contents of an archive.
 fn dump_archive(archive: String) -> Result<(), Error> {
-    for entry in pxar::decoder::Decoder::open(archive)? {
+    let mut appendix_refs = BTreeMap::new();
+    let mut decoder = pxar::decoder::Decoder::open(archive)?;
+
+    while let Some(entry) = decoder.next() {
         let entry = entry?;
+        match entry.kind() {
+            EntryKind::AppendixRef {
+                appendix_offset,
+                file_size,
+            } => {
+                appendix_refs.insert(*appendix_offset, (entry.path().to_path_buf(), *file_size));
+            }
+            EntryKind::Appendix { .. } => {
+                break;
+            }
+            _ => {
+                if log::log_enabled!(log::Level::Debug) {
+                    log::debug!("{}", format_single_line_entry(&entry, None));
+                } else {
+                    log::info!("{:?}", entry.path());
+                }
+            }
+        }
+    }
+
+    // Dump entries in appendix section
+    let mut consumed = 0;
+    for (offset, (base_path, size)) in appendix_refs {
+        let skip = offset - consumed;
+        decoder.skip_bytes(skip)?;
+
+        let entry = match decoder.next() {
+            Some(Ok(entry)) => entry,
+            Some(Err(err)) => return Err(err.into()),
+            None => return Err(format_err!("expected entry")),
+        };
 
         if log::log_enabled!(log::Level::Debug) {
-            log::debug!("{}", format_single_line_entry(&entry));
+            log::debug!("{}", format_single_line_entry(&entry, Some(&base_path)));
         } else {
-            log::info!("{:?}", entry.path());
+            log::info!("{:?}", base_path.join(entry.path().strip_prefix("/")?));
         }
+
+        let metadata = entry.metadata();
+        let file_name_os = entry.file_name();
+        let file_name_bytes = file_name_os.as_bytes();
+        let file_name = CString::new(file_name_bytes)?;
+        let mut bytes = pxar::encoder::sync::encoded_size(file_name.as_c_str(), &metadata)?;
+        // payload header size
+        bytes += std::mem::size_of::<pxar::format::Header>() as u64;
+
+        consumed += skip + bytes + size;
     }
+
     Ok(())
 }
 
-- 
2.39.2





More information about the pbs-devel mailing list