[Mona] FAT12 クラスタの割り当て・解放チェック

昨日の日記にも書いた通り、ファイル削除機能を実装した場合、メタデータであるFATのクラスタ情報がきちんと更新されているかをチェックする必要がある。
もっと具体的に言うと、ファイルを削除した場合にファイルが保持していたクラスタがFAT上で未使用としてマーキングされ解放されているか知りたいのである。



まずは現在のクラスタ情報を表示する機能が必要なので、ツールに機能追加した。
使用方法はこんな感じ。

$ ./FAT12.exe mona.img print clusters
0x000|ff0 fff fff 658 fff fff 007 008 009 00a 00b 00c 00d 00e 00f
0x00f|010 011 012 013 014 015 016 017 018 019 01a 01b 01c 01d 01e
中略
0xed3|08f 041 bc0 007 000 002 000 100 000 000 000 000 000 000 000
0xee2|000 000 000 000 000 000 8f4 410 000 000 000 000 000 000 000
used = 3266, free= 829


クラスタのダンプと使用・未使用クラスタの数が分かるようになった。
次にdebugという適当なシェルスクリプトをでっち上げる。

#!/usr/bin/bash

./FAT12.exe mona.img print cluster > before.cl         # 操作前のクラスタ状態
./FAT12.exe mona.img $1 $2 $3 $4                       # ファイルシステムに対する何らかの操作
./FAT12.exe mona.img print cluster > after.cl          # 操作後のクラスタ状態
diff -y -d --suppress-common-lines before.cl after.cl  # 操作前後でdiffをとる
rm -f before.cl after.cl                               # 後始末
cp mona.img.bak mona.img                               # ファイルシステム復元


このdebugスクリプトを使用してファイル削除のクラスタ状態を調べる。

bash-2.05b$ ./debug rm MAIN.CPP
0xc21|410 000 26e a05 0f0 000 000 00f 000 500 000 000 b40 108 |	0xc21|410 000 26e a05 0f0 000 000 00e 000 500 000 000 b40 108
0xc7b|000 000 000 000 000 f98 051 90a 004 000 540 215 611 554 |	0xc7b|000 000 000 000 000 f98 051 10a 001 000 500 943 494 64e
0xc8a|e61 4a2 750 004 522 0a0 018 000 000 003 000 000 000 000 |	0xc8a|a42 325 700 114 000 000 f40 053 00a 020 000 4c0 032 000
0xc99|052 80a 21b a05 b00 522 0a0 370 052 00a 23f a05 700 524 |	0xc99|000 400 153 112 346 215 611 020 000 800 001 000 000 000
0xca8|4f0 052 00a 257 a05 f00 525 0a0 048 000 000 001 000 a00 |	0xca8|64e 2e4 a42 325 a00 f00 525 0a0 028 000 000 001 000 a00
0xcc6|108 004 210 053 f0a 000 000 0e0 000 000 005 000 400 08b |	0xcc6|108 004 190 053 f0a 000 000 0e0 000 000 005 000 400 08b
0xd20|002 000 200 000 000 c80 533 0a0 019 000 400 152 112 246 |	0xd20|002 000 200 000 000 480 533 0a0 019 000 400 152 112 246
0xd7a|400 0a0 041 b00 51e 0a0 874 410 800 5d4 a05 280 000 000 |	0xd7a|400 0a0 041 b00 51e 0a0 874 410 800 5c8 a05 280 000 000
0xdd4|000 4d0 e4f 414 548 524 345 000 000 020 000 000 cc0 058 |	0xdd4|000 4d0 e4f 414 548 524 345 000 000 020 000 000 b60 058
0xde3|001 000 400 550 0a0 e18 055 00a 5f1 a05 b00 55f 0a0 030 |	0xde3|001 000 800 54f 0a0 d58 055 00a 5e5 a05 f00 55e 0a0 f70
0xe1f|000 a04 410 000 1eb a05 740 108 004 050 054 a0a 000 000 |	0xe1f|000 a04 410 000 1eb a05 740 108 004 440 054 a0a 000 000
0xe79|000 000 000 000 000 000 000 004 000 200 000 000 400 540 |	0xe79|000 000 000 000 000 000 000 004 000 200 000 000 600 51f
0xe88|019 000 400 152 112 486 593 0a0 b98 054 80a 4c3 a05 180 |	0xe88|019 000 400 152 112 e06 591 0a0 ad8 054 80a 4b6 a05 180
used = 3265, free= 830					      |	used = 3261, free= 834


MAIN.CPPを削除した前後で、4つのクラスタが解放されたことが分かる。(更にどのクラスタが解放されたかも分かる。)
削除された MAIN.CPP のファイルサイズは 2441bytesである。
クラスタサイズが512bytesであるから、512 * 4 < 2441 < 512 * 5が成り立つので、本来であればクラスタは5つ解放されなければならない(汗)
というわけで怪しい動作発見ですね。