| author | |
| committer | |
| log | 59073484baf89072aa02f23fe9a09662e5def100 |
| tree | 80091d7af70172ec2c656dce9b407bc21119ae78 |
| parent | e5454ff780ae4571cfa71a2edb6f4287eb8cf4de |
5 files changed, 211 insertions(+), 58 deletions(-)
lib/std/Io.zig+28-1| ... | @@ -257,6 +257,9 @@ pub const VTable = struct { | ... | @@ -257,6 +257,9 @@ pub const VTable = struct { |
| 257 | pub const Operation = union(enum) { | 257 | pub const Operation = union(enum) { |
| 258 | file_read_streaming: FileReadStreaming, | 258 | file_read_streaming: FileReadStreaming, |
| 259 | file_write_streaming: FileWriteStreaming, | 259 | file_write_streaming: FileWriteStreaming, |
| 260 | /// On Windows this is NtDeviceIoControlFile. On POSIX this is ioctl. On | ||
| 261 | /// other systems this tag is unreachable. | ||
| 262 | device_io_control: DeviceIoControl, | ||
| 260 | 263 | ||
| 261 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; | 264 | pub const Tag = @typeInfo(Operation).@"union".tag_type.?; |
| 262 | 265 | ||
| ... | @@ -324,13 +327,37 @@ pub const Operation = union(enum) { | ... | @@ -324,13 +327,37 @@ pub const Operation = union(enum) { |
| 324 | pub const Result = Error!usize; | 327 | pub const Result = Error!usize; |
| 325 | }; | 328 | }; |
| 326 | 329 | ||
| 330 | pub const DeviceIoControl = switch (builtin.os.tag) { | ||
| 331 | .wasi => noreturn, | ||
| 332 | .windows => struct { | ||
| 333 | file: File, | ||
| 334 | IoControlCode: std.os.windows.CTL_CODE, | ||
| 335 | InputBuffer: ?*const anyopaque, | ||
| 336 | InputBufferLength: u32, | ||
| 337 | OutputBuffer: ?*anyopaque, | ||
| 338 | OutputBufferLength: u32, | ||
| 339 | |||
| 340 | pub const Result = std.os.windows.IO_STATUS_BLOCK; | ||
| 341 | }, | ||
| 342 | else => struct { | ||
| 343 | file: File, | ||
| 344 | /// Device-dependent operation code. | ||
| 345 | code: u32, | ||
| 346 | arg: ?*anyopaque, | ||
| 347 | |||
| 348 | /// Device and operation dependent result. Negative values are | ||
| 349 | /// negative errno. | ||
| 350 | pub const Result = i32; | ||
| 351 | }, | ||
| 352 | }; | ||
| 353 | |||
| 327 | pub const Result = Result: { | 354 | pub const Result = Result: { |
| 328 | const operation_fields = @typeInfo(Operation).@"union".fields; | 355 | const operation_fields = @typeInfo(Operation).@"union".fields; |
| 329 | var field_names: [operation_fields.len][]const u8 = undefined; | 356 | var field_names: [operation_fields.len][]const u8 = undefined; |
| 330 | var field_types: [operation_fields.len]type = undefined; | 357 | var field_types: [operation_fields.len]type = undefined; |
| 331 | for (operation_fields, &field_names, &field_types) |field, *field_name, *field_type| { | 358 | for (operation_fields, &field_names, &field_types) |field, *field_name, *field_type| { |
| 332 | field_name.* = field.name; | 359 | field_name.* = field.name; |
| 333 | field_type.* = field.type.Result; | 360 | field_type.* = if (field.type == noreturn) noreturn else field.type.Result; |
| 334 | } | 361 | } |
| 335 | break :Result @Union(.auto, Tag, &field_names, &field_types, &@splat(.{})); | 362 | break :Result @Union(.auto, Tag, &field_names, &field_types, &@splat(.{})); |
| 336 | }; | 363 | }; |
lib/std/Io/Threaded.zig+163-25| ... | @@ -2500,6 +2500,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper | ... | @@ -2500,6 +2500,9 @@ fn operate(userdata: ?*anyopaque, operation: Io.Operation) Io.Cancelable!Io.Oper |
| 2500 | else => |e| e, | 2500 | else => |e| e, |
| 2501 | }, | 2501 | }, |
| 2502 | }, | 2502 | }, |
| 2503 | .device_io_control => |*o| return .{ | ||
| 2504 | .device_io_control = try deviceIoControl(t, o), | ||
| 2505 | }, | ||
| 2503 | } | 2506 | } |
| 2504 | } | 2507 | } |
| 2505 | 2508 | ||
| ... | @@ -2531,6 +2534,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { | ... | @@ -2531,6 +2534,14 @@ fn batchAwaitAsync(userdata: ?*anyopaque, b: *Io.Batch) Io.Cancelable!void { |
| 2531 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.OUT, .revents = 0 }; | 2534 | poll_buffer[poll_len] = .{ .fd = o.file.handle, .events = posix.POLL.OUT, .revents = 0 }; |
| 2532 | poll_len += 1; | 2535 | poll_len += 1; |
| 2533 | }, | 2536 | }, |
| 2537 | .device_io_control => |o| { | ||
| 2538 | poll_buffer[poll_len] = .{ | ||
| 2539 | .fd = o.file.handle, | ||
| 2540 | .events = posix.POLL.OUT | posix.POLL.IN | posix.POLL.ERR, | ||
| 2541 | .revents = 0, | ||
| 2542 | }; | ||
| 2543 | poll_len += 1; | ||
| 2544 | }, | ||
| 2534 | } | 2545 | } |
| 2535 | index = submission.node.next; | 2546 | index = submission.node.next; |
| 2536 | } | 2547 | } |
| ... | @@ -2696,6 +2707,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout | ... | @@ -2696,6 +2707,7 @@ fn batchAwaitConcurrent(userdata: ?*anyopaque, b: *Io.Batch, timeout: Io.Timeout |
| 2696 | switch (submission.operation) { | 2707 | switch (submission.operation) { |
| 2697 | .file_read_streaming => |o| try poll_storage.add(o.file, posix.POLL.IN), | 2708 | .file_read_streaming => |o| try poll_storage.add(o.file, posix.POLL.IN), |
| 2698 | .file_write_streaming => |o| try poll_storage.add(o.file, posix.POLL.OUT), | 2709 | .file_write_streaming => |o| try poll_storage.add(o.file, posix.POLL.OUT), |
| 2710 | .device_io_control => |o| try poll_storage.add(o.file, posix.POLL.IN | posix.POLL.OUT | posix.POLL.ERR), | ||
| 2699 | } | 2711 | } |
| 2700 | index = submission.node.next; | 2712 | index = submission.node.next; |
| 2701 | } | 2713 | } |
| ... | @@ -2874,6 +2886,7 @@ fn batchApc(apc_context: ?*anyopaque, iosb: *windows.IO_STATUS_BLOCK, _: windows | ... | @@ -2874,6 +2886,7 @@ fn batchApc(apc_context: ?*anyopaque, iosb: *windows.IO_STATUS_BLOCK, _: windows |
| 2874 | const result: Io.Operation.Result = switch (pending.tag) { | 2886 | const result: Io.Operation.Result = switch (pending.tag) { |
| 2875 | .file_read_streaming => .{ .file_read_streaming = ntReadFileResult(iosb) }, | 2887 | .file_read_streaming => .{ .file_read_streaming = ntReadFileResult(iosb) }, |
| 2876 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, | 2888 | .file_write_streaming => .{ .file_write_streaming = ntWriteFileResult(iosb) }, |
| 2889 | .device_io_control => .{ .device_io_control = iosb.* }, | ||
| 2877 | }; | 2890 | }; |
| 2878 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; | 2891 | storage.* = .{ .completion = .{ .node = .{ .next = .none }, .result = result } }; |
| 2879 | }, | 2892 | }, |
| ... | @@ -3020,6 +3033,59 @@ fn batchAwaitWindows(b: *Io.Batch, concurrency: bool) error{ Canceled, Concurren | ... | @@ -3020,6 +3033,59 @@ fn batchAwaitWindows(b: *Io.Batch, concurrency: bool) error{ Canceled, Concurren |
| 3020 | else => |status| { | 3033 | else => |status| { |
| 3021 | syscall.finish(); | 3034 | syscall.finish(); |
| 3022 | 3035 | ||
| 3036 | context.iosb.u.Status = status; | ||
| 3037 | batchApc(b, &context.iosb, 0); | ||
| 3038 | break; | ||
| 3039 | }, | ||
| 3040 | }; | ||
| 3041 | } | ||
| 3042 | }, | ||
| 3043 | .device_io_control => |o| { | ||
| 3044 | if (o.file.flags.nonblocking) { | ||
| 3045 | context.file = o.file.handle; | ||
| 3046 | switch (windows.ntdll.NtDeviceIoControlFile( | ||
| 3047 | o.file.handle, | ||
| 3048 | null, // event | ||
| 3049 | &batchApc, | ||
| 3050 | b, | ||
| 3051 | &context.iosb, | ||
| 3052 | o.IoControlCode, | ||
| 3053 | o.InputBuffer, | ||
| 3054 | o.InputBufferLength, | ||
| 3055 | o.OutputBuffer, | ||
| 3056 | o.OutputBufferLength, | ||
| 3057 | )) { | ||
| 3058 | .PENDING, .SUCCESS => {}, | ||
| 3059 | .CANCELLED => unreachable, | ||
| 3060 | else => |status| { | ||
| 3061 | context.iosb.u.Status = status; | ||
| 3062 | batchApc(b, &context.iosb, 0); | ||
| 3063 | }, | ||
| 3064 | } | ||
| 3065 | } else { | ||
| 3066 | if (concurrency) return error.ConcurrencyUnavailable; | ||
| 3067 | |||
| 3068 | const syscall: Syscall = try .start(); | ||
| 3069 | while (true) switch (windows.ntdll.NtDeviceIoControlFile( | ||
| 3070 | o.file.handle, | ||
| 3071 | null, // event | ||
| 3072 | null, // APC routine | ||
| 3073 | null, // APC context | ||
| 3074 | &context.iosb, | ||
| 3075 | o.IoControlCode, | ||
| 3076 | o.InputBuffer, | ||
| 3077 | o.InputBufferLength, | ||
| 3078 | o.OutputBuffer, | ||
| 3079 | o.OutputBufferLength, | ||
| 3080 | )) { | ||
| 3081 | .PENDING => unreachable, // unrecoverable: wrong File nonblocking flag | ||
| 3082 | .CANCELLED => { | ||
| 3083 | try syscall.checkCancel(); | ||
| 3084 | continue; | ||
| 3085 | }, | ||
| 3086 | else => |status| { | ||
| 3087 | syscall.finish(); | ||
| 3088 | |||
| 3023 | context.iosb.u.Status = status; | 3089 | context.iosb.u.Status = status; |
| 3024 | batchApc(b, &context.iosb, 0); | 3090 | batchApc(b, &context.iosb, 0); |
| 3025 | break; | 3091 | break; |
| ... | @@ -12986,31 +13052,18 @@ fn netInterfaceNameResolve( | ... | @@ -12986,31 +13052,18 @@ fn netInterfaceNameResolve( |
| 12986 | }; | 13052 | }; |
| 12987 | 13053 | ||
| 12988 | const syscall: Syscall = try .start(); | 13054 | const syscall: Syscall = try .start(); |
| 12989 | while (true) { | 13055 | while (true) switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { |
| 12990 | switch (posix.errno(posix.system.ioctl(sock_fd, posix.SIOCGIFINDEX, @intFromPtr(&ifr)))) { | 13056 | .SUCCESS => { |
| 12991 | .SUCCESS => { | 13057 | syscall.finish(); |
| 12992 | syscall.finish(); | 13058 | return .{ .index = @bitCast(ifr.ifru.ivalue) }; |
| 12993 | return .{ .index = @bitCast(ifr.ifru.ivalue) }; | 13059 | }, |
| 12994 | }, | 13060 | .INTR => { |
| 12995 | .INTR => { | 13061 | try syscall.checkCancel(); |
| 12996 | try syscall.checkCancel(); | 13062 | continue; |
| 12997 | continue; | 13063 | }, |
| 12998 | }, | 13064 | .NODEV => return syscall.fail(error.InterfaceNotFound), |
| 12999 | else => |e| { | 13065 | else => |err| return syscall.unexpectedErrno(err), |
| 13000 | syscall.finish(); | 13066 | }; |
| 13001 | switch (e) { | ||
| 13002 | .INVAL => |err| return errnoBug(err), // Bad parameters. | ||
| 13003 | .NOTTY => |err| return errnoBug(err), | ||
| 13004 | .NXIO => |err| return errnoBug(err), | ||
| 13005 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. | ||
| 13006 | .FAULT => |err| return errnoBug(err), // Bad pointer parameter. | ||
| 13007 | .IO => |err| return errnoBug(err), // sock_fd is not a file descriptor | ||
| 13008 | .NODEV => return error.InterfaceNotFound, | ||
| 13009 | else => |err| return posix.unexpectedErrno(err), | ||
| 13010 | } | ||
| 13011 | }, | ||
| 13012 | } | ||
| 13013 | } | ||
| 13014 | } | 13067 | } |
| 13015 | 13068 | ||
| 13016 | if (is_windows) { | 13069 | if (is_windows) { |
| ... | @@ -17849,3 +17902,88 @@ fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError! | ... | @@ -17849,3 +17902,88 @@ fn mmSyncWrite(file: File, memory: []u8, offset: u64) File.WritePositionalError! |
| 17849 | } | 17902 | } |
| 17850 | } | 17903 | } |
| 17851 | } | 17904 | } |
| 17905 | |||
| 17906 | fn deviceIoControl(t: *Threaded, o: *const Io.Operation.DeviceIoControl) Io.Cancelable!Io.Operation.DeviceIoControl.Result { | ||
| 17907 | _ = t; | ||
| 17908 | if (is_windows) { | ||
| 17909 | var iosb: windows.IO_STATUS_BLOCK = undefined; | ||
| 17910 | if (o.file.flags.nonblocking) { | ||
| 17911 | var done: bool = false; | ||
| 17912 | switch (windows.ntdll.NtDeviceIoControlFile( | ||
| 17913 | o.file.handle, | ||
| 17914 | null, // event | ||
| 17915 | flagApc, | ||
| 17916 | &done, // APC context | ||
| 17917 | &iosb, | ||
| 17918 | o.IoControlCode, | ||
| 17919 | o.InputBuffer, | ||
| 17920 | o.InputBufferLength, | ||
| 17921 | o.OutputBuffer, | ||
| 17922 | o.OutputBufferLength, | ||
| 17923 | )) { | ||
| 17924 | // We must wait for the APC routine. | ||
| 17925 | .PENDING, .SUCCESS => while (!done) { | ||
| 17926 | // Once we get here we must not return from the function until the | ||
| 17927 | // operation completes, thereby releasing reference to io_status_block. | ||
| 17928 | const alertable_syscall = AlertableSyscall.start() catch |err| switch (err) { | ||
| 17929 | error.Canceled => |e| { | ||
| 17930 | var cancel_iosb: windows.IO_STATUS_BLOCK = undefined; | ||
| 17931 | _ = windows.ntdll.NtCancelIoFileEx(o.file.handle, &iosb, &cancel_iosb); | ||
| 17932 | while (!done) waitForApcOrAlert(); | ||
| 17933 | return e; | ||
| 17934 | }, | ||
| 17935 | }; | ||
| 17936 | waitForApcOrAlert(); | ||
| 17937 | alertable_syscall.finish(); | ||
| 17938 | }, | ||
| 17939 | else => |status| iosb.u.Status = status, | ||
| 17940 | } | ||
| 17941 | } else { | ||
| 17942 | const syscall: Syscall = try .start(); | ||
| 17943 | while (true) switch (windows.ntdll.NtDeviceIoControlFile( | ||
| 17944 | o.file.handle, | ||
| 17945 | null, // event | ||
| 17946 | null, // APC routine | ||
| 17947 | null, // APC context | ||
| 17948 | &iosb, | ||
| 17949 | o.IoControlCode, | ||
| 17950 | o.InputBuffer, | ||
| 17951 | o.InputBufferLength, | ||
| 17952 | o.OutputBuffer, | ||
| 17953 | o.OutputBufferLength, | ||
| 17954 | )) { | ||
| 17955 | .PENDING => unreachable, // unrecoverable: wrong asynchronous flag | ||
| 17956 | .CANCELLED => { | ||
| 17957 | try syscall.checkCancel(); | ||
| 17958 | continue; | ||
| 17959 | }, | ||
| 17960 | else => |status| { | ||
| 17961 | syscall.finish(); | ||
| 17962 | iosb.u.Status = status; | ||
| 17963 | break; | ||
| 17964 | }, | ||
| 17965 | }; | ||
| 17966 | } | ||
| 17967 | return iosb; | ||
| 17968 | } else { | ||
| 17969 | const syscall: Syscall = try .start(); | ||
| 17970 | while (true) { | ||
| 17971 | const rc = posix.system.ioctl(o.file.handle, @bitCast(o.code), @intFromPtr(o.arg)); | ||
| 17972 | switch (posix.errno(rc)) { | ||
| 17973 | .SUCCESS => { | ||
| 17974 | syscall.finish(); | ||
| 17975 | if (@TypeOf(rc) == usize) return @bitCast(@as(u32, @truncate(rc))); | ||
| 17976 | return rc; | ||
| 17977 | }, | ||
| 17978 | .INTR => { | ||
| 17979 | try syscall.checkCancel(); | ||
| 17980 | continue; | ||
| 17981 | }, | ||
| 17982 | else => |err| { | ||
| 17983 | syscall.finish(); | ||
| 17984 | return -@as(i32, @intFromEnum(err)); | ||
| 17985 | }, | ||
| 17986 | } | ||
| 17987 | } | ||
| 17988 | } | ||
| 17989 | } |
lib/std/Progress.zig+14-9| ... | @@ -573,7 +573,7 @@ fn updateTask(io: Io) void { | ... | @@ -573,7 +573,7 @@ fn updateTask(io: Io) void { |
| 573 | { | 573 | { |
| 574 | const resize_flag = wait(io, global_progress.initial_delay_ns); | 574 | const resize_flag = wait(io, global_progress.initial_delay_ns); |
| 575 | if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; | 575 | if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; |
| 576 | maybeUpdateSize(resize_flag); | 576 | maybeUpdateSize(io, resize_flag) catch return; |
| 577 | 577 | ||
| 578 | const buffer, _ = computeRedraw(&serialized_buffer); | 578 | const buffer, _ = computeRedraw(&serialized_buffer); |
| 579 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { | 579 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { |
| ... | @@ -592,7 +592,7 @@ fn updateTask(io: Io) void { | ... | @@ -592,7 +592,7 @@ fn updateTask(io: Io) void { |
| 592 | return clearWrittenWithEscapeCodes(stderr.file_writer) catch {}; | 592 | return clearWrittenWithEscapeCodes(stderr.file_writer) catch {}; |
| 593 | } | 593 | } |
| 594 | 594 | ||
| 595 | maybeUpdateSize(resize_flag); | 595 | maybeUpdateSize(io, resize_flag) catch return; |
| 596 | 596 | ||
| 597 | const buffer, _ = computeRedraw(&serialized_buffer); | 597 | const buffer, _ = computeRedraw(&serialized_buffer); |
| 598 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { | 598 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { |
| ... | @@ -622,7 +622,7 @@ fn windowsApiUpdateTask(io: Io) void { | ... | @@ -622,7 +622,7 @@ fn windowsApiUpdateTask(io: Io) void { |
| 622 | { | 622 | { |
| 623 | const resize_flag = wait(io, global_progress.initial_delay_ns); | 623 | const resize_flag = wait(io, global_progress.initial_delay_ns); |
| 624 | if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; | 624 | if (@atomicLoad(bool, &global_progress.done, .monotonic)) return; |
| 625 | maybeUpdateSize(resize_flag); | 625 | maybeUpdateSize(io, resize_flag) catch return; |
| 626 | 626 | ||
| 627 | const buffer, const nl_n = computeRedraw(&serialized_buffer); | 627 | const buffer, const nl_n = computeRedraw(&serialized_buffer); |
| 628 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { | 628 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { |
| ... | @@ -643,7 +643,7 @@ fn windowsApiUpdateTask(io: Io) void { | ... | @@ -643,7 +643,7 @@ fn windowsApiUpdateTask(io: Io) void { |
| 643 | return clearWrittenWindowsApi() catch {}; | 643 | return clearWrittenWindowsApi() catch {}; |
| 644 | } | 644 | } |
| 645 | 645 | ||
| 646 | maybeUpdateSize(resize_flag); | 646 | maybeUpdateSize(io, resize_flag) catch return; |
| 647 | 647 | ||
| 648 | const buffer, const nl_n = computeRedraw(&serialized_buffer); | 648 | const buffer, const nl_n = computeRedraw(&serialized_buffer); |
| 649 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { | 649 | if (io.vtable.tryLockStderr(io.userdata, null) catch return) |locked_stderr| { |
| ... | @@ -1484,15 +1484,15 @@ fn writevNonblock(io: Io, file: Io.File, iov: [][]const u8) Io.File.Writer.Error | ... | @@ -1484,15 +1484,15 @@ fn writevNonblock(io: Io, file: Io.File, iov: [][]const u8) Io.File.Writer.Error |
| 1484 | } | 1484 | } |
| 1485 | } | 1485 | } |
| 1486 | 1486 | ||
| 1487 | fn maybeUpdateSize(resize_flag: bool) void { | 1487 | fn maybeUpdateSize(io: Io, resize_flag: bool) !void { |
| 1488 | if (!resize_flag) return; | 1488 | if (!resize_flag) return; |
| 1489 | 1489 | ||
| 1490 | const fd = global_progress.terminal.handle; | 1490 | const file = global_progress.terminal; |
| 1491 | 1491 | ||
| 1492 | if (is_windows) { | 1492 | if (is_windows) { |
| 1493 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; | 1493 | var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined; |
| 1494 | 1494 | ||
| 1495 | if (windows.kernel32.GetConsoleScreenBufferInfo(fd, &info) != windows.FALSE) { | 1495 | if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.FALSE) { |
| 1496 | // In the old Windows console, dwSize.Y is the line count of the | 1496 | // In the old Windows console, dwSize.Y is the line count of the |
| 1497 | // entire scrollback buffer, so we use this instead so that we | 1497 | // entire scrollback buffer, so we use this instead so that we |
| 1498 | // always get the size of the screen. | 1498 | // always get the size of the screen. |
| ... | @@ -1512,8 +1512,13 @@ fn maybeUpdateSize(resize_flag: bool) void { | ... | @@ -1512,8 +1512,13 @@ fn maybeUpdateSize(resize_flag: bool) void { |
| 1512 | .ypixel = 0, | 1512 | .ypixel = 0, |
| 1513 | }; | 1513 | }; |
| 1514 | 1514 | ||
| 1515 | const err = posix.system.ioctl(fd, posix.T.IOCGWINSZ, @intFromPtr(&winsize)); | 1515 | const err = (try io.operate(.{ .device_io_control = .{ |
| 1516 | if (posix.errno(err) == .SUCCESS) { | 1516 | .file = file, |
| 1517 | .code = posix.T.IOCGWINSZ, | ||
| 1518 | .arg = &winsize, | ||
| 1519 | } })).device_io_control; | ||
| 1520 | |||
| 1521 | if (err >= 0) { | ||
| 1517 | global_progress.rows = winsize.row; | 1522 | global_progress.rows = winsize.row; |
| 1518 | global_progress.cols = winsize.col; | 1523 | global_progress.cols = winsize.col; |
| 1519 | } else { | 1524 | } else { |
lib/std/c.zig+6-1| ... | @@ -10731,7 +10731,6 @@ pub extern "c" fn sysctlnametomib(name: [*:0]const u8, mibp: ?*c_int, sizep: ?*u | ... | @@ -10731,7 +10731,6 @@ pub extern "c" fn sysctlnametomib(name: [*:0]const u8, mibp: ?*c_int, sizep: ?*u |
| 10731 | pub extern "c" fn tcgetattr(fd: fd_t, termios_p: *termios) c_int; | 10731 | pub extern "c" fn tcgetattr(fd: fd_t, termios_p: *termios) c_int; |
| 10732 | pub extern "c" fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) c_int; | 10732 | pub extern "c" fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) c_int; |
| 10733 | pub extern "c" fn fcntl(fd: fd_t, cmd: c_int, ...) c_int; | 10733 | pub extern "c" fn fcntl(fd: fd_t, cmd: c_int, ...) c_int; |
| 10734 | pub extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int; | ||
| 10735 | pub extern "c" fn uname(buf: *utsname) c_int; | 10734 | pub extern "c" fn uname(buf: *utsname) c_int; |
| 10736 | 10735 | ||
| 10737 | pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int; | 10736 | pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int; |
| ... | @@ -11108,6 +11107,11 @@ pub const clock_nanosleep = switch (native_os) { | ... | @@ -11108,6 +11107,11 @@ pub const clock_nanosleep = switch (native_os) { |
| 11108 | else => {}, | 11107 | else => {}, |
| 11109 | }; | 11108 | }; |
| 11110 | 11109 | ||
| 11110 | pub const ioctl = switch (native_os) { | ||
| 11111 | .windows, .wasi => {}, | ||
| 11112 | else => private.ioctl, | ||
| 11113 | }; | ||
| 11114 | |||
| 11111 | // OS-specific bits. These are protected from being used on the wrong OS by | 11115 | // OS-specific bits. These are protected from being used on the wrong OS by |
| 11112 | // comptime assertions inside each OS-specific file. | 11116 | // comptime assertions inside each OS-specific file. |
| 11113 | 11117 | ||
| ... | @@ -11495,6 +11499,7 @@ const private = struct { | ... | @@ -11495,6 +11499,7 @@ const private = struct { |
| 11495 | }; | 11499 | }; |
| 11496 | extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; | 11500 | extern "c" fn getrusage(who: c_int, usage: *rusage) c_int; |
| 11497 | extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 11501 | extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 11502 | extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int; | ||
| 11498 | extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; | 11503 | extern "c" fn msync(addr: *align(page_size) const anyopaque, len: usize, flags: c_int) c_int; |
| 11499 | extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; | 11504 | extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int; |
| 11500 | extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int; | 11505 | extern "c" fn clock_nanosleep(clockid: clockid_t, flags: TIMER, t: *const timespec, remain: ?*timespec) c_int; |
lib/std/posix.zig-22| ... | @@ -1800,28 +1800,6 @@ pub fn name_to_handle_atZ( | ... | @@ -1800,28 +1800,6 @@ pub fn name_to_handle_atZ( |
| 1800 | } | 1800 | } |
| 1801 | } | 1801 | } |
| 1802 | 1802 | ||
| 1803 | pub const IoCtl_SIOCGIFINDEX_Error = error{ | ||
| 1804 | FileSystem, | ||
| 1805 | InterfaceNotFound, | ||
| 1806 | } || UnexpectedError; | ||
| 1807 | |||
| 1808 | pub fn ioctl_SIOCGIFINDEX(fd: fd_t, ifr: *ifreq) IoCtl_SIOCGIFINDEX_Error!void { | ||
| 1809 | while (true) { | ||
| 1810 | switch (errno(system.ioctl(fd, SIOCGIFINDEX, @intFromPtr(ifr)))) { | ||
| 1811 | .SUCCESS => return, | ||
| 1812 | .INVAL => unreachable, // Bad parameters. | ||
| 1813 | .NOTTY => unreachable, | ||
| 1814 | .NXIO => unreachable, | ||
| 1815 | .BADF => unreachable, // Always a race condition. | ||
| 1816 | .FAULT => unreachable, // Bad pointer parameter. | ||
| 1817 | .INTR => continue, | ||
| 1818 | .IO => return error.FileSystem, | ||
| 1819 | .NODEV => return error.InterfaceNotFound, | ||
| 1820 | else => |err| return unexpectedErrno(err), | ||
| 1821 | } | ||
| 1822 | } | ||
| 1823 | } | ||
| 1824 | |||
| 1825 | pub const lfs64_abi = native_os == .linux and builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); | 1803 | pub const lfs64_abi = native_os == .linux and builtin.link_libc and (builtin.abi.isGnu() or builtin.abi.isAndroid()); |
| 1826 | 1804 | ||
| 1827 | /// Whether or not `error.Unexpected` will print its value and a stack trace. | 1805 | /// Whether or not `error.Unexpected` will print its value and a stack trace. |