One compressor is used for the whole image, named by the compression id in the superblock. Every compressed thing in the image (a data block, a fragment block, a metadata block) is one self-contained compressed stream, so any of them can be decoded alone, and none refers to another. A block that would not get smaller is stored as it is, and says so (bit 15 of a metadata block’s header, bit 24 of a data block’s size word).
The compressors
| Id | Name | What one compressed block is |
|---|---|---|
1 | gzip | A zlib stream (RFC 1950): a 2-byte header (usually 78 da), Deflate data, and an Adler-32 check. |
2 | lzma | “LZMA alone”: a 13-byte header, then the LZMA data. The header is the properties byte ((pb × 5 + lp) × 9 + lc, usually 5D), a 32-bit dictionary size and a 64-bit uncompressed size. The range coder’s data begins with a zero byte. The tools call this compressor deprecated and the Linux kernel does not read it. |
3 | lzo | One raw LZO1X stream with its end marker (the bytes 11 00 00); no header. All five LZO algorithms make the same format. |
4 | xz | A whole .xz file (FD 37 7A 58 5A 00): one block of LZMA2 data, optionally after a BCJ filter, with a CRC-32 check, an index and a footer. |
5 | lz4 | One raw LZ4 block: no frame, no size, no checksum. This is the “legacy” use of LZ4 (version 1 in the options). |
6 | zstd | One Zstandard frame (28 B5 2F FD). |
This site decodes all six with its own decoders, in the browser: Deflate, LZMA, LZMA2 with the BCJ filters, LZ4 and Zstandard are shared with the pages for those formats, and the LZO decoder was written for SquashFS.
The compressor options block
When flag 0x0400 is set, one metadata block follows the
superblock, at offset 96. Its header says it is stored uncompressed, and it holds the settings the
image was made with. mksquashfs leaves the block out when every setting is the compressor’s
default (a plain -comp gzip image has none). A reader does not need it to decode:
each compressed stream says what it needs. All numbers are in the image’s byte order.
| Compressor | Offset | Size | Name | Description |
|---|---|---|---|---|
| gzip | 0 | 4 | Compression level | 1 to 9 (default 9). |
4 | 2 | Window size | 8 to 15: the Deflate window is 2^window bytes (default 15, 32 KiB). | |
6 | 2 | Strategies | Bit flags of the zlib strategies the writer tried, keeping the smallest result: 1 default, 2 filtered, 4 Huffman only, 8 run-length encoded, 16 fixed. | |
| lzo | 0 | 4 | Algorithm | 0 lzo1x_1, 1 lzo1x_1_11, 2 lzo1x_1_12, 3 lzo1x_1_15, 4 lzo1x_999 (the default). |
4 | 4 | Compression level | 1 to 9 (default 8); only lzo1x_999 uses it. | |
| xz | 0 | 4 | Dictionary size | The LZMA2 dictionary in bytes: at least 8192, at most the block size, and of the form 2^n or 2^n + 2^(n−1). |
4 | 4 | Filters | Bit flags of the BCJ (branch) filters the writer tried: 0x01 x86, 0x02 PowerPC, 0x04 IA-64, 0x08 ARM, 0x10 ARM Thumb, 0x20 SPARC, 0x40 ARM64, 0x80 RISC-V. The filter a block was made with is named inside its own xz stream. | |
| lz4 | 0 | 4 | Version | 1: the legacy LZ4 block format. The only value defined. |
4 | 4 | Flags | Bit 0: LZ4 high compression (HC, -Xhc). | |
| zstd | 0 | 4 | Compression level | 1 to 22 (default 15). |
| lzma | No options: the block is not present. | |||
How much a block gives
A data block or fragment block decompresses to at most the block size from the superblock; the last block of a file gives what remains of it. A metadata block decompresses to at most 8192 bytes. A reader passes that limit to the decoder, so a damaged stream cannot make more.