Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package backhand for openSUSE:Factory 
checked in at 2026-03-02 17:35:26
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/backhand (Old)
 and      /work/SRC/openSUSE:Factory/.backhand.new.29461 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "backhand"

Mon Mar  2 17:35:26 2026 rev:6 rq:1335613 version:0.25.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/backhand/backhand.changes        2026-02-16 
13:17:26.586327934 +0100
+++ /work/SRC/openSUSE:Factory/.backhand.new.29461/backhand.changes     
2026-03-02 17:35:29.303211421 +0100
@@ -1,0 +2,12 @@
+Sun Mar  1 08:42:28 UTC 2026 - Martin Hauke <[email protected]>
+
+- Update to version 0.25.1:
+  backhand
+  * v3: Add kinds: BE_V3_1_LZMA_SWAP and LE_V3_1_LZMA_SWAP
+    + Big and little endian, with special magic.
+    + General support for v3.1, no on-disk changes.
+  * v3: Fall back to standard LZMA even if adaptive is picked.
+  backhand-cli
+  * Add --kinds: le_v3_1_lzma_swap and be_v3_1_lzma_swap
+
+-------------------------------------------------------------------

Old:
----
  backhand-0.25.0.obscpio

New:
----
  backhand-0.25.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ backhand.spec ++++++
--- /var/tmp/diff_new_pack.ysTM49/_old  2026-03-02 17:35:34.927445980 +0100
+++ /var/tmp/diff_new_pack.ysTM49/_new  2026-03-02 17:35:34.943446647 +0100
@@ -2,7 +2,7 @@
 # spec file for package backhand
 #
 # Copyright (c) 2026 SUSE LLC and contributors
-# Copyright (c) 2025, Martin Hauke <[email protected]>
+# Copyright (c) 2025-2026, Martin Hauke <[email protected]>
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 
 Name:           backhand
-Version:        0.25.0
+Version:        0.25.1
 Release:        0
 Summary:        Tools for the reading, creating, and modification of SquashFS 
file systems
 License:        Apache-2.0 OR MIT

++++++ _service ++++++
--- /var/tmp/diff_new_pack.ysTM49/_old  2026-03-02 17:35:35.183456657 +0100
+++ /var/tmp/diff_new_pack.ysTM49/_new  2026-03-02 17:35:35.187456824 +0100
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/wcampbell0x2a/backhand</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="scm">git</param>
-    <param name="revision">v0.25.0</param>
+    <param name="revision">v0.25.1</param>
     <param name="versionrewrite-pattern">v(\d+\.\d+\.\d+)</param>
     <param name="changesgenerate">enable</param>
   </service>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.ysTM49/_old  2026-03-02 17:35:35.379464831 +0100
+++ /var/tmp/diff_new_pack.ysTM49/_new  2026-03-02 17:35:35.411466166 +0100
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param 
name="url">https://github.com/wcampbell0x2a/backhand</param>
-              <param 
name="changesrevision">fa6c586fd24af3789992b8034eeec64b7bcc8498</param></service></servicedata>
+              <param 
name="changesrevision">4ac463be1071219b46fc0184ce452704ea705ba0</param></service></servicedata>
 (No newline at EOF)
 

++++++ backhand-0.25.0.obscpio -> backhand-0.25.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/CHANGELOG.md 
new/backhand-0.25.1/CHANGELOG.md
--- old/backhand-0.25.0/CHANGELOG.md    2026-02-14 22:04:50.000000000 +0100
+++ new/backhand-0.25.1/CHANGELOG.md    2026-02-28 20:30:10.000000000 +0100
@@ -7,6 +7,16 @@
 
 ## [Unreleased]
 
+## [v0.25.1] - 2025-02-28
+### `backhand`
+- v3: Add kinds: `BE_V3_1_LZMA_SWAP` and `LE_V3_1_LZMA_SWAP`
+  - Big and little endian, with special magic.
+  - General support for v3.1, no on-disk changes.
+- v3: Fall back to standard LZMA even if adaptive is picked. Thanks vendors!
+
+### `backhand-cli`
+- Add --kinds: `le_v3_1_lzma_swap` and `be_v3_1_lzma_swap`
+
 ## [v0.25.0] - 2025-02-14
 ### `backhand`
 - Update depends
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/Cargo.lock 
new/backhand-0.25.1/Cargo.lock
--- old/backhand-0.25.0/Cargo.lock      2026-02-14 22:04:50.000000000 +0100
+++ new/backhand-0.25.1/Cargo.lock      2026-02-28 20:30:10.000000000 +0100
@@ -112,7 +112,7 @@
 
 [[package]]
 name = "backhand"
