XZ文件
一、介绍
XZ是一种使用LZMA压缩算法的无损数据压缩文件格式。 它由xz utils提供支持,这是一种lzma utils的后续版本,专门用于处理*.xz格式的文件。
XZ Utils是免费的通用数据压缩软件,具有高压缩比。XZ Utils是为类似posix的系统编写的,但也适用于一些不那么posix的系统。XZ Utils是LZMA Utils的继承者。
XZ Utils压缩代码的核心是基于LZMA SDK的,但是为了适合XZ Utils,它已经被修改了很多。目前主要的压缩算法是LZMA2,它在.xz容器格式中使用。对于典型的文件,XZ Utils创建的输出比gzip小30%,比bzip2小15%。
XZ Utils由几个组件组成:
- liblzma是一个压缩库,其API类似于zlib。
- xz是一个命令行工具,语法类似于gzip。
- xzdec是一个只解压的工具,比功能齐全的xz工具小。
- 一组shell脚本(xzgrep, xzdiff等)已经从gzip改编,以方便查看,grepping和比较压缩文件。
- LZMA Utils命令行工具的仿真简化了从LZMA Utils到XZ Utils的过渡。
虽然liblzma有一个类似zlib的API,但liblzma不包括任何文件I/O函数。计划有一个单独的I/O库,它将通过易于使用的API抽象处理.gz、.bz2和.xz文件。
本文以官方源码和文档作为指导,简单分析以下xz的文件组成结构。
二、环境
# 操作系统
Ubuntu 20.04
# 安装xz工具或源码
sudo apt install xz-utils
# 源码地址
https://github.com/tukaani-project/xz/blob/v5.2.6
创建一个text.txt文件,以下为原始内容(包含换行)
0123456789abcdef
使用xz命令压缩,生成test.txt.xz文件
xz test.txt
三、文件结构
参考源码stream_decoder.c,一个xz数据流里面包含多个字段
文件结构,参考官方格式说明
+-+-+-+-+-+-+-+-+-+-+-+-+=======+=======+ +=======+
| Stream Header | Block | Block | ... | Block |
+-+-+-+-+-+-+-+-+-+-+-+-+=======+=======+ +=======+
+=======+-+-+-+-+-+-+-+-+-+-+-+-+
---> | Index | Stream Footer |
+=======+-+-+-+-+-+-+-+-+-+-+-+-+
1、Stream Header
+---+---+---+---+---+---+-------+------+--+--+--+--+
| Header Magic Bytes | Stream Flags | CRC32 |
+---+---+---+---+---+---+-------+------+--+--+--+--+
2、Block
+==============+=================+===============+=======+
| Block Header | Compressed Data | Block Padding | Check |
+==============+=================+===============+=======+
2.1、Block Header
+-------------------+-------------+=================+
| Block Header Size | Block Flags | Compressed Size |
+-------------------+-------------+=================+
+===================+======================+
---> | Uncompressed Size | List of Filter Flags |
+===================+======================+
+================+--+--+--+--+
---> | Header Padding | CRC32 |
+================+--+--+--+--+
3、Index
+-----------------+===================+
| Index Indicator | Number of Records |
+-----------------+===================+
+=================+===============+-+-+-+-+
---> | List of Records | Index Padding | CRC32 |
+=================+===============+-+-+-+-+
4、Stream Footer
+-+-+-+-+---+---+---+---+-------+------+----------+---------+
| CRC32 | Backward Size | Stream Flags | Footer Magic Bytes |
+-+-+-+-+---+---+---+---+-------+------+----------+---------+
四、文件解析
使用hexdump查看十六进制内容
0 1 2 3 4 5 6 7 8 9 a b c d e f
00000000 fd 37 7a 58 5a 00 00 04 e6 d6 b4 46 02 00 21 01 |.7zXZ......F..!.|
00000010 16 00 00 00 74 2f e5 a3 01 00 10 30 31 32 33 34 |....t/.....01234|
00000020 35 36 37 38 39 61 62 63 64 65 66 0a 00 00 00 00 |56789abcdef.....|
00000030 02 e1 9a 86 38 da 4b 0f 00 01 29 11 32 0a 70 0e |....8.K...).2.p.|
00000040 1f b6 f3 7d 01 00 00 00 00 04 59 5a |...}......YZ|
通过源码分析,可以得到xz文件的结构
偏移 | 数据 | 说明 |
0x00-0x05 | \xFD7zXZ\x00 | 1、Stream Header 起始位, lzma_header_magic,xz头标志 |
0x06-0x07 | \x00\x04 | Stream Flags version,版本0x00 check,CRC类型0x04,4&0x0F=4表示CRC64,1是CRC32 |
0x08-0x0b | 0x46B4D6E6 | Stream Flags的 CRC32 |
0x0c | 0x02 | 2、Block Header 的长度,header_size 计算方式:(2+1)*4=12 |
0x0d | 0x00 | Check:与 0x3C相与 > 0 ,表示不支持的标志 Compressed:与 0x40 相与 > 0, 计算压缩大小 Uncompressed:与 0x80 相与 > 0,计算未压缩大小 |
0x0e | 0x21 | Filter ID,这里表示LZMA_FILTER_LZMA2 |
0x0f | 0x01 | Size of Properties,特性大小为1 |
0x10 | 0x16 | props,这里是LZMA2的特性, 字典大小为:(2|(0x16&1))<< (0x16/2+11)=0x800000 |
0x11-0x13 | 0x000000 | 填充0 |
0x14-0x17 | 0xA3E52F74 | BLOCK_HEADER 的 CRC32 |
0x18 | 0x01 | 3、Compressed Data 起始位,使用lzma2压缩 lzma2特性:control |
0x19-0x1a | \x00\x10 | 未压缩的大小0x10+1 = 0x11 |
0x1b-0x2b | 0123456789abcdef\x0a | 未压缩的数据 |
0x2c-0x2f | 0x00000000 | padding,填充0 |
0x30-0x37 | 0x0f4bda38869ae102 | 压缩的数据的 CRC64 |
0x38 | 0x00 | 4、Index 起始位 Index Indicator,索引 |
0x39 | 0x01 | Number of Records |
0x3a | 0x29 | Unpadded Size |
0x3b | 0x11 | Uncompressed Size,未压缩的大小17字节 |
0x3c-0x3f | 0x0e700a32 | Index 的 CRC32 |
0x40-0x43 | 0x7df3b61f | 5、Stream Footer 起始位 Backward Size + Stream Flags 的 CRC32 |
0x44-0x47 | 0x00000001 | Backward Size,后面的大小 计算方式:(1+1)*4=8 |
0x48-0x49 | \x00\x04 | Stream Flags,同stream header里面的Stream Flags |
0x4a-0x4b | YZ | Stream Footer的标志 |