XZ ファイル形式
XZ で圧縮されたデータ。通常は LZMA2 アルゴリズムを使います。
- MIME タイプ
- application/x-xz
- 拡張子
- .xz
- カテゴリ
- アーカイブ・圧縮
マジックナンバー(ファイル署名)
| 0x00000000 | FD377A585A00 | ·7zXZ· | XZ magic |
XZ 形式について
XZ は LZMA2 を整合性チェック付きのコンテナに包んだもので、高い圧縮率が得られるためソフトウェア配布やカーネルイメージで使われます。6 バイトのマジックナンバーは FD 37 7A 58 5A 00 です。置き換えた先輩たちと違って、xz はストリームの上にヘッダを載せただけのものではなく、きちんとしたコンテナです。ストリームヘッダとそれに対応するストリームフッタがあり、ブロックはそれぞれ自分のヘッダと CRC を持ち、末尾には全ブロックの圧縮後・展開後サイズを列挙した索引があります。この索引のおかげで、リーダーは展開せずにファイルを検証したりシークしたりできます。そして同じ理由で、途中で切れた .xz はまったく検証できません。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 6 | Header magic bytes | FD 37 7A 58 5A 00。バイト 1 から 4 は ASCII で 7zXZ と読め、これが 7-Zip の形式との混同を生み続けています。先頭の FD は意図的に ASCII の外に置かれていて、末尾の 00 はテキストモード転送を通したときにファイルがはっきり失敗するようにするためのものです。 |
| 6 | 2 | Stream flags | 1 バイト目は予約で 00 でなければなりません。2 バイト目の下位 4 ビットが整合性チェックの種類を示し、0 が無し、1 が CRC-32、4 が CRC-64、10 が SHA-256 です。標準ツールが書いたファイルは 00 04 と読めます。CRC-64 が既定だからです。 |
| 8 | 4 | CRC-32 of the stream flags | リトルエンディアンで、オフセット 6 の 2 バイトだけを対象にします。何もデコードしないうちに、どのチェック種別を適用すべきかをリーダーが信頼できるようにするために存在します。 |
| 12 | 1 | Block header size | 符号化されています。実際のサイズはこの値に 1 を足して 4 倍したものなので、04 なら 20 バイトのブロックヘッダです。ここが 00 なのは特別で、もうブロックが無く、このオフセットから索引が始まることを意味します。 |
| 13 | 1 | Block flags | 下位 2 ビットがフィルタ数マイナス 1、ビット 6 は圧縮後サイズのフィールドが続くこと、ビット 7 は展開後サイズのフィールドが続くことを示します。フィルタ 1 つで両方のサイズを持つ典型的なブロックは C0 と読めます。 |
| variable | variable | Block sizes and filter flags | ブロックヘッダの中で、この順に並びます。省略可能な圧縮後・展開後サイズを多バイトの可変長整数で、続いてフィルタチェーン(LZMA2 はフィルタ id 0x21 で、辞書サイズを符号化したプロパティバイトが 1 つ)、その後 4 の倍数までのゼロパディング、最後にブロックヘッダ自身の CRC-32 です。 |
| variable | variable | Index | 最後のブロックの後ろに置かれ、ブロックごとに圧縮後・展開後サイズを記録したレコードが並び、4 の倍数までパディングされ、自身の CRC-32 が続きます。xz --list が読むのはこれで、xz が展開せずに中身を報告できるのもこのおかげです。 |
| -12 | 4 | Stream footer CRC-32 | リトルエンディアンで、この後ろに続く 6 バイトのフッタを対象にします。フッタは固定 12 バイトなので、ZIP の終端レコードと違って後ろ向きに走査して探す必要はまったくありません。 |
| -8 | 4 | Backward size | リトルエンディアンで、実際の索引サイズはこの値に 1 を足して 4 倍したものです。索引が 12 バイトのファイルは 02 00 00 00 を格納します。ファイル末尾から索引を見つけられるようにしているのがこれで、つまりこの形式全体がシーク可能なのもこれのおかげです。 |
| -4 | 2 | Stream flags (copy) | オフセット 6 と 7 のバイト単位の複製で、末尾から読み始めたデコーダも、ヘッダが宣言したのと同じチェック種別を知ることができます。両者が食い違っていれば、そのファイルは改ざんされたか継ぎ接ぎされています。 |
| -2 | 2 | Footer magic 'YZ' | 59 5A。無傷の .xz はどれもこの 2 バイトで終わります。ここが末尾でなければファイルは途中で切れており、前のほうにどれだけ正しそうなデータがあっても関係ありません。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| 7-Zip | この形式が自ら招いた混同です。.xz は FD 37 7A 58 5A 00 で始まり、その中のオフセット 1 と 2 に 7z が居座っています。本物の .7z はオフセット 0 が 37 7A BC AF 27 1C です。つまり同じ 2 バイトが 1 つずれた位置で両方に現れるので、7z を雑に検索すると両方に一致します。関係のない形式です。.7z はディレクトリを持つ複数ファイルのアーカイブ、.xz は単一の圧縮ストリームです。 |
| lzma (LZMA_Alone) | 先代であり、.lzma ファイルの識別が難しい理由でもあります。マジックナンバーがまったくありません。ヘッダは 13 バイトで、プロパティバイト 1 つ(たいてい 5D)、4 バイトのリトルエンディアンの辞書サイズ、8 バイトのリトルエンディアンの展開後サイズ(不明なら FF の繰り返し)という構成です。実際のファイルは 5D 00 00 80 00 に FF が 8 バイト続く形になり、これが署名にいちばん近い存在です。 |
| GZIP | 1F 8B と FD 37 7A 58 5A 00 で、見た目以上に構造が離れています。gzip は索引を持たないストリームの上のヘッダですが、xz は末尾にブロック索引を保持するので、展開せずに一覧と検証ができます。 |
| Zstandard | 現代のライバルです。28 B5 2F FD と xz のマジック。最高設定なら圧縮率は今も xz が小さいのですが、Zstandard は展開が数倍速く圧縮ははるかに速いので、パッケージマネージャが移行してきました。 |
| TAR | .tar.xz と、ファイル 1 つを xz したものは同じ形式です。展開して、結果のオフセット 257 が最初の 512 バイトの tar ヘッダの中で ustar になっているかを確認してください。.xz のコンテナ自体には両者を区別するものが何もありません。 |
よくある壊れ方
- 途中切れ。索引もフッタも末尾にあるので、届いたブロックがすべてデコードできても、切れた .xz は一覧も検証もできません。ツールは想定外の入力終端を報告します。目視で確認するいちばん速い方法は、ファイル末尾の 2 バイトが YZ かどうかを見ることです。
- ブロック本体のビット反転。既定の整合性チェックは CRC-64 なので破損は捕まりますが、捕まるのは展開のあとです。オフセット 8 の CRC-32 もブロックヘッダ自身の CRC も、対象はメタデータだけだからです。ひどく壊れたデータでは、チェックサムに到達する前に LZMA2 がデコードエラーで失敗するのが普通です。
- 末尾の NUL バイトが削られた場合。ブロックとストリームは 4 の倍数までゼロバイトでパディングされるので、末尾の NUL を刈り取る転送やビルド処理は、フッタが依存しているアラインメントを壊します。ファイルは xz として認識され、最後の最後で失敗します。
- 連結ストリームを 1 つとして解析してしまうケース。.xz の連結は合法で、間に省略可能なゼロパディングを挟むことも許されていて、標準ツールはそれらを全部展開します。最初のフッタマジックで止める自作リーダーは、その後ろを黙って捨てます。
- テキストモード転送。ヘッダのマジックにある 00 は、これを即座に失敗させるために置かれていて、実際そうなります。ただし同じ変換がストリームのもっと奥で起きた場合はヘッダが無傷で残るので、ファイルは正しく認識され、デコードが破損箇所に届いたときにだけ失敗します。
この形式の現在地
XZ は、一度圧縮して何度もダウンロードされるファイルで、ダウンロードのほうが高くつく場面のための形式です。カーネルの tarball、ディストリビューションのパッケージ、ソースのリリース、コンテナのベースレイヤーは 10 年以上これに頼ってきました。高いプリセットでの LZMA2 は、今もよくある形式の中で汎用の出力としては最小になるからです。代償は本物です。圧縮は遅く、メモリを非常に大量に食いますし、展開時のメモリも書き手が選んだ辞書サイズに比例します。プリセット 9 で作ったアーカイブを開くには 64 MB ほど必要で、組み込み環境では本当に問題になります。それに加えて数倍の速度差があり、2019 年ごろからパッケージマネージャやファイルシステムで Zstandard が着実にその座を奪ってきました。xz が第一候補であり続けるのは、静的なコンテンツを帯域に律速される形で配る場面です。繰り返し書き込むものやライブでストリーミングするものには向きません。
XZ ファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
XZ と混同しやすい形式です。先頭バイトを見比べてください。