Skip to content

FAT Filesystem

opencode-agent[bot] edited this page May 10, 2026 · 1 revision

FAT Filesystem

JNode's FAT12/FAT16/FAT32 filesystem implementation with Long File Name (LFN) support.

Overview

The FAT (File Allocation Table) filesystem in JNode provides read-write support for FAT12, FAT16, and FAT32 variants. It integrates with JNode's VFS layer through the FatFileSystemType factory and uses the block device layer for sector-level I/O. The implementation includes support for Long File Names (VFAT) to overcome the 8.3 filename limitation.

Key Components

Class/File Purpose
FatFileSystem.java Main filesystem implementation, extends AbstractFileSystem
FatDirectory.java Directory entry iteration and management
FatFile.java File I/O with cluster chain navigation
Fat.java FAT table read/write, cluster allocation
FatType.java Enum for FAT12/FAT16/FAT32 variant handling
BootSector.java Boot sector parsing (BPB fields, geometry)
FatLfnDirectory.java, FatLfnDirEntry.java Long File Name support
FatConstants.java Directory entry flags (readonly, hidden, system, label, directory, archive)

Architecture

Filesystem Type Registration

The FatFileSystemType class implements the FileSystemType interface, allowing the VFS to probe block devices and instantiate FatFileSystem instances. This follows the plugin extension point pattern used throughout JNode.

Boot Sector Parsing

The BootSector class parses the BIOS Parameter Block (BPB) from the first sector:

  • getBytesPerSector(), getSectorsPerCluster() — cluster size calculation
  • getNrFats() — number of FAT copies
  • getSectorsPerFat() — FAT size
  • getNrRootDirEntries() — root directory size (FAT12/FAT16 only)
  • getMediumDescriptor() — determines FAT12 vs FAT16

FAT Table Management

The Fat class handles cluster chain operations:

  • Read/Write: Binary encoding for each FAT variant (1.5 bytes/entry for FAT12, 2 bytes for FAT16, 4 bytes for FAT32)
  • Cluster allocation: allocNew(), allocAppend() for file growth
  • Chain traversal: getChain(), getNextCluster() for file I/O
  • EOF detection: Uses variant-specific EOF markers from FatType

Directory Structure

FatDirectory extends AbstractDirectory and handles:

  • Root directory vs subdirectory (root has fixed size, subdirectories are cluster-based)
  • Entry iteration via FSEntry interface
  • Label (volume name) management in root directory
  • LFN sequence handling via FatLfnDirectory

LFN Support

Long File Names are stored in special directory entries (FatLfnDirEntry) preceding the 8.3 alias entry:

  • Unicode name storage (up to 255 characters)
  • Checksum-based association with the short name
  • Unicode conversion via LfnEntry utilities

How It Works

Mounting a FAT Volume

FatFileSystem constructor:
1. Read boot sector (512 bytes)
2. Determine FAT type from medium descriptor (0xf8 = FAT16)
3. Create Fat instances for each FAT copy
4. Read root directory (fixed-size for FAT12/16, cluster-based for FAT32)
5. Validate FAT consistency across copies

File Access

FatFile.getData():
1. Get starting cluster from directory entry
2. Fat.getChain(startCluster) → array of cluster numbers
3. Map clusters to sector offsets
4. Read data from block device

Writing Changes

FatFileSystem.flush():
1. Write dirty boot sector
2. Flush all open FatFile instances
3. Write dirty FAT copies
4. Flush dirty root/subdirectories

Gotchas

  • Root directory: FAT12/FAT16 root has fixed size from BPB; FAT32 root is a cluster chain like any directory
  • Cluster size: Derived from bytesPerSector * sectorsPerCluster, used for all allocation
  • Dirty tracking: Files, FAT, and directories track changes independently; flush must handle all three
  • FAT consistency: On mount, JNode logs warnings if FAT copies differ (first FAT is used)
  • LFN ordering: LFN entries must immediately precede their 8.3 alias; deletion disrupts the chain

Related Pages

Clone this wiki locally