authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-07 00:49:09-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-07 00:49:09-04:00
logfd50a6896bc12af66caaa0da34e19adb3481b404
tree206ce1a5a4ec975b3d2fb8fa6c61d350c93cee6c
parent2c9ed664dd771ebb96f02ede84dd1ce7b6d58e44

std.event.fs support for macos

The file I/O stuff is working, but the fs watching stuff is not yet.

5 files changed, 239 insertions(+), 78 deletions(-)

std/c/index.zig+2
......@@ -21,8 +21,10 @@ pub extern "c" fn lseek(fd: c_int, offset: isize, whence: c_int) isize;
2121pub extern "c" fn open(path: [*]const u8, oflag: c_int, ...) c_int;
2222pub extern "c" fn raise(sig: c_int) c_int;
2323pub extern "c" fn read(fd: c_int, buf: *c_void, nbyte: usize) isize;
24pub extern "c" fn pread(fd: c_int, buf: *c_void, nbyte: usize, offset: u64) isize;
2425pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;
2526pub extern "c" fn write(fd: c_int, buf: *const c_void, nbyte: usize) isize;
27pub extern "c" fn pwrite(fd: c_int, buf: *const c_void, nbyte: usize, offset: u64) isize;
2628pub extern "c" fn mmap(addr: ?*c_void, len: usize, prot: c_int, flags: c_int, fd: c_int, offset: isize) ?*c_void;
2729pub extern "c" fn munmap(addr: *c_void, len: usize) c_int;
2830pub extern "c" fn unlink(path: [*]const u8) c_int;
std/event/fs.zig+12-12
......@@ -27,7 +27,7 @@ pub const Request = struct {
2727
2828 pub const PWriteV = struct {
2929 fd: os.FileHandle,
30 iov: []os.linux.iovec_const,
30 iov: []os.posix.iovec_const,
3131 offset: usize,
3232 result: Error!void,
3333
......@@ -36,7 +36,7 @@ pub const Request = struct {
3636
3737 pub const PReadV = struct {
3838 fd: os.FileHandle,
39 iov: []os.linux.iovec,
39 iov: []os.posix.iovec,
4040 offset: usize,
4141 result: Error!usize,
4242
......@@ -83,11 +83,11 @@ pub async fn pwritev(loop: *event.Loop, fd: os.FileHandle, offset: usize, data:
8383 resume @handle();
8484 }
8585
86 const iovecs = try loop.allocator.alloc(os.linux.iovec_const, data.len);
86 const iovecs = try loop.allocator.alloc(os.posix.iovec_const, data.len);
8787 defer loop.allocator.free(iovecs);
8888
8989 for (data) |buf, i| {
90 iovecs[i] = os.linux.iovec_const{
90 iovecs[i] = os.posix.iovec_const{
9191 .iov_base = buf.ptr,
9292 .iov_len = buf.len,
9393 };
......@@ -116,7 +116,7 @@ pub async fn pwritev(loop: *event.Loop, fd: os.FileHandle, offset: usize, data:
116116 };
117117
118118 suspend {
119 loop.linuxFsRequest(&req_node);
119 loop.posixFsRequest(&req_node);
120120 }
121121
122122 return req_node.data.msg.PWriteV.result;
......@@ -132,11 +132,11 @@ pub async fn preadv(loop: *event.Loop, fd: os.FileHandle, offset: usize, data: [
132132 resume @handle();
133133 }
134134
135 const iovecs = try loop.allocator.alloc(os.linux.iovec, data.len);
135 const iovecs = try loop.allocator.alloc(os.posix.iovec, data.len);
136136 defer loop.allocator.free(iovecs);
137137
138138 for (data) |buf, i| {
139 iovecs[i] = os.linux.iovec{
139 iovecs[i] = os.posix.iovec{
140140 .iov_base = buf.ptr,
141141 .iov_len = buf.len,
142142 };
......@@ -165,7 +165,7 @@ pub async fn preadv(loop: *event.Loop, fd: os.FileHandle, offset: usize, data: [
165165 };
166166
167167 suspend {
168 loop.linuxFsRequest(&req_node);
168 loop.posixFsRequest(&req_node);
169169 }
170170
171171 return req_node.data.msg.PReadV.result;
......@@ -201,7 +201,7 @@ pub async fn openRead(loop: *event.Loop, path: []const u8) os.File.OpenError!os.
201201 };
202202
203203 suspend {
204 loop.linuxFsRequest(&req_node);
204 loop.posixFsRequest(&req_node);
205205 }
206206
207207 return req_node.data.msg.OpenRead.result;
......@@ -243,7 +243,7 @@ pub async fn openReadWrite(
243243 };
244244
245245 suspend {
246 loop.linuxFsRequest(&req_node);
246 loop.posixFsRequest(&req_node);
247247 }
248248
249249 return req_node.data.msg.OpenRW.result;
......@@ -280,7 +280,7 @@ pub const CloseOperation = struct {
280280 /// Defer this after creating.
281281 pub fn deinit(self: *CloseOperation) void {
282282 if (self.have_fd) {
283 self.loop.linuxFsRequest(&self.close_req_node);
283 self.loop.posixFsRequest(&self.close_req_node);
284284 } else {
285285 self.loop.allocator.destroy(self);
286286 }
......@@ -330,7 +330,7 @@ pub async fn writeFileMode(loop: *event.Loop, path: []const u8, contents: []cons
330330 };
331331
332332 suspend {
333 loop.linuxFsRequest(&req_node);
333 loop.posixFsRequest(&req_node);
334334 }
335335
336336 return req_node.data.msg.WriteFile.result;
std/event/loop.zig+99-31
......@@ -127,11 +127,6 @@ pub const Loop = struct {
127127 .finish = fs.Request.Finish.NoAction,
128128 },
129129 };
130 self.os_data.fs_thread = try os.spawnThread(self, linuxFsRun);
131 errdefer {
132 self.linuxFsRequest(&self.os_data.fs_end_request);
133 self.os_data.fs_thread.wait();
134 }
135130
136131 errdefer {
137132 while (self.available_eventfd_resume_nodes.pop()) |node| os.close(node.data.eventfd);
......@@ -168,6 +163,12 @@ pub const Loop = struct {
168163 &self.os_data.final_eventfd_event,
169164 );
170165
166 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);
167 errdefer {
168 self.posixFsRequest(&self.os_data.fs_end_request);
169 self.os_data.fs_thread.wait();
170 }
171
171172 var extra_thread_index: usize = 0;
172173 errdefer {
173174 // writing 8 bytes to an eventfd cannot fail
......@@ -185,10 +186,25 @@ pub const Loop = struct {
185186 self.os_data.kqfd = try os.bsdKQueue();
186187 errdefer os.close(self.os_data.kqfd);
187188
189 self.os_data.fs_kqfd = try os.bsdKQueue();
190 errdefer os.close(self.os_data.fs_kqfd);
191
192 self.os_data.fs_queue = std.atomic.Queue(fs.Request).init();
193 // we need another thread for the file system because Darwin does not have an async
194 // file system I/O API.
195 self.os_data.fs_end_request = fs.RequestNode{
196 .prev = undefined,
197 .next = undefined,
198 .data = fs.Request{
199 .msg = fs.Request.Msg.End,
200 .finish = fs.Request.Finish.NoAction,
201 },
202 };
203
188204 self.os_data.kevents = try self.allocator.alloc(posix.Kevent, extra_thread_count);
189205 errdefer self.allocator.free(self.os_data.kevents);
190206
191 const eventlist = ([*]posix.Kevent)(undefined)[0..0];
207 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
192208
193209 for (self.eventfd_resume_nodes) |*eventfd_node, i| {
194210 eventfd_node.* = std.atomic.Stack(ResumeNode.EventFd).Node{
......@@ -207,12 +223,11 @@ pub const Loop = struct {
207223 .udata = @ptrToInt(&eventfd_node.data.base),
208224 },
209225 },
210 .prev = undefined,
211226 .next = undefined,
212227 };
213228 self.available_eventfd_resume_nodes.push(eventfd_node);
214229 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.data.kevent);
215 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, eventlist, null);
230 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null);
216231 eventfd_node.data.kevent.flags = posix.EV_CLEAR | posix.EV_ENABLE;
217232 eventfd_node.data.kevent.fflags = posix.NOTE_TRIGGER;
218233 // this one is for waiting for events
......@@ -236,14 +251,38 @@ pub const Loop = struct {
236251 .data = 0,
237252 .udata = @ptrToInt(&self.final_resume_node),
238253 };
239 const kevent_array = (*[1]posix.Kevent)(&self.os_data.final_kevent);
240 _ = try os.bsdKEvent(self.os_data.kqfd, kevent_array, eventlist, null);
254 const final_kev_arr = (*[1]posix.Kevent)(&self.os_data.final_kevent);
255 _ = try os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null);
241256 self.os_data.final_kevent.flags = posix.EV_ENABLE;
242257 self.os_data.final_kevent.fflags = posix.NOTE_TRIGGER;
243258
259 self.os_data.fs_kevent_wake = posix.Kevent{
260 .ident = extra_thread_count + 1,
261 .filter = posix.EVFILT_USER,
262 .flags = posix.EV_ADD,
263 .fflags = posix.NOTE_TRIGGER,
264 .data = 0,
265 .udata = undefined,
266 };
267
268 self.os_data.fs_kevent_wait = posix.Kevent{
269 .ident = extra_thread_count + 1,
270 .filter = posix.EVFILT_USER,
271 .flags = posix.EV_ADD|posix.EV_CLEAR,
272 .fflags = 0,
273 .data = 0,
274 .udata = undefined,
275 };
276
277 self.os_data.fs_thread = try os.spawnThread(self, posixFsRun);
278 errdefer {
279 self.posixFsRequest(&self.os_data.fs_end_request);
280 self.os_data.fs_thread.wait();
281 }
282
244283 var extra_thread_index: usize = 0;
245284 errdefer {
246 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, eventlist, null) catch unreachable;
285 _ = os.bsdKEvent(self.os_data.kqfd, final_kev_arr, empty_kevs, null) catch unreachable;
247286 while (extra_thread_index != 0) {
248287 extra_thread_index -= 1;
249288 self.extra_threads[extra_thread_index].wait();
......@@ -312,6 +351,7 @@ pub const Loop = struct {
312351 builtin.Os.macosx => {
313352 self.allocator.free(self.os_data.kevents);
314353 os.close(self.os_data.kqfd);
354 os.close(self.os_data.fs_kqfd);
315355 },
316356 builtin.Os.windows => {
317357 os.close(self.os_data.io_port);
......@@ -375,8 +415,8 @@ pub const Loop = struct {
375415 switch (builtin.os) {
376416 builtin.Os.macosx => {
377417 const kevent_array = (*[1]posix.Kevent)(&eventfd_node.kevent);
378 const eventlist = ([*]posix.Kevent)(undefined)[0..0];
379 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, eventlist, null) catch {
418 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
419 _ = os.bsdKEvent(self.os_data.kqfd, kevent_array, empty_kevs, null) catch {
380420 self.next_tick_queue.unget(next_tick_node);
381421 self.available_eventfd_resume_nodes.push(resume_stack_node);
382422 return;
......@@ -493,16 +533,17 @@ pub const Loop = struct {
493533 // cause all the threads to stop
494534 switch (builtin.os) {
495535 builtin.Os.linux => {
496 self.linuxFsRequest(&self.os_data.fs_end_request);
536 self.posixFsRequest(&self.os_data.fs_end_request);
497537 // writing 8 bytes to an eventfd cannot fail
498538 os.posixWrite(self.os_data.final_eventfd, wakeup_bytes) catch unreachable;
499539 return;
500540 },
501541 builtin.Os.macosx => {
542 self.posixFsRequest(&self.os_data.fs_end_request);
502543 const final_kevent = (*[1]posix.Kevent)(&self.os_data.final_kevent);
503 const eventlist = ([*]posix.Kevent)(undefined)[0..0];
544 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
504545 // cannot fail because we already added it and this just enables it
505 _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, eventlist, null) catch unreachable;
546 _ = os.bsdKEvent(self.os_data.kqfd, final_kevent, empty_kevs, null) catch unreachable;
506547 return;
507548 },
508549 builtin.Os.windows => {
......@@ -576,6 +617,7 @@ pub const Loop = struct {
576617 self.finishOneEvent();
577618 }
578619 }
620 break;
579621 },
580622 builtin.Os.windows => {
581623 var completion_key: usize = undefined;
......@@ -610,19 +652,29 @@ pub const Loop = struct {
610652 }
611653 }
612654
613 fn linuxFsRequest(self: *Loop, request_node: *fs.RequestNode) void {
614 self.beginOneEvent(); // finished in linuxFsRun after processing the msg
655 fn posixFsRequest(self: *Loop, request_node: *fs.RequestNode) void {
656 self.beginOneEvent(); // finished in posixFsRun after processing the msg
615657 self.os_data.fs_queue.put(request_node);
616 _ = @atomicRmw(i32, &self.os_data.fs_queue_len, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); // let this wrap
617 const rc = os.linux.futex_wake(@ptrToInt(&self.os_data.fs_queue_len), os.linux.FUTEX_WAKE, 1);
618 switch (os.linux.getErrno(rc)) {
619 0 => {},
620 posix.EINVAL => unreachable,
621 else => unreachable,
658 switch (builtin.os) {
659 builtin.Os.macosx => {
660 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wake);
661 const empty_kevs = ([*]posix.Kevent)(undefined)[0..0];
662 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, empty_kevs, null) catch unreachable;
663 },
664 builtin.Os.linux => {
665 _ = @atomicRmw(i32, &self.os_data.fs_queue_len, AtomicRmwOp.Add, 1, AtomicOrder.SeqCst); // let this wrap
666 const rc = os.linux.futex_wake(@ptrToInt(&self.os_data.fs_queue_len), os.linux.FUTEX_WAKE, 1);
667 switch (os.linux.getErrno(rc)) {
668 0 => {},
669 posix.EINVAL => unreachable,
670 else => unreachable,
671 }
672 },
673 else => @compileError("Unsupported OS"),
622674 }
623675 }
624676
625 fn linuxFsRun(self: *Loop) void {
677 fn posixFsRun(self: *Loop) void {
626678 var processed_count: i32 = 0; // we let this wrap
627679 while (true) {
628680 while (self.os_data.fs_queue.get()) |node| {
......@@ -664,12 +716,22 @@ pub const Loop = struct {
664716 }
665717 self.finishOneEvent();
666718 }
667 const rc = os.linux.futex_wait(@ptrToInt(&self.os_data.fs_queue_len), os.linux.FUTEX_WAIT, processed_count, null);
668 switch (os.linux.getErrno(rc)) {
669 0 => continue,
670 posix.EINTR => continue,
671 posix.EAGAIN => continue,
672 else => unreachable,
719 switch (builtin.os) {
720 builtin.Os.linux => {
721 const rc = os.linux.futex_wait(@ptrToInt(&self.os_data.fs_queue_len), os.linux.FUTEX_WAIT, processed_count, null);
722 switch (os.linux.getErrno(rc)) {
723 0 => continue,
724 posix.EINTR => continue,
725 posix.EAGAIN => continue,
726 else => unreachable,
727 }
728 },
729 builtin.Os.macosx => {
730 const fs_kevs = (*[1]posix.Kevent)(&self.os_data.fs_kevent_wait);
731 var out_kevs: [1]posix.Kevent = undefined;
732 _ = os.bsdKEvent(self.os_data.fs_kqfd, fs_kevs, out_kevs[0..], null) catch unreachable;
733 },
734 else => @compileError("Unsupported OS"),
673735 }
674736 }
675737 }
......@@ -696,6 +758,12 @@ pub const Loop = struct {
696758 kqfd: i32,
697759 final_kevent: posix.Kevent,
698760 kevents: []posix.Kevent,
761 fs_kevent_wake: posix.Kevent,
762 fs_kevent_wait: posix.Kevent,
763 fs_thread: *os.Thread,
764 fs_kqfd: i32,
765 fs_queue: std.atomic.Queue(fs.Request),
766 fs_end_request: fs.RequestNode,
699767 };
700768};
701769
std/os/darwin.zig+8
......@@ -646,6 +646,10 @@ pub fn read(fd: i32, buf: [*]u8, nbyte: usize) usize {
646646 return errnoWrap(c.read(fd, @ptrCast(*c_void, buf), nbyte));
647647}
648648
649pub fn pread(fd: i32, buf: [*]u8, nbyte: usize, offset: u64) usize {
650 return errnoWrap(c.pread(fd, @ptrCast(*c_void, buf), nbyte, offset));
651}
652
649653pub fn stat(noalias path: [*]const u8, noalias buf: *stat) usize {
650654 return errnoWrap(c.stat(path, buf));
651655}
......@@ -654,6 +658,10 @@ pub fn write(fd: i32, buf: [*]const u8, nbyte: usize) usize {
654658 return errnoWrap(c.write(fd, @ptrCast(*const c_void, buf), nbyte));
655659}
656660
661pub fn pwrite(fd: i32, buf: [*]const u8, nbyte: usize, offset: u64) usize {
662 return errnoWrap(c.pwrite(fd, @ptrCast(*const c_void, buf), nbyte, offset));
663}
664
657665pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, offset: isize) usize {
658666 const ptr_result = c.mmap(
659667 @ptrCast(*c_void, address),
std/os/index.zig+118-35
......@@ -246,23 +246,64 @@ pub fn posixRead(fd: i32, buf: []u8) !void {
246246 }
247247}
248248
249/// Number of bytes read is returned. Upon reading end-of-file, zero is returned.
249250pub fn posix_preadv(fd: i32, iov: [*]const posix.iovec, count: usize, offset: u64) !usize {
250 while (true) {
251 const rc = posix.preadv(fd, iov, count, offset);
252 const err = posix.getErrno(rc);
253 switch (err) {
254 0 => return rc,
255 posix.EINTR => continue,
256 posix.EINVAL => unreachable,
257 posix.EFAULT => unreachable,
258 posix.EAGAIN => return error.WouldBlock,
259 posix.EBADF => return error.FileClosed,
260 posix.EIO => return error.InputOutput,
261 posix.EISDIR => return error.IsDir,
262 posix.ENOBUFS => return error.SystemResources,
263 posix.ENOMEM => return error.SystemResources,
264 else => return unexpectedErrorPosix(err),
265 }
251 switch (builtin.os) {
252 builtin.Os.macosx => {
253 // Darwin does not have preadv but it does have pread.
254 var off: usize = 0;
255 var iov_i: usize = 0;
256 var inner_off: usize = 0;
257 while (true) {
258 const v = iov[iov_i];
259 const rc = darwin.pread(fd, v.iov_base + inner_off, v.iov_len - inner_off, offset + off);
260 const err = darwin.getErrno(rc);
261 switch (err) {
262 0 => {
263 off += rc;
264 inner_off += rc;
265 if (inner_off == v.iov_len) {
266 iov_i += 1;
267 inner_off = 0;
268 if (iov_i == count) {
269 return off;
270 }
271 }
272 if (rc == 0) return off; // EOF
273 continue;
274 },
275 posix.EINTR => continue,
276 posix.EINVAL => unreachable,
277 posix.EFAULT => unreachable,
278 posix.ESPIPE => unreachable, // fd is not seekable
279 posix.EAGAIN => return error.WouldBlock,
280 posix.EBADF => return error.FileClosed,
281 posix.EIO => return error.InputOutput,
282 posix.EISDIR => return error.IsDir,
283 posix.ENOBUFS => return error.SystemResources,
284 posix.ENOMEM => return error.SystemResources,
285 else => return unexpectedErrorPosix(err),
286 }
287 }
288 },
289 builtin.Os.linux, builtin.Os.freebsd => while (true) {
290 const rc = posix.preadv(fd, iov, count, offset);
291 const err = posix.getErrno(rc);
292 switch (err) {
293 0 => return rc,
294 posix.EINTR => continue,
295 posix.EINVAL => unreachable,
296 posix.EFAULT => unreachable,
297 posix.EAGAIN => return error.WouldBlock,
298 posix.EBADF => return error.FileClosed,
299 posix.EIO => return error.InputOutput,
300 posix.EISDIR => return error.IsDir,
301 posix.ENOBUFS => return error.SystemResources,
302 posix.ENOMEM => return error.SystemResources,
303 else => return unexpectedErrorPosix(err),
304 }
305 },
306 else => @compileError("Unsupported OS"),
266307 }
267308}
268309
......@@ -311,25 +352,67 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
311352}
312353
313354pub fn posix_pwritev(fd: i32, iov: [*]const posix.iovec_const, count: usize, offset: u64) PosixWriteError!void {
314 while (true) {
315 const rc = posix.pwritev(fd, iov, count, offset);
316 const err = posix.getErrno(rc);
317 switch (err) {
318 0 => return,
319 posix.EINTR => continue,
320 posix.EINVAL => unreachable,
321 posix.EFAULT => unreachable,
322 posix.EAGAIN => return PosixWriteError.WouldBlock,
323 posix.EBADF => return PosixWriteError.FileClosed,
324 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
325 posix.EDQUOT => return PosixWriteError.DiskQuota,
326 posix.EFBIG => return PosixWriteError.FileTooBig,
327 posix.EIO => return PosixWriteError.InputOutput,
328 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
329 posix.EPERM => return PosixWriteError.AccessDenied,
330 posix.EPIPE => return PosixWriteError.BrokenPipe,
331 else => return unexpectedErrorPosix(err),
332 }
355 switch (builtin.os) {
356 builtin.Os.macosx => {
357 // Darwin does not have pwritev but it does have pwrite.
358 var off: usize = 0;
359 var iov_i: usize = 0;
360 var inner_off: usize = 0;
361 while (true) {
362 const v = iov[iov_i];
363 const rc = darwin.pwrite(fd, v.iov_base + inner_off, v.iov_len - inner_off, offset + off);
364 const err = darwin.getErrno(rc);
365 switch (err) {
366 0 => {
367 off += rc;
368 inner_off += rc;
369 if (inner_off == v.iov_len) {
370 iov_i += 1;
371 inner_off = 0;
372 if (iov_i == count) {
373 return;
374 }
375 }
376 continue;
377 },
378 posix.EINTR => continue,
379 posix.ESPIPE => unreachable, // fd is not seekable
380 posix.EINVAL => unreachable,
381 posix.EFAULT => unreachable,
382 posix.EAGAIN => return PosixWriteError.WouldBlock,
383 posix.EBADF => return PosixWriteError.FileClosed,
384 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
385 posix.EDQUOT => return PosixWriteError.DiskQuota,
386 posix.EFBIG => return PosixWriteError.FileTooBig,
387 posix.EIO => return PosixWriteError.InputOutput,
388 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
389 posix.EPERM => return PosixWriteError.AccessDenied,
390 posix.EPIPE => return PosixWriteError.BrokenPipe,
391 else => return unexpectedErrorPosix(err),
392 }
393 }
394 },
395 builtin.Os.linux => while (true) {
396 const rc = posix.pwritev(fd, iov, count, offset);
397 const err = posix.getErrno(rc);
398 switch (err) {
399 0 => return,
400 posix.EINTR => continue,
401 posix.EINVAL => unreachable,
402 posix.EFAULT => unreachable,
403 posix.EAGAIN => return PosixWriteError.WouldBlock,
404 posix.EBADF => return PosixWriteError.FileClosed,
405 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
406 posix.EDQUOT => return PosixWriteError.DiskQuota,
407 posix.EFBIG => return PosixWriteError.FileTooBig,
408 posix.EIO => return PosixWriteError.InputOutput,
409 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
410 posix.EPERM => return PosixWriteError.AccessDenied,
411 posix.EPIPE => return PosixWriteError.BrokenPipe,
412 else => return unexpectedErrorPosix(err),
413 }
414 },
415 else => @compileError("Unsupported OS"),
333416 }
334417}
335418