diff --git a/examples/mk-format-hashes.rs b/examples/mk-format-hashes.rs index 6e00654..afd0924 100644 --- a/examples/mk-format-hashes.rs +++ b/examples/mk-format-hashes.rs @@ -1,6 +1,11 @@ use pxar::format::hash_filename; const CONSTANTS: &[(&str, &str, &str)] = &[ + ( + "Pxar format version entry, fallback to version 1 if not present", + "PXAR_FORMAT_VERSION", + "__PROXMOX_FORMAT_VERSION__", + ), ( "Beginning of an entry (current version).", "PXAR_ENTRY", diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs index 6a2de73..118681c 100644 --- a/src/accessor/mod.rs +++ b/src/accessor/mod.rs @@ -190,6 +190,18 @@ impl AccessorImpl { io_bail!("too small to contain a pxar archive"); } + let header: format::Header = read_entry_at(&input, 0).await?; + header.check_header_size()?; + + if header.htype == format::PXAR_FORMAT_VERSION { + let version: u64 = read_entry_at( + &input, + size_of::() as u64, + ) + .await?; + io_bail!("format version {version} not compatible with this client"); + } + Ok(Self { input, size, diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index d1fb911..d8bdc9c 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -374,6 +374,9 @@ impl DecoderImpl { self.entry.kind = EntryKind::Hardlink(self.read_hardlink().await?); Ok(Some(self.entry.take())) + } else if header.htype == format::PXAR_FORMAT_VERSION { + let version: u64 = seq_read_entry(&mut self.input).await?; + io_bail!("format version {version} not compatible with this client"); } else if header.htype == format::PXAR_ENTRY || header.htype == format::PXAR_ENTRY_V1 { if header.htype == format::PXAR_ENTRY { self.entry.metadata = Metadata { diff --git a/src/format/mod.rs b/src/format/mod.rs index bfea9f6..50d0e26 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -6,6 +6,7 @@ //! item data. //! //! An archive contains items in the following order: +//! * `FORMAT_VERSION` -- (optional for v1), version of encoding format //! * `ENTRY` -- containing general stat() data and related bits //! * `XATTR` -- one extended attribute //! * ... -- more of these when there are multiple defined @@ -79,6 +80,8 @@ pub mod mode { } // Generated by `cargo run --example mk-format-hashes` +/// Pxar format version entry, fallback to version 1 if not present +pub const PXAR_FORMAT_VERSION: u64 = 0x730f6c75df16a40d; /// Beginning of an entry (current version). pub const PXAR_ENTRY: u64 = 0xd5956474e588acef; /// Previous version of the entry struct @@ -177,6 +180,7 @@ impl Header { impl Display for Header { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let readable = match self.htype { + PXAR_FORMAT_VERSION => "FORMAT_VERSION", PXAR_FILENAME => "FILENAME", PXAR_SYMLINK => "SYMLINK", PXAR_HARDLINK => "HARDLINK",