Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LZBITMAP compression type support #169

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "3rdparty/lzfse"]
path = 3rdparty/lzfse
url = https://github.com/lzfse/lzfse.git
[submodule "3rdparty/libzbitmap"]
path = 3rdparty/libzbitmap
url = https://github.com/eafer/libzbitmap
1 change: 1 addition & 0 deletions 3rdparty/libzbitmap
Submodule libzbitmap added at cc3a3d
23 changes: 20 additions & 3 deletions ApfsLib/Decmpfs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ bool IsDecompAlgoSupported(uint16_t algo)
case 4:
case 7:
case 8:
case 14: // LZBITMAP
return true;
default:
return false;
Expand All @@ -70,6 +71,7 @@ bool IsDecompAlgoInRsrc(uint16_t algo)
{
case 4:
case 8:
case 14: // LZBITMAP
return true;
default:
return false;
Expand All @@ -86,6 +88,9 @@ bool DecompressFile(ApfsDir &dir, uint64_t ino, std::vector<uint8_t> &decompress
size_t csize = compressed.size() - sizeof(CompressionHeader);
size_t decoded_bytes = 0;

// Reference:
// https://github.com/apple-oss-distributions/copyfile/blob/main/copyfile.c

#if 1 // Disable to get compressed data
if (g_debug & Dbg_Cmpfs)
{
Expand All @@ -97,6 +102,12 @@ bool DecompressFile(ApfsDir &dir, uint64_t ino, std::vector<uint8_t> &decompress
case 4: std::cout << " (Zlib, Rsrc)"; break;
case 7: std::cout << " (LZVN, Attr)"; break;
case 8: std::cout << " (LZVN, Rsrc)"; break;
case 9: std::cout << " (uncompressed, Attr)"; break; // https://github.com/sgan81/apfs-fuse/pull/145
case 10: std::cout << " (uncompressed, Rsrc)"; break; // Not supported yet
case 11: std::cout << " (LZFSE, Attr)"; break; // Not supported yet
case 12: std::cout << " (LZFSE, Rsrc)"; break; // Not supported yet
case 13: std::cout << " (LZBITMAP, Attr)"; break; // Not supported yet
case 14: std::cout << " (LZBITMAP, Rsrc)"; break; // https://github.com/sgan81/apfs-fuse/pull/169
default: std::cout << " (Unknown)"; break;
}

Expand Down Expand Up @@ -187,7 +198,7 @@ bool DecompressFile(ApfsDir &dir, uint64_t ino, std::vector<uint8_t> &decompress
}
}
}
else if (hdr->algo == 8)
else if (hdr->algo == 8 || hdr->algo == 14) // LZFSE or LZBITMAP
{
const uint32_t *off_list = reinterpret_cast<const uint32_t *>(rsrc.data());

Expand All @@ -208,15 +219,21 @@ bool DecompressFile(ApfsDir &dir, uint64_t ino, std::vector<uint8_t> &decompress
return false;
}

if (src[0] == 0x06)
if ((src[0] == 0x06 && hdr->algo == 8) || (src[0] == 0xFF && hdr->algo == 14))
{
memcpy(decompressed.data() + (k << 16), src + 1, src_len - 1);
decoded_bytes = src_len - 1;
}
else
else if (hdr->algo == 14)
{
decoded_bytes = DecompressLZBITMAP(decompressed.data() + (k << 16), expected_len, src, src_len);
}
else if (hdr->algo == 8)
{
decoded_bytes = DecompressLZVN(decompressed.data() + (k << 16), expected_len, src, src_len);
}
else
decoded_bytes = 0;

if (decoded_bytes != expected_len)
{
Expand Down
10 changes: 10 additions & 0 deletions ApfsLib/Util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
extern "C" {
#include <lzfse.h>
#include <lzvn_decode_base.h>
#include <libzbitmap/libzbitmap.h>
}

static Crc32 g_crc(true, 0x1EDC6F41);
Expand Down Expand Up @@ -560,6 +561,15 @@ size_t DecompressLZFSE(uint8_t * dst, size_t dst_size, const uint8_t * src, size
return lzfse_decode_buffer(dst, dst_size, src, src_size, nullptr);
}

size_t DecompressLZBITMAP(uint8_t* dst, size_t dst_size, const uint8_t* src, size_t src_size)
{
size_t out_len = 0;
int r = zbm_decompress(dst, dst_size, src, src_size, &out_len);
if (r == 0) // success
return out_len;
return 0; // fail
}

int log2(uint32_t val)
{
int r = 0;
Expand Down
1 change: 1 addition & 0 deletions ApfsLib/Util.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ size_t DecompressADC(uint8_t *dst, size_t dst_size, const uint8_t *src, size_t s
size_t DecompressLZVN(uint8_t *dst, size_t dst_size, const uint8_t *src, size_t src_size);
size_t DecompressBZ2(uint8_t *dst, size_t dst_size, const uint8_t *src, size_t src_size);
size_t DecompressLZFSE(uint8_t *dst, size_t dst_size, const uint8_t *src, size_t src_size);
size_t DecompressLZBITMAP(uint8_t* dst, size_t dst_size, const uint8_t* src, size_t src_size);

bool GetPassword(std::string &pw);

Expand Down
8 changes: 7 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
# set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")

include_directories(. 3rdparty/lzfse/src)
include_directories(. 3rdparty/libzbitmap)

add_library(lzfse
3rdparty/lzfse/src/lzfse.h
Expand All @@ -36,6 +37,11 @@ add_library(lzfse
3rdparty/lzfse/src/lzvn_encode_base.h
)

add_library(libzbitmap
3rdparty/libzbitmap/libzbitmap.c
3rdparty/libzbitmap/libzbitmap.h
)

add_library(apfs
ApfsLib/Aes.cpp
ApfsLib/Aes.h
Expand Down Expand Up @@ -100,7 +106,7 @@ add_library(apfs
ApfsLib/Util.h
ApfsLib/Unicode.cpp
ApfsLib/Unicode.h)
target_link_libraries(apfs z bz2 lzfse)
target_link_libraries(apfs z bz2 lzfse libzbitmap)
target_compile_definitions(apfs PUBLIC _FILE_OFFSET_BITS=64 _DARWIN_USE_64_BIT_INODE)

add_executable(apfs-dump
Expand Down