
OS/File System/FAT
Last Update - 2004/10/10 15:50:46
FAT ( File Allocation Table )
広義の FAT 狭義の FAT
- ディスクをブロック単位で管理し、どのブロックが使用中かを記録するため FAT を使うディスク管理方式。
- FAT -- File Allocation Table
- Windows 以前の OS である MS-DOS で採用された FAT の一形態のことも FAT と呼ぶ。
- 現在では FAT と言えば MS-DOS や Windows で使われた File System のことを指すことが多い。
- このページも以下 FAT と言えば MS-DOS で採用された FAT のことを指す。
FAT12/FAT16/FAT32/VFAT
- FAT16/FAT32 は Windows95/98/Me での標準的な File System で、他の多くの OS でもサポートされている。
- FAT12 はフロッピーディスクのファイルシステムとして良く使われる。
- 長いファイル名を扱えるようにした FAT は VFAT ( Virtual FAT File System ) という。
- Windows では VFAT 対応なので、FAT12 でも長いファイル名を扱える。
ディスクの管理方法
- FAT File System ではディスクの管理を Directory Entry と File Allocation Table で行う。
- File Allocation Table にはファイルを構成する Cluster の情報が管理される。
- Cluster は1つ以上の連続する Sector から構成される単位である。
FAT File System のレイアウト
大きく5つのブロックがあり下記の順で並んでいる。
File Allocation Table は2つあり、片方は予備。
サブディレクトリやファイルは Data Area に配置される。
- Boot Sector
- File Allocation Table
- File Allocation Table (予備 - 全く同じものが配置される)
- Root Directory
- Data Area
Boot Sector
ディスクの先頭 Sector に配置され、ディスクの情報と OS をロードするプログラム ( IPL ) を含む。
PC/AT互換機では 1sector ( 512byte ) の IPL が一般的である。
FAT12/FAT16 のレイアウト
- 00h - 3byte - IPL へ jmp するコード ( 一般的には EB 3E 90 の 3byte )
- 03h - 8byte - OEM name string ( 8byte の ASCII 文字列によるメーカ名 )
- 0Bh - 25byte - BPB ( BIOS Parameter Block )
- 25h - 26byte - Extended BPB ( もしくは IPL がここから始まることもある )
- 3Eh - 448byte - IPL ( Initial Program Loader )
- 1FEh - 2byte - Boot Sigunature ( AA 55 の2バイトで Boot Sector は終わる )
BPB ( BIOS Parameter Block )
- 0Bh - WORD - 1セクタのバイト数
- 0Dh - BYTE - 1クラスタのセクタ数
- 0Eh - WORD - File Allocation Table より前にあるセクタの数 - 通常1
- 10h - BYTE - FAT の個数 - 常に2
- 11h - WORD - Root Directory のエントリ数
- 13h - WORD - セクタ総数 ( ディスクが大きい場合は代わりに 20h が使われ、常に0 )
- 15h - BYTE - メディアタイプ
- F0h - 3.5inch 1.44MB FD, 3.5inch 2.88MB FD
- F8h - hard disk
- 16h - WORD - FAT 1つのセクタ数
- 18h - WORD - 1トラックのセクタ数
- 1Ah - WORD - ヘッドの総数
- 1Ch - DWORD - 隠れたセクタ数 ( Boot Sector よりも前に何セクタあったか )
- 20h - DWORD - セクタの総数 ( サイズの大きいディスクのため )
Extended BPB
- 24h - 1byte - 物理ディスク番号 ( 80h なら最初の HDD, 00h なら最初の FDD )
- 25h - 1byte - 予約領域
- 26h - 1byte - シグニチャ ( 29h ならば以下3つの情報が有効である )
- 27h - 4byte - シリアル番号 ( 生成時刻などからメディア毎にユニークになるような ID を振る )
- 2Bh - 11byte - ボリュームラベル
- 36h - 8byte - File System ID ( FAT12, FAT16, FAT など )
File Allocation Table
Boot Sector に続いて、連続した Sector に FAT が配置される。
2HD の FD では FAT は通常、連続した 9sector が割り当てられる。
FAT にはファイルを確保するために Cluster 番号が並られる。
Cluster は1つ以上の連続する Sector から構成される単位で、ファイルは幾つかのクラスタで構成される。
FAT12 では1つの Cluster 番号は 12bit で表わされる。
12bit FAT のアドレスは Cluster No / 2 + Cluster No で計算できる。
( 奇数番目の Cluster 番号と、偶数版目の Cluster 番号で合わせて 3byte である )
FAT16 では1つの Cluster 番号は 16bit で表され、先頭から順に Cluster 番号が格納される。
ある Cluster 番号に対応する FAT には、この Cluster の次に連続している Cluster 番号が書かれている。
ファイルのデータは FAT に書かれている Cluster 番号を順に辿り、取得することが出来る。
クラスタ
クラスタ 0, 1 は特別で, 0 はメディアタイプ、1 は全てのビットが1である。
- F0h - 3.5inch FD
- F8h - hard disk
FAT 中のクラスタ番号で特別な値が幾つかある。
- 0 - 空き Cluster
- FF8h-FFFh - EOC on FAT12 ( Cluster 連鎖の終わり )
- FFF8h-FFFFh - EOC on FAT16
- FF7h - 不良 Cluster on FAT12
- FFF7h - 不良 Cluster on FAT16
FAT12 の例
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0000 F0 FF FF 03 40 00 06 F0-FF 07 F0 FF 00 00 00 00
1byte目は FAT ID で F0 とか F8 とか、続く 2byte は FF である。( Cluster 番号 0 と 1 はダミー )
03 40 00 -> 00 4-0 03 -> クラスタ番号 3 4
この例では 2 -> 3 -> 4 -> 6 とクラスタが連結されている。
FAT16 の例
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
0000 F0 FF FF FF 03 00 04 00-06 00 FF FF 07 00 FF FF
1byte目は FAT ID で F0 とか F8 とか、続く 3byte は FF である。( Cluster 番号 0 と 1 はダミー )
03 00 04 00 -> 00 03 - 00 04 -> クラスタ番号 3 4
この例では 2 -> 3 -> 4 -> 6 とクラスタが連結されている。
Root Directory
File Allocation Table に続き Root Directory が配置される。
Root Directory にはファイル名やファイル属性の情報を持った Directory Entry が並ぶ。
1つの Directory Entry は 32byte ある。
通常 2HD FD には 224個の Directory Entry があり、14sector が使われる。
通常の Directory Entry には SFN ( Short File Name ) が格納され 8.3 形式のファイル名を使用できる。
LFN ( Long File Name ) を使うと最大 260文字までのパス名を使うことができる。
LFN は Directory Entry を LFN 用に複数並べて構成される。
Directory Entry レイアウト
0Ah で指定される 2byte の開始 Cluster 番号から FAT を辿るとファイルがどこにあるか分かる。
サブディレクトリはファイル名が . の Directory Entry が1つあり親ディレクトリの開始 Cluster を示す。
親ディレクトリがルートの場合は開始 Cluster は 0 にする。
- 00h - 8byte - ファイル名 ( 1byte目が E5h で削除されたファイル、00h で未使用エントリ )
- 08h - 3byte - 拡張子 ( 3文字に満たない残りは 20h、ファイル名も8文字に満たない残りは 20h )
- 0Bh - 1byte - ファイル属性
- 0Ch - 10byte - Extra Data
- 16h - 2byte - 最新更新時間
- 18h - 2byte - 最新更新日付
- 1Ah - 2byte - 開始 Cluster 番号 ( ファイルがサイズ 0 ならば Cluster も 0 )
- 1Ch - 4byte - ファイルサイズ ( 0 ならばディレクトリ )
Extra Data レイアウト
- 0Ch - 1byte - Windows NT 予約領域
- 0Dh - 1byte - 不明 予約領域?
- 0Eh - 2byte - 作成時刻
- 10h - 2byte - 作成日付
- 12h - 2byte - 最新アクセス日付
- 14h - 2byte - cluster 番号の上位 2byte ( FAT12 , FAT16 では常に 0 )
ファイル属性
- bit 7-6 - 予約 常に 0
- bit 5 - アーカイブ属性
- bit 4 - ディレクトリ
- bit 3 - ボリュームラベル
- bit 2 - システムファイル
- bit 1 - 隠しファイル
- bit 0 - 読み取り専用ファイル
時刻
- bit 15-11 - 時 ( 0-23 が有効 )
- bit 10-5 - 分 ( 0-59 が有効 )
- bit 4-0 - 秒/2 ( 0-29 が有効、2倍して秒として扱う )
日付
- bit 15-9 - 1980年からの数えた年 ( 0-127 が有効 で 1980-2107 まで表せる )
- bit 8-5 - 月 ( 1-12 までが有効 1 = 1月 )
- bit 4-0 - 日 ( 1-31 が有効 )
LFN レイアウト
LFN を構成する Directory Entry は最後のものから順に並んで最後に SFN 用のディレクトリエントリが並ぶ。
LFN Directory Entry は 1byte目に並び順を示す flag があり最後の LFN Directory Entry の 1byte目には 40h が OR される。
- 最後の LFN Directory Entry
- ...
- 2番目の LFN Directory Entry
- 1番目の LFN Directory Entry
- SFN Directory Entry
LFN Directory Entry
1つの LFN Entry には13文字が格納できる。
1つの文字は2バイトで表現される。ASCII 文字は上位バイトに 0 をつめる。
ファイル名の終端は2バイトの 0 で、余った部分は FFFF で埋める。
- 00h - 1byte - flag ( LFN 何番目の Directory Entry かを示す番号 1ならば先頭、2ならば2番目 )
- 01h - 10byte - 5文字分の LFN エントリ
- 0Bh - 1byte - 常に 0Fh
- 0Ch - 1byte - 予約領域 常に 0
- 0Dh - 1byte - SFN から作ったチェックサム
- 0Eh - 12byte - 6文字文の LFN エントリ
- 1Ah - 2byte - 常に 0
- 1Ch - 4byte - 2文字分の LFN エントリ
チェックサム計算ロジック
mov si,FNAME
xor bl,bl
mov cx,11
label:
ror bl,1
lodsb
add bl,al
loop label
xchg al,bl
ret
Data Area
Root Directory に続き Data Area が配置される。
Data Area には、ファイルと Sub Directory ( Root Directory と同じサイズ、同じ構造 ) が格納される。( Root Directory と同じサイズてのは勘違いかもしれない。Windows の動作を見ていたら Sub Directory は 1 cluster から作成されて順次伸びて行くようだ - VFAT でだけれど )
Data Area に置かれるファイル・サブディレクトリは FAT で管理される Cluster の Chain (クラスタの連鎖) により確保される。
通常は 3.5inch 1.44MB FD では 1cluster=1sector で、この場合 33sector が Data Area 以前にある。
全セクタ数は 2880sector で、利用可能な cluster 数は 2850 個である。( 2850個てのは読んだ資料に書いてあったんだけれど、ものすごく 2847個な気がする )
参考資料
おまけ
- FAT_TOOL - FAT12用ツールを作ってみた ( 52,275 bytes ) - ライセンス
- fat.cpp の FAT::setNextCluster にバグがあったので修正 2004/03/09
- fat.cpp の FatDirectory::expandFileName にバグがあったので修正 2004/03/11
- fat.cpp の write で追記可能なように変更、fat_tool には影響なし 2004/03/30
- FatFile の initialize と write 辺りを修正。fat_tool の機能には影響ないはず。2004/04/01
- thanks Yui_Neko さん
- FatDirectory::deleteEntry で2回 FAT を解放していたバグを修正 2004/04/13
- FatFile::initalize で確保するメモリサイズの計算を間違っていたバグを修正 2004/04/13
- FAT::searchFreeCluster で確保できないクラスタ番号を返すことがあったバグを修正 2004/04/17
- File::position を追加 2004/04/22
- File::resize の中身を実装 2004/04/23
- FatDirectroy::deleteEntry のバグ修正、ディレクトリエントリのリサイズに対応 - 2004/04/27
- FatDirectory::expandEntry のバグ修正 - 2004/04/27
- セクタ書き込みと、書き出しの機能を追加。使い方は fat_tool help で - 2004/05/02
- "任意一文字" or ".任意一文字" のディレクトリを削除できなかったバグを修正 - 2004/05/20