From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <c.ebner@proxmox.com>
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 0193F90CAD
 for <pbs-devel@lists.proxmox.com>; Thu, 25 Jan 2024 14:27:05 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
 by firstgate.proxmox.com (Proxmox) with ESMTP id AF18119C34
 for <pbs-devel@lists.proxmox.com>; Thu, 25 Jan 2024 14:26:34 +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
 for <pbs-devel@lists.proxmox.com>; Thu, 25 Jan 2024 14:26:32 +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 0F83E492B3
 for <pbs-devel@lists.proxmox.com>; Thu, 25 Jan 2024 14:26:32 +0100 (CET)
From: Christian Ebner <c.ebner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Date: Thu, 25 Jan 2024 14:26:04 +0100
Message-Id: <20240125132608.1172472-26-c.ebner@proxmox.com>
X-Mailer: git-send-email 2.39.2
In-Reply-To: <20240125132608.1172472-1-c.ebner@proxmox.com>
References: <20240125132608.1172472-1-c.ebner@proxmox.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.051 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 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
 T_SCC_BODY_TEXT_LINE    -0.01 -
Subject: [pbs-devel] [PATCH v6 proxmox-backup 25/29] pxar-bin: implement
 listing for appendix entries
X-BeenThere: pbs-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox Backup Server development discussion
 <pbs-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pbs-devel/>
List-Post: <mailto:pbs-devel@lists.proxmox.com>
List-Help: <mailto:pbs-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel>, 
 <mailto:pbs-devel-request@lists.proxmox.com?subject=subscribe>
X-List-Received-Date: Thu, 25 Jan 2024 13:27:05 -0000

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@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