From 45c4f781a5a831dd08cbab745a55834d514e45f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chlo=C3=A9=20Vulquin?= Date: Sun, 31 May 2026 16:37:18 +0200 Subject: [PATCH] std.uefi.protocol.File: add readSize for directory entries EFI_FILE_PROTOCOL does not differentiate between reading directory entries and files in the API. When calling `EFI_FILE_PROTOCOL.Read()` against a File, the buffer is filled up with BufferSize from the file's position. However, when calling it against a Directory, an entire directory entry is placed into the buffer. If the buffer is not large enough, BufferTooSmall is returned, and the BufferSize is updated to the needed size to hold the entire directory entry. When wanting to read an entire file, you can accomplish this by calling `getInfoSize`, allocating a buffer to hold the file's info structure, then calling `getInfo` to get the file's size, allocating that much, then calling `read`. This is impossible in this case, since `getInfo` would return data to do with the directory itself, as opposed to the next directory entry. As such, the only place this information can be gotten is from the `read` call itself. This creates a new `readSize` function that mirrors `getInfoSize`, returning the protocol-given size in case of `BufferTooSmall`. It is called with an initial size of 0 and a zero-item buffer to avoid the case where the buffer happens to be large enough (e.g. if `readSize` is called before `read`), which would advance the file position. Same as `read`, this may return 0 to indicate that there are no future files. As a consequence, it is safe to call either before or after a potentially failing call to `read`. --- lib/std/os/uefi/protocol/file.zig | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/std/os/uefi/protocol/file.zig b/lib/std/os/uefi/protocol/file.zig index 0d3d11c708aa07561751140e7ca528b23b8fac42..1e49cc2195125fcd9f32aba689736959c0d8e7d2 100644 --- a/lib/std/os/uefi/protocol/file.zig +++ b/lib/std/os/uefi/protocol/file.zig @@ -125,6 +125,22 @@ pub const File = extern struct { } } + pub fn readSize(self: *File) ReadError!usize { + const zerobuf: [0]u8 = undefined; + var size: usize = 0; + switch (self._read(self, &size, &zerobuf)) { + .success, .buffer_too_small => return size, + .no_media => return error.NoMedia, + .device_error => return error.DeviceError, + .volume_corrupted => return error.VolumeCorrupted, + else => |status| return uefi.unexpectedStatus(status), + } + } + + /// If `self` is a directory entry and `buffer` is too small to contain the + /// next entry, this function returns `Error.BufferTooSmall`. You can call + /// `readSize` before or after to determine how big the buffer should be to + /// call this function. pub fn read(self: *File, buffer: []u8) ReadError!usize { var size: usize = buffer.len; switch (self._read(self, &size, buffer.ptr)) { -- 2.54.0