§ Файловая система FAT

Это одна из первых и старых файловых систем. Она очень проста для понимания, и вообще, сама по себе эта файловая система использовалась еще с 1976 года, и придумал ее, конечно же, всеми известный Билл Гейтс (Bill Gates) в соавторстве с Марком Мак Дональдсом (шучу, Мак Даком). Сегодня я слегка разберу, как тут все устроено и что с этим дальше делать.
Файловая система (ФС) состоит из компонентов:
  • Загрузочный сектор с описанием структуры ФС - размер, количество записей, стартовые точки, имя тома и т.д.
  • Собственно, сами таблицы FAT (обычно их 2 копии)
  • Кластеры с данными
Кластер это неделимая единица данных, один кластер может состоять из нескольких секторов, от 1 сектора до сколько угодно секторов, но не более 255. Один сектор занимает 512 байт. Для FAT12, который используется для дискет объемом например, 1.44 Мб, достаточно 1 сектора на кластер. FAT12 может адресовать 2^{12} кластеров, то есть, от 0 до 4095, или, 512 x 4095, что приблизительно равняется 2 Мб. Для одной дискеты этого достаточно. Для большего же объема диска потребуется уже не 12 бит на адрес, а 16 или 32. Все зависит от объема диска.
Несмотря на это, если размер кластера, к примеру, 4Кб, то с помощью FAT12 можно адресовать не 2Мб, а уже 16 Мб. Конечно, более чем 4095 файлов в FAT12 записать вообще невозможно в принципе, поскольку минимально занимаемый объем одного файла может быть только 512 байт, не меньше. Другими словами, файл делится на части по 512 байт (или 1кб, 2кб и т.д.) по кластерами и раскидывается на диске. Это является минусом данной файловой системы.

§ Загрузочный сектор

В целом, рассмотрим три варианта загрузочного сектора:
Общая структура для всех типов ФС.
0x000 |      | 3 байта | JMP ...
0x003 |      | 8 байт  | Строка 8 байт, название ФС, например FAT16
0x00B | 0x00 | 2 байта | Байт на логическом секторе
0x00D | 0x02 | 1 байт  | Логических секторов в кластере
0x00E | 0x03 | 2 байта | Зарезервированых секторов
0x010 | 0x05 | 1 байт  | Количество таблиц FAT
0x011 | 0x06 | 2 байта | Количество элементов корневого каталога
0x013 | 0x08 | 2 байта | Всего логических секторов на диске
0x015 | 0x0A | 1 байт  | Тип носителя
0x016 | 0x0B | 2 байта | Логических секторов в FAT
0x018 | 0x0D | 2 байта | Физические секторов на дорожке
0x01A | 0x0F | 2 байта | Количество головок
0x01C | 0x11 | 4 байта | Скрытых секторов
0x020 | 0x15 | 4 байта | Всего логических секторов
FAT12 и FAT16
0x024 | 0x19 | 1 байт  | Номер физического диска
0x025 | 0x1A | 1 байт  | Флаги
0x026 | 0x1B | 1 байт  | Расширенная загрузочная запись
0x027 | 0x1C | 4 байта | Серийный номер тома (при форматировании)
0x02B | 0x20 | 11 байт | Метка тома
0x036 | 0x2B | 8 байт  | Тип файловой системы
FAT32
0x024 | 0x19 | 4 байта | Размер FAT в логических секторах
0x028 | 0x1D | 2 байта | Двойное поле флагов (два одинаковых байтовых поля)
0x02A | 0x1F | 2 байта | Версия
0x02C | 0x21 | 4 байта | Корневой каталог в кластерах
0x030 | 0x25 | 2 байта | Расположение FSI-структуры
0x032 | 0x27 | 2 байта | Расположение резервных секторов
0x034 | 0x29 | 12 байт | Зарезервировано (имя файла загрузки)
0x040 | 0x35 | 1 байт  | Номер физического диска
0x041 | 0x36 | 1 байт  | Флаги
0x042 | 0x37 | 1 байт  | Расширенная загрузочная запись
0x043 | 0x38 | 4 байта | (dword)	Серийный номер тома
0x047 | 0x3C | 11 байт | Метка тома
0x052 | 0x47 | 8 байт  | Тип файловой системы

