マジックナンバー (フォーマット識別子)
マジックナンバーとは、などオブジェクト類の形式を識別するもの、フォーマット識別子のことである。
なお、本項内でのマジックナンバーの具体的な値の表記には、特記無い限り16進表記を用いる。
フォーマット識別子としてのマジックナンバーとは、ファイルの種類を識別するのに使われるファイル本文中の(内容中の)特定の位置にある特定の数値のことである。ファイルの種類を識別する方法としてはファイルの拡張子や属性値(プロパティ)を使う場合もあるが、マジックナンバーとはそれらのことではなく、ファイルの本文中に表れる特定の数値のことである。ほとんどの場合、マジックナンバーはファイルの先頭に位置し、数バイト程度である。
また、ファイル以外にもデータ構造を持ったオブジェクト全般、例えば、マスターブートレコードでのファイルシステムの種類を表す識別子なども、マジックナンバーと呼ばれている。
歴史を辿るとマジックナンバーは、PDP-11のヘッダ部分に配置されている、データをスキップしてプログラムの開始位置にジャンプするインストラクションコードを意味していた。例えば、ファイルの冒頭の1ワード(PDP-11は16ビットワードマシン)がリトルエンディアンの8進数で0407 である場合、PDP-11の命令コードとしては相対アドレス指定の無条件分岐 0400 を意味し、8ワード先(オフセットビットの 07 は命令コードの位置を起点とするために、命令コード自体の1ワードを加算して8ワード先)にジャンプする命令となる。後にa.outフォーマットのマジックナンバーの一つO_MAGICとして認識されるようになった。
Unix系オペレーティングシステムには複数の実行形式のバイナリフォーマットがある。a.out、COFF、ELFなどである。Unix系オペレーティングシステムが実行ファイルを実行する際、それがテキストファイルであればシェルスクリプトと見なしてシェルを呼び出し(さらにシェルは、そのファイルが「#!」で始まっていればそれに後続して示されるアプリケーションを呼び出し)、そうでない場合はその実行ファイルを前述のようなバイナリ形式であると判断して直接呼び出すが、この際のファイル形式の判断にもマジックナンバーが用いられている。
このような仕組みから、Unix系オペレーティングシステムでは起動方法を切り替える仕組みをフックすることで、初期状態ではサポートされていないファイル形式の実行バイナリを実行することも可能となっている。例えば、BSD系での互換レイヤー(Linux互換レイヤーやSVR4互換レイヤーなど)、BSD系でのWin32カーネル互換パッケージの PEACE などは、この機能の実現例である。これが実現可能であるのは、マジックナンバーやマジックナンバーに後続するフラグ類によって判断しているからである。
BSD系もLinuxもELFバイナリが用いられており、マジックナンバーは 「7F ELF」と共通であるが、両者を区別可能なオプションとして、7バイト目にどのオペレーティングシステム向けのELFバイナリであるかが格納されている。例えば、FreeBSDであれば「09」、NetBSDであれば「02」、Linuxであれば「03」などである。
MS-DOS や Windows オペレーティングシステムで使われる実行形式のバイナリーフォーマットには、COMフォーマットとEXEフォーマットの二種類があるが、EXEフォーマットは、COMフォーマットと区別するために、ファイルの先頭が 4D 5A というマジックナンバーになっている。
アプリケーションでも、バイナリファイルの冒頭付近に他のアプリケーション用のファイルと区別可能なマジックナンバーを設けることは一般的であり、他のアプリケーション用のファイルが読み込まれた場合の誤動作防止のためのチェック用コードとして機能している。
Microsoft Office データファイル
ファイルの先頭から8バイトの「D0 CF 11 E0 A1 B1 1A E1」など(何種類か存在する)がマジックナンバーである。
gzip 圧縮ファイル
ファイルの先頭から2バイトの「1F 8B」がマジックナンバーである。
Java仮想マシンのプログラムコードは、ファイルとしてはJavaクラスファイルとして保存されているが、Javaクラスファイルの先頭の4バイトは CA FE BA BE というマジックナンバーになっている。
また、将来、ファイル形式の拡張が必要となる時のために、マジックナンバーにバージョン番号を含めておくこともしばしば行われる。
ファイルの3バイト目からの5バイトがマジックナンバーに相当し、「-lh0-」や「-lh4-」などのように中の3バイトがLZH形式の形式名称と一致する。
ファイルの先頭から5バイトが「%PDF-」となっているが、それにバージョン番号が後続する。
WindowsやMacintoshではマジックナンバーを参照することに特化したアプリケーションはオペレーティングシステムに付属されていないため、このような情報を利用者が参照することはあまりない。ただし、誤った拡張子が付与されているために正しいアプリケーションが開けなくなったファイルの拡張子を補正するようなソフトウェアは、マジックナンバーを参照して本来のファイル形式を判断している。なお、されたファイルの復元アプリケーションではマジックナンバー以外の情報も参照しているが、ここでは単に拡張子が別のものに変わってしまったようなケースを想定して説明している。
マスターブートレコードのパーティションテーブルには、パーティションの種類を示す情報、パーティション識別子が含まれている。例えばであれば 0B、NTFSであれば 07、 FreeBSD のFFSであれば A5 などである。この情報はのフォーマット識別子とも言える。
一部のオペレーティングシステムでは、パーティション識別子の付与とフォーマットを同タイミングで行うため、この両者は一致する。Windowsでは、パーティションの作成(パーティションサイズの決定)は独立操作であるが、パーティション識別子の付与とフォーマットは単一の操作であり、同タイミングで行われる。
一方、パーティション識別子の付与とフォーマットを行うタイミングが異なり、パーティション識別子と無関係の形式でフォーマットを行うことが可能なオペレーティングシステムも存在する。これは、複数のフォーマット形式に対応したPC-UNIX全般について言える。例えば FreeBSD では、パーティション識別子の付与は fdisk コマンドの実行時に行われ、フォーマットは newfs や newfs_msdos で行うこととなるが、これらのフォーマットコマンドはパーティション識別子とは無関係に実行することが可能である。そのため、FAT32の識別子を付けた状態でUFSフォーマットを行うことも可能である。Linuxでも、フォーマットコマンドが「mkfs.ext4」や「mkfs.vfat」や「mkfs -t msdos」などに変わる以外、事情は同じである。このようにして作成されたパーティションは、パーティション識別子を信じて動作するソフトウェアでは使用することができず、誤動作防止用のチェック機能も正しくは働かない。LinuxやFreeBSDのようにmount コマンドでのマウント時にパーティション識別子と無関係にフォーマット形式を指定可能なオペレーティングシステムでのみ使用可能である。
ジャーゴンファイルでは、「既存のファイル形式と重ならないように、新しい番号をどのように決めれば良いか」「簡単である。ランダムに決めれば良い」「まさしくマジック(手品)である」と取り上げられている。