RFC 1952 GZIP file format specification version 4.3 日本語訳

本ドキュメントは、RFC 1952 『GZIP file format specification version 4.3』 を futomi が日本語化したものです。みなさまの理解に役立てれば幸いです。なお、緑色で記載された文章は、futomi が注釈として加筆したものです。また、一部、直訳ではなく、意訳した部分がございます。原文と表現が異なることがございますので、ご了承ください。

注意: この日本語訳は、futomi が理解を深めるために、自分なりに日本語化したものです。本日本語訳には、翻訳上の誤りがある可能性があります。したがって、内容について一切保証をするものではありません。正確さを求める場合には、必ず原文を参照してください。当方は、この文書によって利用者が被るいかなる損害の責任を負いません。

もし誤りなどを見つけたら、こちらからご連絡いただければ幸いです。


Network Working Group P. Deutsch
Request for Comments: 1952 Aladdin Enterprises
Category: Informational May 1996

GZIP file format specification version 4.3

このメモの状態

このメモは、インターネットコミュニティーのために情報を提供するものです。このメモは、いかなる種類のインターネット標準を定めるものではありません。このメモの配布は無制限です。

IESG の注:

IESG は、本文書に含まれるいかなる知的所有権声明の正当性に関して、特定の立場をとりません。

注意事項

Copyright (c) 1996 L. Peter Deutsch

いかなる目的に対しても、多言語への翻訳、編集物への組み込みを含めて、本文書のコピーおよび配布を無償で許諾します。ただし、著作権表示およびこの注意事項を遵守して下さい。また、元文書から実質的な変更や削除があれば、その部分を明確に表示下さい。※本日本語訳においては、緑色で記した箇所が futomi による加筆部分です。実質的な変更や削除は、本日本語訳においてはございません。

本文書の最新版と、HTML フォーマットの関連文書の情報は、こちらに掲載されております。

<ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html>.

要約

この仕様は、広く使われている GZIP ユーティリティーと互換性がある可逆圧縮データフォーマットを定義するものです。このフォーマットは、データの破損を検出するための循環冗長検査値を含みます。現在のところ、このフォーマットは、DEFLATE 圧縮方式を採用しています。しかし、他の圧縮方式を使えるように簡単に拡張することが可能です。このフォーマットは、特許に抵触しない形で、ためらうことなく実装することができます。

目次

1.1. 目的
1.4. 準拠
2.3.1.2. 準拠
5. 謝辞

1. はじめに

1.1. 目的

この仕様は、以下に示す可逆圧縮データフォーマットを定義することを目的としています。

  • CPU タイプ、オペレーティングシステム、ファイルシステム、文字セットから独立しています。従って、交換目的で使うことができます。
  • 事前に制限した中間記憶装置の容量を使うだけで、データストリームを圧縮または解凍して、(ランダムアクセスできるファイルとは対照的に)もう一つのデータストリームを生成することができます。従って、データ通信やUnix フィルターのような仕組みに使うことができます。
  • 現時点でもっとも良いとされる汎用的な圧縮方式に匹敵します。そして、とりわけ、"compress" プログラムより格段に良いのです。
  • 特許に抵触しない形で、ためらうことなく実装することができます。だから、自由に実行することができます。
  • 準拠した解凍器は、現存の gzip 圧縮器 によって生成されたデータを読むことができるという点で、現在広く使われている gzip ユーティリティで生成されたファイルフォーマットと互換性があります。

この仕様書で定義されているデータフォーマットは、以下に示す事項に関して試みません。

  • 圧縮データにランダムアクセスする。
  • 現在利用可能な最も優れた特殊化されたアルゴリズムと同じくらいに、特殊化されたデータ(ラスター画像等)を圧縮する。

1.2. 対象読者

この仕様は、データを gzip フォーマットに圧縮する、もしくは gzip フォーマットから解凍するソフトウェアの開発者による利用を対象としています。

この仕様の文章は、ビットレベルや他の原始的なデータ表現でのプログラミングにおける基本的な知識を前提としています。

1.3. 適用範囲

この仕様書は、圧縮方式とファイルフォーマットを規定します(後者に限っては、ファイルが任意バイト列を蓄積できると仮定しています)。この仕様は、ファイルシステムへの特定のインタフェースを規定しません。また、文字セットやエンコーディングも規定しません(但し、オプション機能のファイル名とコメントについては除きます。)。

1.4. 準拠

