V tomto článku si povíme něco o souborových systémech, jimiž byly formátovnány diskety a pevné disky v dobách MS-DOSu a "raných" verzí Windows. FAT souborové systémy se sice stále používají, ale s příchodem Windows NT byly zvláště na pevných discích nahrazeny souborovým systémem NTFS, o kterém si možná v budoucnu také něco řekneme.
Cílem tohoto článku není podat informace o tom, co FAT (ne)umí či jej srovnávat s NTFS (důvody vzniku obou systémů jsou rozdílné), ale podívat se, jak to na médiu formátovaném takovýmto jednoduchým souborovým systémem vypadá.
Mezi FAT souborové systémy patří FAT12, FAT16 (zkráceně zvaný FAT) a FAT32. Mezi nimi nenajdeme zásadní odlišnosti – liší se pouze v několika aspektech (velikostí záznamů v tabulce FAT, umístěním kořenového adresáře). Systém FAT12 je již celkem nezajímavý, protože jej využívaly diskety (nelze s ním formátovat média s velkou kapacitou). FAT16 se používá na USB flash discích, pokud jejich kapacita nepřesahuje řádově několik GB. FAT32 na pevných discích do velikosti 32 GB. 32 GB ale není dáno omezením souborového systému, ale Microsoftem. POmocí aplikací třetích stran samozřejmě můžete zformátovat systémem FAT32 i médium s kapacitou větší 32 GB.
Disk se systémem FAT12 či FAT16 má tuto strukturu:
Rezervované sektory (včetně boot sektoru) |
Tabulky FAT (většinou bývají dvě) |
Kořenový adresář |
Datová oblast (ostatní adresáře, soubory atd.) |
Souborový systém FAT32 je rozdělen pouze na tři oblasti
Rezervované sektory (včetně boot sektoru) |
Vlastní tabulky FAT (většinou bývají dvě) |
Datová oblast (adresáře, soubory. Včetně kořenového adresáře) |
Jednotlivé oblasti nejsou zarovnány na clustery od začátku disku, jak by se mohlo zdát, ale na sektory. Nepočítejte tedy s tím, že by datová oblast začínala na celém clusteru.
Tyto sektory se nacházejí hned na začátku diskového prostoru a obsahují podrobné informace o souborovém systému. Typicky se na FAT12/16 nachází jeden takový sektor – boot sektor – ve FAT32 těchto sektorů bývá třicet dva. Za rezervovanými sektory se ihned nachází tabulky FAT (žádné zarovnání na clustery!).
Prvním rezervovaným sektorem je boot sektor. Jeho struktura je různá v závislosti na FATu, kterým je disk formátován. Prvních 36 bytů však mají všechny FATy společných. Struktura je následující:
Název | Offset | Velikost | Popis |
JMPBoot | 0x000 | 3 | Instrukce skoku na zaváděcí kód. Sem předá BIOS řízení |
OEMName | 0x003 | 8 | Řetězec. Obyčejně je zde hodnota „MSWIN41“. OS na ni nedbá (některé drivery bohužel ano) |
BytesPerSector | 0x00B | 2 | Počet bytů na sektor. Většinou 512 |
SectorsPerCluster | 0x00D | 1 | Velikost clusteru v sektorech |
ReservedSectors | 0x00E | 2 | Počet rezervovaných sektorů (u FAT12/16 většinou 1, u FAT32 většinou 32) |
NumberOfFATs | 0x010 | 1 | Počet FAT tabulek. Obyčejně bývá 2 |
RootEntriesCount | 0x011 | 2 | Maximální počet položek v kořenovém adresáři (pouze pro FAT12/16). Pro FAT32 se rovná 0 |
TotalSectors16 | 0x013 | 2 | Počet sektorů na disku. Význam má pouze pro FAT12/16. Používá se tehdy, je-li počet sektorů menší 65536 |
MediaDescriptor | 0x015 | 1 | 0xF8 – pevný disk
0xF0 – vyjímatelný disk
Zastaralé
|
FATSize16 | 0x016 | 2 | Velikost jedné FAT tabulky (pouze pro FAT12/16, jinak 0) v sektorech |
SectorsPerTrack | 0x018 | 2 | |
NumberOfHeads | 0x01A | 2 | |
HiddenSectors | 0x01C | 4 | Počet sektorů předcházejících partition na disku. Ale pozor! Záleží to jen na OS, co tam bude |
TotalSectors32 | 0x020 | 4 | Pokud je počet sektorů disku/partition větší než 65536, je uložen na tomto místě a TotalSectors16 je 0 |
V systémech FAT12 a FAT16 je struktura dalších 476ti bytů následující:
Název | Offset | Velikost | Popis |
DriveNumber | 0x024 | 1 | Číslo disku (pro INT 0x13). 0 = první disk (A), 1 = C atd. Známe z DOSu |
Reserved1 | 0x025 | 1 | Rezervováno |
BootSignature | 0x026 | 1 | Pokud je 0x29, tři další položky se v boot sektoru nacházejí |
VolumeID | 0x027 | 4 | Sériové číslo. Obyčejně vzniká kombinací data a času |
VolumeLabel | 0x02B | 11 | Název disku (pro názvy delší než 11 znaků se v kořenovém adresáři vytváří soubor s atributem 0x08 |
FileSystemType | 0x036 | 8 | Buď „FAT12 “, nebo „FAT16 “. Ale nespoléhejte se na to. Microsoft vymyslel mnohem rafinovanější způsob, jak určit typ FATu, kterým je disk zformátován |
Do offsetu 0x1FE se nachází zaváděcí kód operačního systému. Posladní dva byty sektoru obsahují značku konce sektoru.
Ve FAT32 to vypadá trochu jinak:
Název | Offset | Velikost | Popis |
FATSize32 | 0x024 | 4 | Velikost jedné tabulky FAT v sektorech |
ExtFlags | 0x028 | 2 | Bit 0-3 je počet aktivních FAT tabulek (když je zrcadlení zakázáno)
Bit 7 = 0 – tabulka FAT je zrcadlena do ostatních
Bit 7 é 1 – Pouze jedna tabulka FAT je aktivní (viz bity 0-3)
Zbytek je rezervován |
FSVersion | 0x02A | 2 | Horní byte – majoritní verze souborového systému
Dolní byte – minoritní verze souborového systému
Standardně 0, 0. Dovoluje rozšířit možnosti FAT32, aniž bychom se museli bát nekompatibility se starými disky |
RootCluster | 0x02C | 4 | Index do FAT tabulky pro kořenový adresář. Obvykle 2. NENÍ TO POINTER NA KOŘENOVÝ ADRESÁŘ!!! |
FSInfo | 0x030 | 2 | Číslo sektoru, kde je uložena struktura FSINFO (bude to jeden z rezervovaných sektorů) |
BackupBootSector | 0x032 | 2 | Číslo rezervovaného sektoru, kde se nachází kopie tohoto boot sektoru |
Reserved1 | 0x034 | 12 | Rezervováno pro budoucí využití |
DriveNumber | 0x040 | 1 | Stejná účel jako pole v boot sektoru pro FAT12/16 |
Reserved2 | 0x041 | 1 | Zase rezervováno pro bůhvíco |
BootSignature | 0x042 | 1 | Stejné jako u FAT12/16 |
VolumeID | 0x043 | 4 | Stejné jako u FAT12/16 |
VolumeLabel | 0x047 | 11 | Název disku |
Pak opět následuje položka FsType (na 8 bytů a má mít hodnotu „FAT32 “. Offset 0x052). Do offsetu 0x1FE je pak zaváděcí kód operačního systému. Poslední dva byty jsou opět vyplněny značkou konce boot sektoru.
Tabulky FAT se nachází hned za posledním rezervovaným sektorem. V drtivé většině případů bývají dvě. Adresa počátku první tabulky se tedy vypočítá takto:
Tabulka_FAT = BootSector.ReservedSectors * BootSector.BytesPerSector
Tabulka FAT je vlastně pole záznamů. Pro každý cluster z datové oblasti disku je zde jeden záznam, který udává stav tohoto clusteru. Velikost záznamů je 12 bitů pro FAT12, 16 bitů pro FAT16 a 32 bitů pro FAT32. První cluster datové oblasti se v tomto poli nachází pod indexem 2. První záznam (index 0) totiž obsahuje stejnou hodnotu jako BootSector.MediaDescriptor a druhý (index 1) je vyplněn jakousi značkou. Význam hodnot záznamů (pro index větší než 1) je v následující tabulce.
FAT12 | FAT16 | FAT32 | Popis |
0x000 | 0x0000 | 0x?0000000 | Volný cluster |
0x001 | 0x0001 | 0x?0000001 | Rezervovaný cluster |
0x002 – 0xFEF | 0x0002 – 0xFFEF | 0x?0000002 – 0x?FFFFFEF | Zaplněný cluster. Hodnota obsahuje číslo následujícího clusteru (tvoří se jednosměrné spojové seznamy) |
0xFF0 – 0xFF6 | 0xFFF0 – 0xFFF6 | 0x?FFFFFF0 – 0x?FFFFFF6 | Rezervováno |
0xFF7 | 0xFFF7 | 0x?FFFFFF7 | Špatný cluster |
0xFF8 – 0xFFF | 0xFFF8 – 0xFFFF | 0x?FFFFFF8 – 0x?FFFFFFF | Cluster je posledním clusterem souboru (adresáře) |
Pozor na to, že systém FAT32 nepoužívá ze záznamů ve FAT tabulce 32 bitů, ale pouze 28. Zbývající bity mohou mít libovolnou hodnotu (příslušné místo je proto určeno znakem „?“).
FAT12 a FAT16 mají vyčleněno speciální místo pro kořenový adresář. Kořenový adresář má tedy omezenou velikost. Maximální počet položek v něm je obsažen v BootSector.RootEntriesCount. Adresu vypočítáme následujícím způsobem:
RootDir = Tabulka_FAT + BootSector.NumberOfFATs * BootSector.FATSize16 *
* BootSector.BytesPerSector
Kořenový adresář (stejně jako ostatní adresáře) se skládá ze záznamů o velikosti 32 bytů, jejichž struktura bude popsána později.
Určit velikost kořenového adresáře není až tak prosté, jak se zdá. Nikdo totiž netvrdí,že je zarovnán na sektory – a na sektory zarovnávat musíme. Velikost tedy dostaneme takto:
RootDir_Size = (BootSector.RootEntriesCount *
* 32 + BootSector.BytesPerSector – 1) / BootSector.BytesPerSector
Tak dostaneme v sektorech – pokud chceme v bytech, musíme vynásobit BootSector.BytesPerSector.
Kořenový adresář ve FAT32 má naprosto stejnou strukturu jako jakýkoli jiný adresář. Jelikož se již nachází v datové oblasti (zaujímá hned první cluster, popř. i další, obsahuje-li hodně položek), jsou clustery, které jej obsahují, popsány v tabulce FAT. To dovoluje kořenovému adresáři obsahovat mnoho položek – jednotlivé clustery pak vytvoří spojový seznam. Počátek kořenového adresáře ve FAT32 vypočítáme tedy následovně:
RootDir = Tabulka_FAT + (BootSector.NumberOfFATS *
* BootSector.FATSize32) * BootSector.BytesPerSector
Datová oblast začíná ihned za kořenovým adresářem (v případě FAT12/16), nebo hned za posledním sektorem poslední tabulky FAT (v případě FAT32). Pro systémy FAT12/16 vypočteime počátek datové oblasti takto:
Data = RootDir + RootDir_Size * BootSector.BytesPerSector
Pro FAT32 vypočítáme takto:
Data = RootDir
V datové oblasti se nacházejí adresáře a soubory. Každá adresářová položka je charakterizována záznamem dlouhým 32 bytů, který v sobě obsahuje ukazatel na první cluster dat. Rozdíl mezi souborem a adresářem je jen v tom, že adresář ve svých datech obsahuje svoje podadresáře a „podsoubory“. Jelikož nelze poznat, co jsou data adresáře a co data souboru, musíme vždy začít od kořenového adresáře a postupně se stromem propracovat.
Struktura záznamu adresářové položky vypadá takto:
Název | Offset | Velikost | Popis |
Name | 0x00 | 11 | Krátké jméno (8 + 3 znaků) |
Attributes | 0x0B | 1 | Atributy. Mohou nabývat těchto hodnot:
ATTR_READONLY 0x01
ATTR_HIDDEN 0x02
ATTR_SYSTEM 0x04
ATTR_VOLUME_ID 0x08
ATTR_DIRECTORY 0x10
ATTR_ARCHIVE 0x20
ATTR_LONG_NAME 0x0F
ATTR_DEVICE 0x40 |
NTRes | 0x0C | 1 | Rezervováno pro Windows NT |
CreateTime_Sec | 0x0D | 1 | Čas vytvoření - setiny sekundy (validní hodnoty 0 – 199) |
CreateTime | 0x0E | 2 | Hodina, minuta a sekunda vytvoření souboru (přesnost na 2 s) |
CreateDate | 0x10 | 2 | Datum vytvoření (DOS formát) |
LastAccessDate | 0x12 | 2 | Datum posledního přístupu (DOS formát) |
ClusterHi | 0x14 | 2 | Horní WORD čísla prvního clusteru s daty adresářové položky (validní pouze pro FAT32) |
WriteTime | 0x16 | 2 | Čas posledního zápisu (DOS formát) |
WriteDate | 0x18 | 2 | Datum posledního zápisu (DOS formát) |
ClusterLO | 0x0A | 2 | Dolní WORD čísla prvního clusteru s daty adresářové položky (pro FAT12/16 je to vlastně celé číslo clusteru). Jedná se pravděpodobně o index do tabulky FAT – číslo clusteru v datové oblasti bude o 2 nižší |
FileSize | 0x0C | 4 | Velikost souboru v bytech |
Každá adresářová položka má na disku záznam v této podobě. Pokud však daná položka má dlouhé jméno, tento záznam je předcházen speciálními strukturami, které to dlouhé jméno obsahují. Tyto struktury mají rovněž 32 bytů a každý z nich obsahuje 13 znaků jména položky v kódování UTF-16. Těchto záznamů je povoleno maximálně 20 pro každou adresářovou položku. Z toho tedy vyplývá maximální délka názvu souboru (adresáře) - 260 znaků. Struktura tohoto speciálního záznamu je následující:
Název | Offset | Velikost | Popis |
SequenceNumber | 0x00 | 1 | Pořadové číslo záznamu. Maximální hodnota je 0x14..Význam vysvětlen níže |
Name1 | 0x01 | 10 | 5 znaků jména v UTF-16 |
Attributes | 0x0B | 1 | Vždy 0xF. Mají stejný offset jako ve struktuře položky s krátkým názvem |
Type | 0x0C | 1 | Rezervováno. Když je 0, prý jde o adresář |
CheckSum | 0x0D | 1 | Nějaký kontrolní součet. Aby se poznalo, které krátké jméno patří k jakému dlouhému |
Name2 | 0x0E | 12 | Znaky 6-11 v UTF-16 |
FirstClusterLO | 0x1A | 2 | Musí být 0 |
Name3 | 0x1C | 4 | Znaky 12-13 v UTF-16 |
Mějme adresářovou položku, jejíž jméno se vejde do N záznamů. Na disku to bude vypadat následovně.
„Dlouhý“ záznam s pořadovým číslem N. Pořadové číslo je ORováno hodnotou 0x40. Tím se dává na vědomí, zde začíná řada „dlouhých“ záznamů adresářové položky |
„Dlouhý“ záznam s pořadovým číslem N - 1 |
... |
„Dlouhý“ záznam s pořadovým číslem 1 |
„Krátký“ záznam. Zde se dozvíme všechny informace o adresářové struktuře |
Vše ukážeme na příkladu. V kořenovém adresáři diskového oddílu „C“ se nachází složka „Systém Volume Information“. Na disku to bude vypadat takto:
„Dlouhý“ záznam s pořadovým číslem 0x42 (0x2 OR 0x40). Obsahuje část jména – podřetězec „ Information“ |
„Dlouhý“ záznam s pořadovým číslem 0x01. Obsahuje část jména – podřetězec „Systém Volume“ |
„Krátký“ záznam. Obsahuje krátké jméno adresáře, atributy a všechny ostatní informace |
Z příkladu vidíme, jaký význam má pořadové číslo „dlouhého“ záznamu a také to, jak je jméno do jednotlivých struktur zapsáno – odzadu dopředu.
Typ použitého FAT systému se zjišťuje naprosto jedinečným způsobem, který mohl vymyslet pouze opravdový génius. Géniů asi mají v Microsoftu mnoho, tudíž není divu, že technika zjištění typu FAT systému je tak dokonalá. Typ se určí tak, že se spočítá počet clusterů v datové oblasti. Je-li menší než 4086, jedná se o FAT12, je-li vypočtená hodnota mezi 4086 a 65526, jedná se o FAT16. Pokud je clusterů více než 65526, jde o FAT32. Toto je napsáno přímo ve specifikaci souborového systému FAT. Na řetězce „FATXX “, které se nachází v boot sektoru se prý nemá spoléhat.