How VFAT Long File Names Worked in Windows 95
When Microsoft introduced Windows 95, it brought support for Long File Names (LFN) up to 255 characters through the Virtual File Allocation Table (VFAT) driver. To maintain absolute backward compatibility with existing MS-DOS environments and legacy 16-bit software, Microsoft designed VFAT as an extension of the existing FAT12 and FAT16 formats rather than creating an entirely new file system. This article examines the ingenious mechanism VFAT used to store long names, generate legacy-compatible aliases, and protect data integrity on traditional FAT-formatted drives.
The 8.3 Limitation and Backward Compatibility
Standard FAT file systems allocated 32 bytes for each directory entry. Within that fixed structure, only 11 bytes were allocated for the filename: 8 bytes for the base name and 3 bytes for the extension (the "8.3" standard). Simply expanding this structure would have rendered the file system unreadable to older operating systems and utility software.
VFAT resolved this problem by ensuring that every single file maintained a dual identity: a standard 8.3 "short" filename for legacy programs and a "long" filename for modern 32-bit Windows applications.
Generating the Short Filename (8.3 Alias)
When a user created a file with a long name (for example,
Financial Report 1995.document), VFAT automatically
synthesized an 8.3 alias using the following process:
- Stripping Invalid Characters: Spaces and characters
unsupported by MS-DOS (such as
+,,,;,=,[, and]) were removed. - Truncation and Capitalization: The first six valid characters were extracted and converted to uppercase.
- Collision Tail: A tilde followed by a numeric
counter (e.g.,
~1) was appended to the base name. - Extension Extraction: The final extension characters (up to three) were converted to uppercase.
Using this process, Financial Report 1995.document
became FINANC~1.DOC. If another file named
Financial Report 1996.document was added to the same
directory, VFAT incremented the numeric tail to
FINANC~2.DOC.
Storing Long Names via Dummy Directory Entries
To store the complete, case-sensitive long name, VFAT chained additional 32-byte directory entries immediately before the primary 8.3 entry.
Each standard 32-byte FAT directory entry contained an attribute byte
at offset 0x0B defining file flags such as Read-Only
(0x01), Hidden (0x02), System
(0x04), and Volume Label (0x08).
VFAT marked all LFN-specific entries with an attribute byte set to
0x0F (a combination of Read-Only, Hidden, System, and
Volume Label). To legacy MS-DOS applications and disk utilities, an
entry marked with 0x0F was an impossible combination that
signified an invalid or special volume label. Consequently, older
operating systems ignored these entries entirely, leaving the directory
structure intact and visible only through the standard 8.3 entries.
Structure of an LFN Entry
Because long file names supported Unicode (specifically UCS-2/UTF-16LE, taking 2 bytes per character), each 32-byte directory entry could hold up to 13 characters of the name. If a filename exceeded 13 characters, multiple entries were chained together in reverse order.
Each 32-byte LFN entry was structured as follows:
- Byte 0x00 (Sequence Number): Identified the entry’s
order in the sequence (1, 2, 3, etc.). The final physical entry in the
chain had bit 6 (
0x40) set to designate it as the stop marker. - Bytes 0x01–0x0A: First 5 characters of the filename (10 bytes).
- Byte 0x0B (Attributes): Always set to
0x0F. - Byte 0x0C (Type): Reserved, always set to
0x00. - Byte 0x0D (Checksum): An 8-bit checksum calculated from the associated 8.3 short filename.
- Bytes 0x0E–0x19: Next 6 characters of the filename (12 bytes).
- Bytes 0x1A–0x1B (Starting Cluster): Always set to
0x0000to prevent legacy disk defragmenters from treating the entry as a real file with clusters. - Bytes 0x1C–0x1F: Final 2 characters of the filename (4 bytes).
If the filename did not fill an entry, the remaining space was
terminated with a null character (0x0000) and padded with
0xFFFF.
Data Integrity and Orphan Prevention
One significant risk was that a user might boot into MS-DOS and rename, move, or delete an 8.3 file without using the VFAT driver.
To prevent an LFN chain from pointing to a modified or different file, VFAT computed an 8-bit checksum based on the 11 characters of the 8.3 entry and stored that value inside every corresponding LFN entry. When Windows 95 read a directory, it recalculated the checksum of the 8.3 entry. If the calculated checksum did not match the checksum stored in the preceding LFN entries, VFAT recognized that the 8.3 file had been altered outside Windows. The operating system would discard the orphaned LFN entries, preventing filename corruption.