以降で特に指定がない限り、準拠復号器は、ここで示される仕様に完全に準拠したどんなファイルでも受け入れ、解凍することができなければいけません。準拠圧縮器は、ここで示される仕様に完全に準拠したファイルを生成しなければいけません。付録に掲載されている資料は、それ自体は仕様の役割を果たすわけではなく、準拠とは関係がありません。

1.5. 用語・規約の定義

バイト: 一つのユニットとして、蓄積もしくは転送された 8 ビット です。(オクテットと同義)。(たとえ 8 ビットで一つの文字を蓄積しないマシンにおいても、この仕様では、バイトは正確に 8 ビットを意味します。) バイトの中でのビットの番号付けは、下記をご覧下さい。

1.6. 前バージョンからの変更点

この仕様のバージョン 4.1 から、gzip フォーマットに技術的な変更は一切加えられておりません。バージョン 4.2 では、いくつかの用語が変更され、CRC 符号のサンプルが分かりやすくなるよう書き直されました。pre- and post-conditioning をするために、呼出側に対する必須条件を削除しました。バージョン 4.3 では、RFC スタイルへ仕様を変換しました。

2. 詳細仕様

2.1. 全体的な規約

下図をご覧下さい。

+---+
|   | <-- 垂直棒は表示されない場合があります。
+---+

上図のような箱は 1 バイトを表します。

+==============+
|              |
+==============+

上図のような箱は、可変長バイトを表します。

コンピュータに蓄積されているバイトは、ビットの順番に意味はありません。なぜなら、それらは常に一つの単位として扱われるからです。しかし、0 ~ 255 までの整数としてみなされるバイトは、最上位ビット(MSB)もしくは最下位ビット(LSB)を持っています。私達は左から最上位桁の数字を書きますから、左に最上位ビットを持つバイトを書き込みます。下図をご覧下さい。ビット 0 が最下位ビットとなるように、バイトのビットを番号付けしています。

+--------+
|76543210|
+--------+

この文書では、バイト内のビットが、ビット列の中に転送される順番に関する問題については取り扱いません。なぜなら、ここで説明されるデータフォーマットは、ビット指向というよりはバイト指向だからです。

コンピュータ内部では、数字はマルチバイトで構成される場合があります。ここで説明するフォーマット内のすべてのマルチバイト数字は、最初に最下位バイトから蓄積されます(低いメモリアドレスに)。例えば、十進数 520 は、次のように蓄積されます。

    0        1
+--------+--------+
|00001000|00000010|
+--------+--------+
 ^        ^
 |        |
 |        + 上位バイト = 2 x 256
 + 下位バイト = 8

2.2. ファイルフォーマット

gzip ファイルは、連続する "メンバー" (圧縮データ集合)と呼ばれる列から構成されます。各メンバーのフォーマットは、次章で規定されています。メンバーは、ただ単に、ファイル内で次々に出現するだけです。前後には一切の付加情報を持ちません。

2.3. メンバーフォーマット

各メンバーは、次に示す構造になっています。

+---+---+---+---+---+---+---+---+---+---+
|ID1|ID2|CM |FLG|     MTIME     |XFL|OS | (続く-->)
+---+---+---+---+---+---+---+---+---+---+

(FLG.FEXTRA がセットされた場合)

+---+---+=================================+
| XLEN  | "拡張フィールド" の XLEN バイト | (続く-->)
+---+---+=================================+

(FLG.FNAME がセットされた場合)

+=========================================+
|..元ファイルの名前。ゼロで終端されます...| (続く-->)
+=========================================+

(FLG.FCOMMENT がセットされた場合)

+===================================+
|..ファイルのコメント。ゼロで終端...| (続く-->)
+===================================+

(FLG.FHCRC がセットされた場合)

+---+---+
| CRC16 |
+---+---+
+=======================+
|..圧縮されたブロック...| (続く-->)
+=======================+
  0   1   2   3   4   5   6   7
+---+---+---+---+---+---+---+---+
|     CRC32     |     ISIZE     |
+---+---+---+---+---+---+---+---+

2.3.1. メンバーヘッダーとトレイラー

ID1 (IDentification 1)
ID2 (IDentification 2)

ID1 = 31 (0x1f, \037), ID2 = 139 (0x8b, \213) で固定です。gzip フォーマットであることを特定するためのものです。

CM (Compression Method)

ファイルで使われている圧縮方式を指定します。CM = 0-7 は予約、CM = 8 は "deflate" 圧縮方式であることを表します。"deflate" 圧縮方式は、通常、gzip で使われる方式の一つです。それは他のどこかで文書化されています。※ RFC 1951 のことと思われます。

