From bed9cb93bfecfe3838587576c01a1e961e689228 Mon Sep 17 00:00:00 2001
From: iCrazeiOS <39101269+iCrazeiOS@users.noreply.github.com>
Date: Mon, 5 Oct 2026 11:52:16 +0100
Subject: [PATCH 1/6] feat: LZMA support
---
MacPacker/Info.plist | 34 +++++++++++++++++++++++
MacPacker/Info_Store.plist | 34 +++++++++++++++++++++++
Modules/Sources/Core/Formats/Catalog.json | 19 +++++++++++++
README.md | 4 +--
4 files changed, 89 insertions(+), 2 deletions(-)
diff --git a/MacPacker/Info.plist b/MacPacker/Info.plist
index 32b6f573..1f904ee4 100644
--- a/MacPacker/Info.plist
+++ b/MacPacker/Info.plist
@@ -205,6 +205,40 @@
LSTypeIsPackage
+
+ CFBundleTypeExtensions
+
+ lzma
+
+ CFBundleTypeName
+ LZMA Archive
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Default
+ LSItemContentTypes
+
+ org.tukaani.lzma-archive
+
+ LSTypeIsPackage
+
+
+
+ CFBundleTypeExtensions
+
+ tar.lzma
+
+ CFBundleTypeName
+ LZMA Tarball Archive
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Default
+ LSItemContentTypes
+
+ LSTypeIsPackage
+
+
CFBundleTypeExtensions
diff --git a/MacPacker/Info_Store.plist b/MacPacker/Info_Store.plist
index fbbd42b6..f4daa445 100644
--- a/MacPacker/Info_Store.plist
+++ b/MacPacker/Info_Store.plist
@@ -205,6 +205,40 @@
LSTypeIsPackage
+
+ CFBundleTypeExtensions
+
+ lzma
+
+ CFBundleTypeName
+ LZMA Archive
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Default
+ LSItemContentTypes
+
+ org.tukaani.lzma-archive
+
+ LSTypeIsPackage
+
+
+
+ CFBundleTypeExtensions
+
+ tar.lzma
+
+ CFBundleTypeName
+ LZMA Tarball Archive
+ CFBundleTypeRole
+ Viewer
+ LSHandlerRank
+ Default
+ LSItemContentTypes
+
+ LSTypeIsPackage
+
+
CFBundleTypeExtensions
diff --git a/Modules/Sources/Core/Formats/Catalog.json b/Modules/Sources/Core/Formats/Catalog.json
index a0e54b46..c91c6845 100644
--- a/Modules/Sources/Core/Formats/Catalog.json
+++ b/Modules/Sources/Core/Formats/Catalog.json
@@ -202,6 +202,18 @@
{ "id": "swc", "capabilities": ["listContents", "extractFiles"], "default": true }
]
},
+ {
+ "id": "lzma",
+ "name": "LZMA File",
+ "kind": "compression",
+ "uti": ["org.tukaani.lzma-archive"],
+ "extensions": ["lzma"],
+ "mime": ["application/x-lzma"],
+ "rules": [],
+ "engines": [
+ { "id": "7zip", "capabilities": ["listContents", "extractFiles"], "default": true }
+ ]
+ },
{
"id": "lzx",
"name": "LZX Archive",
@@ -571,6 +583,13 @@
"extensions": ["tlz4","tar.lz4"],
"components": ["tar","lz4"]
},
+ {
+ "id": "tar.lzma",
+ "name": "LZMA Tar Archive",
+ "uti": [],
+ "extensions": ["tar.lzma"],
+ "components": ["tar","lzma"]
+ },
{
"id": "tar.xz",
"name": "XZ Tar Archive",
diff --git a/README.md b/README.md
index bb368542..c457f70d 100644
--- a/README.md
+++ b/README.md
@@ -55,8 +55,8 @@ MacPacker reads and extracts 40+ formats across archives, disk images, and compr
| --- | --- |
| **Archives** | 7z · ar · arj · cab · chm · cpio · deb · exe · lha · lzh · lzx · msi · pkg · rar · rpm · sea · sit · sitx · tar · xar · zip · zipx |
| **Disk images** | dmg · fat · iso · ntfs · qcow2 · squashfs · vdi · vhd · vhdx · vmdk · wim |
-| **Compression** | bz2 · gz · lz4 · xz · z |
-| **Tarballs** | tar.gz (tgz) · tar.bz2 (tbz2) · tar.xz (txz) · tar.lz4 · tar.z (taz) |
+| **Compression** | bz2 · gz · lz4 · lzma · xz · z |
+| **Tarballs** | tar.gz (tgz) · tar.bz2 (tbz2) · tar.lzma · tar.xz (txz) · tar.lz4 · tar.z (taz) |
See the [full format reference and per-format guides](https://macpacker.app/en/docs) on the website.
From 4ab9951639e0d20de5c74b971d7d158cc527b68e Mon Sep 17 00:00:00 2001
From: iCrazeiOS <39101269+iCrazeiOS@users.noreply.github.com>
Date: Mon, 5 Oct 2026 11:53:02 +0100
Subject: [PATCH 2/6] fix: deb files no longer only show "unknown" file entry
---
Modules/Sources/CSevenZip/sevenzip_bridge.cpp | 61 ++++++++++---------
1 file changed, 33 insertions(+), 28 deletions(-)
diff --git a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
index 92e18a4d..11de2402 100644
--- a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
+++ b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
@@ -1163,37 +1163,42 @@ SZArchiveRef sz_open(const char *path, const char *password,
for (int depth = 0; depth < kMaxNestingDepth; depth++) {
IInArchive *currentArc = handle->levels.back().archive;
- // Check if this archive signals a nested container
- NWindows::NCOM::CPropVariant prop;
- currentArc->GetArchiveProperty(kpidMainSubfile, &prop);
- if (prop.vt != VT_UI4)
- break;
- UInt32 mainSubfile = prop.ulVal;
-
- // Validate index
- UInt32 itemCount = 0;
- currentArc->GetNumberOfItems(&itemCount);
- if (mainSubfile >= itemCount)
- break;
+ // The stream 7-Zip names through kpidMainSubfile.
+ CMyComPtr subStream;
- // Get IInArchiveGetStream from current archive
- CMyComPtr getStream;
- if (currentArc->QueryInterface(
- IID_IInArchiveGetStream_Local,
- (void **)&getStream) != S_OK || !getStream)
- break;
+ // Do not drill into a deb: its payload is a tar under a compression
+ // wrapper whose level has no usable kpidPath, which would render a
+ // lone entry named "unknown" instead of the deb's members.
+ NWindows::NCOM::CPropVariant ownExt;
+ currentArc->GetArchiveProperty(kpidExtension, &ownExt);
+ const bool isDeb = ownExt.vt == VT_BSTR && ownExt.bstrVal
+ && wcscmp(ownExt.bstrVal, L"deb") == 0;
- // Extract the sub-stream
- CMyComPtr subSeqStream;
- if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK
- || !subSeqStream)
- break;
+ NWindows::NCOM::CPropVariant prop;
+ currentArc->GetArchiveProperty(kpidMainSubfile, &prop);
+ if (!isDeb && prop.vt == VT_UI4) {
+ UInt32 mainSubfile = prop.ulVal;
+
+ UInt32 itemCount = 0;
+ currentArc->GetNumberOfItems(&itemCount);
+ if (mainSubfile < itemCount) {
+ CMyComPtr getStream;
+ if (currentArc->QueryInterface(
+ IID_IInArchiveGetStream_Local,
+ (void **)&getStream) == S_OK && getStream) {
+ CMyComPtr subSeqStream;
+ if (getStream->GetStream(mainSubfile, &subSeqStream) == S_OK
+ && subSeqStream) {
+ CMyComPtr in;
+ if (subSeqStream->QueryInterface(
+ IID_IInStream_Local, (void **)&in) == S_OK && in)
+ subStream = in;
+ }
+ }
+ }
+ }
- // Need seekable IInStream for archive opening
- CMyComPtr subStream;
- if (subSeqStream->QueryInterface(
- IID_IInStream_Local,
- (void **)&subStream) != S_OK || !subStream)
+ if (!subStream)
break;
// Try to open the sub-stream as a new archive, with the password: a 7z
From 3ab1dc45d43ac2f273966f94e5235dd827fd5c78 Mon Sep 17 00:00:00 2001
From: iCrazeiOS <39101269+iCrazeiOS@users.noreply.github.com>
Date: Wed, 14 Oct 2026 09:51:06 +0100
Subject: [PATCH 3/6] fix: add changelog entries for deb contents and LZMA
support
---
Config/products/macpacker.json | 48 ++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/Config/products/macpacker.json b/Config/products/macpacker.json
index 0620e343..549e80dd 100644
--- a/Config/products/macpacker.json
+++ b/Config/products/macpacker.json
@@ -88,6 +88,30 @@
"132"
]
},
+ {
+ "type": "feat",
+ "title": {
+ "en": "Open and extract LZMA files",
+ "zh-Hans": "打开并解压 LZMA 文件",
+ "fr": "Ouvrir et extraire les fichiers LZMA",
+ "de": "LZMA-Dateien öffnen und entpacken",
+ "it": "Aprire ed estrarre i file LZMA",
+ "ja": "LZMA ファイルを開いて展開する",
+ "fa": "باز کردن و استخراج فایلهای LZMA",
+ "pl": "Otwieranie i wypakowywanie plików LZMA",
+ "pt-BR": "Abrir e extrair arquivos LZMA",
+ "ru": "Открытие и извлечение файлов LZMA",
+ "uk": "Відкриття та розпакування файлів LZMA",
+ "es-MX": "Abrir y extraer archivos LZMA",
+ "ko": "LZMA 파일 열기 및 압축 해제",
+ "nl": "LZMA-bestanden openen en uitpakken",
+ "tr": "LZMA dosyalarını açma ve çıkarma",
+ "vi": "Mở và giải nén tệp LZMA"
+ },
+ "issues": [
+ "340"
+ ]
+ },
{
"type": "fix",
"highlight": true,
@@ -187,6 +211,30 @@
"275"
]
},
+ {
+ "type": "fix",
+ "title": {
+ "en": "Deb files list their contents correctly",
+ "zh-Hans": "deb 文件正确显示内容",
+ "fr": "Les fichiers deb affichent correctement leur contenu",
+ "de": "Deb-Dateien listen ihren Inhalt korrekt auf",
+ "it": "I file deb mostrano correttamente il contenuto",
+ "ja": "deb ファイルの内容を正しく表示",
+ "fa": "نمایش صحیح محتوای فایلهای deb",
+ "pl": "Pliki deb pokazują poprawnie zawartość",
+ "pt-BR": "Arquivos deb listam corretamente seu conteúdo",
+ "ru": "Deb-файлы корректно показывают содержимое",
+ "uk": "Deb-файли коректно показують вміст",
+ "es-MX": "Los archivos deb muestran correctamente su contenido",
+ "ko": "deb 파일 내용을 올바르게 표시",
+ "nl": "Deb-bestanden tonen hun inhoud correct",
+ "tr": "Deb dosyaları içeriğini doğru gösteriyor",
+ "vi": "Tệp deb hiển thị đúng nội dung"
+ },
+ "issues": [
+ "340"
+ ]
+ },
{
"type": "core",
"title": {
From fdad125feaa13e8b53678e6016b28d2aa9e6de53 Mon Sep 17 00:00:00 2001
From: iCrazeiOS <39101269+iCrazeiOS@users.noreply.github.com>
Date: Wed, 14 Oct 2026 12:11:31 +0100
Subject: [PATCH 4/6] add lzma UTType
---
MacPacker/Info.plist | 4 +++-
MacPacker/Info_Store.plist | 4 +++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/MacPacker/Info.plist b/MacPacker/Info.plist
index 1f904ee4..8672900b 100644
--- a/MacPacker/Info.plist
+++ b/MacPacker/Info.plist
@@ -235,7 +235,9 @@
LSHandlerRank
Default
LSItemContentTypes
-
+
+ org.tukaani.tar-lzma-archive
+
LSTypeIsPackage
diff --git a/MacPacker/Info_Store.plist b/MacPacker/Info_Store.plist
index f4daa445..caacdcd4 100644
--- a/MacPacker/Info_Store.plist
+++ b/MacPacker/Info_Store.plist
@@ -235,7 +235,9 @@
LSHandlerRank
Default
LSItemContentTypes
-
+
+ org.tukaani.tar-lzma-archive
+
LSTypeIsPackage
From 180e8385d3fb996c8b3b51aa4d6b70c0e6f7c8ee Mon Sep 17 00:00:00 2001
From: iCrazeiOS <39101269+iCrazeiOS@users.noreply.github.com>
Date: Wed, 14 Oct 2026 12:30:56 +0100
Subject: [PATCH 5/6] add docstring as requested by coderabbit
---
Modules/Sources/CSevenZip/sevenzip_bridge.cpp | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
index 36472dd4..a423e015 100644
--- a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
+++ b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
@@ -1100,6 +1100,24 @@ static void sz_indexAppleDoubleSidecars(SZArchiveHandle *handle) {
}
}
+/// Open an archive at the given filesystem path.
+///
+/// Tries each registered 7-Zip handler on the file, then drills into nested
+/// containers (disk images containing filesystems) up to a fixed depth via
+/// the `kpidMainSubfile` stream. A `deb` level is not drilled into: its
+/// payload is a tar under a compression wrapper with no usable entry paths,
+/// which would otherwise list as a lone entry named "unknown" instead of the
+/// deb's members.
+///
+/// @param path Filesystem path of the archive (UTF-8).
+/// @param password Password for reading encrypted headers (7z `-mhe=on`,
+/// RAR `-hp`), or NULL. Also pre-sets the extraction password.
+/// @param needs_password_out If non-NULL, set to true when a handler asked
+/// for a password during the open. Meaningful only on failure: it tells the
+/// caller to prompt and retry rather than report an unsupported file.
+/// @param error_out If non-NULL, set to a malloc'd UTF-8 error string on
+/// failure; caller must free() it.
+/// @return Opaque archive handle on success, NULL on failure.
SZArchiveRef sz_open(const char *path, const char *password,
bool *needs_password_out, char **error_out) {
if (needs_password_out) *needs_password_out = false;
From 5d3855b613dcb97e795e58d17846563299744fd0 Mon Sep 17 00:00:00 2001
From: Stephan Arenswald
Date: Wed, 21 Oct 2026 14:48:01 +0200
Subject: [PATCH 6/6] fix: tests, tlzma and Finder types for LZMA, 1.2.0
changelog (#340)
- Bridge: main's nesting loop again, with an early break for a deb.
- Tests: a deb as dpkg-deb writes it lists its members, not "unknown";
tar.lzma and tlzma open as tar. Fixtures from MacPacker-TestArchives#15:
a dpkg-deb deb, and the lzma tarballs as real LZMA (they were xz).
- tlzma is recognised, like tgz beside tar.gz.
- Finder and Quick Look: import org.tukaani.lzma-archive and
org.tukaani.tar-lzma-archive. macOS declares neither, so .lzma had no
app on a clean Mac. The tar.lzma document type that claimed an
undeclared type is gone.
- Changelog: both items move from the released 1.1.0 and 1.0.0 blocks
to a new 1.2.0 block, in all 21 languages.
---
Config/products/macpacker.json | 112 ++++++++++--------
MacPacker/Info.plist | 41 +++++++
MacPacker/Info_Store.plist | 41 +++++++
Modules/Sources/CSevenZip/sevenzip_bridge.cpp | 58 ++++-----
Modules/Sources/Core/Formats/Catalog.json | 4 +-
.../Tests/CoreTests/DefaultArchiveTests.swift | 23 ++++
Modules/Tests/CoreTests/TestArchives | 2 +-
QuickLookExtension/Info.plist | 1 +
README.md | 2 +-
9 files changed, 205 insertions(+), 79 deletions(-)
diff --git a/Config/products/macpacker.json b/Config/products/macpacker.json
index 36e58ce0..774e8bf5 100644
--- a/Config/products/macpacker.json
+++ b/Config/products/macpacker.json
@@ -35,6 +35,70 @@
"tr": "Bütünlük kontrolü ve kurtarma"
},
"versions": [
+ {
+ "version": "1.2.0",
+ "items": [
+ {
+ "type": "feat",
+ "highlight": true,
+ "title": {
+ "en": "Open and extract LZMA files",
+ "zh-Hans": "打开并解压 LZMA 文件",
+ "fr": "Ouvrir et extraire les fichiers LZMA",
+ "de": "LZMA-Dateien öffnen und entpacken",
+ "it": "Aprire ed estrarre i file LZMA",
+ "ja": "LZMA ファイルを開いて展開",
+ "fa": "باز کردن و استخراج فایلهای LZMA",
+ "pl": "Otwieranie i wypakowywanie plików LZMA",
+ "pt-BR": "Abrir e extrair arquivos LZMA",
+ "ru": "Открытие и извлечение файлов LZMA",
+ "uk": "Відкриття та розпакування файлів LZMA",
+ "es-MX": "Abrir y extraer archivos LZMA",
+ "ko": "LZMA 파일 열기 및 압축 해제",
+ "nl": "LZMA-bestanden openen en uitpakken",
+ "tr": "LZMA dosyalarını açma ve çıkarma",
+ "vi": "Mở và giải nén tệp LZMA",
+ "ar": "فتح ملفات LZMA واستخراجها",
+ "ca": "Obre i extreu fitxers LZMA",
+ "el": "Άνοιγμα και εξαγωγή αρχείων LZMA",
+ "nb": "Åpne og pakk ut LZMA-filer",
+ "zh-TW": "開啟並解壓縮 LZMA 檔案"
+ },
+ "issues": [
+ "340"
+ ]
+ },
+ {
+ "type": "fix",
+ "title": {
+ "en": "Deb files open as one “unknown” file",
+ "zh-Hans": "deb 文件打开后只有一个“unknown”文件",
+ "fr": "Les fichiers deb s’ouvrent en un seul fichier « unknown »",
+ "de": "Deb-Dateien öffnen sich als eine Datei „unknown“",
+ "it": "I file deb si aprono come un unico file «unknown»",
+ "ja": "deb ファイルを開くと「unknown」だけが表示される",
+ "fa": "فایلهای deb فقط بهصورت یک فایل «unknown» باز میشوند",
+ "pl": "Pliki deb otwierają się jako jeden plik „unknown”",
+ "pt-BR": "Arquivos deb abrem como um único arquivo “unknown”",
+ "ru": "Deb-файлы открываются как один файл «unknown»",
+ "uk": "Deb-файли відкриваються як один файл «unknown»",
+ "es-MX": "Los archivos deb se abren como un solo archivo «unknown»",
+ "ko": "deb 파일이 “unknown” 파일 하나로 열림",
+ "nl": "Deb-bestanden openen als één bestand “unknown”",
+ "tr": "Deb dosyaları tek bir “unknown” dosyası olarak açılıyor",
+ "vi": "Tệp deb mở ra chỉ với một tệp “unknown”",
+ "ar": "ملفات deb تُفتح كملف واحد باسم «unknown»",
+ "ca": "Els fitxers deb s’obren com un sol fitxer «unknown»",
+ "el": "Τα αρχεία deb ανοίγουν ως ένα μόνο αρχείο «unknown»",
+ "nb": "Deb-filer åpnes som én fil kalt «unknown»",
+ "zh-TW": "deb 檔案開啟後只有一個「unknown」檔案"
+ },
+ "issues": [
+ "340"
+ ]
+ }
+ ]
+ },
{
"version": "1.1.0",
"items": [
@@ -98,30 +162,6 @@
"132"
]
},
- {
- "type": "feat",
- "title": {
- "en": "Open and extract LZMA files",
- "zh-Hans": "打开并解压 LZMA 文件",
- "fr": "Ouvrir et extraire les fichiers LZMA",
- "de": "LZMA-Dateien öffnen und entpacken",
- "it": "Aprire ed estrarre i file LZMA",
- "ja": "LZMA ファイルを開いて展開する",
- "fa": "باز کردن و استخراج فایلهای LZMA",
- "pl": "Otwieranie i wypakowywanie plików LZMA",
- "pt-BR": "Abrir e extrair arquivos LZMA",
- "ru": "Открытие и извлечение файлов LZMA",
- "uk": "Відкриття та розпакування файлів LZMA",
- "es-MX": "Abrir y extraer archivos LZMA",
- "ko": "LZMA 파일 열기 및 압축 해제",
- "nl": "LZMA-bestanden openen en uitpakken",
- "tr": "LZMA dosyalarını açma ve çıkarma",
- "vi": "Mở và giải nén tệp LZMA"
- },
- "issues": [
- "340"
- ]
- },
{
"type": "fix",
"highlight": true,
@@ -242,30 +282,6 @@
"275"
]
},
- {
- "type": "fix",
- "title": {
- "en": "Deb files list their contents correctly",
- "zh-Hans": "deb 文件正确显示内容",
- "fr": "Les fichiers deb affichent correctement leur contenu",
- "de": "Deb-Dateien listen ihren Inhalt korrekt auf",
- "it": "I file deb mostrano correttamente il contenuto",
- "ja": "deb ファイルの内容を正しく表示",
- "fa": "نمایش صحیح محتوای فایلهای deb",
- "pl": "Pliki deb pokazują poprawnie zawartość",
- "pt-BR": "Arquivos deb listam corretamente seu conteúdo",
- "ru": "Deb-файлы корректно показывают содержимое",
- "uk": "Deb-файли коректно показують вміст",
- "es-MX": "Los archivos deb muestran correctamente su contenido",
- "ko": "deb 파일 내용을 올바르게 표시",
- "nl": "Deb-bestanden tonen hun inhoud correct",
- "tr": "Deb dosyaları içeriğini doğru gösteriyor",
- "vi": "Tệp deb hiển thị đúng nội dung"
- },
- "issues": [
- "340"
- ]
- },
{
"type": "fix",
"title": {
diff --git a/MacPacker/Info.plist b/MacPacker/Info.plist
index ea64840f..95a63597 100644
--- a/MacPacker/Info.plist
+++ b/MacPacker/Info.plist
@@ -226,6 +226,7 @@
CFBundleTypeExtensions
+ tlzma
tar.lzma
CFBundleTypeName
@@ -1096,6 +1097,46 @@
+
+ UTTypeConformsTo
+
+ public.archive
+ public.data
+
+ UTTypeDescription
+ LZMA File
+ UTTypeIcons
+
+ UTTypeIdentifier
+ org.tukaani.lzma-archive
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ lzma
+
+
+
+
+ UTTypeConformsTo
+
+ public.archive
+ public.data
+
+ UTTypeDescription
+ LZMA Tar Archive
+ UTTypeIcons
+
+ UTTypeIdentifier
+ org.tukaani.tar-lzma-archive
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ tlzma
+
+
+
ITSAppUsesNonExemptEncryption
diff --git a/MacPacker/Info_Store.plist b/MacPacker/Info_Store.plist
index 761be9dc..2e708e6b 100644
--- a/MacPacker/Info_Store.plist
+++ b/MacPacker/Info_Store.plist
@@ -226,6 +226,7 @@
CFBundleTypeExtensions
+ tlzma
tar.lzma
CFBundleTypeName
@@ -1090,6 +1091,46 @@
+
+ UTTypeConformsTo
+
+ public.archive
+ public.data
+
+ UTTypeDescription
+ LZMA File
+ UTTypeIcons
+
+ UTTypeIdentifier
+ org.tukaani.lzma-archive
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ lzma
+
+
+
+
+ UTTypeConformsTo
+
+ public.archive
+ public.data
+
+ UTTypeDescription
+ LZMA Tar Archive
+ UTTypeIcons
+
+ UTTypeIdentifier
+ org.tukaani.tar-lzma-archive
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ tlzma
+
+
+
ITSAppUsesNonExemptEncryption
diff --git a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
index 80f4fc9b..7e324ff8 100644
--- a/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
+++ b/Modules/Sources/CSevenZip/sevenzip_bridge.cpp
@@ -1214,42 +1214,46 @@ SZArchiveRef sz_open(const char *path, const char *password,
for (int depth = 0; depth < kMaxNestingDepth; depth++) {
IInArchive *currentArc = handle->levels.back().archive;
- // The stream 7-Zip names through kpidMainSubfile.
- CMyComPtr subStream;
-
// Do not drill into a deb: its payload is a tar under a compression
// wrapper whose level has no usable kpidPath, which would render a
// lone entry named "unknown" instead of the deb's members.
NWindows::NCOM::CPropVariant ownExt;
currentArc->GetArchiveProperty(kpidExtension, &ownExt);
- const bool isDeb = ownExt.vt == VT_BSTR && ownExt.bstrVal
- && wcscmp(ownExt.bstrVal, L"deb") == 0;
+ if (ownExt.vt == VT_BSTR && ownExt.bstrVal
+ && wcscmp(ownExt.bstrVal, L"deb") == 0)
+ break;
+ // Check if this archive signals a nested container
NWindows::NCOM::CPropVariant prop;
currentArc->GetArchiveProperty(kpidMainSubfile, &prop);
- if (!isDeb && prop.vt == VT_UI4) {
- UInt32 mainSubfile = prop.ulVal;
-
- UInt32 itemCount = 0;
- currentArc->GetNumberOfItems(&itemCount);
- if (mainSubfile < itemCount) {
- CMyComPtr getStream;
- if (currentArc->QueryInterface(
- IID_IInArchiveGetStream_Local,
- (void **)&getStream) == S_OK && getStream) {
- CMyComPtr subSeqStream;
- if (getStream->GetStream(mainSubfile, &subSeqStream) == S_OK
- && subSeqStream) {
- CMyComPtr in;
- if (subSeqStream->QueryInterface(
- IID_IInStream_Local, (void **)&in) == S_OK && in)
- subStream = in;
- }
- }
- }
- }
+ if (prop.vt != VT_UI4)
+ break;
+ UInt32 mainSubfile = prop.ulVal;
- if (!subStream)
+ // Validate index
+ UInt32 itemCount = 0;
+ currentArc->GetNumberOfItems(&itemCount);
+ if (mainSubfile >= itemCount)
+ break;
+
+ // Get IInArchiveGetStream from current archive
+ CMyComPtr getStream;
+ if (currentArc->QueryInterface(
+ IID_IInArchiveGetStream_Local,
+ (void **)&getStream) != S_OK || !getStream)
+ break;
+
+ // Extract the sub-stream
+ CMyComPtr subSeqStream;
+ if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK
+ || !subSeqStream)
+ break;
+
+ // Need seekable IInStream for archive opening
+ CMyComPtr subStream;
+ if (subSeqStream->QueryInterface(
+ IID_IInStream_Local,
+ (void **)&subStream) != S_OK || !subStream)
break;
// Try to open the sub-stream as a new archive, with the password: a 7z
diff --git a/Modules/Sources/Core/Formats/Catalog.json b/Modules/Sources/Core/Formats/Catalog.json
index a9bb6191..55c61e36 100644
--- a/Modules/Sources/Core/Formats/Catalog.json
+++ b/Modules/Sources/Core/Formats/Catalog.json
@@ -586,8 +586,8 @@
{
"id": "tar.lzma",
"name": "LZMA Tar Archive",
- "uti": [],
- "extensions": ["tar.lzma"],
+ "uti": ["org.tukaani.tar-lzma-archive"],
+ "extensions": ["tlzma", "tar.lzma"],
"components": ["tar","lzma"]
},
{
diff --git a/Modules/Tests/CoreTests/DefaultArchiveTests.swift b/Modules/Tests/CoreTests/DefaultArchiveTests.swift
index e2dd99c0..9edf1a80 100644
--- a/Modules/Tests/CoreTests/DefaultArchiveTests.swift
+++ b/Modules/Tests/CoreTests/DefaultArchiveTests.swift
@@ -68,11 +68,13 @@ extension AllCoreTests {
// compounds
("tar.bz2", "tar", 5, 2),
("tar.gz", "tar", 5, 2),
+ ("tar.lzma", "tar", 5, 2),
("tar.xz", "tar", 5, 2),
("tar.Z", "tar", 5, 2),
// comounds with one ending
("tbz2", "tar", 5, 2),
("tgz", "tar", 5, 2),
+ ("tlzma", "tar", 5, 2),
("txz", "tar", 5, 2),
("taz", "tar", 5, 2)
])
@@ -97,6 +99,27 @@ extension AllCoreTests {
#expect(state.root === state.selectedItem)
}
+ /// A deb lists its members, not a lone "unknown". dpkg-deb names the
+ /// first member `debian-binary`, and 7-Zip then offers the compressed
+ /// `data.tar.*` as the main subfile, whose one nameless stream was all
+ /// that showed. fpm names it `debian-binary/`, which 7-Zip reads as a
+ /// plain ar, so that deb always listed its members.
+ @Test(arguments: [
+ ("defaultarchive-dpkg.deb", ["control.tar.xz", "data.tar.xz"]),
+ ("defaultarchive.deb", ["control.tar.gz", "data.tar.gz", "debian-binary"])
+ ])
+ func debListsItsMembers(arg: (String, [String])) async throws {
+ let state = ArchiveState(catalog: ArchiveTypeCatalog(), engineSelector: ArchiveEngineSelector7zip())
+ let url = Bundle.module.url(forResource: "defaultArchives", withExtension: nil)!
+ .appendingPathComponent(arg.0)
+
+ state.open(url: url)
+ try await state.openTask?.value
+
+ let names = state.root?.children?.compactMap { state.entries[$0]?.name }.sorted()
+ #expect(names == arg.1)
+ }
+
@Test("Test all defaultArchives on xad", arguments: [
("zip", "zip"),
("7z", "7zip"),
diff --git a/Modules/Tests/CoreTests/TestArchives b/Modules/Tests/CoreTests/TestArchives
index a4f5a291..00abea7c 160000
--- a/Modules/Tests/CoreTests/TestArchives
+++ b/Modules/Tests/CoreTests/TestArchives
@@ -1 +1 @@
-Subproject commit a4f5a291276cb1257f3f918971d8a9c2d5c586c3
+Subproject commit 00abea7ccff3411420ed05ebe2bafd096e780160
diff --git a/QuickLookExtension/Info.plist b/QuickLookExtension/Info.plist
index 50a7d6a7..5b4853e2 100644
--- a/QuickLookExtension/Info.plist
+++ b/QuickLookExtension/Info.plist
@@ -35,6 +35,7 @@
org.gnu.gnu-zip-archive
org.gnu.gnu-zip-tar-archive
org.tukaani.lzma-archive
+ org.tukaani.tar-lzma-archive
org.tukaani.tar-xz-archive
org.tukaani.xz-archive
public.archive
diff --git a/README.md b/README.md
index c457f70d..e10fa0fc 100644
--- a/README.md
+++ b/README.md
@@ -56,7 +56,7 @@ MacPacker reads and extracts 40+ formats across archives, disk images, and compr
| **Archives** | 7z · ar · arj · cab · chm · cpio · deb · exe · lha · lzh · lzx · msi · pkg · rar · rpm · sea · sit · sitx · tar · xar · zip · zipx |
| **Disk images** | dmg · fat · iso · ntfs · qcow2 · squashfs · vdi · vhd · vhdx · vmdk · wim |
| **Compression** | bz2 · gz · lz4 · lzma · xz · z |
-| **Tarballs** | tar.gz (tgz) · tar.bz2 (tbz2) · tar.lzma · tar.xz (txz) · tar.lz4 · tar.z (taz) |
+| **Tarballs** | tar.gz (tgz) · tar.bz2 (tbz2) · tar.lzma (tlzma) · tar.xz (txz) · tar.lz4 · tar.z (taz) |
See the [full format reference and per-format guides](https://macpacker.app/en/docs) on the website.