![]() |
FAT датируется аж 1977-годом и пришла к нам из проприетарного DOS. Благодаря простой реализации, сейчас это способ хранения данных на таких носителях как USB-брелки, карты-памяти телефонов и ЦФК, в EFI для хранения кода загрузчика, в системах реального времени RTOS, и многое другое. В данной статье рассматриваются гендерные признаки зоопарка FAT, и в какую сущность превратила эволюция конкретно взятую FAT32. Детальный её разбор позволит понять алгоритм восстановления удалённых файлов, а так-же подтолкнёт на создание своих утилит форматирования, с широким спектром логической геометрии. Из инструментов понадобится любой (способный работать с дисками) HEX-редактор типа WinHex или HxD, штатный калькулятор Win, испека на FATот Microsoft.
https://forum.antichat.xyz/attachmen...5d0ea65b56.png Оглавление: 1. Вводная часть; 2. Загрузочная запись и блок BPB – Bios Parametr Block; 3. Таблицы FAT – File Allocation Table; 4. Корневой каталог "RootDir"; 5. Практика – разбор служебных структур; 6. Заключение. 1. Вводная часть В основе проектирования операционных систем лежит работа с информацией. Здесь перед инженерами встают три задачи: во-первых определиться с типом накопителей (HDD, SSD, Flash), чтобы предоставить системе соответствующий драйвер. Второй момент – это способ хранения данных в виде файловых систем Ext, HPFS, FAT, NTFS и прочие. Но что ещё немаловажно, это предусмотреть возможность восстановления инфы в случае критических сбоев. Последний вопрос стоит ребром, что побудило Microsoft создать до блеска отшлифованную NTFS (New-Technology-File-System). Её мы не будем пока трогать, и отправив на скамейку запасных, рассмотрим только FAT. 1.1. Иерархия: диск[сектор] + том[кластер] Для начала разберём геометрию накопителей. • На нижнем уровне, производитель делит всю поверхность на 512-байтные сектора (отсчёт с единицы). Но утилиты и ОС могут предоставлять нам секторы > 512-байт, однако они по-любому будут кратны 512, например 1024-байт. Сектор – мин.порция обмена с диском, мы не сможем прочитать с него кол-во байт не кратное 512. Это нужно учитывать при вызове функций Read/WriteFile(). Самый первый сектор всегда отводится под MBR (MasterBootRecord), где указывается объём накопителя, и смещение к его логическому тому. Вместо устаревшей трехмерной CHS с лимитом в 8 ГБ, в современном мире используется уже линейный подход LBA48 (48-bit Logical Block Address), в которой секторы нумеруются с нуля, а не как прежде с единицы. LBA позволяет адресовать диск размером 128 ПетаБайт, при размере блока 512. • ОС не может хранить файлы на дисках без логических разделов (том, volume, макс=26 с литерами от А: до Z. Значит нужно создать этот том, и установить на него какую-нибудь файловую систему (далее FS), чтобы ОС знала о порядке расположения файлов – эта операция известна как форматирование. Бинарные файлы можно сбрасывать и на "сырой" RAW-том, только за доступ к ним будем отвечать уже сами. Такой изврат применяется редко, например при работе с дисками без поддержки их со-стороны ОС (см.прерывание BIOS int-13h). • Допустим, имеем первый раздел C:\. Его смещение от начала диска указывается в секторе(1) MBR. У всех накопителей, первый раздел начинается как-минимум с сектора(63). Если учесть, что непосредственно данные и код MBR занимают всего 1-сектор, следовательно перед началом тома в загашнике остаётся аж 62 свободных, а это: 62*512=31 КБ пространства, где можно скрыть от FS конфиденциальную инфу. Важно понять, что FS устанавливается не на диск, а на его логический том, поэтому драйвер считает началом тома LBA(0), хотя в глазах биоса это сектор(63). Такой расклад создаёт путаницу, но достаточно запомнить, что функцией CreateFile() можно открыть как физ.диск (тогда LBA(0) указывает на его начало), а можно запросить и логический том диска, например по букве C:\. В этом случае LBA(0) считается уже указателем на начало раздела. То-есть всё зависит от того, какой объект мы открываем. • Каждая запись в таблице FAT указывает на определённый блок-информации в области данных. Если указателями адресовать мелкие секторы диска, то во-первых нужно будет увеличить разрядность этих указателей до 64-бит (т.к. диски могут быть исполинских размеров), а во-вторых потребуется огромное кол-во самих линков, что повлияет на размер таблицы. Файлы до 512-байт встречаются редко, а значит нет смысла искать их в каждом секторе. По этой причине, несколько секторов всегда собираются в "кластер", что позволяет увеличить полезное пространство, за счёт уменьшения таблицы FAT. C дефолтными настройками, все FS создают кластеры размером 4096-байт, а это 8-секторов. В служебной таблице FAT лежат теперь указатели не на секторы, а на кластеры, и соответственно размер её сокращается в 8-раз! Но помимо плюсов есть и минусы.. Если в txt-файле у нас 11-байтная строка "Hello World", на диске этот файл будет занимать 4 КБ, т.к. мин.блоком хранения данных уже получается кластер. Зайдите в свойства любого файла и посмотрите, какой он имеет реальный размер, и сколько ему выделено на диске: https://forum.antichat.xyz/attachmen...45c7360524.png Как видим – картина удручающая, и при кластерном распределении у нас улетает в трубу огромная часть пространства. Но говорят, "случaйнaя удaчa принocит бoльшe рaдocти, чeм зaкoнoмeрный уcпex", и видимо инженеры с этим согласны. Здесь они вынуждены сесть на шпагат и только надеяться, что большинство файлов юзера будут размером больше 4КБ. Исключительно в этом случае экономия на размере таблицы оправдает себя. Чтобы предотвратить суицид крайне впечатлительных юзверей, инженеры построили себе хату-с-краю, и предложили нам самостоятельно выбирать кол-во секторов в кластере – данный параметр имеется у большинства приличных утилит форматирования и называется "SectorPerCluster". Если у вас много мелких файлов и вы считаете 4КБ для хранения каждого из них слишком расточительным, то всегда можете изменить размер кластера в диапазоне от 512-байт, до 64КБ. Вот скрин одной из таких утилит "Fat32format": https://forum.antichat.xyz/attachmen...0bddc6a9e8.png 1.2. ОрганизацияFAT– вид сверху На рис.ниже представлены основные отличия FAT12/16, от более совершенной FAT32. Здесь видно, что раньше, в системной области четыре служебные структуры располагались плотно друг-к-другу: это блок параметров BPB с адресом LBA(0) (не путать с MBR), далее основная таблица FAT, следом её резервная копия FAT2, и в хвосте корневой каталог. Размер таблицы зависит от общего кол-ва секторов в накопителе. Очевидно, что чем больше размер диска, тем больше в нём кластеров, и соответственно больше указателей на кластеры в таблице FAT. Теперь посмотрим на организацию FAT32 справа.. Корневой каталог уже съехал с насиженных мест и может находится где угодно. Драйвер FS считает его обычным файлом с доступом на запись, что даёт возможность каталогу RootDir расширяться динамически. Кроме того, блок BPB разбух с одного до трёх секторов, хотя в FSInfo нет ничего интересного, а последний отправлен в резерв для наших потомков. Причём имеется и зеркало ВРВ, всегда по адресу LBA(6). В доке на FAT32 эту область назвали "Резервные сектора", сразу после которых расположилась уже таблица FAT со-своей копией. Благодаря такой организации, драйвер FS может восстанавливать теперь не только таблицу FAT, но и загрузочный сектор ОС в блоке параметров BPB. https://forum.antichat.xyz/attachmen...74fbb6c1d8.png 2. Загрузочная запись и блокBPB – Bios ParametrBlock В самом начале тома с адресом LBA(0), во всех версиях FAT лежит блок параметров биос ВРВ. Он занимает ровно один 512-байтный сектор и содержит в себе базовые параметры файловой системы, а так-же код загрузчика ОС с сигнатурой 0x55AA. Запустим HEX-редактор и через меню "Инструменты" откроем в нём свою флэш – вот как это выглядит у меня: https://forum.antichat.xyz/attachmen...3a17b57723.png Загрузчик нас не интересует, ..более того, если Flash не загрузочная, Boot-block вообще забит нулями, и это часто практикуется (например на microSD телефонов). Зато ВРВ критически важен для драйвера, посколько именно в нём зарыта инфа о расположении оставшихся трёх/системных структур – это парочка FAT, и корневой каталог RootDir. Для программного доступа к этому блоку я создал инклуд, и поместил в него структуру ВРВ с описанием каждого поля. Здесь-же перечислю только те поля, которые откроют нам доступ к FAT и корневому каталогу: https://forum.antichat.xyz/attachmen...14ed5888e1.png В спеке на FAT32 от Microsoft говорится, что положение корневого каталога "RootDir" строго не регламентируется, и он может лежать в произвольном кластере области данных. Однако на практике, Root в моих тестах всегда расположен сразу после двух таблиц FAT, т.е. адрес его фиксирован. Не знаю, может и есть в природе отбившиеся от стада утилиты форматирования, но лично мне таковые ещё не встречались. В любом случае, найти каталог можно по приведённой выше формуле, и если это штатный форматер Win (как и большинство других), то вторая часть формулы Код:
(RootCluster-2) * SectorPerCluster3. ТаблицаFAT – File AllocationTable Теперь выйдем из матрицы, и поговорим о более насущном.. Организация любой файловой системы – невероятно сложный механизм. Однако в случае с FAT, это утверждение сильно притянуто за-уши. Именно благодаря свой простоте она дожила до наших дней и не собирается уходить со-сцены, а наоборот мутировала в 64-битную ExFAT. Значит чтобы получить указатель на таблицу, нужно прочитать поле "RsvdSectorCount" структуры ВРВ. В данном случае там прописан сектор(1000), и если умножить его на 512, получим смещение в байтах от начала тома = 0x0007D000. Далее, читаем из той-же ВРВ поле "FATSz32" с размером, и передаём оба полученных значения функции ReadFile(). Так, в приёмном буфере функции получим дамп таблицы FAT, для её детального разбора. Таблица – это массив указателей на кластеры, без каких-либо служебных полей. Отсчёт кластеров в массиве начинается с нуля, а разрядность указателей 32-бит (отсюда и название FAT). Старшие 4-бита отправлены в резерв, остаётся 28. Тогда получается, что FAT32 может адресовать всего: Код:
2^28=268.435.456На рисунке ниже представлен фрагмент таблицы FAT (для удобства, в меню "Вид" сгруппируйте отображение по 4-байта). • Два/первых элемента массива всегда равны Код:
0x0FFFFFF8Код:
0xFFFFFFFFhttps://forum.antichat.xyz/attachmen...c42ebeb18c.png • 32-битные элементы начиная со-смещения(8), отображают уже состояние соответствующих кластеров в области-данных диска. Он может быть свободным(0), выделенным(2), зарезервированным(F6) или повреждённым(F7). Элемент с макс.значением Код:
0x0FFFFFFF• Древовидная структура расположения файлов на диске, начинается с корневого каталога – мы не видим его среди привычных нам папок, но он присутствует всегда. Ему назначается имя в виде "метки тома", которую запрашивает у нас система, при форматировании раздела. Именно поэтому второй элемент таблицы по смещению(8) имеет маркер окончания Код:
0x0FFFFFFFЧтобы продемонстрировать организацию таблицы FAT, я форматнул свою флэш и сбросил на неё всего два файла. Первый размером 7.4КБ, поэтому занимает на диске два 4К-байтных кластера (выделен зелёным), а второй размером 20.2КБ и как видим, загребает 5 (выделенных синим) кластеров. Далее следуют null-элементы, которые информируют о свободном пространстве. Обратите внимание, что после кластера(2), следующий элемент таблицы указывает сразу на кластер Код:
0х00000004Код:
0х0FFFFFFFДело в том, что в таблице FAT хранятся указатели на следующие кластеры файла, а первый – прописывается в корневом каталоге RootDir, где лежит полный паспорт файла. То-есть когда файл меньше 4096-байт, выделенный под него первый кластер указывается в корневом каталоге, а в таблице получим лишь связанный с ним EOC. Но если файл выходит за границы одного кластера, то следующие указываются уже в таблице FAT, пока не встретится маркер окончания. 4. Корневой каталог "RootDirectory" Файловая система требует базы, где хранилась-бы информация о всех, существующих на диске, файлах. Для FAT32(16) такой базой является "корневой каталог". Чтобы описать свойства одного файла, инженерам потребовался блок размером в 32-байта, где можно найти: имя файла/каталога в формате 8.3, его размер, дату создания, атрибуты, а так-же номер первого кластера, с которого начинается данный файл. Если-же хвост файла торчит снаружи выделенного кластера, номер следующего указывается уже в таблице FAT. Иначе, в таблице будет прописан только маркер окончания EOC. Таким образом, таблица и корневой-каталог логически связаны между собой, и потеря любого из них приведёт к краху всей FS. В доках, 32-байтную запись каталога назвали SFN, что подразумевает "Short File Name". Короткая (short) она потому, что хранит имя в досовском формате(8.3). Но в современном мире мы уже отвыкли от всевозможных рамок, и предпочитаем для файлов более длинные имена, которые Win всё-же ограничивает до 256-символов. Поэтому в FAT предусмотрена родственная к SFN структура LFN (Long) – она имеет такой-же размер 32-байт, но является не самостоятельной, а дополнением к SFN. Если в имени файла меньше 8-ми символов, структура LFN может вообще отсутствовать, но SFN в наличии всегда. Нужно признать, что организация длинных имён в FAT выполнена через известное место. Так, каждая структура LFN несёт в себе макс. 13-символов имени файла, а если их больше, то добавляется ещё одна структура и получаем 26-символов. Если-же и этого мало, то подключается сл.структура и т.д. Причём имя задаётся в Unicode (где на каждый символ расходуются по 2-байта) и внутри одной структуры разбросано по трём/разным полям. Более того, порядок следования цепочки структур обратный – т.е. сначала идёт последняя LFN(x), после неё LFN(x-1) и далее в том-же духе. Общее кол-во структур указывается в первом байте "Ordinal". Здесь становится очевидным, что разработчик явно был под веществами. Выше упоминалось, что LBA каталога можно найти по формуле из ВРВ: Код:
RsvdSecCount + (FATSz*2) + ((RootCluster-2) * SecPerCluster)Проясним некоторые моменты.. 1. Первая структура SFN (синий блок) будет всегда описывать корневую папку диска. Это единственная структура, которой может быть присвоен атрибут "VolumeID" со-значением 08h. Атрибуты файлов/каталогов лежат по смещению(0Вh) от начала структур, и я заключил их в синий овал. Все остальные поля первой структуры SFN считаются не действительными! 2. На моей флэш всего два файла с именами "dCrypt.asm" и "usbVIDbase.txt". Чем руководствуется драйвер FAT при добавлении к SFN структуры LFN остаётся загадкой, поскольку имя первого файла меньше 8-ми символов, но дров всё-равно вставил LFN (см.красный блок). А вот имя второго файла уже 10-символов, и для него выделено две LFN в зелёном блоке. Обратите внимание, что у первой в поле-ординала лежит значение(1) (+40h маска), а у второй LFN ординал равен(2). Эти поля я выделил чёрным, и они определяют кол-во структур LFN для текущего файла. Записи LFN можно обнаружить по атрибуту(0F). https://forum.antichat.xyz/attachmen...dc4df09040.png Из чёрной таблицы с расшифровкой полей видно, что номер первого кластера разделён на две части Hi/Low. Первый файл "dCrypt.asm" размером 7.4КБ и начинается с кластера(3). Но поскольку он требует два 4К-байтных, следующий указывается уже в таблице FAT (см.зелёный dword на предыдущем скрине). Здесь нужно отметить, что номера кластеров представляются относительно начала области-данных, которая совпадает с началом рассматриваемого корневого-каталога RootDir. Так как-же найти злополучный файл на диске? Для этого в спеке FAT32 приведена формула такого вида: Код:
FileFirstCluster = RootDir + (SFN.FstClus - RootCluster)Код: Код:
RootDir = сектор 163844.1. Алгоритм поиска удалённых файлов Когда мы удаляем файл с диска FAT, он фактически остаётся на своём месте и так-же занимает свой кластер. Просто в соответствующей структуре SFN, первому байту присваивается маркер(Е5). Аналогичную ситуацию наблюдаем и в случае "Быстрого форматирования" тома. Такой расклад способствует восстановлению удалённых файлов. Чтобы создать их список, достаточно в корневом-каталоге с шагом в 32, проверять каждый/первый байт на маркер(Е5). В качестве доказательства, я удалил со-своей флэш "usbVIDbase.txt", а второй файл оставил. В результате, SFN удалённого файла(и две предшествующие ей LFN) приобрели вид как на скрине ниже, а причастные к файлу элементы таблицы FAT сбросились в нуль. т.е. кластеры освободились для последующей записи. Таким образом, информация в кластерах удалённых файлов будет доступна нам до тех пор, пока драйвер FS не перезапишет их новыми данными. https://forum.antichat.xyz/attachmen...ca849818c2.png 5. Практика – разбор служебных структур Теперь попробуем автоматизировать весь изложенный процесс.. Код ниже покажет основную информацию об USB-Flash или карте-памяти, если они имею формат FAT32. Здесь есть нюанс, на который советую обратить внимание.. Значит получаем букву диска, и проверяем его на съёмный носитель "Removable". Если ок, то открываем раздел диска через CreateFile(), и пытаемся прочитать с него сектор ВРВ. Суть в том, что читать рекомендуется в асинхронном режиме, поскольку том может быть занят кем-то другим, например антивирусом. Если функцией ReadFile() читать синхронно, то функция может вернуть ошибку, мол диск недоступен. Поэтому мы используем асинхронный режим, в котором запрос ставится в очередь, а нам после вызова необходимо выждать пару секунд при помощи Sleep(). Этот способ требует в параметрах ReadFile() указатель на структуру "OVERLAPPED" и никогда не даёт осечек. C-подобный: Код:
format pe consoleВо-втором случае я решил поинтересоваться картой-памяти своего телефона и обнаружил, что размер кластера у неё 32КБ, поэтому и таблица FAT намного меньшего размера: была 7.692 секторов в длину, а стала 951. Более того, и сам том начинается не как обычно с физ.сектора(63), а съехал аж к сектору(8192), о чём говорит поле "Volume First LBA". В такой организации пространства есть смысл, т.к. нам заранее известны ориентировочные размеры файлов – это фотки, мультимедиа и прочие, т.е. больше стандартного кластера 4КБ: https://forum.antichat.xyz/attachmen...bf48b08ad1.png 6. Заключение Если не брать во-внимание детали оформления служебных структур, основным недостатком FAT32 является полное отсутствие "инстинкта самосохранения" при критических сбоях. Хорошо хоть инженеры предусмотрели некую пародию, в виде резервных блоков ВРВ и таблицы FAT2. Зато в NTFS всё продумано до мелочей, и в этом большое её преимущество. Например метафайл NTFS под названием "$LogFile" представляет собой журнал последней удачной конфигурации. Если случается крах, то при следующей перезагрузке, все параметры считываются уже из этого журнала, который драйвер NTFS обновляет при обычном выключении компьютера. Однако выбор у пользователей должен быть всегда, и FAT как-раз нам его предоставляет. В скрепке лежит инклуд, и ехе-файл для тестов. Увидимся теперь на пороге Нового года, пока! |
Ох, сколько всего интересного в этой fs, особенно в 32-й, ведь именно там увеличили размер файла до 4гб.
Я помню писал свой драйвер для МК, но только для чтения, только корневого раздела и только wav файлов |
Цитата:
Размер файла определяет поле "DIR_FileSize" в структуре SFN. В обоих FAT32/16 под него выделяется DWORD, однако в FAT16 макс.значение было ограничено числом со-знаком (т.е. 31-бит), поэтому макс.размер файла был 2 ГБ. Начиная с FAT32 данное ограничение было снято, и теперь это DWORD без знака 32-бит = 4 ГБ. |
Цитата:
|
Вырвим жывьем из контекста. "Именно благодаря свой простоте она дожила до наших дней и не собирается уходить со-сцены, а наоборот мутировала в 64-битную ExFAT." Вопрос - почему не NTFS, fat64 лучше ? вроде просто больше адрисация. Или дело в устройствах памяти в разных устройствах.
|
Цитата:
Во-первых в NTFS есть защита файлов (например админ/юзер), а в FAT никогда её не было. Во-вторых, мало иметь эту защиту, но и ОС должна её поддерживать, иначе смысла в ней нет. Поэтому если имеем флэш-накопитель для фотоаппарата, в целях экономии места лучше использовать простую FAT чем NTFS, т.к. защита на ЦФК не нужна в принципе. То-есть здесь вопрос в области применении самих накопителей. |
| Время: 04:29 |