boot: survive hand-written sticks — case-fold the /system walk, skip host litter

The loader ENUMERATES /system now, so it sees whatever the stick's
directory entries literally store — and a hand-copied stick differs
from our generated image: firmware returns bare 8.3 short entries
UPPERCASE (INIT, SYSTEM), and host OSes leave litter next to every file
(macOS '._' AppleDouble forks, .fseventsd). Verified in QEMU/OVMF: an
uppercase-stored volume booted to a dead kernel-only system before this
change and boots fully (display up, logger writing /var/log) after.

The walk now lowers ASCII names (the danos tree is canonically
lowercase; FAT lookups are case-insensitive by definition), skips any
dot-prefixed entry, and treats malformed or unreadable entries as
skip-this-file instead of abort-the-whole-walk. Reader.find compares
case-insensitively as belt and braces.
This commit is contained in:
Daniel Samson
2026-07-21 18:01:12 +01:00
parent 0a4388c3bc
commit d446ddd2ed
2 changed files with 31 additions and 11 deletions
+6 -3
View File
@@ -76,17 +76,20 @@ pub const Reader = struct {
/// Look a binary up by name: an exact path match wins; otherwise a unique
/// basename match ("fat" finds "/system/services/fat") keeps pre-path callers
/// working. The returned Item's name is always the stored full path.
/// working. Comparisons are ASCII case-insensitive — the entries come from a
/// FAT volume, whose name lookups are case-insensitive by definition (and
/// whose short entries store uppercase). The returned Item's name is always
/// the stored full path.
pub fn find(self: Reader, name: []const u8) ?Item {
var i: u32 = 0;
while (i < self.count) : (i += 1) {
const item = self.entry(i) orelse continue;
if (std.mem.eql(u8, item.name, name)) return item;
if (std.ascii.eqlIgnoreCase(item.name, name)) return item;
}
i = 0;
while (i < self.count) : (i += 1) {
const item = self.entry(i) orelse continue;
if (std.mem.eql(u8, basename(item.name), name)) return item;
if (std.ascii.eqlIgnoreCase(basename(item.name), name)) return item;
}
return null;
}