I just today started making this. It could be useful for making file system scans faster on Darwin. Without further ado:
A library that provides efficient bulk retrieval of file attributes using the native
getattrlistbulksyscall. This allows fetching multiple file attributes for directory entries in a single system call, which is significantly more efficient than individualstatcalls.
The library uses Zig’s comptime features to generate type-safe structs based on the attributes you request, ensuring you only pay for what you use.
const std = @import("std");
const wtfs = @import("wtfs");
// Open directory with .iterate flag (required for getattrlistbulk)
const dir = try std.fs.cwd().openDir(".", .{ .iterate = true });
defer dir.close();
// Configure which attributes to retrieve at compile time
const mask = wtfs.AttrGroupMask{
.common = .{
.name = true, // File/directory name
.obj_type = true, // Object type (file/dir/symlink)
.file_id = true, // inode number
},
.dir = .{
.entry_count = true, // Number of entries in directory
},
.file = .{
.total_size = true, // Logical file size
.alloc_size = true, // Allocated size on disk
},
};
// The scanner type is generated at compile time based on your mask
const Scanner = wtfs.DirScanner(mask);
// Provide your own buffer for the syscall results
var buffer: [16384]u8 = undefined;
var scanner = Scanner.init(dir.handle, &buffer);
// Iterate through entries
while (try scanner.next()) |entry| {
// The entry type has only the fields you requested
std.debug.print("{s}: ", .{entry.name});
switch (entry.kind) {
.dir => {
// dir-specific fields are available when requested
std.debug.print("directory with {} entries\n", .{entry.details.dir.entrycount});
},
.file => {
// file-specific fields are available when requested
std.debug.print("file, {}B ({}B allocated)\n", .{
entry.details.file.totalsize,
entry.details.file.allocsize,
});
},
.symlink => std.debug.print("symlink\n", .{}),
.other => std.debug.print("other\n", .{}),
}
}
