| author | |
| committer | |
| log | f160d5f979c9f2bcc98ef0169a879a76d0234ed2 |
| tree | 0d0ffdb2d1399ed0001c792d81d11491743bab58 |
| parent | feeed922e1a7d89b99572d5577c814f9e6293b9b |
3 files changed, 92 insertions(+), 167 deletions(-)
lib/std/Io/Threaded.zig+88-2| ... | ... | @@ -7420,7 +7420,18 @@ fn fileWritePositional( |
| 7420 | 7420 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 7421 | 7421 | const current_thread = Thread.getCurrent(t); |
| 7422 | 7422 | |
| 7423 | if (is_windows) @panic("TODO implement fileWritePositional windows"); | |
| 7423 | if (is_windows) { | |
| 7424 | if (header.len != 0) { | |
| 7425 | return writeFilePositionalWindows(current_thread, file.handle, header, offset); | |
| 7426 | } | |
| 7427 | for (data[0 .. data.len - 1]) |buf| { | |
| 7428 | if (buf.len == 0) continue; | |
| 7429 | return writeFilePositionalWindows(current_thread, file.handle, buf, offset); | |
| 7430 | } | |
| 7431 | const pattern = data[data.len - 1]; | |
| 7432 | if (pattern.len == 0 or splat == 0) return 0; | |
| 7433 | return writeFilePositionalWindows(current_thread, file.handle, pattern, offset); | |
| 7434 | } | |
| 7424 | 7435 | |
| 7425 | 7436 | var iovecs: [max_iovecs_len]posix.iovec_const = undefined; |
| 7426 | 7437 | var iovlen: iovlen_t = 0; |
| ... | ... | @@ -7532,6 +7543,44 @@ fn fileWritePositional( |
| 7532 | 7543 | } |
| 7533 | 7544 | } |
| 7534 | 7545 | |
| 7546 | fn writeFilePositionalWindows( | |
| 7547 | current_thread: *Thread, | |
| 7548 | handle: windows.HANDLE, | |
| 7549 | bytes: []const u8, | |
| 7550 | offset: u64, | |
| 7551 | ) File.WritePositionalError!usize { | |
| 7552 | try current_thread.checkCancel(); | |
| 7553 | ||
| 7554 | var bytes_written: windows.DWORD = undefined; | |
| 7555 | var overlapped: windows.OVERLAPPED = .{ | |
| 7556 | .Internal = 0, | |
| 7557 | .InternalHigh = 0, | |
| 7558 | .DUMMYUNIONNAME = .{ | |
| 7559 | .DUMMYSTRUCTNAME = .{ | |
| 7560 | .Offset = @truncate(offset), | |
| 7561 | .OffsetHigh = @truncate(offset >> 32), | |
| 7562 | }, | |
| 7563 | }, | |
| 7564 | .hEvent = null, | |
| 7565 | }; | |
| 7566 | const adjusted_len = std.math.lossyCast(u32, bytes.len); | |
| 7567 | if (windows.kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, &overlapped) == 0) { | |
| 7568 | switch (windows.GetLastError()) { | |
| 7569 | .INVALID_USER_BUFFER => return error.SystemResources, | |
| 7570 | .NOT_ENOUGH_MEMORY => return error.SystemResources, | |
| 7571 | .OPERATION_ABORTED => return error.Canceled, | |
| 7572 | .NOT_ENOUGH_QUOTA => return error.SystemResources, | |
| 7573 | .NO_DATA => return error.BrokenPipe, | |
| 7574 | .INVALID_HANDLE => return error.NotOpenForWriting, | |
| 7575 | .LOCK_VIOLATION => return error.LockViolation, | |
| 7576 | .ACCESS_DENIED => return error.AccessDenied, | |
| 7577 | .WORKING_SET_QUOTA => return error.SystemResources, | |
| 7578 | else => |err| return windows.unexpectedError(err), | |
| 7579 | } | |
| 7580 | } | |
| 7581 | return bytes_written; | |
| 7582 | } | |
| 7583 | ||
| 7535 | 7584 | fn fileWriteStreaming( |
| 7536 | 7585 | userdata: ?*anyopaque, |
| 7537 | 7586 | file: File, |
| ... | ... | @@ -7542,7 +7591,18 @@ fn fileWriteStreaming( |
| 7542 | 7591 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 7543 | 7592 | const current_thread = Thread.getCurrent(t); |
| 7544 | 7593 | |
| 7545 | if (is_windows) @panic("TODO implement fileWriteStreaming windows"); | |
| 7594 | if (is_windows) { | |
| 7595 | if (header.len != 0) { | |
| 7596 | return writeFileStreamingWindows(current_thread, file.handle, header); | |
| 7597 | } | |
| 7598 | for (data[0 .. data.len - 1]) |buf| { | |
| 7599 | if (buf.len == 0) continue; | |
| 7600 | return writeFileStreamingWindows(current_thread, file.handle, buf); | |
| 7601 | } | |
| 7602 | const pattern = data[data.len - 1]; | |
| 7603 | if (pattern.len == 0 or splat == 0) return 0; | |
| 7604 | return writeFileStreamingWindows(current_thread, file.handle, pattern); | |
| 7605 | } | |
| 7546 | 7606 | |
| 7547 | 7607 | var iovecs: [max_iovecs_len]posix.iovec_const = undefined; |
| 7548 | 7608 | var iovlen: iovlen_t = 0; |
| ... | ... | @@ -7647,6 +7707,32 @@ fn fileWriteStreaming( |
| 7647 | 7707 | } |
| 7648 | 7708 | } |
| 7649 | 7709 | |
| 7710 | fn writeFileStreamingWindows( | |
| 7711 | current_thread: *Thread, | |
| 7712 | handle: windows.HANDLE, | |
| 7713 | bytes: []const u8, | |
| 7714 | ) File.Writer.Error!usize { | |
| 7715 | try current_thread.checkCancel(); | |
| 7716 | ||
| 7717 | var bytes_written: windows.DWORD = undefined; | |
| 7718 | const adjusted_len = std.math.lossyCast(u32, bytes.len); | |
| 7719 | if (windows.kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, null) == 0) { | |
| 7720 | switch (windows.GetLastError()) { | |
| 7721 | .INVALID_USER_BUFFER => return error.SystemResources, | |
| 7722 | .NOT_ENOUGH_MEMORY => return error.SystemResources, | |
| 7723 | .OPERATION_ABORTED => return error.Canceled, | |
| 7724 | .NOT_ENOUGH_QUOTA => return error.SystemResources, | |
| 7725 | .NO_DATA => return error.BrokenPipe, | |
| 7726 | .INVALID_HANDLE => return error.NotOpenForWriting, | |
| 7727 | .LOCK_VIOLATION => return error.LockViolation, | |
| 7728 | .ACCESS_DENIED => return error.AccessDenied, | |
| 7729 | .WORKING_SET_QUOTA => return error.SystemResources, | |
| 7730 | else => |err| return windows.unexpectedError(err), | |
| 7731 | } | |
| 7732 | } | |
| 7733 | return bytes_written; | |
| 7734 | } | |
| 7735 | ||
| 7650 | 7736 | fn fileWriteFileStreaming( |
| 7651 | 7737 | userdata: ?*anyopaque, |
| 7652 | 7738 | file: File, |
lib/std/os/windows.zig-109| ... | ... | @@ -2830,115 +2830,6 @@ pub fn CloseHandle(hObject: HANDLE) void { |
| 2830 | 2830 | assert(ntdll.NtClose(hObject) == .SUCCESS); |
| 2831 | 2831 | } |
| 2832 | 2832 | |
| 2833 | pub const ReadFileError = error{ | |
| 2834 | BrokenPipe, | |
| 2835 | /// The specified network name is no longer available. | |
| 2836 | ConnectionResetByPeer, | |
| 2837 | Canceled, | |
| 2838 | /// Unable to read file due to lock. | |
| 2839 | LockViolation, | |
| 2840 | /// Known to be possible when: | |
| 2841 | /// - Unable to read from disconnected virtual com port (Windows) | |
| 2842 | AccessDenied, | |
| 2843 | NotOpenForReading, | |
| 2844 | Unexpected, | |
| 2845 | }; | |
| 2846 | ||
| 2847 | /// If buffer's length exceeds what a Windows DWORD integer can hold, it will be broken into | |
| 2848 | /// multiple non-atomic reads. | |
| 2849 | pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usize { | |
| 2850 | while (true) { | |
| 2851 | const want_read_count: DWORD = @min(@as(DWORD, maxInt(DWORD)), buffer.len); | |
| 2852 | var amt_read: DWORD = undefined; | |
| 2853 | var overlapped_data: OVERLAPPED = undefined; | |
| 2854 | const overlapped: ?*OVERLAPPED = if (offset) |off| blk: { | |
| 2855 | overlapped_data = .{ | |
| 2856 | .Internal = 0, | |
| 2857 | .InternalHigh = 0, | |
| 2858 | .DUMMYUNIONNAME = .{ | |
| 2859 | .DUMMYSTRUCTNAME = .{ | |
| 2860 | .Offset = @as(u32, @truncate(off)), | |
| 2861 | .OffsetHigh = @as(u32, @truncate(off >> 32)), | |
| 2862 | }, | |
| 2863 | }, | |
| 2864 | .hEvent = null, | |
| 2865 | }; | |
| 2866 | break :blk &overlapped_data; | |
| 2867 | } else null; | |
| 2868 | if (kernel32.ReadFile(in_hFile, buffer.ptr, want_read_count, &amt_read, overlapped) == 0) { | |
| 2869 | switch (GetLastError()) { | |
| 2870 | .IO_PENDING => unreachable, | |
| 2871 | .OPERATION_ABORTED => continue, | |
| 2872 | .BROKEN_PIPE => return 0, | |
| 2873 | .HANDLE_EOF => return 0, | |
| 2874 | .NETNAME_DELETED => return error.ConnectionResetByPeer, | |
| 2875 | .LOCK_VIOLATION => return error.LockViolation, | |
| 2876 | .ACCESS_DENIED => return error.AccessDenied, | |
| 2877 | .INVALID_HANDLE => return error.NotOpenForReading, | |
| 2878 | else => |err| return unexpectedError(err), | |
| 2879 | } | |
| 2880 | } | |
| 2881 | return amt_read; | |
| 2882 | } | |
| 2883 | } | |
| 2884 | ||
| 2885 | pub const WriteFileError = error{ | |
| 2886 | SystemResources, | |
| 2887 | Canceled, | |
| 2888 | BrokenPipe, | |
| 2889 | NotOpenForWriting, | |
| 2890 | /// The process cannot access the file because another process has locked | |
| 2891 | /// a portion of the file. | |
| 2892 | LockViolation, | |
| 2893 | /// The specified network name is no longer available. | |
| 2894 | ConnectionResetByPeer, | |
| 2895 | /// Known to be possible when: | |
| 2896 | /// - Unable to write to disconnected virtual com port (Windows) | |
| 2897 | AccessDenied, | |
| 2898 | Unexpected, | |
| 2899 | }; | |
| 2900 | ||
| 2901 | pub fn WriteFile( | |
| 2902 | handle: HANDLE, | |
| 2903 | bytes: []const u8, | |
| 2904 | offset: ?u64, | |
| 2905 | ) WriteFileError!usize { | |
| 2906 | var bytes_written: DWORD = undefined; | |
| 2907 | var overlapped_data: OVERLAPPED = undefined; | |
| 2908 | const overlapped: ?*OVERLAPPED = if (offset) |off| blk: { | |
| 2909 | overlapped_data = .{ | |
| 2910 | .Internal = 0, | |
| 2911 | .InternalHigh = 0, | |
| 2912 | .DUMMYUNIONNAME = .{ | |
| 2913 | .DUMMYSTRUCTNAME = .{ | |
| 2914 | .Offset = @truncate(off), | |
| 2915 | .OffsetHigh = @truncate(off >> 32), | |
| 2916 | }, | |
| 2917 | }, | |
| 2918 | .hEvent = null, | |
| 2919 | }; | |
| 2920 | break :blk &overlapped_data; | |
| 2921 | } else null; | |
| 2922 | const adjusted_len = math.cast(u32, bytes.len) orelse maxInt(u32); | |
| 2923 | if (kernel32.WriteFile(handle, bytes.ptr, adjusted_len, &bytes_written, overlapped) == 0) { | |
| 2924 | switch (GetLastError()) { | |
| 2925 | .INVALID_USER_BUFFER => return error.SystemResources, | |
| 2926 | .NOT_ENOUGH_MEMORY => return error.SystemResources, | |
| 2927 | .OPERATION_ABORTED => return error.Canceled, | |
| 2928 | .NOT_ENOUGH_QUOTA => return error.SystemResources, | |
| 2929 | .IO_PENDING => unreachable, | |
| 2930 | .NO_DATA => return error.BrokenPipe, | |
| 2931 | .INVALID_HANDLE => return error.NotOpenForWriting, | |
| 2932 | .LOCK_VIOLATION => return error.LockViolation, | |
| 2933 | .NETNAME_DELETED => return error.ConnectionResetByPeer, | |
| 2934 | .ACCESS_DENIED => return error.AccessDenied, | |
| 2935 | .WORKING_SET_QUOTA => return error.SystemResources, | |
| 2936 | else => |err| return unexpectedError(err), | |
| 2937 | } | |
| 2938 | } | |
| 2939 | return bytes_written; | |
| 2940 | } | |
| 2941 | ||
| 2942 | 2833 | pub const GetCurrentDirectoryError = error{ |
| 2943 | 2834 | NameTooLong, |
| 2944 | 2835 | Unexpected, |
lib/std/posix.zig+4-56| ... | ... | @@ -486,34 +486,8 @@ pub const ReadError = std.Io.File.Reader.Error; |
| 486 | 486 | /// The corresponding POSIX limit is `maxInt(isize)`. |
| 487 | 487 | pub fn read(fd: fd_t, buf: []u8) ReadError!usize { |
| 488 | 488 | if (buf.len == 0) return 0; |
| 489 | if (native_os == .windows) { | |
| 490 | return windows.ReadFile(fd, buf, null); | |
| 491 | } | |
| 492 | if (native_os == .wasi and !builtin.link_libc) { | |
| 493 | const iovs = [1]iovec{iovec{ | |
| 494 | .base = buf.ptr, | |
| 495 | .len = buf.len, | |
| 496 | }}; | |
| 497 | ||
| 498 | var nread: usize = undefined; | |
| 499 | switch (wasi.fd_read(fd, &iovs, iovs.len, &nread)) { | |
| 500 | .SUCCESS => return nread, | |
| 501 | .INTR => unreachable, | |
| 502 | .INVAL => unreachable, | |
| 503 | .FAULT => unreachable, | |
| 504 | .AGAIN => unreachable, | |
| 505 | .BADF => return error.NotOpenForReading, // Can be a race condition. | |
| 506 | .IO => return error.InputOutput, | |
| 507 | .ISDIR => return error.IsDir, | |
| 508 | .NOBUFS => return error.SystemResources, | |
| 509 | .NOMEM => return error.SystemResources, | |
| 510 | .NOTCONN => return error.SocketUnconnected, | |
| 511 | .CONNRESET => return error.ConnectionResetByPeer, | |
| 512 | .TIMEDOUT => return error.Timeout, | |
| 513 | .NOTCAPABLE => return error.AccessDenied, | |
| 514 | else => |err| return unexpectedErrno(err), | |
| 515 | } | |
| 516 | } | |
| 489 | if (native_os == .windows) @compileError("unsupported OS"); | |
| 490 | if (native_os == .wasi) @compileError("unsupported OS"); | |
| 517 | 491 | |
| 518 | 492 | // Prevents EINVAL. |
| 519 | 493 | const max_count = switch (native_os) { |
| ... | ... | @@ -606,34 +580,8 @@ pub const WriteError = error{ |
| 606 | 580 | /// The corresponding POSIX limit is `maxInt(isize)`. |
| 607 | 581 | pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { |
| 608 | 582 | if (bytes.len == 0) return 0; |
| 609 | if (native_os == .windows) { | |
| 610 | return windows.WriteFile(fd, bytes, null); | |
| 611 | } | |
| 612 | ||
| 613 | if (native_os == .wasi and !builtin.link_libc) { | |
| 614 | const ciovs = [_]iovec_const{iovec_const{ | |
| 615 | .base = bytes.ptr, | |
| 616 | .len = bytes.len, | |
| 617 | }}; | |
| 618 | var nwritten: usize = undefined; | |
| 619 | switch (wasi.fd_write(fd, &ciovs, ciovs.len, &nwritten)) { | |
| 620 | .SUCCESS => return nwritten, | |
| 621 | .INTR => unreachable, | |
| 622 | .INVAL => unreachable, | |
| 623 | .FAULT => unreachable, | |
| 624 | .AGAIN => unreachable, | |
| 625 | .BADF => return error.NotOpenForWriting, // can be a race condition. | |
| 626 | .DESTADDRREQ => unreachable, // `connect` was never called. | |
| 627 | .DQUOT => return error.DiskQuota, | |
| 628 | .FBIG => return error.FileTooBig, | |
| 629 | .IO => return error.InputOutput, | |
| 630 | .NOSPC => return error.NoSpaceLeft, | |
| 631 | .PERM => return error.PermissionDenied, | |
| 632 | .PIPE => return error.BrokenPipe, | |
| 633 | .NOTCAPABLE => return error.AccessDenied, | |
| 634 | else => |err| return unexpectedErrno(err), | |
| 635 | } | |
| 636 | } | |
| 583 | if (native_os == .windows) @compileError("unsupported OS"); | |
| 584 | if (native_os == .wasi) @compileError("unsupported OS"); | |
| 637 | 585 | |
| 638 | 586 | const max_count = switch (native_os) { |
| 639 | 587 | .linux => 0x7ffff000, |