TAR ファイル形式
POSIX の tape archive。無圧縮でファイルを連結するコンテナです。
- MIME タイプ
- application/x-tar
- 拡張子
- .tar
- カテゴリ
- アーカイブ・圧縮
マジックナンバー(ファイル署名)
| 0x00000101 | 7573746172 | ustar | 'ustar' marker in the first header |
TAR 形式について
TAR は 512 バイトブロックの連なりです。メンバーごとにヘッダブロックが 1 つ、続いてそのメンバーのバイト列を次の 512 バイト境界までゼロ埋めしたもの。これを繰り返し、全ゼロのブロックが 2 つ続いたところでアーカイブが終わります。圧縮もインデックスもディレクトリもありません。.tar がほぼ必ず gzip や xz や zstd で包まれているのも、.tar.gz の一覧を取るのに全体を展開しなければならないのもそのためです。ヘッダの数値フィールドはすべてバイナリではなく ASCII の 8 進数で書かれています。1979 年の判断ですが、おかげでツールなしの hex ダンプでも tar のヘッダが読めます。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 100 | name | メンバーのパスを NUL 埋めの ASCII で入れます。相対パスで、区切りはスラッシュ。ディレクトリは末尾にスラッシュを付けて格納します。100 バイトを超えるパスはオフセット 345 の prefix フィールドに分割するか、GNU の 'L' レコードか pax の 'x' レコードで丸ごと逃がすしかありません。 |
| 100 | 8 | mode | パーミッションを 8 進 6 桁+空白+NUL で書きます。たとえば '000644\0'(終端の前に空白)。移植性があるのは下位 12 ビットだけで、setuid や sticky は残っても Linux の capability や ACL は残りません。 |
| 108 | 8 | uid | 所有者の数値 uid を 8 進 ASCII で。2097151 を超える id は 8 進 7 桁に収まりません。GNU 版や pax 版が存在する理由がこれです。対応する名前はオフセット 265 に別途入っています。 |
| 116 | 8 | gid | 所有グループの数値 id。エンコードも桁あふれの限界も uid と同じです。root 以外で展開すると、この値も uid も黙って無視されます。 |
| 124 | 12 | size | メンバーのバイト数を 8 進 11 桁+空白か NUL で。したがって素の ustar メンバーの上限は 8 GiB 引く 1 です。読む側はこの値を 512 の倍数に切り上げて現在位置に足し、次のヘッダを見つけます。ディレクトリのエントリはゼロです。 |
| 136 | 12 | mtime | 更新時刻を 1970 年からの秒数の 8 進で。メンバーあたりタイムスタンプはちょうど 1 つ、作成時刻もアクセス時刻もなく、分解能は 1 秒、タイムゾーンもありません。秒未満が必要なら pax の拡張ヘッダを使います。 |
| 148 | 8 | chksum | 512 バイトのヘッダ全体を、このフィールド自身を空白 8 個とみなして符号なしで合計した値を、8 進 6 桁+NUL+空白で書いたものです。tar が持つ唯一の整合性チェックで(CRC もハッシュもありません)、しかも対象はヘッダだけ。ファイルデータは一切カバーしません。 |
| 156 | 1 | typeflag | '0' か NUL で通常ファイル、'1' ハードリンク、'2' シンボリックリンク、'3' と '4' がキャラクタ/ブロックデバイス、'5' ディレクトリ、'6' FIFO、'7' contiguous file。'x' と 'g' は pax の拡張ヘッダ、'L' と 'K' は GNU の長い名前/長いリンク先のレコードです。 |
| 157 | 100 | linkname | typeflag が '1' と '2' のときのリンク先パスを NUL 埋めで、それ以外は空です。展開先の外へ抜け出すシンボリックリンク先は tar のパストラバーサルの定番なので、信用できないアーカイブではここを覗く価値があります。 |
| 257 | 6 | magic | POSIX ustar では 'ustar' に NUL が 1 つ、GNU tar の古い版では 'ustar' に空白 2 つが続きます。この形式で位置が固定されている署名はこれだけで、しかもファイルの 257 バイト目にあります。先頭 16 バイトしか読まないツールが tar をまったく識別できないのはこのためです。 |
| 263 | 2 | version | POSIX ustar では '00'。GNU 版は magic フィールドの空白 2 つがそのままここまで流れ込むので、257〜264 バイト目が 'ustar \0' というひとかたまりに見えます。2 つの方言を見分ける一番安上がりな方法です。 |
| 265 | 32 | uname | 所有者のログイン名を NUL 終端の ASCII で。展開先でこの名前が解決できるなら、数値 uid よりこちらが優先されます。uid 501 で作った tar が、同じ人が uid 1000 のマシンでも正しく着地するのはこの仕組みです。 |
| 297 | 32 | gname | 所有グループの名前で、規則は uname と同じ。macOS で作られたアーカイブでは 'staff' や 'wheel'、Linux ではユーザー自身の名前になっていることが多いです。 |
| 329 | 8 | devmajor | デバイスのメジャー番号を 8 進で。意味があるのは typeflag が '3' と '4' のときだけで、通常のファイルではゼロ埋めです。 |
| 337 | 8 | devminor | マイナー番号。エンコードも制約も devmajor と同じ。この 2 つがあるおかげで tar は /dev のノードまで運べます。ほかの一般的なアーカイブ形式にはできない芸当です。 |
| 345 | 155 | prefix | 長いパスの先頭部分です。読む側は prefix とスラッシュと name を連結してパスを組み立て直すので、上限が 255 バイトまで伸びます。ただしパスの都合の良い位置にスラッシュがある場合に限られ、GNU や pax の長名レコードが存在するのはそのためです。 |
| 500 | 12 | padding | ヘッダをちょうど 512 バイトに整えるためのゼロバイト。メンバーのデータはオフセット 512 から始まり、それ自体も次の 512 バイト境界までゼロで埋められるので、2 つ目のヘッダも必ず 512 の倍数の位置に来ます。 |
| -1024 | 1024 | End-of-archive marker | 全ゼロの 512 バイトブロックが 2 つ続くとアーカイブの終わりです。多くの書き手はさらに 10 KiB や 20 KiB のブロック係数まで埋めるので、マーカーの後ろにゼロが続いているのはよくあること。ただし最後の 1024 バイトが全ゼロでなければ、そのアーカイブは途中で切れています。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| GZIP | .tar.gz は gzip ストリームの中に tar が入ったものなので、オフセット 0 は 1F 8B 08 で、展開するまで 'ustar' はどこにも出てきません。あまりに混同されるので、この組み合わせ 1 つに .tgz という拡張子まであるほどです。gzip の層を 1 枚外し、結果のオフセット 257 が 'ustar' ならば tar。そうでなければ、gzip で包まれた別の何かだったということです。 |
| ZIP | どちらも「ファイル 1 つになったフォルダ」で、拡張子の習慣だけでは区別できませんが、バイトのほうは明快です。オフセット 0 の 50 4B 03 04 か、オフセット 257 の 'ustar' か。実務上の違いは、ZIP がセントラルディレクトリを持ちランダムアクセスできるのに対し、tar は前から読むしかない点です。大きな .tar.gz の一覧には全展開のコストがかかり、.zip の一覧は seek 一発で済みます。 |
| cpio | もう 1 つの Unix のストリーミングアーカイバで、RPM や initramfs の中身はこれです。ポータブル ASCII の cpio はメンバーの境界ごとに ASCII の '070701' か '070707' で始まり、オフセット 257 のような固定位置ではありません。512 バイト境界への整列も一切ありません。 |
| GNU tar/pax | 3 つとも 257 バイト目に 'ustar' を書き、違いはその後ろだけです。POSIX ustar は 'ustar\0' に '00'、GNU tar は 'ustar' の後ろの空白 2 つが version フィールドまで流れ込む形。pax は ustar アーカイブに typeflag 'x' か 'g' のメンバーヘッダを追加し、そこに key=value のレコードで長い名前・大きな uid・秒未満の時刻を持たせます。これらのレコードを無視する読み手はエラーにならず、メタデータを黙って落とします。 |
よくある壊れ方
- 転送の途中切れ。tar は前方に連なるストリームなので、切れる前のものは完璧に展開でき、失われるのは最後のメンバーだけです。GNU tar なら 'Unexpected EOF' と報告しつつ、そこまで書いた分は残してくれます。確認するのは最後の 1024 バイト。全ゼロブロックが 2 つあれば意図どおりの終端、そうでなければ切られています。
- 壊れているのが tar ではなく gzip の層。deflate ストリーム内で 1 バイト反転すると、それ以降がすべて壊れます。だから .tar.gz は破損地点で止まり、その下にある無傷の tar には手が届きません。.tar.zst を勧める、あるいは大きなアーカイブを無圧縮のまま置いておく実務的な根拠がこれです。tar 自体は緩やかに劣化しますが、圧縮のラッパーはそうではありません。
- オフセット 148 のヘッダチェックサム不一致。tar の唯一の整合性チェックは 512 バイトのヘッダしか見ないので、名前やサイズの 1 バイト反転はすぐに露見する一方、ファイルデータの 1 バイト反転はまったく引っかかりません。チェックサムが全部通ったうえで、壊れたファイルが出てくることがあり得るということです。
- 8 進の桁あふれ。8 GiB を超えるファイルや 2097151 より大きい uid は、オフセット 124 や 108 の 8 進フィールドに収まりません。古い実装は値を回すかゴミを書きました。GNU tar は先頭バイトの最上位ビットを立てて base-256 のバイナリに切り替えますが、厳密な ustar リーダーはこれを門前払いします。size フィールドの先頭バイトが 0x80 なら、それは破損ではなくこれです。
- テキストモード転送。メンバーのデータ内部で改行変換が起きても、ヘッダもオフセットも無傷なので、一覧は正しく出て警告 1 つなく展開されます。tar にはデータのチェックサムがないので気づけません。破損が表に出るのは後になってから、展開したバイナリが動かないときです。
この形式の現在地
TAR は Unix における既定のアーカイブ形式で、動く気配もありません。理由は 1 つ、Unix のファイルシステムが大事にしているものを保てるからです。パーミッション、所有者、シンボリックリンク、ハードリンク、デバイスノード、スパースファイル。これらはすべて tar の往復を生き延びますが、ZIP ではどれも綺麗には残りません。ソースの配布物、コンテナイメージのレイヤー、バックアップ、そしてその上に乗るパッケージ形式が軒並み tarball なのはこのためです。弱点は構造的で、直しようがありません。インデックスがないので一覧するには全部読むしかない。データのチェックサムがないので静かな破損に気づけない。圧縮はメンバー単位ではなく外側に貼り付けるので、gzip 層の 1 バイトが壊れるとアーカイブ全体を失う。ZIP が勝つのはランダムアクセスで、4 GB の .tar.gz から 1 ファイル取り出すにはそこまで展開する必要があります。文書やアプリのコンテナが ZIP を選んだのはまさにこの点です。現代的な流れは tar から離れることではなく、包み方を替えることでした。.tar.zst は .tar.gz より圧縮も展開も数倍速く、圧縮率でも上回ります。時間より容量が大事な場面では .tar.xz が今も第一候補です。
TAR ファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
TAR と混同しやすい形式です。先頭バイトを見比べてください。