VFAT: Explanation & Insights

The Linux driver that reads FAT and smuggles long filenames into a format that never wanted them.

What It Is

VFAT is the name of the Linux kernel driver that reads and writes FAT filesystems — and it's the name you'll type far more often than "FAT" itself, because on Linux you almost always mount a FAT volume with -t vfat. The "V" stands for Virtual File Allocation Table, but don't overthink it: VFAT isn't a separate, virtual filesystem. It's FAT — the same clusters, the same table, the same on-disk layout described on the FAT page — plus one important extension bolted on top: long filenames.

That's the whole story in a sentence, but the how is one of the more entertaining hacks in filesystem history, and it's worth understanding, because it explains both why your USB stick's MyHolidayPhotos2024.jpeg shows up correctly and why the same file is somehow also called MYHOLI~1.JPE underneath. So before the practical commands, let's pull that thread.

If you want the filesystem concept itself — the allocation table, the cluster chains, the FAT12/16/32 family, the 4 GiB limit, the EFI System Partition — read the FAT page first; it's the foundation. This page is about the Linux driver and the long-filename trick layered over it.

The 8.3 Problem and the Long-Filename Trick

Original FAT was a child of the late 1970s, and it inherited the era's idea of a filename: 8.3. Eight characters for the name, a dot, three for the extension, uppercase only. REPORT.TXT. AUTOEXEC.BAT. That was the entire namespace — no spaces, no lowercase, no My Tax Return (final, really).pdf. The directory entry on disk has a rigid 11-byte field for exactly this, and nothing more.

By the mid-1990s that was unbearable, but Microsoft had a problem: billions of existing programs and devices read the old 8.3 directory entries directly, and any change that broke them was a non-starter. They needed long filenames that new software could see while old software carried on reading the same disk as if nothing had changed. The solution, shipped with Windows 95 and christened VFAT, is gloriously sneaky.

Each FAT directory entry carries an attribute byte. VFAT defines a never-before-valid combination of attribute bits — read-only + hidden + system + volume-label all set at once — that no sane old program would ever produce. Entries flagged with that magic combination are long-filename (LFN) entries: extra directory slots, sitting right before the real 8.3 entry, that store the long name in fragments (13 UTF-16 characters each, chained together). Old software sees those entries, decides "this is some weird system/volume thing, none of my business," and skips right over them — landing on the ordinary 8.3 entry, which still holds a valid short name like MYHOLI~1.JPE. New software recognises the magic flag, reassembles the fragments, and shows you MyHolidayPhotos2024.jpeg.

On disk, one file occupies several directory entries:

  [LFN entry 3]  "eg"                          ← magic attr 0x0F
  [LFN entry 2]  "tos2024.jp"                  ← magic attr 0x0F
  [LFN entry 1]  "MyHolidayPho"                ← magic attr 0x0F
  [8.3 entry]    "MYHOLI~1JPE"  → cluster 41   ← what old DOS sees

New OS: reads the LFN chain → "MyHolidayPhotos2024.jpeg"
Old OS: ignores the magic entries → "MYHOLI~1.JPE"

It is a backward-compatibility magic trick of real beauty: the same bytes mean two different things to two different readers, and neither one corrupts the other. The cost is that long names ride along as that string of "system" entries, which is why a directory of long-named files holds far more entries than files — and why, on a cramped FAT12 floppy, you could run out of directory slots long before you ran out of disk.

Backstory

Microsoft patented the LFN trick (US 5,758,352 and relatives), and for years it was a quiet legal cloud over every device that read a FAT card — which is to say, nearly all of them. The patents featured in lawsuits against TomTom and others, and the question of whether Linux's vfat driver infringed was a genuine worry in the 2000s. There was even a kernel patch floating around to disable long-filename support and dodge the issue entirely. The patents have since expired (the core ones around 2013–2015), and the whole thing quietly evaporated — but for a stretch, the most boring filesystem on earth sat at the center of a patent fight, all over the right to call a file by a long name.

Faking Ownership: uid, gid, and umask

Here's the practical wrinkle that bites everyone the first time. FAT stores no owner, no group, and no permission bits — the fields simply don't exist on disk. But Linux is built on the assumption that every file has an owner and a mode. So when the vfat driver mounts a FAT volume, it has to invent that information out of thin air, and you control the fiction with mount options:

  • uid= — the user ID that every file on the volume will appear to be owned by.
  • gid= — likewise for the group.
  • umask= / dmask= / fmask= — the permission bits to mask off, for everything / directories only / files only.
mount -t vfat -o uid=1000,gid=1000,umask=022 /dev/sdb1 /mnt/stick

Mount a stick as root with no options and every file is owned by root with restrictive bits, and your normal login can't write to it — the classic "why can't I copy to my own USB stick" head-scratch. The fix is to tell the driver who should own it. The crucial thing to internalise: none of this is written to the disk. Unmount and remount with a different uid= and the same files now "belong" to someone else. It's ownership as a runtime costume the driver dresses the files in — pull the card, plug it into another machine, and the costume is gone. For interchange media that's fine; for anything needing real access control it's another reason FAT belongs nowhere near server data.

Pro Tip

When a FAT volume is listed in /etc/fstab for a normal user to access, set uid= and gid= to that user's IDs and a sane umask=022 (or 077 for privacy). It saves the eternal confusion of a stick that mounts but won't accept writes — and remember it's cosmetic: the same options must be repeated on every machine, because the disk remembers nothing.

How I Inspect It

