From f4eecf8d7d4026a9e0ab8986b1c049ad2a0e01fc Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Sat, 21 Mar 2026 09:57:05 -0600 Subject: [PATCH] handle EROFS in create/open file I hit an unexpected errno 30 on macos attempting to call createFile on a directory in PATH. errno 30 is EROFS, this change propagates that error as error.ReadOnlyFileSystem. --- lib/std/Io/Dispatch.zig | 2 ++ lib/std/Io/File.zig | 1 + lib/std/Io/Threaded.zig | 2 ++ lib/std/Io/Uring.zig | 1 + lib/std/debug/SelfInfo/Windows.zig | 1 + lib/std/zig/system.zig | 2 ++ 6 files changed, 9 insertions(+) diff --git a/lib/std/Io/Dispatch.zig b/lib/std/Io/Dispatch.zig index 76e23d6818..259a233d57 100644 --- a/lib/std/Io/Dispatch.zig +++ b/lib/std/Io/Dispatch.zig @@ -2512,6 +2512,7 @@ fn dirCreateFile( .OPNOTSUPP => return error.FileLocksUnsupported, .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, + .ROFS => return error.ReadOnlyFileSystem, .NXIO => return error.NoDevice, .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), @@ -2647,6 +2648,7 @@ fn dirOpenFile( .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, + .ROFS => return error.ReadOnlyFileSystem, .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } diff --git a/lib/std/Io/File.zig b/lib/std/Io/File.zig index 4d6afbfef9..8030cfc846 100644 --- a/lib/std/Io/File.zig +++ b/lib/std/Io/File.zig @@ -202,6 +202,7 @@ pub const OpenError = error{ NotDir, /// The path already exists and the `CREAT` and `EXCL` flags were provided. PathAlreadyExists, + ReadOnlyFileSystem, DeviceBusy, FileLocksUnsupported, /// One of these three things: diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index 6554e145d9..0bec8a068f 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -4290,6 +4290,7 @@ fn dirCreateFilePosix( .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, + .ROFS => return error.ReadOnlyFileSystem, .ILSEQ => return error.BadPathName, else => |err| return posix.unexpectedErrno(err), } @@ -4871,6 +4872,7 @@ fn dirOpenFilePosix( .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, + .ROFS => return error.ReadOnlyFileSystem, .ILSEQ => return error.BadPathName, else => |err| return posix.unexpectedErrno(err), } diff --git a/lib/std/Io/Uring.zig b/lib/std/Io/Uring.zig index 15e66f2346..b28d78db79 100644 --- a/lib/std/Io/Uring.zig +++ b/lib/std/Io/Uring.zig @@ -5673,6 +5673,7 @@ fn openat( .AGAIN => return error.WouldBlock, .TXTBSY => return error.FileBusy, .NXIO => return error.NoDevice, + .ROFS => return error.ReadOnlyFileSystem, .ILSEQ => return error.BadPathName, else => |err| return unexpectedErrno(err), } diff --git a/lib/std/debug/SelfInfo/Windows.zig b/lib/std/debug/SelfInfo/Windows.zig index 4c46f7d0c4..c7323c722a 100644 --- a/lib/std/debug/SelfInfo/Windows.zig +++ b/lib/std/debug/SelfInfo/Windows.zig @@ -360,6 +360,7 @@ const Module = struct { error.SystemFdQuotaExceeded, error.FileLocksUnsupported, error.FileBusy, + error.ReadOnlyFileSystem, => return error.ReadFailed, }; errdefer coff_file.close(io); diff --git a/lib/std/zig/system.zig b/lib/std/zig/system.zig index b32b554dee..524c5e29af 100644 --- a/lib/std/zig/system.zig +++ b/lib/std/zig/system.zig @@ -423,6 +423,7 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target { error.ConnectionResetByPeer => return error.Unexpected, error.NotOpenForReading => return error.Unexpected, error.SocketUnconnected => return error.Unexpected, + error.ReadOnlyFileSystem => return error.Unexpected, error.AccessDenied, error.SymLinkLoop, @@ -853,6 +854,7 @@ fn glibcVerFromRPath(io: Io, rpath: []const u8) !std.SemanticVersion { error.PathAlreadyExists => return error.Unexpected, // read-only error.DeviceBusy => return error.Unexpected, // read-only error.FileBusy => return error.Unexpected, // read-only + error.ReadOnlyFileSystem => return error.Unexpected, // read-only error.NoDevice => return error.Unexpected, // not asking for a special device error.FileTooBig => return error.Unexpected, error.WouldBlock => return error.Unexpected, // not opened in non-blocking