exfat: cross-engine discrimination + the exfat-test fixture (S4 step 7)

Each engine now refuses the other's volume at mount(): the exFAT engine
rejects a FAT boot sector (a non-zero byte where exFAT keeps MustBeZero),
and the FAT engine rejects an exFAT one (MustBeZero reads as a zero
bytes-per-sector), each mounting its own as a control. The two engines
can never claim the same medium.

exfat-test is the mount round-trip client, cloned from fat-test: it waits
for /volumes/exfat-e0fa0001, reads the seeded HELLO.TXT, then exercises
mkdir + write + rename + read-back + remove through the VFS and reports
"exfat-test: ok". It ships as a lazy fixture in test builds (the
exfat-volume QEMU case, step 8, drives it). build + zig build test +
bounds green.
This commit is contained in:
Daniel Samson
2026-08-10 03:32:55 +01:00
parent 2c2745e9e5
commit 90906bcefe
7 changed files with 155 additions and 0 deletions
+18
View File
@@ -1276,3 +1276,21 @@ test "rename keeps the file's contents under the new name" {
_ = fs.readFile(renamed, 0, &readback);
try std.testing.expectEqualSlices(u8, &payload, &readback);
}
test "the exFAT engine rejects a FAT volume (mutual exclusion at mount)" {
const allocator = std.testing.allocator;
const bytes = try allocator.alloc(u8, 128 * sector_size);
defer allocator.free(bytes);
@memset(bytes, 0);
// A FAT-shaped boot sector: an OEM name and a non-zero bytes-per-sector where
// exFAT keeps MustBeZero zero, plus the 0x55AA signature.
@memcpy(bytes[3..11], "MSWIN4.1");
std.mem.writeInt(u16, bytes[11..13], 512, .little); // FAT bytes_per_sector = exFAT MustBeZero
bytes[510] = 0x55;
bytes[511] = 0xAA;
var disk = RamDisk{ .bytes = bytes };
try std.testing.expect(FileSystem.mount(disk.device()) == null);
// Control: it mounts its own.
formatExfat(bytes);
try std.testing.expect(FileSystem.mount(disk.device()) != null);
}
+18
View File
@@ -1657,3 +1657,21 @@ test "short-name checksum matches the reference vector" {
const c = FileSystem.shortChecksum("REDAME TXT".*);
try std.testing.expect(a != c);
}
test "the FAT engine rejects an exFAT volume (mutual exclusion at mount)" {
const allocator = std.testing.allocator;
const bytes = try allocator.alloc(u8, 5000 * sector_size);
defer allocator.free(bytes);
@memset(bytes, 0);
// An exFAT boot sector: the "EXFAT " name and 0x55AA, but MustBeZero (offset
// 11, where a FAT BPB keeps bytes-per-sector) stays zero — so this engine's
// geometryOf reads a zero bytes-per-sector and rejects it.
@memcpy(bytes[3..11], "EXFAT ");
bytes[on_disk.boot_signature_offset] = 0x55;
bytes[on_disk.boot_signature_offset + 1] = 0xAA;
var disk = RamDisk{ .bytes = bytes };
try std.testing.expect(FileSystem.mount(disk.device()) == null);
// Control: a real FAT16 mounts.
formatFat16(bytes);
try std.testing.expect(FileSystem.mount(disk.device()) != null);
}