-version = "0.25.0"
+version = "0.25.1"
 dependencies = [
  "assert_cmd",
  "criterion",
@@ -142,7 +142,7 @@
 
 [[package]]
 name = "backhand-cli"
-version = "0.25.0"
+version = "0.25.1"
 dependencies = [
  "backhand",
  "clap",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/Cargo.toml 
new/backhand-0.25.1/Cargo.toml
--- old/backhand-0.25.0/Cargo.toml      2026-02-14 22:04:50.000000000 +0100
+++ new/backhand-0.25.1/Cargo.toml      2026-02-28 20:30:10.000000000 +0100
@@ -9,7 +9,7 @@
 resolver = "2"
 
 [workspace.package]
-version = "0.25.0"
+version = "0.25.1"
 authors = ["wcampbell <[email protected]>"]
 license = "MIT OR Apache-2.0"
 edition = "2024"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/kinds.rs 
new/backhand-0.25.1/backhand/src/kinds.rs
--- old/backhand-0.25.0/backhand/src/kinds.rs   2026-02-14 22:04:50.000000000 
+0100
+++ new/backhand-0.25.1/backhand/src/kinds.rs   2026-02-28 20:30:10.000000000 
+0100
@@ -232,6 +232,10 @@
             "netgear_be_v3_0_lzma" => NETGEAR_BE_V3_0_LZMA,
             #[cfg(feature = "v3_lzma")]
             "netgear_be_v3_0_lzma_standard" => NETGEAR_BE_V3_0_LZMA_STANDARD,
+            #[cfg(feature = "v3_lzma")]
+            "le_v3_1_lzma_swap" => LE_V3_1_LZMA_SWAP,
+            #[cfg(feature = "v3_lzma")]
+            "be_v3_1_lzma_swap" => BE_V3_1_LZMA_SWAP,
             _ => return Err("not a valid kind".to_string()),
         };
 
@@ -431,3 +435,27 @@
     compressor: 
VersionedCompressor::V3LzmaStandard(&V3_LZMA_STANDARD_COMPRESSOR),
     bit_order: Some(deku::ctx::Order::Msb0),
 };
