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\x001、Stream Header 起始位,
lzma_header_magic,xz头标志
0x06-0x07\x00\x04Stream Flags
version,版本0x00
check,CRC类型0x04,4&0x0F=4表示CRC64,1是CRC32
0x08-0x0b0x46B4D6E6Stream Flags的 CRC32
0x0c0x022、Block Header 的长度,header_size
计算方式:(2+1)*4=12
0x0d0x00Check:与 0x3C相与 > 0 ,表示不支持的标志
Compressed:与 0x40 相与 > 0, 计算压缩大小
Uncompressed:与 0x80 相与 > 0,计算未压缩大小
0x0e0x21Filter ID,这里表示LZMA_FILTER_LZMA2
0x0f0x01Size of Properties,特性大小为1
0x100x16props,这里是LZMA2的特性,
字典大小为:(2|(0x16&1))<< (0x16/2+11)=0x800000
0x11-0x130x000000填充0
0x14-0x170xA3E52F74BLOCK_HEADER 的 CRC32
0x180x013、Compressed Data 起始位,使用lzma2压缩
lzma2特性:control
0x19-0x1a\x00\x10未压缩的大小0x10+1 = 0x11
0x1b-0x2b0123456789abcdef\x0a未压缩的数据
0x2c-0x2f0x00000000padding,填充0
0x30-0x370x0f4bda38869ae102压缩的数据的 CRC64
0x380x004、Index 起始位
Index Indicator,索引
0x390x01Number of Records
0x3a0x29Unpadded Size
0x3b0x11Uncompressed Size,未压缩的大小17字节
0x3c-0x3f0x0e700a32Index 的 CRC32
0x40-0x430x7df3b61f5、Stream Footer 起始位
Backward Size + Stream Flags 的 CRC32
0x44-0x470x00000001Backward Size,后面的大小
计算方式:(1+1)*4=8
0x48-0x49\x00\x04Stream Flags,同stream header里面的Stream Flags
0x4a-0x4bYZStream Footer的标志

五、参考链接

https://github.com/tukaani-project/xz/blob/v5.2.6

https://tukaani.org/xz/xz-file-format.txt

留下评论

您的电子邮箱地址不会被公开。 必填项已用*标注