§ FAT12

Пример блока загрузки для файловой системы FAT12 для дискеты 1.44 Мб:
1jmp     near start      ; 00 Переход (3 байта)
2db      'FLOPPY12'      ; 03 Имя
3dw      200h            ; 0B Байт в секторе (512)
4db      1               ; 0D Секторов на кластер
5dw      1               ; 0E Количество резервированных секторов перед началом FAT (1 - бутсектор)
6db      2               ; 10 Количество FAT
7dw      00E0h           ; 11 Количество записей в ROOT Entries (224 x 32 = 1C00h байт), 14 секторов
8dw      0B40h           ; 13 Всего логических секторов (2880)
9db      0F0h            ; 15 Дескриптор медиа (F0h - флоппи-диск)
10dw      9h              ; 16 Секторов на FAT
11dw      12h             ; 18 Секторов на трек
12dw      2h              ; 1A Количество головок
13dd      0               ; 1C Скрытых секторов (large)
14dd      0               ; 20 Всего секторов (large)
15db      0               ; 24 Номер физического устройства
16db      1               ; 25 Флаги
17db      29h             ; 26 Расширенная сигнатура загрузчика
18dd      07E00000h       ; 27 Serial Number
19db      'LOADER  BIN'   ; 2B Метка тома
20db      'FAT12   '      ; 36 Тип файловой системы
Это уже готовый к использованию код, поэтому можно его брать для создания бут-сектора для дискет. Как ранее и упоминалось, в "имя" можно написать абсолютно любую строку, можно даже сказать, просто название для файловой системы. Количество байт в секторе неизменно и равно 512 (200h), а количество секторов на кластер, обычно равно 1, потому что такого количества хватит для дискеты.
Резервированные сектора перед началом FAT — это количество секторов, которые необходимо пропустить с текущего положения бутсектора до старта таблиц FAT. В данном случае, таблицы идут сразу же за бутсектором, а он занимает ровно 1 сектор, так что тут число 1.
Во избежание повреждений секторов в одной из FAT, используются 2 копии, поэтому количество FAT здесь равно 2, хотя можно и 3 и более, но это уже будет слишком избыточно. При повреждении одного сектора, используется резервный.
Для FAT12 и FAT16 непосредственно сразу же за таблицами FAT идет корневая директория, которая содержит в себе указанное количество записей, в данном случае их 00E0h (224). Одна запись представляет из себя структуру на 32 байт, которая описывает имя файла и то, где он лежит, его длина, дата создания, и прочие атрибуты. Для файловой системы FAT32 это поле равно 0, поскольку корневая директория указывается в другом месте, и работает иначе. В любом случае, об этом будет рассказано далее.
Логических секторов указано 2880, то есть если 2880 x 512 = 1474560 байт, размер дискеты (1.4 Mb). Дескриптор медиа здесь равен 0xF0, что означает, что это флоппи диск. Секторов на FAT, это общее количество секторов, которые содержатся в таблицах FAT, Здесь их 9, то есть, одна таблица FAT занимает 9 * 512 = 4608 байт. Учитывая, что размер одного элемента FAT12 (именно 12) равен 1.5 байта, то тогда для адресации доступно 4608 / 1.5 = 3072 кластеров. Один элемент FAT указывает на определенный кластер.
Прокомментирую оставшиеся поля:
  • Секторов на трек — 18 секторов на один трек, один цилиндр составляет 2 x 18 = 36 секторов. Как известно, на диске 2880 секторов, а значит, ровно 80 цилиндров. Это легко рассчитать, зная общее количество секторов.
  • Скрытых секторов — количество секторов, которые располагаются до файловой системы, их тут 0. Актуально для для диска
  • Номер физического устройства — поскольку дисковод один, то и номер начинается с 0
  • Флаги и расширенная сигнатура загрузчика всего равны 1 и 29h
  • Serial Number — серийный номер диска, присваивается при форматировании дискеты
  • Метка тома — просто 11-байтное название тома (8+3)
  • Тип файловой системы — обычно сюда пишут название FAT12, FAT16, FAT32
