OSD Home

- # - FAT filesystem
  - # - Layout of a FAT volume
  - # - FAT bootsector and BPB
  - # - FAT directory entries
  - # - The FAT
- # - ext2 filesystem
- # - ISO-9660 (CD-ROM) filesystem
- # - Overview of common filesystems
- # - Filesystem code snippets
- # - Links
- REPORT BUGS OR ERRORS IN THIS DOCUMENT

## FAT filesystem

FAT stands for File Allocation Table, the main feature of this filesystem. The FAT filesystem is associated with DOS and some versions of Windows. VFAT (virtual FAT) is FAT with long filenames.

Newly-purchased floppy disks advertised as 'formatted' usually contain a FAT12 filesystem.

### Layout of a FAT volume

A FAT volume contains:

- boot sector (more than one for FAT32)
- one or more copies of the FAT (almost always 2 copies)
- root directory (not present for FAT32)
- the data area, where files and subdirectories are stored. For FAT32, the root directory is also stored here.

### FAT bootsector and BPB

The FAT boot sector contains:

- Code to load and run the DOS kernel
- The poorly-named BIOS Parameter Block (BPB), with disk geometry and filesystem info. The BPB corresponds to the superblock of UNIX filesystems.
- Magic values: 55h at offset 510, 0AAh at offset 511.

Layout of FAT12/FAT16 bootsector with minimal BPB:

    typedef unsigned char	uint8_t;	/* or #include <stdint.h> */
    typedef unsigned short	uint16_t;	/* Note: multi-byte values are little-endian */
    typedef unsigned long	uint32_t;
    struct fat_bootsector			/* Warning: this struct must be packed */
    {
            uint8_t  jump[3];               /* 16-bit JMP to boot code, or 8-bit JMP + NOP */
            uint8_t  oem_id[8];             /* e.g. 'MSWIN4.0' */
    	uint16_t bytes_per_sector;	/* usu. =512 */
            uint8_t  sectors_per_cluster;
    	uint16_t num_boot_sectors;	/* usu. =1 */
            uint8_t  num_fats;              /* usu. =2 */
    	uint16_t num_root_dir_ents;
            uint16_t total_sectors;         /* 16-bit; 0 if num sectors > 65535 */
            uint8_t  media_ID_byte;         /* usu. =0F0h */
    	uint16_t sectors_per_fat;
    	uint16_t sectors_per_track;
    	uint16_t heads;
    	uint32_t hidden_sectors;	/* =LBA partition start */
            uint32_t total_sectors_large;   /* 32-bit; 0 if num sectors < 65536 */
            uint8_t  boot_code[474];
            uint8_t  magic[2];              /* 55h, 0AAh */
    };                              /* 512 bytes total */

There are additional fields which are required by FAT32, but are optional for FAT12 and FAT16 (xxx - todo).

### FAT directory entries

FAT directory entries are 32 bytes long:

    typedef unsigned char	uint8_t;	/* or #include <stdint.h> */
    typedef unsigned short	uint16_t;	/* Note: multi-byte values are little-endian */
    typedef unsigned long	uint32_t;
    struct fat_dirent               	/* Warning: this struct must be packed */
    {
            uint8_t  name[8];               /* ALL-CAPS, pad right with spaces */
            uint8_t  ext[3];                /* ALL-CAPS, pad right with spaces */
            uint8_t  attrib;                /* attribute byte */
            uint8_t  reserved;              /* =0 */
            uint8_t  ctime_ms;              /* file creation time, 10ms units */
    	uint16_t ctime;              	/* file creation time, in DOS format */
    	uint16_t cdate;              	/* file creation date, in DOS format */
    	uint16_t adate;              	/* DOS date of last file access */
    	uint16_t st_clust_msw;       	/* high 16 bits of starting cluster (FAT32) */
    	uint16_t mtime;              	/* DOS time of last file modification */
    	uint16_t mdate;              	/* DOS date of last file modification */
    	uint16_t st_clust;           	/* starting cluster */
    	uint32_t file_size;          	/* in bytes */
    };                              /* 32 bytes total */

DOS times and dates are stored in these formats:

    struct dos_time                 /* Warning: this struct must be packed */
    {
    	unsigned two_secs : 5;  /* low 5 bits: 2-second increments */
    	unsigned minutes : 6;   /* middle 6 bits: minutes */
    	unsigned hours : 5;     /* high 5 bits: hours (0-23) */
    };                              /* 2 bytes total */

    struct dos_date                 /* Warning: this struct must be packed */
    {
    	unsigned date : 5;      /* low 5 bits: date (1-31) */
    	unsigned month : 4;     /* middle 4 bits: month (1-12) */
    	unsigned year : 7;      /* high 7 bits: year - 1980 */
    };                              /* 2 bytes total */

The Attribute byte is similar to the file 'mode' under UNIX filesystems:

    struct attrib                   /* Warning: this struct must be packed */
    {
    	int read_only : 1;      /* b0 */
    	int hidden : 1;
    	int system : 1;
    	int volume_label : 1;
    	int directory : 1;
    	int archive : 1;
    	int reserved : 2;       /* b6, b7 */
    };                              /* 1 byte total */

