Commit f47c6d3c6b

Luna <git@l4.pm>
2020-06-28 22:38:24
std.os: make EBADF return error for read and write
1 parent 374e3e4
Changed files (5)
lib
src-self-hosted
lib/std/zig/system.zig
@@ -851,6 +851,7 @@ pub const NativeTargetInfo = struct {
             const len = file.pread(buf[i .. buf.len - i], offset + i) catch |err| switch (err) {
                 error.OperationAborted => unreachable, // Windows-only
                 error.WouldBlock => unreachable, // Did not request blocking mode
+                error.NotOpenForReading => unreachable,
                 error.SystemResources => return error.SystemResources,
                 error.IsDir => return error.UnableToReadElfFile,
                 error.BrokenPipe => return error.UnableToReadElfFile,
lib/std/elf.zig
@@ -551,6 +551,7 @@ fn preadNoEof(file: std.fs.File, buf: []u8, offset: u64) !void {
             error.InputOutput => return error.FileSystem,
             error.Unexpected => return error.Unexpected,
             error.WouldBlock => return error.Unexpected,
+            error.NotOpenForReading => return error.Unexpected,
         };
         if (len == 0) return error.UnexpectedEndOfFile;
         i += len;
lib/std/os.zig
@@ -296,6 +296,7 @@ pub const ReadError = error{
     BrokenPipe,
     ConnectionResetByPeer,
     ConnectionTimedOut,
+    NotOpenForReading,
 
     /// This error occurs when no global event loop is configured,
     /// and reading from the file descriptor would block.
@@ -359,7 +360,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForReading, // Can be a race condition.
             EIO => return error.InputOutput,
             EISDIR => return error.IsDir,
             ENOBUFS => return error.SystemResources,
@@ -420,7 +421,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // always a race condition
+            EBADF => return error.NotOpenForReading, // can be a race condition
             EIO => return error.InputOutput,
             EISDIR => return error.IsDir,
             ENOBUFS => return error.SystemResources,
@@ -483,7 +484,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForReading, // Can be a race condition.
             EIO => return error.InputOutput,
             EISDIR => return error.IsDir,
             ENOBUFS => return error.SystemResources,
@@ -623,7 +624,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // always a race condition
+            EBADF => return error.NotOpenForReading, // can be a race condition
             EIO => return error.InputOutput,
             EISDIR => return error.IsDir,
             ENOBUFS => return error.SystemResources,
@@ -645,6 +646,7 @@ pub const WriteError = error{
     BrokenPipe,
     SystemResources,
     OperationAborted,
+    NotOpenForWriting,
 
     /// This error occurs when no global event loop is configured,
     /// and reading from the file descriptor would block.
@@ -720,7 +722,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForWriting, // can be a race condition.
             EDESTADDRREQ => unreachable, // `connect` was never called.
             EDQUOT => return error.DiskQuota,
             EFBIG => return error.FileTooBig,
@@ -792,7 +794,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForWriting, // Can be a race condition.
             EDESTADDRREQ => unreachable, // `connect` was never called.
             EDQUOT => return error.DiskQuota,
             EFBIG => return error.FileTooBig,
@@ -880,7 +882,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize {
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForWriting, // Can be a race condition.
             EDESTADDRREQ => unreachable, // `connect` was never called.
             EDQUOT => return error.DiskQuota,
             EFBIG => return error.FileTooBig,
@@ -967,7 +969,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz
             } else {
                 return error.WouldBlock;
             },
-            EBADF => unreachable, // Always a race condition.
+            EBADF => return error.NotOpenForWriting, // Can be a race condition.
             EDESTADDRREQ => unreachable, // `connect` was never called.
             EDQUOT => return error.DiskQuota,
             EFBIG => return error.FileTooBig,
@@ -1162,7 +1164,7 @@ pub fn dup2(old_fd: fd_t, new_fd: fd_t) !void {
             EBUSY, EINTR => continue,
             EMFILE => return error.ProcessFdQuotaExceeded,
             EINVAL => unreachable, // invalid parameters passed to dup2
-            EBADF => unreachable, // always a race condition
+            EBADF => unreachable, // invalid file descriptor
             else => |err| return unexpectedErrno(err),
         }
     }
src-self-hosted/main.zig
@@ -696,6 +696,7 @@ const FmtError = error{
     LinkQuotaExceeded,
     FileBusy,
     EndOfStream,
+    NotOpenForWriting,
 } || fs.File.OpenError;
 
 fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void {
@@ -761,6 +762,7 @@ fn fmtPathFile(
     const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) {
         error.ConnectionResetByPeer => unreachable,
         error.ConnectionTimedOut => unreachable,
+        error.NotOpenForReading => unreachable,
         else => |e| return e,
     };
     source_file.close();
src-self-hosted/stage2.zig
@@ -153,6 +153,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
     const c_out_stream = std.io.cOutStream(output_file);
     _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
         error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
+        error.NotOpenForWriting => unreachable,
         error.SystemResources => return .SystemResources,
         error.OperationAborted => return .OperationAborted,
         error.BrokenPipe => return .BrokenPipe,
@@ -585,6 +586,8 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [
         error.SystemResources => return .SystemResources,
         error.OperationAborted => return .OperationAborted,
         error.WouldBlock => unreachable,
+        error.NotOpenForWriting => unreachable,
+        error.NotOpenForReading => unreachable,
         error.Unexpected => return .Unexpected,
         error.EndOfStream => return .EndOfFile,
         error.IsDir => return .IsDir,
@@ -640,6 +643,7 @@ export fn stage2_libc_render(stage1_libc: *Stage2LibCInstallation, output_file:
     const c_out_stream = std.io.cOutStream(output_file);
     libc.render(c_out_stream) catch |err| switch (err) {
         error.WouldBlock => unreachable, // stage1 opens stuff in exclusively blocking mode
+        error.NotOpenForWriting => unreachable,
         error.SystemResources => return .SystemResources,
         error.OperationAborted => return .OperationAborted,
         error.BrokenPipe => return .BrokenPipe,