FLG (FLaGs)

このフラグバイトは、下記の通り、個々のビットで分割されます。

bit 0 FTEXT
bit 1 FHCRC
bit 2 FEXTRA
bit 3 FNAME
bit 4 FCOMMENT
bit 5 予約
bit 6 予約
bit 7 予約

FTEXT がセットされていれば、ファイルは恐らく ASCII テキストです。これは、オプションの識別子で、圧縮器が、非 ASCII 文字が存在するかを見るために、少量の入力データをチェックすることによって、セットされるかもしれません。疑わしい場合には、FTEXT はクリアーされ、バイナリーデータを示唆します。アスキーテキストとバイナリーデータでファイルフォーマットが異なるシステムでは、圧縮器は適切なフォーマットを選択するために FTEXT を使うことができます。我々はこのビットをセットするために使われるアルゴリズムをあえて特定しません。なぜなら圧縮器は常にそれをクリアしたままにするという選択の自由が与えられており、そして、解凍器は常にそれを無視し、別のプログラムにデータ変換の問題を処理させるという選択の自由を与えられているからです。

FHCRC がセットされていれば、gzip ヘッダーの CRC16 が、圧縮データの直前に現れます。CRC16 は、CRC16 直前までの gzip ヘッダーすべてのバイトの CRC32 の最下位 2 バイトから構成されます。[ FHCRC ビットは、gzip 1.2.4 の中ではそれが違う意味を持つと規定されていましたが、実際には、バージョン 1.2.4 までの gzip では決してセットされませんでした。]

FEXTRA がセットされていれば、次のセクションで説明されている通り、オプションの拡張フィールドが存在します。

FNAME がセットされていれば、元ファイルの名前が存在し、ゼロバイトによって終端されます。名前は、ISO 8859-1 (LATIN-1) の文字から成り立っていなければいけません。ファイル名に EBCDIC や他の文字セットを使うオペレーティングシステム上では、そのファイル名は ISO LATIN-1 文字セットに変換されなければいけません。これは、圧縮されているファイルのオリジナルの名前です。どんなディレクトリコンポーネントも取り除かれています。そして、もしファイル名に大文字・小文字の区別がないファイルシステム上にあるなら、小文字に強制的に変換されます。名前があるファイル以外のソースからデータが圧縮されたなら、オリジナルのファイル名は存在しません。例えば、もしソースが Unix システム上の標準出力だったら、ファイル名は存在しません。

FCOMMENT がセットされていれば、ゼロ終端のファイルのコメントが存在します。このコメントは、解釈されません。それは人間が使うためだけに用意されたものです。コメントは ISO 8859-1 (LATIN-1) の文字から成り立っていなければいけません。改行は、単一の改行文字 (10 進数の 10) (※ LF のことです。)で表されなければいけません。

予約 FLG ビットはゼロでなければいけません。

MTIME (Modification TIME)

これは、圧縮されている元ファイルの最終更新時刻を与えます。この時刻は、Unix フォーマットになります。つまり、グリニッジ標準時刻の 1970/1/1 00:00:00 からの秒数です(世界時刻というよりむしろローカル時刻を使う MS-DOS 等では問題が起こるかもしれませんので、注意して下さい。)。もし圧縮データがファイルから来たのではないなら、MTIME は、圧縮が開始された時刻にセットされます。MTIME = 0 は、タイムスタンプが利用できないことを意味します。

XFL (eXtra FLags)

これらのフラグは、特定の圧縮方式に使われるために利用可能です。"deflate" 方式 (CM = 8) は、これらのフラグを次のようにセットします。

XFL = 2 - 圧縮器は、最高の圧縮だが、遅いアルゴリズムを使った。
XFL = 4 - 圧縮器は、最も速いアルゴリズムを使った。

OS (Operating System)

これは、圧縮が行われたファイルシステムのタイプを識別します。これは、テキストファイルの行末の仕様を判断するのに役立ちます。現状定義されている値は、次の通りです。

0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
1 - Amiga
2 - VMS (or OpenVMS)
3 - Unix
4 - VM/CMS
5 - Atari TOS
6 - HPFS filesystem (OS/2, NT)
7 - Macintosh
8 - Z-System
9 - CP/M
10 - TOPS-20
11 - NTFS filesystem (NT)
12 - QDOS
13 - Acorn RISCOS
255 - 不明

XLEN (eXtra LENgth)

FLG.FEXTRA がセットされている場合、これは、オプションの拡張フィールド長を与えます。詳細は以降をご覧下さい。

CRC32 (CRC-32)