FAT directory entries contain all metadata for a particular file. This is different from UNIX filesystems, which store metadata separately from the directory entries (in inodes). FAT directory entries are also used for disk volume labels and VFAT long filenames (xxx - todo).

### The FAT

Entries in the FAT can be 12 bits wide (FAT12), 16 bits wide (FAT16), or 32 bits wide (FAT32). FAT entries do not necessarily refer to disk sectors, but to clusters, which are groups of contiguous sectors. The number of sectors per cluster is always a power of 2. The FAT format used is determined solely by the number of clusters in the volume:

- FAT12: 1...4084 (0FF4h) clusters
- FAT16: 4085...65524 (0FFF4h) clusters
- FAT32: 65525... clusters

Used FAT entries form singly linked lists, indicating which clusters are used by each file or subdirectory. Some FAT entry values are special:

Meaning of FAT entry value | FAT12 | FAT16 | FAT32
--- | --- | --- | ---
Free cluster | 0 | 0 | 0
Used cluster; pointer to next | 2-0FF5h | 2-0FFF5h | 2-0FFFFFF5h (28-bit)
Reserved | 0FF6h | 0FFF6h | 0FFFFFF6h (28-bit)
Bad cluster | 0FF7h | 0FFF7h | 0FFFFFF7h (28-bit)
Reserved | 0FF8h-0FFEh | 0FFF8h-0FFFEh | 0FFFFFF8h-0FFFFFFEh(28-bit)
Used cluster; last in chain | 0FFFh | 0FFFFh | 0FFFFFFFh (28-bit)

## ext2 filesystem

xxx - to do

## ISO-9660 (CD-ROM) filesystem

http://www.alumni.caltech.edu/~pje/iso9660.html

## Overview of common filesystems

Thanks to Peter Montagner, Michael Cook, Grzegorz Niemirowski, and Mike Garnsey for helping with this table.

| FAT12/16 (DOS) | VFAT (Win95), FAT32 (Win98) | NTFS | ext2 (Linux)
--- | --- | --- | --- | ---
Filename length | 8.3 | 255 | 255 | 255
Path length | 80 | 260 | 32767 |
Illegal characters in filenames | `(nul) " * + , . / : ; < = > ? [ \ ] |` | `(nul) " * / : < > ? \ |` | `(chars 0x01-0x1F) " / \ * ? < > | :` | `(nul)`
Legal characters in filenames | `(space) ! # $ % & ' ( ) - 0-9 @ A-Z ^ _ ` a-z { } ~` Leading . or space is illegal Trailing . or space ignored. | `(space) ! # $ % & ' ( ) + , - . 0-9 ; = @ A-Z [ ] ^ _ ` a-z { } ~` Leading space ignored Single . or space is illegal Trailing . or space ignored. | `(space) ! # $ % & ' ( ) + , - . 0-9 ; = @ A-Z [ ] ^ _ ` a-z { } ~` Some filenames are reserved | everything but `(nul)`
Limit to number of root directory entries | YES | VFAT12/16: YES FAT32: no | no | no
Maximum subdirectory depth | no | no | no | no
Directories sorted by name | no | no | yes; stored in B-trees | no
Character set |  | UCS-2 Unicode | UCS-2 Unicode | ISO-Latin-1
Endian | little | little | ? | little

| ISO9660 (CD-ROM) | Joliet | Mac HFS+
--- | --- | --- | ---
Filename length | Level 1: 8.3 files, 8 for subdirectories Level 2/3: 31 | 64 | 255
Path length |  |  |
Illegal characters in filenames | `(nul) (space) ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ ` { | } ~` Extension with directory name is not allowed |  | `(nul) :`
Legal characters in filenames | `0-9 A-Z _` |  | everything but `(nul) :`
Limit to number of root directory entries | no ? | no | no
Maximum subdirectory depth | 8 | no |
Directories sorted by name | yes | yes |
Character set | ASCII | UCS-2 Unicode | UCS-2 Unicode
Endian | big AND little (committee invention :) |  | big

## Filesystem code snippets

Check disk for FAT filesystem, display info

Check disk for ext2 filesystem, display info

## Links

Lotsa filesystem info: http://www.nondot.org/sabre/os/articles/FileSystems/

Information on FAT12/FAT16 (DOS) filesystems:

- http://home.no.net/tkos/info/fat.html
- Official MS docs for FAT: http://www.microsoft.com/hwdev/hardware/fatgendown.asp

Information on ext2fs (Linux filesystem):

- http://www.freesoftware.fsf.org/ext2-doc/
- http://uranus.it.swin.edu.au/~jn/explore2fs/es2fs.htm

NTFS info: http://my.fit.edu/~mtaylor/ntfs_nutshell.html

LTOOLS; an ext2 analog of MTOOLS (lets DOS access ext2 partitions): http://www.it.fht-esslingen.de/~zimmerma/software/ltools.html

Reentrant DOS-Compatible File System, by Philip J. Erdelsky: http://www.alumni.caltech.edu/~pje/software.html
Public domain. Includes disk cache.

## TO DO

    - tree for used sectors, bitmap for free (UNIX family)
    - subdirectories
    - advanced: journalling, striping
    - sorted directories let you perform a fast binary search

## REPORT BUGS OR ERRORS IN THIS DOCUMENT