+
+/// Little-Endian SquashFS v3.1 with LZMA compression and swapped magic 
(Thomson/Technicolor/NETGEAR)
+#[cfg(feature = "v3_lzma")]
+pub const LE_V3_1_LZMA_SWAP: InnerKind = InnerKind {
+    magic: *b"shsq",
+    type_endian: deku::ctx::Endian::Little,
+    data_endian: deku::ctx::Endian::Little,
+    version_major: 3,
+    version_minor: 1,
+    compressor: VersionedCompressor::V3Lzma(&V3LzmaCompressor),
+    bit_order: Some(deku::ctx::Order::Lsb0),
+};
+
+/// Big-Endian SquashFS v3.1 with LZMA compression and swapped magic 
(Thomson/Technicolor/NETGEAR)
+#[cfg(feature = "v3_lzma")]
+pub const BE_V3_1_LZMA_SWAP: InnerKind = InnerKind {
+    magic: *b"shsq",
+    type_endian: deku::ctx::Endian::Big,
+    data_endian: deku::ctx::Endian::Big,
+    version_major: 3,
+    version_minor: 1,
+    compressor: VersionedCompressor::V3Lzma(&V3LzmaCompressor),
+    bit_order: Some(deku::ctx::Order::Msb0),
+};
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/lib.rs 
new/backhand-0.25.1/backhand/src/lib.rs
--- old/backhand-0.25.0/backhand/src/lib.rs     2026-02-14 22:04:50.000000000 
+0100
+++ new/backhand-0.25.1/backhand/src/lib.rs     2026-02-28 20:30:10.000000000 
+0100
@@ -103,7 +103,8 @@
     pub use crate::kinds::{BE_V3_0, LE_V3_0};
     #[cfg(feature = "v3_lzma")]
     pub use crate::kinds::{
-        BE_V3_0_LZMA, LE_V3_0_LZMA, NETGEAR_BE_V3_0_LZMA, 
NETGEAR_BE_V3_0_LZMA_STANDARD,
+        BE_V3_0_LZMA, BE_V3_1_LZMA_SWAP, LE_V3_0_LZMA, LE_V3_1_LZMA_SWAP, 
NETGEAR_BE_V3_0_LZMA,
+        NETGEAR_BE_V3_0_LZMA_STANDARD,
     };
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/traits/squashfs.rs 
new/backhand-0.25.1/backhand/src/traits/squashfs.rs
--- old/backhand-0.25.0/backhand/src/traits/squashfs.rs 2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand/src/traits/squashfs.rs 2026-02-28 
20:30:10.000000000 +0100
@@ -122,7 +122,7 @@
     let (major, minor) = (kind.version_major(), kind.version_minor());
     match (major, minor) {
         #[cfg(feature = "v3")]
-        (3, 0) => {
+        (3, 0) | (3, 1) => {
             let squashfs = 
crate::v3::squashfs::Squashfs::from_reader_with_offset_and_kind(
                 reader, offset, kind,
             )?;
@@ -130,7 +130,7 @@
             Ok(Box::new(filesystem) as Box<dyn FilesystemReaderTrait + 'b>)
         }
         #[cfg(not(feature = "v3"))]
-        (3, 0) => 
Err(crate::error::BackhandError::UnsupportedSquashfsVersion(3, 0)),
+        (3, 0) | (3, 1) => 
Err(crate::error::BackhandError::UnsupportedSquashfsVersion(3, 0)),
         (4, 0) => {
             let squashfs = 
crate::v4::squashfs::Squashfs::from_reader_with_offset_and_kind(
                 reader, offset, kind,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/v3/metadata.rs 
new/backhand-0.25.1/backhand/src/v3/metadata.rs
--- old/backhand-0.25.0/backhand/src/v3/metadata.rs     2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand/src/v3/metadata.rs     2026-02-28 
20:30:10.000000000 +0100
@@ -18,14 +18,22 @@
     let mut deku_reader = Reader::new(&mut *reader);
     let metadata_len = u16::from_reader_with_ctx(&mut deku_reader, 
kind.inner.data_endian)?;
 
+    if superblock.check_data() {
+        let mut check_byte = [0u8; 1];
+        reader.read_exact(&mut check_byte)?;
+        tracing::trace!("check_data: skipped check byte 0x{:02x}", 
check_byte[0]);
+    }
+
     let byte_len = len(metadata_len);
     tracing::trace!("len: 0x{:02x?}", byte_len);
     let mut buf = vec![0u8; byte_len as usize];
     reader.read_exact(&mut buf)?;
 
+    // NOTE: We intentionally ignore superblock.inodes_uncompressed() here.
+    // Some v3 images set that flag but still use per-block compression,
+    // so we rely solely on the per-block compressed bit.
     let is_block_compressed = is_compressed(metadata_len);
-    let is_superblock_uncompressed = superblock.inodes_uncompressed();
-    let bytes = if is_block_compressed && !is_superblock_uncompressed {
+    let bytes = if is_block_compressed {
         let mut out = Vec::with_capacity(8 * 1024);
         kind.inner.compressor.decompress(&buf, &mut out, None)?;
         out
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/v3/reader.rs 
new/backhand-0.25.1/backhand/src/v3/reader.rs
--- old/backhand-0.25.0/backhand/src/v3/reader.rs       2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand/src/v3/reader.rs       2026-02-28 
20:30:10.000000000 +0100
@@ -10,7 +10,7 @@
 
 use super::export::Export;
 use super::fragment::Fragment;
-use super::inode::{Inode, InodeInner};
+use super::inode::Inode;
 use super::metadata::METADATA_MAXSIZE;
 use super::squashfs::SuperBlock;
 use super::{fragment, metadata};
@@ -92,23 +92,16 @@
             metadata_offsets.push(self.stream_position()? - start);
             // parse into metadata
             let mut bytes = metadata::read_block(self, superblock, kind)?;
-            trace!("wowo");
 
             // parse as many inodes as you can
             let mut inode_bytes = next;
             inode_bytes.append(&mut bytes);
-            trace!("after");
             let mut c_inode_bytes = Cursor::new(inode_bytes.clone());
-            // trace!("{:02x?}", &c_inode_bytes);
             let mut container = Reader::new(&mut c_inode_bytes);
 
             // store last successful read position
             let mut container_bits_read = container.bits_read;
             loop {
-                tracing::debug!(
-                    "rest: {:02x?}",
-                    inode_bytes.clone()[(container_bits_read / 8)..].to_vec()
-                );
                 match Inode::from_reader_with_ctx(
                     &mut container,
                     (
@@ -120,20 +113,17 @@
                     ),
                 ) {
                     Ok(inode) => {
-                        // Push the new Inode to the return, with the position 
this was read from
-                        tracing::debug!("new: {inode:02x?}");
                         ret_vec.insert(inode.header.inode_number, inode);
                         container_bits_read = container.bits_read;
                     }
                     Err(e) => {
-                        trace!("err");
                         if matches!(e, DekuError::Incomplete(_)) {
                             // try next block, inodes can span multiple blocks!
                             next = inode_bytes.clone()[(container_bits_read / 
8)..].to_vec();
                             break;
                         } else {
-                            // panic!("{:?} {:02x?}", e, c_inode_bytes);
-                            panic!("{:?}", e);
+                            error!("Fatal error parsing inode: {:?}", e);
+                            return Err(BackhandError::Deku(e));
                         }
                     }
                 }
@@ -141,20 +131,10 @@
         }
 
         if ret_vec.len() != superblock.inode_count.try_into().unwrap() {
-            panic!("Parsed {} inodes, expected {}", ret_vec.len(), 
superblock.inode_count);
+            error!("Parsed {} inodes, expected {}", ret_vec.len(), 
superblock.inode_count);
+            return Err(BackhandError::CorruptedOrInvalidSquashfs);
         }
 
-        // Debug: Print out directory inode numbers to see what we have
-        let mut _dir_inodes: Vec<_> = ret_vec
-            .iter()
-            .filter_map(|(inode_num, inode)| match &inode.inner {
-                InodeInner::BasicDirectory(_) | 
InodeInner::ExtendedDirectory(_) => {
-                    Some(*inode_num)
-                }
-                _ => None,
-            })
-            .collect();
-
         Ok(ret_vec)
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/v3/squashfs.rs 
new/backhand-0.25.1/backhand/src/v3/squashfs.rs
--- old/backhand-0.25.0/backhand/src/v3/squashfs.rs     2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand/src/v3/squashfs.rs     2026-02-28 
20:30:10.000000000 +0100
@@ -144,6 +144,11 @@
     pub fn nfs_export_table_exists(&self) -> bool {
         u16::from(self.flags) & Flags::NFSExportTableExists as u16 != 0
     }
+
+    /// If set to true, metadata blocks have a leading check byte
+    pub fn check_data(&self) -> bool {
+        u16::from(self.flags) & Flags::Unused as u16 != 0
+    }
 }
 
 #[derive(Default, Clone, Debug)]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand/src/v3_lzma/compressor.rs 
new/backhand-0.25.1/backhand/src/v3_lzma/compressor.rs
--- old/backhand-0.25.0/backhand/src/v3_lzma/compressor.rs      2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand/src/v3_lzma/compressor.rs      2026-02-28 
20:30:10.000000000 +0100
@@ -1,5 +1,7 @@
 use std::sync::Mutex;
 
+use no_std_io2::io::Read;
+
 pub use crate::traits::CompressionAction;
 pub use crate::traits::types::Compressor;
 use tracing::trace;
@@ -61,6 +63,16 @@
             return Ok(());
         }
 
+        // Fall back to standard LZMA (some blocks like fragments in 
le_v3_0_lzma_swap use standard format)
+        trace!("Adaptive LZMA failed, trying standard LZMA");
+        if let Ok(mut reader) = lzma_rust2::LzmaReader::new_mem_limit(bytes, 
u32::MAX, None) {
+            if reader.read_to_end(out).is_ok() {
+                trace!("Standard LZMA decompression successful: {} bytes", 
out.len());
+                return Ok(());
+            }
+            out.clear();
+        }
+
         Err(crate::BackhandError::UnsupportedCompression(
             "Failed to decompress LZMA adaptive data".to_string(),
         ))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand-cli/Cargo.toml 
new/backhand-0.25.1/backhand-cli/Cargo.toml
--- old/backhand-0.25.0/backhand-cli/Cargo.toml 2026-02-14 22:04:50.000000000 
+0100
+++ new/backhand-0.25.1/backhand-cli/Cargo.toml 2026-02-28 20:30:10.000000000 
+0100
@@ -19,7 +19,7 @@
 indicatif = "0.18.3"
 console = "0.16.1"
 rayon = "1.10.0"
-backhand = { path = "../backhand", default-features = false, version = 
"0.25.0" }
+backhand = { path = "../backhand", default-features = false, version = 
"0.25.1" }
 tracing = "0.1.40"
 color-print = "0.3.6"
 clap-cargo = "0.18.3"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand-cli/src/bin/unsquashfs.rs 
new/backhand-0.25.1/backhand-cli/src/bin/unsquashfs.rs
--- old/backhand-0.25.0/backhand-cli/src/bin/unsquashfs.rs      2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand-cli/src/bin/unsquashfs.rs      2026-02-28 
20:30:10.000000000 +0100
@@ -49,6 +49,10 @@
     "netgear_be_v3_0_lzma_standard",
     #[cfg(feature = "v3_lzma")]
     "netgear_be_v3_0_lzma",
+    #[cfg(feature = "v3_lzma")]
+    "le_v3_1_lzma_swap",
+    #[cfg(feature = "v3_lzma")]
+    "be_v3_1_lzma_swap",
     "avm_be_v4_0",
 ];
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/backhand-test/tests/v3.rs 
new/backhand-0.25.1/backhand-test/tests/v3.rs
--- old/backhand-0.25.0/backhand-test/tests/v3.rs       2026-02-14 
22:04:50.000000000 +0100
+++ new/backhand-0.25.1/backhand-test/tests/v3.rs       2026-02-28 
20:30:10.000000000 +0100
@@ -139,3 +139,17 @@
         "be_v3_0_lzma",
     );
 }
+
+#[test]
+#[cfg(feature = "v3_lzma")]
+fn test_v3_lzma_swap() {
+    use backhand::kind::LE_V3_1_LZMA_SWAP;
+
+    common::download_asset("v3_le_lzma_swap");
+    only_read(
+        Kind::from_const(LE_V3_1_LZMA_SWAP).unwrap(),
+        "test-assets/squashfs_v3_le_lzma_swap.sqfs",
+        0,
+        "le_v3_1_lzma_swap",
+    );
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/backhand-0.25.0/test-assets.toml 
new/backhand-0.25.1/test-assets.toml
--- old/backhand-0.25.0/test-assets.toml        2026-02-14 22:04:50.000000000 
+0100
+++ new/backhand-0.25.1/test-assets.toml        2026-02-28 20:30:10.000000000 
+0100
@@ -211,3 +211,8 @@
 filepath = "test-assets/many_dirs_v3/many_dirs_v3.sqsh"
 hash = "00d9b4d0dbe98fdb57997da7481b1a6ffaa812aa536d3d8e1c72a8c3eb71e6c4"
 url = "https://wcampbell.dev/squashfs/testing/many_dirs_v3.sqsh";
+
+[test_assets.v3_le_lzma_swap]
+filepath = "test-assets/squashfs_v3_le_lzma_swap.sqfs"
+hash = "2eada74aee4336c4489b4a3551b73471785bc2a7a760f4acbb8bc94faa586197"
+url = "https://wcampbell.dev/squashfs/testing/squashfs_v3_le_lzma_swap.sqfs";

++++++ backhand.obsinfo ++++++
--- /var/tmp/diff_new_pack.ysTM49/_old  2026-03-02 17:35:36.439509040 +0100
+++ /var/tmp/diff_new_pack.ysTM49/_new  2026-03-02 17:35:36.471510375 +0100
@@ -1,5 +1,5 @@
 name: backhand
-version: 0.25.0
-mtime: 1771103090
-commit: fa6c586fd24af3789992b8034eeec64b7bcc8498
+version: 0.25.1
+mtime: 1772307010
+commit: 4ac463be1071219b46fc0184ce452704ea705ba0
 

++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/backhand/vendor.tar.zst 
/work/SRC/openSUSE:Factory/.backhand.new.29461/vendor.tar.zst differ: char 7, 
line 1

Reply via email to