これは、CRC-32 アルゴリズムによって計算された非圧縮データの循環冗長検査値が入っています。CRC-32 アルゴリズムは、ISO 3309 や ITU-T 勧告 V.42 のセクション 8.1.1.6.2 で使われているものです。(ISO 文書の注文は、http://www.iso.ch をご覧下さい。ITU-T V.42 のオンライン版は、gopher://info.itu.ch をご覧下さい。)

ISIZE (Input SIZE)

これは、オリジナル(非圧縮)の入力データ長のモジュロ 2^32 の値が入っています。

2.3.1.1. 拡張フィールド

FLG.FEXTRA がセットされている場合、"拡張フィールド" が合計長 XLEN バイトとともにヘッダー内に存在します。拡張フィールドは、サブフィールドの列から成り立ち、各フォームは次の通りです。

+---+---+---+---+==================================+
|SI1|SI2|  LEN  |... LEN bytes of subfield data ...|
+---+---+---+---+==================================+

SI1 と SI2 は、サブフィールド ID を提供します。一般的には、いくつかの記憶を助ける値を持った 2 つの ASCII 文字です。Jean-Loup Gailly <gzip@prep.ai.mit.edu> は、サブフィールド ID の登録を管理しています。どうそ、貴方が使いたいサブフィールド ID を彼に送って下さい。SI2 = 0 となるサブフィールド ID は、将来の利用のために予約されてます。現状、次の ID は登録済みです。

SI1         SI2         Data
----------  ----------  ----
0x41 ('A')  0x70 ('P')  Apollo file type information

LEN は、サブフィールドのデータ長を与え、始めの 4 バイトを除外しています。

2.3.1.2. 準拠

準拠した圧縮器は、正確な ID1, ID2, CM, CRC32, そして ISIZE となるファイルを生成しなければいけません。しかし、それ以外のヘッダーの固定長部分の値をデフォルト値(OS に 255, それ以外に 0)をセットしても構いません。圧縮器はすべての予約ビットをゼロにセットしなければいけません。

準拠した解凍器は、ID1, ID2, そして CM をチェックしなければいけません。そして、これらのうち一つでも不正な値があれば、エラーを表示して下さい。少なくとも、FEXTRA/XLEN, FNAME, FCOMMENT and FHCRC を検査しなければいけません。そうすれば、オプションのフィールドが存在した場合、それらをスキップできるのです。その他のヘッダーやトレーラー部分は検査する必要はありません。特に、解凍器は、FTEXT と OS を無視しても構いません。それでも準拠してるのです。準拠した解凍器は、予約ビットがゼロでなければエラーを表示しなければいけません。なぜなら、そのようなビットは、もしかしたら新しいフィールドの存在を意味し、後続のデータを誤って解釈してしまうかもしれないからです。

3. 参考文献

[1] "Information Processing - 8-bit single-byte coded graphic character sets - Part 1: Latin alphabet No.1" (ISO 8859-1:1987). ISO 8859-1 (Latin-1) 文字セットは、7-bit ASCII の上位セットです。この文字セットを定義しているファイルは、ftp://ftp.uu.net/graphics/png/documents/ から iso_8859-1.* として入手可能です。
[2] ISO 3309
[3] ITU-T 勧告 V.42
[4] Deutsch, L.P.,"DEFLATE Compressed Data Format Specification" ftp://ftp.uu.net/pub/archiving/zip/doc/ から入手できます。
[5] Gailly, J.-L., GZIP documentation, ftp://prep.ai.mit.edu/pub/gnu/ から gzip-*.tar ファイルとして入手できます。
[6] Sarwate, D.V., "Computation of Cyclic Redundancy Checks via Table Look-Up", Communications of the ACM, 31(8), pp.1008-1013.
[7] Schwaderer, W.D., "CRC Calculation", April 85 PC Tech Journal, pp.118-133.
[8] ftp://ftp.adelaide.edu.au/pub/rocksoft/papers/crc_v3.txt, これは CRC の概念を説明しています。
すでにファイルは移動されており上記 URL からは入手できません。現在(2005/01/06 時点)では、こちらから入手できます。ftp://ftp.rocksoft.com/papers/crc_v3.txt

4. セキュリティーに関して

どんな圧縮方式でも、データ内の冗長性の削除を伴います。結果として、どんなデータの破損でも、深刻な影響を受け、補正が難しいでしょう。それに対して、非圧縮のテキストであれば、いくつか破損したバイトがあったとしても、それでも尚、読むことができるでしょう。

このデータフォーマットを使っているシステムは、圧縮データの完全性を確認する方法をいくつか提供することが推奨されます。例えば、CRC-32 チェック値をセットしチェックするなどの方法です。

5. 謝辞

この文書で引用されている商標は、各所有者の財産です。

Jean-Loup Gailly は、gzip フォーマットを設計ました。そして、Mark Adler と一緒に、この仕様で説明されている関連ソフトウェアを欠きました。Glenn Randers-Pehrson は、この文書を RFC と HTML フォーマットに変換しました。

6. 著者のアドレス

L. Peter Deutsch
Aladdin Enterprises
203 Santa Margarita Ave.
Menlo Park, CA 94025

Phone: (415) 322-0103 (AM only)
FAX: (415) 322-1734
EMail: <ghost@aladdin.com>

この仕様の技術的な内容に関して質問があれば、こちらにメールを送って下さい。

Jean-Loup Gailly <gzip@prep.ai.mit.edu>
Mark Adler <madler@alumni.caltech.edu>

この仕様の編集上におけるご意見は、こちらにメールを送って下さい。

L. Peter Deutsch <ghost@aladdin.com>
Glenn Randers-Pehrson <randeg@alumni.rpi.edu>

7. 付録: Jean-Loup Gailly の gzip ユーティリティー

もっとも広く使われている gzip 圧縮の実装、そしてこの仕様に基づいているオリジナル文書は、Jean-Loup Gailly <gzip@prep.ai.mit.edu> によって作られました。この実装がデファクトスタンダードだから、我々はここでさらにいくつかの特徴をお話します。重ねて申し上げますが、このセクション内の資料は、それ自身仕様の役割を果たすももではありません。そして、実装は、それを準拠するよう従わせる必要はありません。

圧縮もしくは解凍するとき、gzip は、ローカルのファイルシステム上に、プロテクション属性、所有者属性、更新時刻属性を保存します。なぜなら、gzip ファイルフォーマットそれ自身にプロテクション属性を表すための対策がなされていないからです。ファイルフォーマットは更新時刻を含んでいるので、gzip 解凍器は、圧縮された入力のローカル更新時刻というよりはむしろ、ファイルからの更新時刻をアサインするコマンドラインスイッチを解凍された出力に提供します。

8. 付録: CRC コードサンプル

次のサンプルコードは、CRC (循環冗長検査) の実際の実装を表しています。(公式な仕様は、ISO 3309 と ITU-T V.42 をご覧下さい。)

このサンプルコードは、ANSI C プログラミング言語で書かかれています。C 言語利用者でない方は、次のヒントを使えば、読みやすくなるでしょう。

& AND ビット演算子
^ 排他的論理和ビット演算子
>> 右ビットシフト演算子。符号なしの数量に適用すると、右にシフトした分だけ、左側にゼロビットを挿入します。
! 論理否定演算子
++ "n++" は、n の値を加算します。
0xNNN 0x は 16 進数の定数を表します。添え字 L は long 値を意味します。(少なくとも 32 ビット)
/* Table of CRCs of all 8-bit messages. */
unsigned long crc_table[256];

/* Flag: has the table been computed? Initially false. */
int crc_table_computed = 0;

/* Make the table for a fast CRC. */
void make_crc_table(void)
{
  unsigned long c;
  int n, k;
  for (n = 0; n < 256; n++) {
    c = (unsigned long) n;
    for (k = 0; k < 8; k++) {
      if (c & 1) {
        c = 0xedb88320L ^ (c >> 1);
      } else {
        c = c >> 1;
      }
    }
    crc_table[n] = c;
  }
  crc_table_computed = 1;
}

/*
   Update a running crc with the bytes buf[0..len-1] and return
 the updated crc. The crc should be initialized to zero. Pre- and
 post-conditioning (one's complement) is performed within this
 function so it shouldn't be done by the caller. Usage example:

   unsigned long crc = 0L;

   while (read_buffer(buffer, length) != EOF) {
     crc = update_crc(crc, buffer, length);
   }
   if (crc != original_crc) error();
*/
unsigned long update_crc(unsigned long crc,
                unsigned char *buf, int len)
{
  unsigned long c = crc ^ 0xffffffffL;
  int n;

  if (!crc_table_computed)
    make_crc_table();
  for (n = 0; n < len; n++) {
    c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8);
  }
  return c ^ 0xffffffffL;
}

/* Return the CRC of the bytes buf[0..len-1]. */
unsigned long crc(unsigned char *buf, int len)
{
  return update_crc(0L, buf, len);
}