authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-14 18:23:40-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-15 14:18:20-08:00
logbed7bc37c43afce335610867aedbcd506ade65f4
treee424a2954fb6f8de3bbe07ada4504cc03053a1b1
parenta70e0061579a4365da0092554470ffeadb4594a4

std.File.MemoryMap updates

- change offset to u64 - make len non-optional - make write take a file_size parameter - std.Io.Threaded: introduce disable_memory_mapping flag to force it to take the fallback path. Additionally: - introduce BlockSize to File.Stat. On Windows, based on cached call to NtQuerySystemInformation. On unsupported OS's, set to 1. - support File.NLink on Windows. this was available the whole time, we just didn't see the field at first. - remove EBADF / INVALID_HANDLE from reading/writing file error sets

7 files changed, 131 insertions(+), 67 deletions(-)

lib/std/Io.zig+1-1
......@@ -658,7 +658,7 @@ pub const VTable = struct {
658658 fileMemoryMapDestroy: *const fn (?*anyopaque, *File.MemoryMap) void,
659659 fileMemoryMapSetLength: *const fn (?*anyopaque, *File.MemoryMap, n: usize) File.MemoryMap.SetLengthError!void,
660660 fileMemoryMapRead: *const fn (?*anyopaque, *File.MemoryMap) File.ReadPositionalError!void,
661 fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap) File.WritePositionalError!void,
661 fileMemoryMapWrite: *const fn (?*anyopaque, *File.MemoryMap, file_size: u64) File.WritePositionalError!void,
662662
663663 processExecutableOpen: *const fn (?*anyopaque, File.OpenFlags) std.process.OpenExecutableError!File,
664664 processExecutablePath: *const fn (?*anyopaque, buffer: []u8) std.process.ExecutablePathError!usize,
lib/std/Io/File.zig+9
......@@ -22,6 +22,7 @@ pub const INode = std.posix.ino_t;
2222pub const NLink = std.posix.nlink_t;
2323pub const Uid = std.posix.uid_t;
2424pub const Gid = std.posix.gid_t;
25pub const BlockSize = u32;
2526
2627pub const Kind = enum {
2728 block_device,
......@@ -65,6 +66,14 @@ pub const Stat = struct {
6566 mtime: Io.Timestamp,
6667 /// Last status/metadata change time in nanoseconds, relative to UTC 1970-01-01.
6768 ctime: Io.Timestamp,
69 /// Smallest chunk length in bytes appropriate for optimal I/O. This will
70 /// be set to `1` for operating systems or file systems that do not
71 /// recognize this concept. Not always a power of two. When creating a
72 /// `MemoryMap`, the mapping length must be a multiple of this value.
73 ///
74 /// On Windows, this is whichever is larger: PageSize or
75 /// AllocationGranularity.
76 block_size: BlockSize,
6877};
6978
7079pub fn stdout() File {
lib/std/Io/File/MemoryMap.zig+31-16
......@@ -10,10 +10,11 @@ const File = Io.File;
1010const Allocator = std.mem.Allocator;
1111
1212file: File,
13/// Byte index inside `file` where `memory` starts.
14offset: usize,
13/// Byte index inside `file` where `memory` starts. Page-aligned.
14offset: u64,
1515/// Memory that may or may not remain consistent with file contents. Use `read`
16/// and `write` to ensure synchronization points.
16/// and `write` to ensure synchronization points. No minimum alignment on the
17/// pointer is guaranteed, but the length is page-aligned.
1718memory: []u8,
1819/// Tells whether it is memory-mapped or file operations. On Windows this also
1920/// has a section handle.
......@@ -22,10 +23,10 @@ section: ?Section,
2223pub const Section = if (is_windows) std.os.windows.HANDLE else void;
2324
2425pub const CreateError = error{
25 /// A file descriptor refers to a non-regular file. Or a file mapping was requested,
26 /// but the file descriptor is not open for reading. Or `MAP.SHARED` was requested
27 /// and `PROT_WRITE` is set, but the file descriptor is not open in `RDWR` mode.
28 /// Or `PROT_WRITE` is set, but the file is append-only.
26 /// One of the following:
27 /// * The `File.Kind` is not `file`.
28 /// * The file is not open for reading and read access protections enabled.
29 /// * The file is not open for writing and write access protections enabled.
2930 AccessDenied,
3031 /// The `prot` argument asks for `PROT_EXEC` but the mapped area belongs to a file on
3132 /// a filesystem that was mounted no-exec.
......@@ -36,6 +37,12 @@ pub const CreateError = error{
3637} || Allocator.Error || File.ReadPositionalError;
3738
3839pub const CreateOptions = struct {
40 /// Size of the mapping, in bytes. If this is longer than the file size, it
41 /// will be filled with zeroes.
42 ///
43 /// Asserted to be a multiple of page size which can be obtained via
44 /// `std.heap.pageSize`.
45 len: usize,
3946 /// When this has read set to false, bytes that are not modified before a
4047 /// sync may have the original file contents, or may be set to zero.
4148 protection: std.process.MemoryProtection = .{ .read = true, .write = true },
......@@ -45,12 +52,9 @@ pub const CreateOptions = struct {
4552 undefined_contents: bool = false,
4653 /// Prefault the pages.
4754 populate: bool = true,
48 /// Byte index of file to start from.
55 /// Asserted to be a multiple of page size which can be obtained via
56 /// `std.heap.pageSize`.
4957 offset: u64 = 0,
50 /// `null` indicates to map the entire file. If mapping the entire file is
51 /// desired and the file size is known, it is more efficient to populate
52 /// the value here.
53 len: ?usize = null,
5458};
5559
5660/// To release the resources associated with the returned `MemoryMap`, call
......@@ -73,8 +77,15 @@ pub const SetLengthError = error{
7377/// of the file after calling this is unspecified until `write` is called.
7478///
7579/// May change the pointer address of `memory`.
76pub fn setLength(mm: *MemoryMap, io: Io, n: usize) File.SetLengthError!void {
77 return io.vtable.fileMemoryMapSetLength(io.userdata, mm, n);
80pub fn setLength(
81 mm: *MemoryMap,
82 io: Io,
83 /// New size of the mapping, in bytes. If this is longer than the file
84 /// size, it will be filled with zeroes. Asserted to be a multiple of page
85 /// size which can be obtained with `std.heap.pageSize`.
86 new_length: usize,
87) File.SetLengthError!void {
88 return io.vtable.fileMemoryMapSetLength(io.userdata, mm, new_length);
7889}
7990
8091/// Synchronizes the contents of `memory` from `file`.
......@@ -83,6 +94,10 @@ pub fn read(mm: *MemoryMap, io: Io) File.ReadPositionalError!void {
8394}
8495
8596/// Synchronizes the contents of `memory` to `file`.
86pub fn write(mm: *MemoryMap, io: Io) File.WritePositionalError!void {
87 return io.vtable.fileMemoryMapWrite(io.userdata, mm);
97///
98/// Size of the mapping may be longer than the file size, so the `file_size`
99/// argument is used to avoid writing too many bytes. If `file_size` is not
100/// handy, use `File.length` to get it.
101pub fn write(mm: *MemoryMap, io: Io, file_size: u64) File.WritePositionalError!void {
102 return io.vtable.fileMemoryMapWrite(io.userdata, mm, file_size);
88103}
lib/std/Io/Threaded.zig+79-32
......@@ -57,6 +57,7 @@ use_sendfile: UseSendfile = .default,
5757use_copy_file_range: UseCopyFileRange = .default,
5858use_fcopyfile: UseFcopyfile = .default,
5959use_fchmodat2: UseFchmodat2 = .default,
60disable_memory_mapping: bool,
6061
6162stderr_writer: File.Writer = .{
6263 .io = undefined,
......@@ -75,6 +76,13 @@ random_file: RandomFile = .{},
7576
7677csprng: Csprng = .{},
7778
79system_basic_information: SystemBasicInformation = .{},
80
81const SystemBasicInformation = if (!is_windows) struct {} else struct {
82 buffer: windows.SYSTEM_BASIC_INFORMATION = undefined,
83 initialized: std.atomic.Value(bool) = .{ .raw = false },
84};
85
7886pub const Csprng = struct {
7987 rng: std.Random.DefaultCsprng = .{
8088 .state = undefined,
......@@ -1220,6 +1228,8 @@ pub const InitOptions = struct {
12201228 /// * `processExecutablePath` on OpenBSD and Haiku (observes "PATH").
12211229 /// * `processSpawn`, `processSpawnPath`, `processReplace`, `processReplacePath`
12221230 environ: process.Environ,
1231 /// If set to `true`, `File.MemoryMap` APIs will always take the fallback path.
1232 disable_memory_mapping: bool = false,
12231233};
12241234
12251235/// Related:
......@@ -1247,6 +1257,7 @@ pub fn init(
12471257 .argv0 = options.argv0,
12481258 .environ = .{ .process_environ = options.environ },
12491259 .worker_threads = init_single_threaded.worker_threads,
1260 .disable_memory_mapping = options.disable_memory_mapping,
12501261 };
12511262
12521263 const cpu_count = std.Thread.getCpuCount();
......@@ -1263,6 +1274,7 @@ pub fn init(
12631274 .argv0 = options.argv0,
12641275 .environ = .{ .process_environ = options.environ },
12651276 .worker_threads = .init(null),
1277 .disable_memory_mapping = options.disable_memory_mapping,
12661278 };
12671279
12681280 if (posix.Sigaction != void) {
......@@ -1299,6 +1311,7 @@ pub const init_single_threaded: Threaded = .{
12991311 .argv0 = .empty,
13001312 .environ = .{},
13011313 .worker_threads = .init(null),
1314 .disable_memory_mapping = false,
13021315};
13031316
13041317var global_single_threaded_instance: Threaded = .init_single_threaded;
......@@ -2935,7 +2948,11 @@ fn fileStatLinux(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
29352948
29362949fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
29372950 const t: *Threaded = @ptrCast(@alignCast(userdata));
2938 _ = t;
2951
2952 const block_size: u32 = if (t.systemBasicInformation()) |sbi|
2953 @intCast(@max(sbi.PageSize, sbi.AllocationGranularity))
2954 else
2955 std.heap.page_size_max;
29392956
29402957 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
29412958 var info: windows.FILE.ALL_INFORMATION = undefined;
......@@ -2997,10 +3014,31 @@ fn fileStatWindows(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
29973014 .atime = windows.fromSysTime(info.BasicInformation.LastAccessTime),
29983015 .mtime = windows.fromSysTime(info.BasicInformation.LastWriteTime),
29993016 .ctime = windows.fromSysTime(info.BasicInformation.ChangeTime),
3000 .nlink = 0,
3017 .nlink = info.StandardInformation.NumberOfLinks,
3018 .block_size = block_size,
30013019 };
30023020}
30033021
3022fn systemBasicInformation(t: *Threaded) ?*const windows.SYSTEM_BASIC_INFORMATION {
3023 if (!t.system_basic_information.initialized.load(.acquire)) {
3024 t.mutex.lock();
3025 defer t.mutex.unlock();
3026
3027 switch (windows.ntdll.NtQuerySystemInformation(
3028 .SystemBasicInformation,
3029 &t.system_basic_information.buffer,
3030 @sizeOf(windows.SYSTEM_BASIC_INFORMATION),
3031 null,
3032 )) {
3033 .SUCCESS => {},
3034 else => return null,
3035 }
3036
3037 t.system_basic_information.initialized.store(true, .release);
3038 }
3039 return &t.system_basic_information.buffer;
3040}
3041
30043042fn fileStatWasi(userdata: ?*anyopaque, file: File) File.StatError!File.Stat {
30053043 if (builtin.link_libc) return fileStatPosix(userdata, file);
30063044
......@@ -8008,10 +8046,10 @@ fn fileReadStreamingWindows(userdata: ?*anyopaque, file: File, data: []const []u
80088046 syscall.finish();
80098047 return 0;
80108048 },
8011 .NETNAME_DELETED => return syscall.fail(error.ConnectionResetByPeer),
8049 .NETNAME_DELETED => if (is_debug) unreachable else return error.Unexpected,
80128050 .LOCK_VIOLATION => return syscall.fail(error.LockViolation),
80138051 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
8014 .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading),
8052 .INVALID_HANDLE => if (is_debug) unreachable else return error.Unexpected,
80158053 // TODO: Determine if INVALID_FUNCTION is possible in more scenarios than just passing
80168054 // a handle to a directory.
80178055 .INVALID_FUNCTION => return syscall.fail(error.IsDir),
......@@ -8158,10 +8196,10 @@ fn fileReadPositionalWindows(userdata: ?*anyopaque, file: File, data: []const []
81588196 syscall.finish();
81598197 return 0;
81608198 },
8161 .NETNAME_DELETED => return syscall.fail(error.ConnectionResetByPeer),
8199 .NETNAME_DELETED => if (is_debug) unreachable else return error.Unexpected,
81628200 .LOCK_VIOLATION => return syscall.fail(error.LockViolation),
81638201 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
8164 .INVALID_HANDLE => return syscall.fail(error.NotOpenForReading),
8202 .INVALID_HANDLE => if (is_debug) unreachable else return error.Unexpected,
81658203 // TODO: Determine if INVALID_FUNCTION is possible in more scenarios than just passing
81668204 // a handle to a directory.
81678205 .INVALID_FUNCTION => return syscall.fail(error.IsDir),
......@@ -8842,7 +8880,7 @@ fn writeFilePositionalWindows(
88428880 .NOT_ENOUGH_MEMORY => return syscall.fail(error.SystemResources),
88438881 .NOT_ENOUGH_QUOTA => return syscall.fail(error.SystemResources),
88448882 .NO_DATA => return syscall.fail(error.BrokenPipe),
8845 .INVALID_HANDLE => return syscall.fail(error.NotOpenForWriting),
8883 .INVALID_HANDLE => if (is_debug) unreachable else return error.Unexpected, // use after free
88468884 .LOCK_VIOLATION => return syscall.fail(error.LockViolation),
88478885 .ACCESS_DENIED => return syscall.fail(error.AccessDenied),
88488886 .WORKING_SET_QUOTA => return syscall.fail(error.SystemResources),
......@@ -12470,6 +12508,7 @@ const linux_statx_request: std.os.linux.STATX = .{
1247012508 .INO = true,
1247112509 .SIZE = true,
1247212510 .NLINK = true,
12511 .BLOCKS = true,
1247312512};
1247412513
1247512514const linux_statx_check: std.os.linux.STATX = .{
......@@ -12481,6 +12520,7 @@ const linux_statx_check: std.os.linux.STATX = .{
1248112520 .INO = true,
1248212521 .SIZE = true,
1248312522 .NLINK = true,
12523 .BLOCKS = false,
1248412524};
1248512525
1248612526fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat {
......@@ -12499,6 +12539,7 @@ fn statFromLinux(stx: *const std.os.linux.Statx) Io.UnexpectedError!File.Stat {
1249912539 },
1250012540 .mtime = .{ .nanoseconds = @intCast(@as(i128, stx.mtime.sec) * std.time.ns_per_s + stx.mtime.nsec) },
1250112541 .ctime = .{ .nanoseconds = @intCast(@as(i128, stx.ctime.sec) * std.time.ns_per_s + stx.ctime.nsec) },
12542 .block_size = if (stx.mask.BLOCKS) stx.blksize else 1,
1250212543 };
1250312544}
1250412545
......@@ -12547,6 +12588,7 @@ fn statFromPosix(st: *const posix.Stat) File.Stat {
1254712588 .atime = timestampFromPosix(&atime),
1254812589 .mtime = timestampFromPosix(&mtime),
1254912590 .ctime = timestampFromPosix(&ctime),
12591 .block_size = st.blksize,
1255012592 };
1255112593}
1255212594
......@@ -12568,6 +12610,7 @@ fn statFromWasi(st: *const std.os.wasi.filestat_t) File.Stat {
1256812610 .atime = .fromNanoseconds(st.atim),
1256912611 .mtime = .fromNanoseconds(st.mtim),
1257012612 .ctime = .fromNanoseconds(st.ctim),
12613 .block_size = 1,
1257112614 };
1257212615}
1257312616
......@@ -16127,28 +16170,29 @@ fn fileMemoryMapCreate(
1612716170) File.MemoryMap.CreateError!File.MemoryMap {
1612816171 const t: *Threaded = @ptrCast(@alignCast(userdata));
1612916172 const offset = options.offset;
16173 const len = options.len;
1613016174
16131 const page_size = std.heap.pageSize();
16132 const aligned_len: usize = options.len.?; // TODO query if necessary
16175 assert(std.mem.isAligned(len, std.heap.page_size_min));
1613316176
16134 if (createFileMap(file, options.protection, offset, options.populate, aligned_len)) |result| {
16135 return result;
16136 } else |err| switch (err) {
16137 error.Unseekable, error.Canceled => |e| return e,
16138 else => {
16139 if (builtin.mode == .Debug)
16140 std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err});
16141 },
16177 if (!t.disable_memory_mapping) {
16178 if (createFileMap(file, options.protection, offset, options.populate, len)) |result| {
16179 return result;
16180 } else |err| switch (err) {
16181 error.Unseekable, error.Canceled, error.AccessDenied => |e| return e,
16182 else => {
16183 if (builtin.mode == .Debug)
16184 std.log.warn("memory mapping failed with {t}, falling back to file operations", .{err});
16185 },
16186 }
1614216187 }
1614316188
1614416189 const gpa = t.allocator;
16145 const alignment: Alignment = .fromByteUnits(page_size);
1614616190 const memory = m: {
16147 const ptr = gpa.rawAlloc(aligned_len, alignment, @returnAddress()) orelse
16191 const ptr = gpa.rawAlloc(len, .@"1", @returnAddress()) orelse
1614816192 return error.OutOfMemory;
16149 break :m ptr[0..aligned_len];
16193 break :m ptr[0..len];
1615016194 };
16151 errdefer gpa.rawFree(memory, alignment, @returnAddress());
16195 errdefer gpa.rawFree(memory, .@"1", @returnAddress());
1615216196
1615316197 if (!options.undefined_contents) try mmSyncRead(file, memory, offset);
1615416198
......@@ -16180,12 +16224,13 @@ const CreateFileMapError = error{
1618016224 OutOfMemory,
1618116225 MappingAlreadyExists,
1618216226 Unseekable,
16227 FileLockConflict,
1618316228} || Io.Cancelable || Io.UnexpectedError;
1618416229
1618516230fn createFileMap(
1618616231 file: File,
1618716232 protection: std.process.MemoryProtection,
16188 offset: usize,
16233 offset: u64,
1618916234 populate: bool,
1619016235 aligned_len: usize,
1619116236) CreateFileMapError!File.MemoryMap {
......@@ -16212,7 +16257,7 @@ fn createFileMap(
1621216257 file.handle,
1621316258 )) {
1621416259 .SUCCESS => {},
16215 .FILE_LOCK_CONFLICT => return error.FileLocked,
16260 .FILE_LOCK_CONFLICT => return error.FileLockConflict,
1621616261 .INVALID_FILE_FOR_SECTION => return error.OperationUnsupported,
1621716262 else => |status| return windows.unexpectedStatus(status),
1621816263 }
......@@ -16318,9 +16363,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void {
1631816363 }
1631916364 } else {
1632016365 const gpa = t.allocator;
16321 const page_size = std.heap.pageSize();
16322 const alignment: Alignment = .fromByteUnits(page_size);
16323 gpa.rawFree(memory, alignment, @returnAddress());
16366 gpa.rawFree(memory, .@"1", @returnAddress());
1632416367 }
1632516368 mm.* = undefined;
1632616369}
......@@ -16331,6 +16374,7 @@ fn fileMemoryMapSetLength(
1633116374 new_len: usize,
1633216375) File.MemoryMap.SetLengthError!void {
1633316376 const t: *Threaded = @ptrCast(@alignCast(userdata));
16377 assert(std.mem.isAligned(new_len, std.heap.page_size_min));
1633416378 if (mm.section) |section| switch (native_os) {
1633516379 .windows => {
1633616380 _ = section;
......@@ -16366,12 +16410,10 @@ fn fileMemoryMapSetLength(
1636616410 },
1636716411 } else {
1636816412 const gpa = t.allocator;
16369 const page_size = std.heap.pageSize();
16370 const alignment: Alignment = .fromByteUnits(page_size);
16371 if (gpa.rawRemap(mm.memory, alignment, new_len, @returnAddress())) |new_ptr| {
16413 if (gpa.rawRemap(mm.memory, .@"1", new_len, @returnAddress())) |new_ptr| {
1637216414 mm.memory = new_ptr[0..new_len];
1637316415 } else {
16374 const new_ptr = gpa.rawAlloc(new_len, alignment, @returnAddress()) orelse
16416 const new_ptr = gpa.rawAlloc(new_len, .@"1", @returnAddress()) orelse
1637516417 return error.OutOfMemory;
1637616418 const copy_len = @min(new_len, mm.memory.len);
1637716419 @memcpy(new_ptr[0..copy_len], mm.memory[0..copy_len]);
......@@ -16387,11 +16429,16 @@ fn fileMemoryMapRead(userdata: ?*anyopaque, mm: *File.MemoryMap) File.ReadPositi
1638716429 return mmSyncRead(mm.file, mm.memory, mm.offset);
1638816430}
1638916431
16390fn fileMemoryMapWrite(userdata: ?*anyopaque, mm: *File.MemoryMap) File.WritePositionalError!void {
16432fn fileMemoryMapWrite(
16433 userdata: ?*anyopaque,
16434 mm: *File.MemoryMap,
16435 file_size: u64,
16436) File.WritePositionalError!void {
1639116437 const t: *Threaded = @ptrCast(@alignCast(userdata));
1639216438 _ = t;
1639316439 if (mm.section != null) return;
16394 return mmSyncWrite(mm.file, mm.memory, mm.offset);
16440 const offset = mm.offset;
16441 return mmSyncWrite(mm.file, mm.memory[0..@intCast(file_size - offset)], offset);
1639516442}
1639616443
1639716444fn mmSyncRead(file: File, memory: []u8, offset: u64) File.ReadPositionalError!void {
lib/std/Io/test.zig+9-17
......@@ -605,31 +605,23 @@ test "memory mapping" {
605605 });
606606
607607 {
608 var file = try tmp.dir.openFile(io, "blah.txt", .{});
608 var file = try tmp.dir.openFile(io, "blah.txt", .{ .mode = .read_write });
609609 defer file.close(io);
610610
611 var mm = try file.createMemoryMap(io, .{});
611 const stat = try file.stat(io);
612 const aligned_len = std.mem.alignForward(usize, @intCast(stat.size), std.heap.pageSize());
613
614 var mm = try file.createMemoryMap(io, .{ .len = aligned_len });
612615 defer mm.destroy(io);
613616
614 try expectEqualStrings("this is my data123", mm.memory);
615 mm.memory[5] = '9';
616 mm.memory[8] = '9';
617 try expectEqualStrings("this is my data123", std.mem.sliceTo(mm.memory, 0));
618 mm.memory[4] = '9';
619 mm.memory[7] = '9';
617620
618 try mm.write(io);
621 try mm.write(io, stat.size);
619622 }
620623
621624 var buffer: [100]u8 = undefined;
622625 const updated_contents = try tmp.dir.readFile(io, "blah.txt", &buffer);
623626 try expectEqualStrings("this9is9my data123", updated_contents);
624
625 var file = try tmp.dir.openFile(io, "blah.txt", .{});
626 defer file.close(io);
627
628 var mm = try file.createMemoryMap(io, .{
629 .protection = .{ .read = true },
630 .offset = 2,
631 });
632 defer mm.destroy(io);
633
634 try expectEqualStrings("is9is9my data123", mm.memory);
635627}
lib/std/c.zig+1-1
......@@ -212,7 +212,7 @@ pub const nlink_t = switch (native_os) {
212212 .wasi => c_ulonglong,
213213 // https://github.com/SerenityOS/serenity/blob/b98f537f117b341788023ab82e0c11ca9ae29a57/Kernel/API/POSIX/sys/types.h#L45
214214 .freebsd, .serenity => u64,
215 .openbsd, .netbsd, .dragonfly, .illumos => u32,
215 .openbsd, .netbsd, .dragonfly, .illumos, .windows => u32,
216216 .haiku => i32,
217217 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => u16,
218218 else => u0,
lib/std/posix.zig+1
......@@ -55,6 +55,7 @@ else switch (native_os) {
5555 pub const gid_t = void;
5656 pub const mode_t = u0;
5757 pub const nlink_t = u0;
58 pub const blksize_t = void;
5859 pub const ino_t = void;
5960 pub const IFNAMESIZE = {};
6061 pub const SIG = void;