| ... | @@ -446,103 +446,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { | ... | @@ -446,103 +446,6 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 446 | } | 446 | } |
| 447 | } | 447 | } |
| 448 | | 448 | |
| 449 | pub const WriteError = error{ | | |
| 450 | DiskQuota, | | |
| 451 | FileTooBig, | | |
| 452 | InputOutput, | | |
| 453 | NoSpaceLeft, | | |
| 454 | DeviceBusy, | | |
| 455 | InvalidArgument, | | |
| 456 | | | |
| 457 | /// File descriptor does not hold the required rights to write to it. | | |
| 458 | AccessDenied, | | |
| 459 | PermissionDenied, | | |
| 460 | BrokenPipe, | | |
| 461 | SystemResources, | | |
| 462 | Canceled, | | |
| 463 | NotOpenForWriting, | | |
| 464 | | | |
| 465 | /// The process cannot access the file because another process has locked | | |
| 466 | /// a portion of the file. Windows-only. | | |
| 467 | LockViolation, | | |
| 468 | | | |
| 469 | /// This error occurs when no global event loop is configured, | | |
| 470 | /// and reading from the file descriptor would block. | | |
| 471 | WouldBlock, | | |
| 472 | | | |
| 473 | /// Connection reset by peer. | | |
| 474 | ConnectionResetByPeer, | | |
| 475 | | | |
| 476 | /// This error occurs in Linux if the process being written to | | |
| 477 | /// no longer exists. | | |
| 478 | ProcessNotFound, | | |
| 479 | /// This error occurs when a device gets disconnected before or mid-flush | | |
| 480 | /// while it's being written to - errno(6): No such device or address. | | |
| 481 | NoDevice, | | |
| 482 | | | |
| 483 | /// The socket type requires that message be sent atomically, and the size of the message | | |
| 484 | /// to be sent made this impossible. The message is not transmitted. | | |
| 485 | MessageOversize, | | |
| 486 | } || UnexpectedError; | | |
| 487 | | | |
| 488 | /// Write to a file descriptor. | | |
| 489 | /// Retries when interrupted by a signal. | | |
| 490 | /// Returns the number of bytes written. If nonzero bytes were supplied, this will be nonzero. | | |
| 491 | /// | | |
| 492 | /// Note that a successful write() may transfer fewer than count bytes. Such partial writes can | | |
| 493 | /// occur for various reasons; for example, because there was insufficient space on the disk | | |
| 494 | /// device to write all of the requested bytes, or because a blocked write() to a socket, pipe, or | | |
| 495 | /// similar was interrupted by a signal handler after it had transferred some, but before it had | | |
| 496 | /// transferred all of the requested bytes. In the event of a partial write, the caller can make | | |
| 497 | /// another write() call to transfer the remaining bytes. The subsequent call will either | | |
| 498 | /// transfer further bytes or may result in an error (e.g., if the disk is now full). | | |
| 499 | /// | | |
| 500 | /// For POSIX systems, if `fd` is opened in non blocking mode, the function will | | |
| 501 | /// return error.WouldBlock when EAGAIN is received. | | |
| 502 | /// On Windows, if the application has a global event loop enabled, I/O Completion Ports are | | |
| 503 | /// used to perform the I/O. `error.WouldBlock` is not possible on Windows. | | |
| 504 | /// | | |
| 505 | /// Linux has a limit on how many bytes may be transferred in one `write` call, which is `0x7ffff000` | | |
| 506 | /// on both 64-bit and 32-bit systems. This is due to using a signed C int as the return value, as | | |
| 507 | /// well as stuffing the errno codes into the last `4096` values. This is noted on the `write` man page. | | |
| 508 | /// The limit on Darwin is `0x7fffffff`, trying to read more than that returns EINVAL. | | |
| 509 | /// The corresponding POSIX limit is `maxInt(isize)`. | | |
| 510 | pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { | | |
| 511 | if (bytes.len == 0) return 0; | | |
| 512 | if (native_os == .windows) @compileError("unsupported OS"); | | |
| 513 | if (native_os == .wasi) @compileError("unsupported OS"); | | |
| 514 | | | |
| 515 | const max_count = switch (native_os) { | | |
| 516 | .linux => 0x7ffff000, | | |
| 517 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => maxInt(i32), | | |
| 518 | else => maxInt(isize), | | |
| 519 | }; | | |
| 520 | while (true) { | | |
| 521 | const rc = system.write(fd, bytes.ptr, @min(bytes.len, max_count)); | | |
| 522 | switch (errno(rc)) { | | |
| 523 | .SUCCESS => return @intCast(rc), | | |
| 524 | .INTR => continue, | | |
| 525 | .INVAL => return error.InvalidArgument, | | |
| 526 | .FAULT => unreachable, | | |
| 527 | .AGAIN => return error.WouldBlock, | | |
| 528 | .BADF => return error.NotOpenForWriting, // can be a race condition. | | |
| 529 | .DESTADDRREQ => unreachable, // `connect` was never called. | | |
| 530 | .DQUOT => return error.DiskQuota, | | |
| 531 | .FBIG => return error.FileTooBig, | | |
| 532 | .IO => return error.InputOutput, | | |
| 533 | .NOSPC => return error.NoSpaceLeft, | | |
| 534 | .ACCES => return error.AccessDenied, | | |
| 535 | .PERM => return error.PermissionDenied, | | |
| 536 | .PIPE => return error.BrokenPipe, | | |
| 537 | .CONNRESET => return error.ConnectionResetByPeer, | | |
| 538 | .BUSY => return error.DeviceBusy, | | |
| 539 | .NXIO => return error.NoDevice, | | |
| 540 | .MSGSIZE => return error.MessageOversize, | | |
| 541 | else => |err| return unexpectedErrno(err), | | |
| 542 | } | | |
| 543 | } | | |
| 544 | } | | |
| 545 | | | |
| 546 | pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; | 449 | pub const OpenError = std.Io.File.OpenError || error{WouldBlock}; |
| 547 | | 450 | |
| 548 | /// Open and possibly create a file. Keeps trying if it gets interrupted. | 451 | /// Open and possibly create a file. Keeps trying if it gets interrupted. |