Я расписал только то, как устроен первый сектор файловой системы FAT12. Сразу же за сектором в данном случае идет таблица FAT.

§ Таблица FAT

Как уже и упоминалось ранее, ФС состоит из нескольких частей:
  • Загрузочный сектор с BPB - Bios Parameter Block
  • Таблицы FAT (1 или 2 копии)
  • (Опционально) Корневой каталог
  • Кластеры с данными
Файловая система крайне проста и работает на очень простом принципе цепочечного сбора файлов. Дело в том, что файл может быть разбит на мелкие кусочки и разбросан по всему диску. Как файловая система находит эти кусочки файлов?
Все дело в том, что существует таблица для этого, File Allocation Table. Она выглядит примерно так:
0000 | F000
0001 | FFF0
0002 | 0005
0003 | 0004
0004 | 0006
0005 | 0003
0006 | 0007
0007 | FFF0
....
Эта таблица имеет порядковый номер и значение. Порядковый номер равен номеру кластера, на который он и указывает. Теперь представим, что файл начинается с кластера 2. Сначала читается кластер 2 в память, после чего проверяется позиция 2 в FAT. Как видно, там число 5 — это значит, что будет прочтен кластер 5 и записан в память. Снова проверяем что в позиции 5, а так 3. Читаем кластер 3, проверяем FAT в позиции 3. Там 4. Читаем 4 кластер, и так далее, до тех пор, пока не достигнет значения FFF0 - EOF (End Of File). То есть, прочтя кластер 7, дальнейшее чтение завершается.
Это и есть цепочка сборки файлов из фрагментов. В данном случае, он получилась следующей: 2, 5, 3, 4, 6, 7. Вот, собственно, и все, как устроена таблица FAT.
В случае FAT32, меняется содержание BPB в первом секторе, и вместо того, чтобы использовать корневой каталог (его больше нет), используется указатель на номер кластера, где этот каталог находится. То есть теперь каталог может быть где угодно на диске и быть сколько угодно большим. Можно сказать так, что корневой каталог стал специальным файлом.

§ Файловые записи

Файловые записи используются в каталогах для указания имени файла, его размера, даты, атрибутов и номера кластера, откуда файл начинается. Одна запись занимает 32 байта и содержит в себе имя на 8 байт с расширением на 3. Это базовая запись, существует возможность расширить имя файла до сколь угодно большого размера, но рассматривать в этой статье я не буду, как это получается.
Байты   Длина   Содержание
0x00    8       Файловое имя
0x00    3       Расширение
0x0B    1       Атрибуты
                Бит 0: Только чтение
                Бит 1: Скрытый
                Бит 2: Системный
                Бит 3: Метка тома
                Бит 4: Этот файл является директорией
                Бит 5: Архивный
                Бит 6-7: Не используются

0x0C    1       Зарезервировано
0x0D    1       - Время создания файла (сотые доли секунды) по 10 мс (от 0 до 199)
                - Первый символ удаленного файла (если есть E5 в имени файла)

0x0E    2       Время создания файла (час, минута, двойная секунда)
                Бит 15-11: Часы (0..23)
                Бит 10-5:  Минуты (0..59)
                Бит 4-0:   Секунды, деленные на 2 (0..29)

0x10    2       Дата создания файла
                Бит 15-9:  Год (0 = 1980 ... 119 = 2099 ... 127 = 2107)
                Бит 8-5:   Месяц (1-12)
                Бит 4-0:   День (1-31)

0x12    2       Дата доступа к файлу
0x14    2       Старшие 2 байта номера первого кластера файла
0x16    2       Время модификации (час, минута, двойная секунда)
0x18    2       Дата модификации
0x1A    2       Младшие 2 байта номера первого кластера файла
0x1C    4       Размер файла (до 4 Гб)
Для времени используется формат 5/6/5, где указывается час/минута/двойная секунда.