From 9fc0440fd6a1fd7510d52b2165a6da133835bdcb Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Wed, 27 Mar 2024 13:46:50 +0100 Subject: [PATCH] upgrade to zig 0.12 0.12.0-dev.3439+31a7f22b8 --- .github/workflows/zig-fmt.yml | 2 +- .github/workflows/zig-test.yml | 2 +- io/darwin.zig | 180 ++++++++++++++--------------- io/linux.zig | 200 ++++++++++++++++----------------- io/test.zig | 92 +++++++-------- time.zig | 8 +- 6 files changed, 240 insertions(+), 244 deletions(-) diff --git a/.github/workflows/zig-fmt.yml b/.github/workflows/zig-fmt.yml index 0a94a2a..7761853 100644 --- a/.github/workflows/zig-fmt.yml +++ b/.github/workflows/zig-fmt.yml @@ -12,7 +12,7 @@ jobs: name: zig fmt runs-on: ubuntu-latest container: - image: ghcr.io/browsercore/zig:0.11.0 + image: ghcr.io/browsercore/zig:0.12.0-dev.3439-31a7f22b8 credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/zig-test.yml b/.github/workflows/zig-test.yml index 432b1c5..1d3d625 100644 --- a/.github/workflows/zig-test.yml +++ b/.github/workflows/zig-test.yml @@ -18,7 +18,7 @@ jobs: name: zig test runs-on: ubuntu-latest container: - image: ghcr.io/browsercore/zig:0.11.0 + image: ghcr.io/browsercore/zig:0.12.0-dev.3439-31a7f22b8 credentials: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} diff --git a/io/darwin.zig b/io/darwin.zig index d44e04b..37f7dae 100644 --- a/io/darwin.zig +++ b/io/darwin.zig @@ -1,5 +1,5 @@ const std = @import("std"); -const os = std.os; +const posix = std.posix; const mem = std.mem; const assert = std.debug.assert; const log = std.log.scoped(.io); @@ -10,7 +10,7 @@ const Time = @import("../time.zig").Time; const buffer_limit = @import("../io.zig").buffer_limit; pub const IO = struct { - kq: os.fd_t, + kq: posix.fd_t, time: Time = .{}, io_inflight: usize = 0, timeouts: FIFO(Completion) = .{}, @@ -21,14 +21,14 @@ pub const IO = struct { _ = entries; _ = flags; - const kq = try os.kqueue(); + const kq = try posix.kqueue(); assert(kq > -1); return IO{ .kq = kq }; } pub fn deinit(self: *IO) void { assert(self.kq > -1); - os.close(self.kq); + posix.close(self.kq); self.kq = -1; } @@ -74,7 +74,7 @@ pub const IO = struct { fn flush(self: *IO, wait_for_completions: bool) !void { var io_pending = self.io_pending.peek(); - var events: [256]os.Kevent = undefined; + var events: [256]posix.Kevent = undefined; // Check timeouts and fill events with completions in io_pending // (they will be submitted through kevent). @@ -85,7 +85,7 @@ pub const IO = struct { // Only call kevent() if we need to submit io events or if we need to wait for completions. if (change_events > 0 or self.completed.empty()) { // Zero timeouts for kevent() implies a non-blocking poll - var ts = std.mem.zeroes(os.timespec); + var ts = std.mem.zeroes(posix.timespec); // We need to wait (not poll) on kevent if there's nothing to submit or complete. // We should never wait indefinitely (timeout_ptr = null for kevent) given: @@ -101,7 +101,7 @@ pub const IO = struct { } } - const new_events = try os.kevent( + const new_events = try posix.kevent( self.kq, events[0..change_events], events[0..events.len], @@ -131,25 +131,25 @@ pub const IO = struct { } } - fn flush_io(_: *IO, events: []os.Kevent, io_pending_top: *?*Completion) usize { + fn flush_io(_: *IO, events: []posix.Kevent, io_pending_top: *?*Completion) usize { for (events, 0..) |*event, flushed| { const completion = io_pending_top.* orelse return flushed; io_pending_top.* = completion.next; const event_info = switch (completion.operation) { - .accept => |op| [2]c_int{ op.socket, os.system.EVFILT_READ }, - .connect => |op| [2]c_int{ op.socket, os.system.EVFILT_WRITE }, - .read => |op| [2]c_int{ op.fd, os.system.EVFILT_READ }, - .write => |op| [2]c_int{ op.fd, os.system.EVFILT_WRITE }, - .recv => |op| [2]c_int{ op.socket, os.system.EVFILT_READ }, - .send => |op| [2]c_int{ op.socket, os.system.EVFILT_WRITE }, + .accept => |op| [2]c_int{ op.socket, posix.system.EVFILT_READ }, + .connect => |op| [2]c_int{ op.socket, posix.system.EVFILT_WRITE }, + .read => |op| [2]c_int{ op.fd, posix.system.EVFILT_READ }, + .write => |op| [2]c_int{ op.fd, posix.system.EVFILT_WRITE }, + .recv => |op| [2]c_int{ op.socket, posix.system.EVFILT_READ }, + .send => |op| [2]c_int{ op.socket, posix.system.EVFILT_WRITE }, else => @panic("invalid completion operation queued for io"), }; event.* = .{ .ident = @as(u32, @intCast(event_info[0])), .filter = @as(i16, @intCast(event_info[1])), - .flags = os.system.EV_ADD | os.system.EV_ENABLE | os.system.EV_ONESHOT, + .flags = posix.system.EV_ADD | posix.system.EV_ENABLE | posix.system.EV_ONESHOT, .fflags = 0, .data = 0, .udata = @intFromPtr(completion), @@ -196,29 +196,29 @@ pub const IO = struct { const Operation = union(enum) { accept: struct { - socket: os.socket_t, + socket: posix.socket_t, }, close: struct { - fd: os.fd_t, + fd: posix.fd_t, }, connect: struct { - socket: os.socket_t, + socket: posix.socket_t, address: std.net.Address, initiated: bool, }, read: struct { - fd: os.fd_t, + fd: posix.fd_t, buf: [*]u8, len: u32, offset: u64, }, recv: struct { - socket: os.socket_t, + socket: posix.socket_t, buf: [*]u8, len: u32, }, send: struct { - socket: os.socket_t, + socket: posix.socket_t, buf: [*]const u8, len: u32, }, @@ -226,7 +226,7 @@ pub const IO = struct { expires: u64, }, write: struct { - fd: os.fd_t, + fd: posix.fd_t, buf: [*]const u8, len: u32, offset: u64, @@ -286,7 +286,7 @@ pub const IO = struct { } } - pub const AcceptError = os.AcceptError || os.SetSockOptError; + pub const AcceptError = posix.AcceptError || posix.SetSockOptError; pub fn accept( self: *IO, @@ -295,10 +295,10 @@ pub const IO = struct { comptime callback: fn ( context: Context, completion: *Completion, - result: AcceptError!os.socket_t, + result: AcceptError!posix.socket_t, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, ) void { self.submit( context, @@ -309,21 +309,21 @@ pub const IO = struct { .socket = socket, }, struct { - fn do_operation(op: anytype) AcceptError!os.socket_t { - const fd = try os.accept( + fn do_operation(op: anytype) AcceptError!posix.socket_t { + const fd = try posix.accept( op.socket, null, null, - os.SOCK.NONBLOCK | os.SOCK.CLOEXEC, + posix.SOCK.NONBLOCK | posix.SOCK.CLOEXEC, ); - errdefer os.close(fd); + errdefer posix.close(fd); - // Darwin doesn't support os.MSG_NOSIGNAL to avoid getting SIGPIPE on socket send(). + // Darwin doesn't support posix.MSG_NOSIGNAL to avoid getting SIGPIPE on socket send(). // Instead, it uses the SO_NOSIGPIPE socket option which does the same for all send()s. - os.setsockopt( + posix.setsockopt( fd, - os.SOL.SOCKET, - os.SO.NOSIGPIPE, + posix.SOL.SOCKET, + posix.SO.NOSIGPIPE, &mem.toBytes(@as(c_int, 1)), ) catch |err| return switch (err) { error.TimeoutTooBig => unreachable, @@ -344,7 +344,7 @@ pub const IO = struct { DiskQuota, InputOutput, NoSpaceLeft, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn close( self: *IO, @@ -356,7 +356,7 @@ pub const IO = struct { result: CloseError!void, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, ) void { self.submit( context, @@ -368,19 +368,19 @@ pub const IO = struct { }, struct { fn do_operation(op: anytype) CloseError!void { - return switch (os.errno(os.system.close(op.fd))) { + return switch (posix.errno(posix.system.close(op.fd))) { .SUCCESS => {}, .BADF => error.FileDescriptorInvalid, .INTR => {}, // A success, see https://github.com/ziglang/zig/issues/2425 .IO => error.InputOutput, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; } }, ); } - pub const ConnectError = os.ConnectError; + pub const ConnectError = posix.ConnectError; pub fn connect( self: *IO, @@ -392,7 +392,7 @@ pub const IO = struct { result: ConnectError!void, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, address: std.net.Address, ) void { self.submit( @@ -410,8 +410,8 @@ pub const IO = struct { // Don't call connect after being rescheduled by io_pending as it gives EISCONN. // Instead, check the socket error to see if has been connected successfully. const result = switch (op.initiated) { - true => os.getsockoptError(op.socket), - else => os.connect(op.socket, &op.address.any, op.address.getOsSockLen()), + true => posix.getsockoptError(op.socket), + else => posix.connect(op.socket, &op.address.any, op.address.getOsSockLen()), }; op.initiated = true; @@ -431,7 +431,7 @@ pub const IO = struct { SystemResources, Unseekable, ConnectionTimedOut, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn read( self: *IO, @@ -443,7 +443,7 @@ pub const IO = struct { result: ReadError!usize, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, buffer: []u8, offset: u64, ) void { @@ -461,13 +461,13 @@ pub const IO = struct { struct { fn do_operation(op: anytype) ReadError!usize { while (true) { - const rc = os.system.pread( + const rc = posix.system.pread( op.fd, op.buf, op.len, @as(isize, @bitCast(op.offset)), ); - return switch (os.errno(rc)) { + return switch (posix.errno(rc)) { .SUCCESS => @as(usize, @intCast(rc)), .INTR => continue, .AGAIN => error.WouldBlock, @@ -483,7 +483,7 @@ pub const IO = struct { .OVERFLOW => error.Unseekable, .SPIPE => error.Unseekable, .TIMEDOUT => error.ConnectionTimedOut, - else => |err| os.unexpectedErrno(err), + else => |err| posix.unexpectedErrno(err), }; } } @@ -491,7 +491,7 @@ pub const IO = struct { ); } - pub const RecvError = os.RecvFromError; + pub const RecvError = posix.RecvFromError; pub fn recv( self: *IO, @@ -503,7 +503,7 @@ pub const IO = struct { result: RecvError!usize, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, buffer: []u8, ) void { self.submit( @@ -518,13 +518,13 @@ pub const IO = struct { }, struct { fn do_operation(op: anytype) RecvError!usize { - return os.recv(op.socket, op.buf[0..op.len], 0); + return posix.recv(op.socket, op.buf[0..op.len], 0); } }, ); } - pub const SendError = os.SendError; + pub const SendError = posix.SendError; pub fn send( self: *IO, @@ -536,7 +536,7 @@ pub const IO = struct { result: SendError!usize, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, buffer: []const u8, ) void { self.submit( @@ -551,13 +551,13 @@ pub const IO = struct { }, struct { fn do_operation(op: anytype) SendError!usize { - return os.send(op.socket, op.buf[0..op.len], 0); + return posix.send(op.socket, op.buf[0..op.len], 0); } }, ); } - pub const TimeoutError = error{Canceled} || os.UnexpectedError; + pub const TimeoutError = error{Canceled} || posix.UnexpectedError; pub fn timeout( self: *IO, @@ -606,7 +606,7 @@ pub const IO = struct { ); } - pub const WriteError = os.PWriteError; + pub const WriteError = posix.PWriteError; pub fn write( self: *IO, @@ -618,7 +618,7 @@ pub const IO = struct { result: WriteError!usize, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, buffer: []const u8, offset: u64, ) void { @@ -635,7 +635,7 @@ pub const IO = struct { }, struct { fn do_operation(op: anytype) WriteError!usize { - return os.pwrite(op.fd, op.buf[0..op.len], op.offset); + return posix.pwrite(op.fd, op.buf[0..op.len], op.offset); } }, ); @@ -644,23 +644,23 @@ pub const IO = struct { pub const INVALID_SOCKET = -1; /// Creates a socket that can be used for async operations with the IO instance. - pub fn open_socket(self: *IO, family: u32, sock_type: u32, protocol: u32) !os.socket_t { + pub fn open_socket(self: *IO, family: u32, sock_type: u32, protocol: u32) !posix.socket_t { _ = self; - const fd = try os.socket(family, sock_type | os.SOCK.NONBLOCK, protocol); - errdefer os.closeSocket(fd); + const fd = try posix.socket(family, sock_type | posix.SOCK.NONBLOCK, protocol); + errdefer posix.closeSocket(fd); - // darwin doesn't support os.MSG_NOSIGNAL, but instead a socket option to avoid SIGPIPE. - try os.setsockopt(fd, os.SOL.SOCKET, os.SO.NOSIGPIPE, &mem.toBytes(@as(c_int, 1))); + // darwin doesn't support posix.MSG_NOSIGNAL, but instead a socket option to avoid SIGPIPE. + try posix.setsockopt(fd, posix.SOL.SOCKET, posix.SO.NOSIGPIPE, &mem.toBytes(@as(c_int, 1))); return fd; } /// Opens a directory with read only access. - pub fn open_dir(dir_path: []const u8) !os.fd_t { - return os.open(dir_path, os.O.CLOEXEC | os.O.RDONLY, 0); + pub fn open_dir(dir_path: []const u8) !posix.fd_t { + return posix.open(dir_path, posix.O.CLOEXEC | posix.O.RDONLY, 0); } - pub const INVALID_FILE: os.fd_t = -1; + pub const INVALID_FILE: posix.fd_t = -1; /// Opens or creates a journal file: /// - For reading and writing. @@ -671,11 +671,11 @@ pub const IO = struct { /// The caller is responsible for ensuring that the parent directory inode is durable. /// - Verifies that the file size matches the expected file size before returning. pub fn open_file( - dir_fd: os.fd_t, + dir_fd: posix.fd_t, relative_path: []const u8, size: u64, must_create: bool, - ) !os.fd_t { + ) !posix.fd_t { assert(relative_path.len > 0); assert(size >= constants.sector_size); assert(size % constants.sector_size == 0); @@ -685,41 +685,41 @@ pub const IO = struct { // Opening with O_DSYNC is essential for both durability and correctness. // O_DSYNC enables us to omit fsync() calls in the data plane, since we sync to the disk on every write. - var flags: u32 = os.O.CLOEXEC | os.O.RDWR | os.O.DSYNC; - var mode: os.mode_t = 0; + var flags: u32 = posix.O.CLOEXEC | posix.O.RDWR | posix.O.DSYNC; + var mode: posix.mode_t = 0; // TODO Document this and investigate whether this is in fact correct to set here. - if (@hasDecl(os.O, "LARGEFILE")) flags |= os.O.LARGEFILE; + if (@hasDecl(posix.O, "LARGEFILE")) flags |= posix.O.LARGEFILE; if (must_create) { log.info("creating \"{s}\"...", .{relative_path}); - flags |= os.O.CREAT; - flags |= os.O.EXCL; + flags |= posix.O.CREAT; + flags |= posix.O.EXCL; mode = 0o666; } else { log.info("opening \"{s}\"...", .{relative_path}); } // This is critical as we rely on O_DSYNC for fsync() whenever we write to the file: - assert((flags & os.O.DSYNC) > 0); + assert((flags & posix.O.DSYNC) > 0); // Be careful with openat(2): "If pathname is absolute, then dirfd is ignored." (man page) assert(!std.fs.path.isAbsolute(relative_path)); - const fd = try os.openat(dir_fd, relative_path, flags, mode); + const fd = try posix.openat(dir_fd, relative_path, flags, mode); // TODO Return a proper error message when the path exists or does not exist (init/start). - errdefer os.close(fd); + errdefer posix.close(fd); // TODO Check that the file is actually a file. // On darwin assume that Direct I/O is always supported. // Use F_NOCACHE to disable the page cache as O_DIRECT doesn't exist. if (constants.direct_io) { - _ = try os.fcntl(fd, os.F.NOCACHE, 1); + _ = try posix.fcntl(fd, posix.F.NOCACHE, 1); } // Obtain an advisory exclusive lock that works only if all processes actually use flock(). // LOCK_NB means that we want to fail the lock without waiting if another process has it. - os.flock(fd, os.LOCK.EX | os.LOCK.NB) catch |err| switch (err) { + posix.flock(fd, posix.LOCK.EX | posix.LOCK.NB) catch |err| switch (err) { error.WouldBlock => @panic("another process holds the data file lock"), else => return err, }; @@ -741,7 +741,7 @@ pub const IO = struct { try fs_sync(dir_fd); // TODO Document that `size` is now `data_file_size_min` from `main.zig`. - const stat = try os.fstat(fd); + const stat = try posix.fstat(fd); if (stat.size < size) @panic("data file inode size was truncated or corrupted"); return fd; @@ -749,13 +749,13 @@ pub const IO = struct { /// Darwin's fsync() syscall does not flush past the disk cache. We must use F_FULLFSYNC instead. /// https://twitter.com/TigerBeetleDB/status/1422491736224436225 - fn fs_sync(fd: os.fd_t) !void { - _ = os.fcntl(fd, os.F.FULLFSYNC, 1) catch return os.fsync(fd); + fn fs_sync(fd: posix.fd_t) !void { + _ = posix.fcntl(fd, posix.F.FULLFSYNC, 1) catch return posix.fsync(fd); } /// Allocates a file contiguously using fallocate() if supported. /// Alternatively, writes to the last sector so that at least the file size is correct. - fn fs_allocate(fd: os.fd_t, size: u64) !void { + fn fs_allocate(fd: posix.fd_t, size: u64) !void { log.info("allocating {}...", .{std.fmt.fmtIntSizeBin(size)}); // Darwin doesn't have fallocate() but we can simulate it using fcntl()s. @@ -770,27 +770,27 @@ pub const IO = struct { const fstore_t = extern struct { fst_flags: c_uint, fst_posmode: c_int, - fst_offset: os.off_t, - fst_length: os.off_t, - fst_bytesalloc: os.off_t, + fst_offset: posix.off_t, + fst_length: posix.off_t, + fst_bytesalloc: posix.off_t, }; var store = fstore_t{ .fst_flags = F_ALLOCATECONTIG | F_ALLOCATEALL, .fst_posmode = F_PEOFPOSMODE, .fst_offset = 0, - .fst_length = @as(os.off_t, @intCast(size)), + .fst_length = @as(posix.off_t, @intCast(size)), .fst_bytesalloc = 0, }; // Try to pre-allocate contiguous space and fall back to default non-contiguous. - var res = os.system.fcntl(fd, os.F.PREALLOCATE, @intFromPtr(&store)); - if (os.errno(res) != .SUCCESS) { + var res = posix.system.fcntl(fd, posix.F.PREALLOCATE, @intFromPtr(&store)); + if (posix.errno(res) != .SUCCESS) { store.fst_flags = F_ALLOCATEALL; - res = os.system.fcntl(fd, os.F.PREALLOCATE, @intFromPtr(&store)); + res = posix.system.fcntl(fd, posix.F.PREALLOCATE, @intFromPtr(&store)); } - switch (os.errno(res)) { + switch (posix.errno(res)) { .SUCCESS => {}, .ACCES => unreachable, // F_SETLK or F_SETSIZE of F_WRITEBOOTSTRAP .BADF => return error.FileDescriptorInvalid, @@ -802,11 +802,11 @@ pub const IO = struct { .OVERFLOW => return error.FileTooBig, .SRCH => unreachable, // F_SETOWN .OPNOTSUPP => return error.OperationNotSupported, // not reported but need same error union - else => |errno| return os.unexpectedErrno(errno), + else => |errno| return posix.unexpectedErrno(errno), } // Now actually perform the allocation. - return os.ftruncate(fd, size) catch |err| switch (err) { + return posix.ftruncate(fd, size) catch |err| switch (err) { error.AccessDenied => error.PermissionDenied, else => |e| e, }; diff --git a/io/linux.zig b/io/linux.zig index 0e295bd..72c3fc0 100644 --- a/io/linux.zig +++ b/io/linux.zig @@ -1,8 +1,8 @@ const std = @import("std"); const assert = std.debug.assert; -const os = std.os; -const linux = os.linux; -const IO_Uring = linux.IO_Uring; +const posix = std.posix; +const linux = std.os.linux; +const IO_Uring = linux.IoUring; const io_uring_cqe = linux.io_uring_cqe; const io_uring_sqe = linux.io_uring_sqe; const log = std.log.scoped(.io); @@ -23,7 +23,7 @@ pub const IO = struct { pub fn init(entries: u12, flags: u32) !IO { // Detect the linux version to ensure that we support all io_uring ops used. - const uts = std.os.uname(); + const uts = posix.uname(); const release = std.mem.sliceTo(&uts.release, 0); const version = try std.SemanticVersion.parse(release); if (version.order(std.SemanticVersion{ .major = 5, .minor = 5, .patch = 0 }) == .lt) { @@ -67,10 +67,10 @@ pub const IO = struct { // We must use the same clock source used by io_uring (CLOCK_MONOTONIC) since we specify the // timeout below as an absolute value. Otherwise, we may deadlock if the clock sources are // dramatically different. Any kernel that supports io_uring will support CLOCK_MONOTONIC. - var current_ts: os.timespec = undefined; - os.clock_gettime(os.CLOCK.MONOTONIC, ¤t_ts) catch unreachable; + var current_ts: posix.timespec = undefined; + posix.clock_gettime(posix.CLOCK.MONOTONIC, ¤t_ts) catch unreachable; // The absolute CLOCK_MONOTONIC time after which we may return from this function: - const timeout_ts: os.linux.kernel_timespec = .{ + const timeout_ts: linux.kernel_timespec = .{ .tv_sec = current_ts.tv_sec, .tv_nsec = current_ts.tv_nsec + nanoseconds, }; @@ -83,7 +83,7 @@ pub const IO = struct { break :blk self.ring.get_sqe() catch unreachable; }; // Submit an absolute timeout that will be canceled if any other SQE completes first: - linux.io_uring_prep_timeout(timeout_sqe, &timeout_ts, 1, os.linux.IORING_TIMEOUT_ABS); + timeout_sqe.prep_timeout(&timeout_ts, 1, linux.IORING_TIMEOUT_ABS); timeout_sqe.user_data = 0; timeouts += 1; // The amount of time this call will block is bounded by the timeout we just submitted: @@ -144,7 +144,7 @@ pub const IO = struct { // it was completed due to the completion of an event, in which case `cqe.res` // would be 0. It is possible for multiple timeout operations to complete at the // same time if the nanoseconds value passed to `run_for_ns()` is very short. - if (-cqe.res == @intFromEnum(os.E.TIME)) etime.* = true; + if (-cqe.res == @intFromEnum(posix.E.TIME)) etime.* = true; continue; } const completion = @as(*Completion, @ptrFromInt(@as(usize, @intCast(cqe.user_data)))); @@ -199,45 +199,41 @@ pub const IO = struct { fn prep(completion: *Completion, sqe: *io_uring_sqe) void { switch (completion.operation) { .accept => |*op| { - linux.io_uring_prep_accept( - sqe, + sqe.prep_accept( op.socket, &op.address, &op.address_size, - os.SOCK.CLOEXEC, + posix.SOCK.CLOEXEC, ); }, .close => |op| { - linux.io_uring_prep_close(sqe, op.fd); + sqe.prep_close(op.fd); }, .connect => |*op| { - linux.io_uring_prep_connect( - sqe, + sqe.prep_connect( op.socket, &op.address.any, op.address.getOsSockLen(), ); }, .read => |op| { - linux.io_uring_prep_read( - sqe, + sqe.prep_read( op.fd, op.buffer[0..buffer_limit(op.buffer.len)], op.offset, ); }, .recv => |op| { - linux.io_uring_prep_recv(sqe, op.socket, op.buffer, os.MSG.NOSIGNAL); + sqe.prep_recv(op.socket, op.buffer, posix.MSG.NOSIGNAL); }, .send => |op| { - linux.io_uring_prep_send(sqe, op.socket, op.buffer, os.MSG.NOSIGNAL); + sqe.prep_send(op.socket, op.buffer, posix.MSG.NOSIGNAL); }, .timeout => |*op| { - linux.io_uring_prep_timeout(sqe, &op.timespec, 0, 0); + sqe.prep_timeout(&op.timespec, 0, 0); }, .write => |op| { - linux.io_uring_prep_write( - sqe, + sqe.prep_write( op.fd, op.buffer[0..buffer_limit(op.buffer.len)], op.offset, @@ -250,9 +246,9 @@ pub const IO = struct { fn complete(completion: *Completion) void { switch (completion.operation) { .accept => { - const result: AcceptError!os.socket_t = blk: { + const result: AcceptError!posix.socket_t = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -270,11 +266,11 @@ pub const IO = struct { .OPNOTSUPP => error.OperationNotSupported, .PERM => error.PermissionDenied, .PROTO => error.ProtocolFailure, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { - break :blk @as(os.socket_t, @intCast(completion.result)); + break :blk @as(posix.socket_t, @intCast(completion.result)); } }; completion.callback(completion.context, completion, &result); @@ -282,13 +278,13 @@ pub const IO = struct { .close => { const result: CloseError!void = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => {}, // A success, see https://github.com/ziglang/zig/issues/2425 .BADF => error.FileDescriptorInvalid, .DQUOT => error.DiskQuota, .IO => error.InputOutput, .NOSPC => error.NoSpaceLeft, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -300,7 +296,7 @@ pub const IO = struct { .connect => { const result: ConnectError!void = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -322,7 +318,7 @@ pub const IO = struct { .PERM => error.PermissionDenied, .PROTOTYPE => error.ProtocolNotSupported, .TIMEDOUT => error.ConnectionTimedOut, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -334,7 +330,7 @@ pub const IO = struct { .read => { const result: ReadError!usize = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -352,7 +348,7 @@ pub const IO = struct { .OVERFLOW => error.Unseekable, .SPIPE => error.Unseekable, .TIMEDOUT => error.ConnectionTimedOut, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -364,7 +360,7 @@ pub const IO = struct { .recv => { const result: RecvError!usize = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -380,7 +376,7 @@ pub const IO = struct { .CONNRESET => error.ConnectionResetByPeer, .TIMEDOUT => error.ConnectionTimedOut, .OPNOTSUPP => error.OperationNotSupported, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -392,7 +388,7 @@ pub const IO = struct { .send => { const result: SendError!usize = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -415,7 +411,7 @@ pub const IO = struct { .OPNOTSUPP => error.OperationNotSupported, .PIPE => error.BrokenPipe, .TIMEDOUT => error.ConnectionTimedOut, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -426,21 +422,21 @@ pub const IO = struct { }, .timeout => { assert(completion.result < 0); - const result: TimeoutError!void = switch (@as(os.E, @enumFromInt(-completion.result))) { + const result: TimeoutError!void = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; }, .CANCELED => error.Canceled, .TIME => {}, // A success. - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; completion.callback(completion.context, completion, &result); }, .write => { const result: WriteError!usize = blk: { if (completion.result < 0) { - const err = switch (@as(os.E, @enumFromInt(-completion.result))) { + const err = switch (@as(posix.E, @enumFromInt(-completion.result))) { .INTR => { completion.io.enqueue(completion); return; @@ -459,7 +455,7 @@ pub const IO = struct { .PERM => error.AccessDenied, .PIPE => error.BrokenPipe, .SPIPE => error.Unseekable, - else => |errno| os.unexpectedErrno(errno), + else => |errno| posix.unexpectedErrno(errno), }; break :blk err; } else { @@ -475,35 +471,35 @@ pub const IO = struct { /// This union encodes the set of operations supported as well as their arguments. const Operation = union(enum) { accept: struct { - socket: os.socket_t, - address: os.sockaddr = undefined, - address_size: os.socklen_t = @sizeOf(os.sockaddr), + socket: posix.socket_t, + address: posix.sockaddr = undefined, + address_size: posix.socklen_t = @sizeOf(posix.sockaddr), }, close: struct { - fd: os.fd_t, + fd: posix.fd_t, }, connect: struct { - socket: os.socket_t, + socket: posix.socket_t, address: std.net.Address, }, read: struct { - fd: os.fd_t, + fd: posix.fd_t, buffer: []u8, offset: u64, }, recv: struct { - socket: os.socket_t, + socket: posix.socket_t, buffer: []u8, }, send: struct { - socket: os.socket_t, + socket: posix.socket_t, buffer: []const u8, }, timeout: struct { - timespec: os.linux.kernel_timespec, + timespec: linux.kernel_timespec, }, write: struct { - fd: os.fd_t, + fd: posix.fd_t, buffer: []const u8, offset: u64, }, @@ -521,7 +517,7 @@ pub const IO = struct { OperationNotSupported, PermissionDenied, ProtocolFailure, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn accept( self: *IO, @@ -530,10 +526,10 @@ pub const IO = struct { comptime callback: fn ( context: Context, completion: *Completion, - result: AcceptError!os.socket_t, + result: AcceptError!posix.socket_t, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, ) void { completion.* = .{ .io = self, @@ -543,7 +539,7 @@ pub const IO = struct { callback( @as(Context, @ptrFromInt(@intFromPtr(ctx))), comp, - @as(*const AcceptError!os.socket_t, @ptrFromInt(@intFromPtr(res))).*, + @as(*const AcceptError!posix.socket_t, @ptrFromInt(@intFromPtr(res))).*, ); } }.wrapper, @@ -551,7 +547,7 @@ pub const IO = struct { .accept = .{ .socket = socket, .address = undefined, - .address_size = @sizeOf(os.sockaddr), + .address_size = @sizeOf(posix.sockaddr), }, }, }; @@ -563,7 +559,7 @@ pub const IO = struct { DiskQuota, InputOutput, NoSpaceLeft, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn close( self: *IO, @@ -575,7 +571,7 @@ pub const IO = struct { result: CloseError!void, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, ) void { completion.* = .{ .io = self, @@ -613,7 +609,7 @@ pub const IO = struct { PermissionDenied, ProtocolNotSupported, ConnectionTimedOut, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn connect( self: *IO, @@ -625,7 +621,7 @@ pub const IO = struct { result: ConnectError!void, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, address: std.net.Address, ) void { completion.* = .{ @@ -660,7 +656,7 @@ pub const IO = struct { SystemResources, Unseekable, ConnectionTimedOut, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn read( self: *IO, @@ -672,7 +668,7 @@ pub const IO = struct { result: ReadError!usize, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, buffer: []u8, offset: u64, ) void { @@ -709,7 +705,7 @@ pub const IO = struct { ConnectionResetByPeer, ConnectionTimedOut, OperationNotSupported, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn recv( self: *IO, @@ -721,7 +717,7 @@ pub const IO = struct { result: RecvError!usize, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, buffer: []u8, ) void { completion.* = .{ @@ -760,7 +756,7 @@ pub const IO = struct { OperationNotSupported, BrokenPipe, ConnectionTimedOut, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn send( self: *IO, @@ -772,7 +768,7 @@ pub const IO = struct { result: SendError!usize, ) void, completion: *Completion, - socket: os.socket_t, + socket: posix.socket_t, buffer: []const u8, ) void { completion.* = .{ @@ -797,7 +793,7 @@ pub const IO = struct { self.enqueue(completion); } - pub const TimeoutError = error{Canceled} || os.UnexpectedError; + pub const TimeoutError = error{Canceled} || posix.UnexpectedError; pub fn timeout( self: *IO, @@ -832,7 +828,7 @@ pub const IO = struct { // Special case a zero timeout as a yield. if (nanoseconds == 0) { - completion.result = -@as(i32, @intCast(@intFromEnum(std.os.E.TIME))); + completion.result = -@as(i32, @intCast(@intFromEnum(posix.E.TIME))); self.completed.push(completion); return; } @@ -852,7 +848,7 @@ pub const IO = struct { Unseekable, AccessDenied, BrokenPipe, - } || os.UnexpectedError; + } || posix.UnexpectedError; pub fn write( self: *IO, @@ -864,7 +860,7 @@ pub const IO = struct { result: WriteError!usize, ) void, completion: *Completion, - fd: os.fd_t, + fd: posix.fd_t, buffer: []const u8, offset: u64, ) void { @@ -894,17 +890,17 @@ pub const IO = struct { pub const INVALID_SOCKET = -1; /// Creates a socket that can be used for async operations with the IO instance. - pub fn open_socket(self: *IO, family: u32, sock_type: u32, protocol: u32) !os.socket_t { + pub fn open_socket(self: *IO, family: u32, sock_type: u32, protocol: u32) !posix.socket_t { _ = self; - return os.socket(family, sock_type, protocol); + return posix.socket(family, sock_type, protocol); } /// Opens a directory with read only access. - pub fn open_dir(dir_path: []const u8) !os.fd_t { - return os.open(dir_path, os.O.CLOEXEC | os.O.RDONLY, 0); + pub fn open_dir(dir_path: []const u8) !posix.fd_t { + return posix.open(dir_path, posix.O.CLOEXEC | posix.O.RDONLY, 0); } - pub const INVALID_FILE: os.fd_t = -1; + pub const INVALID_FILE: posix.fd_t = -1; /// Opens or creates a journal file: /// - For reading and writing. @@ -915,11 +911,11 @@ pub const IO = struct { /// The caller is responsible for ensuring that the parent directory inode is durable. /// - Verifies that the file size matches the expected file size before returning. pub fn open_file( - dir_fd: os.fd_t, + dir_fd: posix.fd_t, relative_path: []const u8, size: u64, must_create: bool, - ) !os.fd_t { + ) !posix.fd_t { assert(relative_path.len > 0); assert(size >= constants.sector_size); assert(size % constants.sector_size == 0); @@ -927,17 +923,17 @@ pub const IO = struct { // TODO Use O_EXCL when opening as a block device to obtain a mandatory exclusive lock. // This is much stronger than an advisory exclusive lock, and is required on some platforms. - var flags: u32 = os.O.CLOEXEC | os.O.RDWR | os.O.DSYNC; - var mode: os.mode_t = 0; + var flags: u32 = posix.O.CLOEXEC | posix.O.RDWR | posix.O.DSYNC; + var mode: posix.mode_t = 0; // TODO Document this and investigate whether this is in fact correct to set here. - if (@hasDecl(os.O, "LARGEFILE")) flags |= os.O.LARGEFILE; + if (@hasDecl(posix.O, "LARGEFILE")) flags |= posix.O.LARGEFILE; var direct_io_supported = false; if (constants.direct_io) { direct_io_supported = try fs_supports_direct_io(dir_fd); if (direct_io_supported) { - flags |= os.O.DIRECT; + flags |= posix.O.DIRECT; } else if (!constants.direct_io_required) { log.warn("file system does not support Direct I/O", .{}); } else { @@ -949,27 +945,27 @@ pub const IO = struct { if (must_create) { log.info("creating \"{s}\"...", .{relative_path}); - flags |= os.O.CREAT; - flags |= os.O.EXCL; + flags |= posix.O.CREAT; + flags |= posix.O.EXCL; mode = 0o666; } else { log.info("opening \"{s}\"...", .{relative_path}); } // This is critical as we rely on O_DSYNC for fsync() whenever we write to the file: - assert((flags & os.O.DSYNC) > 0); + assert((flags & posix.O.DSYNC) > 0); // Be careful with openat(2): "If pathname is absolute, then dirfd is ignored." (man page) assert(!std.fs.path.isAbsolute(relative_path)); - const fd = try os.openat(dir_fd, relative_path, flags, mode); + const fd = try posix.openat(dir_fd, relative_path, flags, mode); // TODO Return a proper error message when the path exists or does not exist (init/start). - errdefer os.close(fd); + errdefer posix.close(fd); // TODO Check that the file is actually a file. // Obtain an advisory exclusive lock that works only if all processes actually use flock(). // LOCK_NB means that we want to fail the lock without waiting if another process has it. - os.flock(fd, os.LOCK.EX | os.LOCK.NB) catch |err| switch (err) { + posix.flock(fd, posix.LOCK.EX | posix.LOCK.NB) catch |err| switch (err) { error.WouldBlock => @panic("another process holds the data file lock"), else => return err, }; @@ -991,7 +987,7 @@ pub const IO = struct { const write_offset = size - sector.len; var written: usize = 0; while (written < sector.len) { - written += try os.pwrite(fd, sector[written..], write_offset + written); + written += try posix.pwrite(fd, sector[written..], write_offset + written); } }, else => |e| return e, @@ -1002,14 +998,14 @@ pub const IO = struct { // making decisions on data that was never durably written by a previously crashed process. // We therefore always fsync when we open the path, also to wait for any pending O_DSYNC. // Thanks to Alex Miller from FoundationDB for diving into our source and pointing this out. - try os.fsync(fd); + try posix.fsync(fd); // We fsync the parent directory to ensure that the file inode is durably written. // The caller is responsible for the parent directory inode stored under the grandparent. // We always do this when opening because we don't know if this was done before crashing. - try os.fsync(dir_fd); + try posix.fsync(dir_fd); - const stat = try os.fstat(fd); + const stat = try posix.fstat(fd); if (stat.size < size) @panic("data file inode size was truncated or corrupted"); return fd; @@ -1017,39 +1013,39 @@ pub const IO = struct { /// Detects whether the underlying file system for a given directory fd supports Direct I/O. /// Not all Linux file systems support `O_DIRECT`, e.g. a shared macOS volume. - fn fs_supports_direct_io(dir_fd: std.os.fd_t) !bool { - if (!@hasDecl(std.os.O, "DIRECT")) return false; + fn fs_supports_direct_io(dir_fd: posix.fd_t) !bool { + if (!@hasDecl(posix.O, "DIRECT")) return false; const path = "fs_supports_direct_io"; const dir = std.fs.Dir{ .fd = dir_fd }; - const fd = try os.openatZ(dir_fd, path, os.O.CLOEXEC | os.O.CREAT | os.O.TRUNC, 0o666); - defer os.close(fd); + const fd = try posix.openatZ(dir_fd, path, posix.O.CLOEXEC | posix.O.CREAT | posix.O.TRUNC, 0o666); + defer posix.close(fd); defer dir.deleteFile(path) catch {}; while (true) { - const res = os.linux.openat(dir_fd, path, os.O.CLOEXEC | os.O.RDONLY | os.O.DIRECT, 0); - switch (os.linux.getErrno(res)) { + const res = linux.openat(dir_fd, path, posix.O.CLOEXEC | posix.O.RDONLY | posix.O.DIRECT, 0); + switch (linux.getErrno(res)) { .SUCCESS => { - os.close(@as(os.fd_t, @intCast(res))); + posix.close(@as(posix.fd_t, @intCast(res))); return true; }, .INTR => continue, .INVAL => return false, - else => |err| return os.unexpectedErrno(err), + else => |err| return posix.unexpectedErrno(err), } } } /// Allocates a file contiguously using fallocate() if supported. /// Alternatively, writes to the last sector so that at least the file size is correct. - fn fs_allocate(fd: os.fd_t, size: u64) !void { + fn fs_allocate(fd: posix.fd_t, size: u64) !void { const mode: i32 = 0; const offset: i64 = 0; const length = @as(i64, @intCast(size)); while (true) { - const rc = os.linux.fallocate(fd, mode, offset, length); - switch (os.linux.getErrno(rc)) { + const rc = linux.fallocate(fd, mode, offset, length); + switch (linux.getErrno(rc)) { .SUCCESS => return, .BADF => return error.FileDescriptorInvalid, .FBIG => return error.FileTooBig, @@ -1063,7 +1059,7 @@ pub const IO = struct { .PERM => return error.PermissionDenied, .SPIPE => return error.Unseekable, .TXTBSY => return error.FileBusy, - else => |errno| return os.unexpectedErrno(errno), + else => |errno| return posix.unexpectedErrno(errno), } } } diff --git a/io/test.zig b/io/test.zig index eee2c3c..518c0c9 100644 --- a/io/test.zig +++ b/io/test.zig @@ -1,6 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); -const os = std.os; +const posix = std.posix; const testing = std.testing; const assert = std.debug.assert; @@ -13,7 +13,7 @@ test "write/read/close" { io: IO, done: bool = false, - fd: os.fd_t, + fd: posix.fd_t, write_buf: [20]u8 = [_]u8{97} ** 20, read_buf: [20]u8 = [_]u8{98} ** 20, @@ -87,10 +87,10 @@ test "accept/connect/send/receive" { io: *IO, done: bool = false, - server: os.socket_t, - client: os.socket_t, + server: posix.socket_t, + client: posix.socket_t, - accepted_sock: os.socket_t = undefined, + accepted_sock: posix.socket_t = undefined, send_buf: [10]u8 = [_]u8{ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 }, recv_buf: [5]u8 = [_]u8{ 0, 1, 0, 1, 0 }, @@ -104,20 +104,20 @@ test "accept/connect/send/receive" { const address = try std.net.Address.parseIp4("127.0.0.1", 3131); const kernel_backlog = 1; - const server = try io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(server); + const server = try io.open_socket(address.any.family, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(server); - const client = try io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(client); + const client = try io.open_socket(address.any.family, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(client); - try os.setsockopt( + try posix.setsockopt( server, - os.SOL.SOCKET, - os.SO.REUSEADDR, + posix.SOL.SOCKET, + posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)), ); - try os.bind(server, &address.any, address.getOsSockLen()); - try os.listen(server, kernel_backlog); + try posix.bind(server, &address.any, address.getOsSockLen()); + try posix.listen(server, kernel_backlog); var self: Context = .{ .io = &io, @@ -176,7 +176,7 @@ test "accept/connect/send/receive" { fn accept_callback( self: *Context, completion: *IO.Completion, - result: IO.AcceptError!os.socket_t, + result: IO.AcceptError!posix.socket_t, ) void { self.accepted_sock = result catch @panic("accept error"); self.io.recv( @@ -310,7 +310,7 @@ test "tick to wait" { const Context = @This(); io: IO, - accepted: os.socket_t = IO.INVALID_SOCKET, + accepted: posix.socket_t = IO.INVALID_SOCKET, connected: bool = false, received: bool = false, @@ -321,20 +321,20 @@ test "tick to wait" { const address = try std.net.Address.parseIp4("127.0.0.1", 3131); const kernel_backlog = 1; - const server = try self.io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(server); + const server = try self.io.open_socket(address.any.family, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(server); - try os.setsockopt( + try posix.setsockopt( server, - os.SOL.SOCKET, - os.SO.REUSEADDR, + posix.SOL.SOCKET, + posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)), ); - try os.bind(server, &address.any, address.getOsSockLen()); - try os.listen(server, kernel_backlog); + try posix.bind(server, &address.any, address.getOsSockLen()); + try posix.listen(server, kernel_backlog); - const client = try self.io.open_socket(address.any.family, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(client); + const client = try self.io.open_socket(address.any.family, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(client); // Start the accept var server_completion: IO.Completion = undefined; @@ -360,7 +360,7 @@ test "tick to wait" { assert(self.connected); assert(self.accepted != IO.INVALID_SOCKET); - defer os.closeSocket(self.accepted); + defer posix.close(self.accepted); // Start receiving on the client var recv_completion: IO.Completion = undefined; @@ -402,7 +402,7 @@ test "tick to wait" { fn accept_callback( self: *Context, completion: *IO.Completion, - result: IO.AcceptError!os.socket_t, + result: IO.AcceptError!posix.socket_t, ) void { _ = completion; @@ -434,15 +434,15 @@ test "tick to wait" { self.received = true; } - // TODO: use os.send() instead when it gets fixed for windows - fn os_send(sock: os.socket_t, buf: []const u8, flags: u32) !usize { + // TODO: use posix.send() instead when it gets fixed for windows + fn os_send(sock: posix.socket_t, buf: []const u8, flags: u32) !usize { if (builtin.target.os.tag != .windows) { - return os.send(sock, buf, flags); + return posix.send(sock, buf, flags); } - const rc = os.windows.sendto(sock, buf.ptr, buf.len, flags, null, 0); - if (rc == os.windows.ws2_32.SOCKET_ERROR) { - switch (os.windows.ws2_32.WSAGetLastError()) { + const rc = posix.windows.sendto(sock, buf.ptr, buf.len, flags, null, 0); + if (rc == posix.windows.ws2_32.SOCKET_ERROR) { + switch (posix.windows.ws2_32.WSAGetLastError()) { .WSAEACCES => return error.AccessDenied, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAECONNRESET => return error.ConnectionResetByPeer, @@ -462,7 +462,7 @@ test "tick to wait" { .WSAESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. .WSAEWOULDBLOCK => return error.WouldBlock, .WSANOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. - else => |err| return os.windows.unexpectedWSAError(err), + else => |err| return posix.windows.unexpectedWSAError(err), } } else { return @as(usize, @intCast(rc)); @@ -482,7 +482,7 @@ test "pipe data over socket" { const Context = @This(); const Socket = struct { - fd: os.socket_t = IO.INVALID_SOCKET, + fd: posix.socket_t = IO.INVALID_SOCKET, completion: IO.Completion = undefined, }; const Pipe = struct { @@ -506,19 +506,19 @@ test "pipe data over socket" { }; defer self.io.deinit(); - self.server.fd = try self.io.open_socket(os.AF.INET, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(self.server.fd); + self.server.fd = try self.io.open_socket(posix.AF.INET, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(self.server.fd); const address = try std.net.Address.parseIp4("127.0.0.1", 3131); - try os.setsockopt( + try posix.setsockopt( self.server.fd, - os.SOL.SOCKET, - os.SO.REUSEADDR, + posix.SOL.SOCKET, + posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)), ); - try os.bind(self.server.fd, &address.any, address.getOsSockLen()); - try os.listen(self.server.fd, 1); + try posix.bind(self.server.fd, &address.any, address.getOsSockLen()); + try posix.listen(self.server.fd, 1); self.io.accept( *Context, @@ -528,8 +528,8 @@ test "pipe data over socket" { self.server.fd, ); - self.tx.socket.fd = try self.io.open_socket(os.AF.INET, os.SOCK.STREAM, os.IPPROTO.TCP); - defer os.closeSocket(self.tx.socket.fd); + self.tx.socket.fd = try self.io.open_socket(posix.AF.INET, posix.SOCK.STREAM, posix.IPPROTO.TCP); + defer posix.close(self.tx.socket.fd); self.io.connect( *Context, @@ -553,7 +553,7 @@ test "pipe data over socket" { try testing.expect(self.server.fd != IO.INVALID_SOCKET); try testing.expect(self.tx.socket.fd != IO.INVALID_SOCKET); try testing.expect(self.rx.socket.fd != IO.INVALID_SOCKET); - os.closeSocket(self.rx.socket.fd); + posix.close(self.rx.socket.fd); try testing.expectEqual(self.tx.transferred, buffer_size); try testing.expectEqual(self.rx.transferred, buffer_size); @@ -563,7 +563,7 @@ test "pipe data over socket" { fn on_accept( self: *Context, completion: *IO.Completion, - result: IO.AcceptError!os.socket_t, + result: IO.AcceptError!posix.socket_t, ) void { assert(self.rx.socket.fd == IO.INVALID_SOCKET); assert(&self.server.completion == completion); diff --git a/time.zig b/time.zig index e894b6c..18c81dd 100644 --- a/time.zig +++ b/time.zig @@ -67,8 +67,8 @@ pub const Time = struct { // CLOCK_BOOTTIME is the same as CLOCK_MONOTONIC but includes elapsed time during a suspend. // For more detail and why CLOCK_MONOTONIC_RAW is even worse than CLOCK_MONOTONIC, // see https://github.com/ziglang/zig/pull/933#discussion_r656021295. - var ts: os.timespec = undefined; - os.clock_gettime(os.CLOCK.BOOTTIME, &ts) catch @panic("CLOCK_BOOTTIME required"); + var ts: std.posix.timespec = undefined; + std.posix.clock_gettime(std.posix.CLOCK.BOOTTIME, &ts) catch @panic("CLOCK_BOOTTIME required"); break :blk @as(u64, @intCast(ts.tv_sec)) * std.time.ns_per_s + @as(u64, @intCast(ts.tv_nsec)); }; @@ -103,8 +103,8 @@ pub const Time = struct { // https://opensource.apple.com/source/Libc/Libc-1158.1.2/gen/clock_gettime.3.auto.html } - var ts: os.timespec = undefined; - os.clock_gettime(os.CLOCK.REALTIME, &ts) catch unreachable; + var ts: std.posix.timespec = undefined; + std.posix.clock_gettime(std.posix.CLOCK.REALTIME, &ts) catch unreachable; return @as(i64, ts.tv_sec) * std.time.ns_per_s + ts.tv_nsec; }