You confirm what a FAT volume is, then confirm it's healthy. lsblk -f labels the FAT partitions as vfat and shows where each is mounted — the EFI System Partition jumps right out:

lsblk -f
NAME   FSTYPE FSVER LABEL UUID                                 MOUNTPOINTS
sda
├─sda1 vfat   FAT32       ABCD-1234                            /boot/efi
└─sda2 ext4   1.0         a1b2c3d4-...                         /
sdb
└─sdb1 vfat   FAT32 STICK 5E3F-9A02                            /mnt/stick

blkid gives the type and that short pseudo-UUID for /etc/fstab (FAT has no room for a real UUID, so Linux fabricates an 8-hex-digit one from the volume serial — only probably unique, but stable enough to reference):

blkid /dev/sdb1
/dev/sdb1: SEC_TYPE="msdos" LABEL_FATBOOT="STICK" UUID="5E3F-9A02" TYPE="vfat"

And df -hT confirms type and fullness — handy for the ESP, which is tiny and should stay almost empty.

Cheat Sheet

The one quirk to keep straight: the tools are named after vfat, fat, and dos, never "vfat" alone, and several are the same binary under two names:

# --- Identify ---
lsblk -f                              # which partitions are vfat, mounted where
blkid /dev/sdb1                       # type + pseudo-UUID for fstab
df -hT /mnt/stick                     # size and usage

# --- Mount (the verb you'll type most) ---
mount -t vfat /dev/sdb1 /mnt/stick                       # plain
mount -t vfat -o uid=1000,gid=1000,umask=022 \
      /dev/sdb1 /mnt/stick                                # with fake ownership

# --- Create ---
mkfs.vfat -F 32 /dev/sdb1             # FAT32 (mkfs.fat is the very same binary)
mkfs.vfat -n STICK /dev/sdb1          # with a volume label

# --- Check / repair (always UNMOUNT first) ---
fsck.vfat -a /dev/sdb1                # auto-repair the safe stuff
dosfsck -v /dev/sdb1                 # identical tool, classic name, verbose

Warning

Always umount a FAT volume before pulling it, and never yank a stick mid-write. FAT has no journaling, so an interrupted write can leave the table and directory entries disagreeing about reality — a cross-linked chain, a file pointing into freed clusters. That's the "my USB stick is corrupt now" story in one move. fsck.vfat -a can often clean it up, but the only reliable cure is to unmount cleanly in the first place.

Reading It by Example

A few sights you'll meet and what they mean:

  • mount -t vfat succeeds but you can't write as a normal user — the volume mounted owned by root. Remount with uid= set to your user. Nothing's broken.
  • A file named GENERA~1.LOG alongside general-server-log.txt — you're looking at the same file through an old-style 8.3 view and the VFAT long name. The ~1 is the LFN short-name alias, not a second file.
  • fsck.vfat reports "Cluster X is cross-linked" — two files' chains claim the same cluster, the signature of an unclean unmount. Let fsck.vfat -a resolve it; one of the files will likely lose data, which is the price of pulling the stick early.
  • A 4.7 GB file refuses to copy to a FAT32 stick — that's the 4 GiB-per-file ceiling, not a fault. Reformat the stick as exFAT (-t exfat) or split the file.

History and Philosophy

VFAT is a study in a very Microsoft kind of engineering: not the elegant clean-sheet design, but the pragmatic, backward-compatible bolt-on that ships on time and breaks nothing. Long filenames could have meant a new filesystem and a flag day where old software stopped working. Instead, Windows 95 reused the existing FAT on-disk format and hid the new data in plain sight, behind an attribute combination so improbable that decade-old programs would politely ignore it. It's not pretty under the hood, but it let hundreds of millions of machines gain long filenames overnight without reformatting a single disk — and the same trick is why a FAT32 card written by a 1996 camera is still perfectly readable today.

Linux's vfat driver, in the kernel since the mid-1990s, reads all of it: FAT12, FAT16, FAT32, short names and long. It is unglamorous, rock-solid, and used on essentially every Linux machine on earth — if only for the few megabytes of the EFI System Partition that gets the box booting. The driver that nobody thinks about is reading a filesystem that nobody chose, doing the humblest job in the system, and doing it flawlessly. There's a quiet dignity in being the part of the stack that just works while everyone's attention is on the ZFS pool upstairs.

See Also

  • fat — the filesystem itself: the allocation table, the cluster chains, the FAT32 limits, the ESP
  • filesystem — the broader concept and where FAT sits among the filesystems you'd run a server on
  • ntfs — Microsoft's serious filesystem, with the permissions and journaling FAT/vfat lack
  • mounting — attaching a vfat volume to the directory tree, and the uid/gid/umask options
  • permission — the ownership and mode bits FAT can't store, only fake at mount time
  • gpt — the partition scheme behind the FAT32 EFI System Partition
  • partition — the slice of disk a vfat volume occupies
  • mbr — the older DOS-era partition scheme, FAT's historical companion
  • mkfs.vfat — create a FAT filesystem (same binary as mkfs.fat)
  • blkid — read a vfat volume's type and pseudo-UUID
  • fsck — check and repair a FAT volume (as fsck.vfat / dosfsck)
  • mountmount -t vfat, the command you'll reach for most

Did a USB stick or the EFI partition come back corrupt after an unclean unmount?

CleverUptime keeps an eye on every mounted filesystem — the vfat-formatted EFI partition included — and tells you in plain language the moment one fills up or flips to read-only, so a botched boot partition surfaces on a dashboard instead of at the next reboot.

Want to see your own server's health right now? One command, no signup, no install.

Check your server →