From 031044b3994d4510f64bd08ecba0ab01a7ed48c6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 15 Oct 2025 19:31:28 -0700 Subject: [PATCH] std: fix macos compilation errors --- lib/std/Io/IoUring.zig | 2 +- lib/std/Io/Threaded.zig | 82 +++++++++++++-------- lib/std/Io/net.zig | 9 ++- lib/std/c.zig | 2 +- lib/std/crypto/Certificate/Bundle.zig | 45 +++++------ lib/std/crypto/Certificate/Bundle/macos.zig | 12 +-- lib/std/debug/SelfInfo/MachO.zig | 3 + lib/std/fs.zig | 2 + lib/std/http/Client.zig | 23 +++--- lib/std/http/Server.zig | 8 +- lib/std/os/windows.zig | 2 +- lib/std/posix.zig | 52 ++++++------- 12 files changed, 138 insertions(+), 104 deletions(-) diff --git a/lib/std/Io/IoUring.zig b/lib/std/Io/IoUring.zig index 84ea0035ae..c6dca1597d 100644 --- a/lib/std/Io/IoUring.zig +++ b/lib/std/Io/IoUring.zig @@ -1469,7 +1469,7 @@ fn pwrite(userdata: ?*anyopaque, file: Io.File, buffer: []const u8, offset: std. .OVERFLOW => return error.Unseekable, .BUSY => return error.DeviceBusy, .CONNRESET => return error.ConnectionResetByPeer, - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, else => |err| return std.posix.unexpectedErrno(err), } } diff --git a/lib/std/Io/Threaded.zig b/lib/std/Io/Threaded.zig index fb70c8af79..6ceebc79e1 100644 --- a/lib/std/Io/Threaded.zig +++ b/lib/std/Io/Threaded.zig @@ -966,7 +966,7 @@ fn dirStatPathPosix( try t.checkCancel(); var stat = std.mem.zeroes(posix.Stat); switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &stat, flags))) { - .SUCCESS => return statFromPosix(stat), + .SUCCESS => return statFromPosix(&stat), .INTR => continue, .INVAL => |err| return errnoBug(err), .BADF => |err| return errnoBug(err), // Always a race condition. @@ -1166,8 +1166,9 @@ fn dirCreateFilePosix( if (has_flock_open_flags and flags.lock_nonblocking) { var fl_flags: usize = while (true) { try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { - .SUCCESS => break, + const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); + switch (posix.errno(rc)) { + .SUCCESS => break @intCast(rc), .INTR => continue, else => |err| return posix.unexpectedErrno(err), } @@ -1295,8 +1296,9 @@ fn dirOpenFile( if (has_flock_open_flags and flags.lock_nonblocking) { var fl_flags: usize = while (true) { try t.checkCancel(); - switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { - .SUCCESS => break, + const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0)); + switch (posix.errno(rc)) { + .SUCCESS => break @intCast(rc), .INTR => continue, else => |err| return posix.unexpectedErrno(err), } @@ -1755,7 +1757,7 @@ fn sleepPosix(userdata: ?*anyopaque, timeout: Io.Timeout) Io.SleepError!void { .sec = std.math.maxInt(sec_type), .nsec = std.math.maxInt(nsec_type), }; - break :t timestampToPosix(d.duration.nanoseconds); + break :t timestampToPosix(d.raw.toNanoseconds()); }; while (true) { try t.checkCancel(); @@ -1850,6 +1852,7 @@ fn netListenUnix( error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, error.SocketModeUnsupported => return error.AddressFamilyUnsupported, + error.OptionUnsupported => return error.Unexpected, else => |e| return e, }; errdefer posix.close(socket_fd); @@ -2037,7 +2040,10 @@ fn netConnectUnix( ) net.UnixAddress.ConnectError!net.Socket.Handle { if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; const t: *Threaded = @ptrCast(@alignCast(userdata)); - const socket_fd = try openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }); + const socket_fd = openSocketPosix(t, posix.AF.UNIX, .{ .mode = .stream }) catch |err| switch (err) { + error.OptionUnsupported => return error.Unexpected, + else => |e| return e, + }; errdefer posix.close(socket_fd); var storage: UnixAddress = undefined; const addr_len = addressUnixToPosix(address, &storage); @@ -2064,7 +2070,22 @@ fn netBindIpPosix( }; } -fn openSocketPosix(t: *Threaded, family: posix.sa_family_t, options: IpAddress.BindOptions) !posix.socket_t { +fn openSocketPosix( + t: *Threaded, + family: posix.sa_family_t, + options: IpAddress.BindOptions, +) error{ + AddressFamilyUnsupported, + ProtocolUnsupportedBySystem, + ProcessFdQuotaExceeded, + SystemFdQuotaExceeded, + SystemResources, + ProtocolUnsupportedByAddressFamily, + SocketModeUnsupported, + OptionUnsupported, + Unexpected, + Canceled, +}!posix.socket_t { const mode = posixSocketMode(options.mode); const protocol = posixProtocol(options.protocol); const socket_fd = while (true) { @@ -2209,7 +2230,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net. .NOTCONN => return error.SocketUnconnected, .CONNRESET => return error.ConnectionResetByPeer, .TIMEDOUT => return error.Timeout, - .PIPE => return error.BrokenPipe, + .PIPE => return error.SocketUnconnected, .NETDOWN => return error.NetworkDown, else => |err| return posix.unexpectedErrno(err), } @@ -2253,29 +2274,29 @@ fn netSendOne( flags: u32, ) net.Socket.SendError!void { var addr: PosixAddress = undefined; - var iovec: posix.iovec = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; - const msg: posix.msghdr = .{ + var iovec: posix.iovec_const = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; + const msg: posix.msghdr_const = .{ .name = &addr.any, .namelen = addressToPosix(message.address, &addr), - .iov = iovec[0..1], + .iov = (&iovec)[0..1], .iovlen = 1, .control = @constCast(message.control.ptr), - .controllen = message.control.len, + .controllen = @intCast(message.control.len), .flags = 0, }; while (true) { try t.checkCancel(); - const rc = posix.system.sendmsg(handle, msg, flags); + const rc = posix.system.sendmsg(handle, &msg, flags); if (is_windows) { if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { .WSAEACCES => return error.AccessDenied, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAECONNRESET => return error.ConnectionResetByPeer, - .WSAEMSGSIZE => return error.MessageTooBig, + .WSAEMSGSIZE => return error.MessageOversize, .WSAENOBUFS => return error.SystemResources, .WSAENOTSOCK => return error.FileDescriptorNotASocket, - .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported, .WSAEDESTADDRREQ => unreachable, // A destination address is required. .WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. .WSAEHOSTUNREACH => return error.NetworkUnreachable, @@ -2285,7 +2306,6 @@ fn netSendOne( .WSAENETUNREACH => return error.NetworkUnreachable, .WSAENOTCONN => return error.SocketUnconnected, .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 windows.unexpectedWSAError(err), } @@ -2299,28 +2319,24 @@ fn netSendOne( message.data_len = @intCast(rc); return; }, + .INTR => continue, + .ACCES => return error.AccessDenied, - .AGAIN => return error.WouldBlock, .ALREADY => return error.FastOpenAlreadyInProgress, .BADF => |err| return errnoBug(err), .CONNRESET => return error.ConnectionResetByPeer, .DESTADDRREQ => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err), - .INTR => continue, .INVAL => |err| return errnoBug(err), .ISCONN => |err| return errnoBug(err), - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, .NOBUFS => return error.SystemResources, .NOMEM => return error.SystemResources, .NOTSOCK => |err| return errnoBug(err), .OPNOTSUPP => |err| return errnoBug(err), - .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, - .LOOP => return error.SymLinkLoop, - .NAMETOOLONG => return error.NameTooLong, - .NOENT => return error.FileNotFound, - .NOTDIR => return error.NotDir, - .HOSTUNREACH => return error.NetworkUnreachable, + .PIPE => return error.SocketUnconnected, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, + .HOSTUNREACH => return error.HostUnreachable, .NETUNREACH => return error.NetworkUnreachable, .NOTCONN => return error.SocketUnconnected, .NETDOWN => return error.NetworkDown, @@ -2447,7 +2463,7 @@ fn netReceive( .iov = (&iov)[0..1], .iovlen = 1, .control = message.control.ptr, - .controllen = message.control.len, + .controllen = @intCast(message.control.len), .flags = undefined, }; @@ -2465,7 +2481,7 @@ fn netReceive( .trunc = (msg.flags & posix.MSG.TRUNC) != 0, .ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0, .oob = (msg.flags & posix.MSG.OOB) != 0, - .errqueue = (msg.flags & posix.MSG.ERRQUEUE) != 0, + .errqueue = if (@hasDecl(posix.MSG, "ERRQUEUE")) (msg.flags & posix.MSG.ERRQUEUE) != 0 else false, }, }; message_i += 1; @@ -2605,6 +2621,7 @@ fn netInterfaceNameResolve( error.ProtocolUnsupportedBySystem => return error.Unexpected, error.ProtocolUnsupportedByAddressFamily => return error.Unexpected, error.SocketModeUnsupported => return error.Unexpected, + error.OptionUnsupported => return error.Unexpected, else => |e| return e, }; defer posix.close(sock_fd); @@ -3079,9 +3096,10 @@ fn lookupDns( } } - var ip4_mapped: [HostName.ResolvConf.max_nameservers]IpAddress = undefined; + var ip4_mapped_buffer: [HostName.ResolvConf.max_nameservers]IpAddress = undefined; + const ip4_mapped = ip4_mapped_buffer[0..rc.nameservers_len]; var any_ip6 = false; - for (rc.nameservers(), &ip4_mapped) |*ns, *m| { + for (rc.nameservers(), ip4_mapped) |*ns, *m| { m.* = .{ .ip6 = .fromAny(ns.*) }; any_ip6 = any_ip6 or ns.* == .ip6; } @@ -3101,7 +3119,7 @@ fn lookupDns( }; defer socket.close(t_io); - const mapped_nameservers = if (any_ip6) ip4_mapped[0..rc.nameservers_len] else rc.nameservers(); + const mapped_nameservers = if (any_ip6) ip4_mapped else rc.nameservers(); const queries = queries_buffer[0..nq]; const answers = answers_buffer[0..queries.len]; var answers_remaining = answers.len; diff --git a/lib/std/Io/net.zig b/lib/std/Io/net.zig index 6b407eb504..81ad077667 100644 --- a/lib/std/Io/net.zig +++ b/lib/std/Io/net.zig @@ -209,6 +209,9 @@ pub const IpAddress = union(enum) { ProtocolUnsupportedBySystem, ProtocolUnsupportedByAddressFamily, SocketModeUnsupported, + /// One of the `ListenOptions` is not supported by the Io + /// implementation. + OptionUnsupported, } || Io.UnexpectedError || Io.Cancelable; pub const ListenOptions = struct { @@ -1057,6 +1060,9 @@ pub const Socket = struct { /// Local end has been shut down on a connection-oriented socket, or /// the socket was never connected. SocketUnconnected, + /// An attempt was made to send to a network/broadcast address as + /// though it was a unicast address. + AccessDenied, } || Io.UnexpectedError || Io.Cancelable; /// Transfers `data` to `dest`, connectionless, in one packet. @@ -1167,7 +1173,6 @@ pub const Stream = struct { pub const Error = error{ SystemResources, - BrokenPipe, ConnectionResetByPeer, Timeout, SocketUnconnected, @@ -1233,7 +1238,7 @@ pub const Stream = struct { pub const Error = std.posix.SendMsgError || error{ ConnectionResetByPeer, SocketNotBound, - MessageTooBig, + MessageOversize, NetworkDown, SystemResources, SocketUnconnected, diff --git a/lib/std/c.zig b/lib/std/c.zig index 24ad58e242..b96ca2e458 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -4104,7 +4104,7 @@ pub const msghdr = switch (native_os) { .visionos, .watchos, .serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82 - => private.posix_msghdr, + => posix_msghdr, else => void, }; diff --git a/lib/std/crypto/Certificate/Bundle.zig b/lib/std/crypto/Certificate/Bundle.zig index 1a96688a0f..e2090e01ac 100644 --- a/lib/std/crypto/Certificate/Bundle.zig +++ b/lib/std/crypto/Certificate/Bundle.zig @@ -70,18 +70,18 @@ pub const RescanError = RescanLinuxError || RescanMacError || RescanWithPathErro /// file system standard locations for certificates. /// For operating systems that do not have standard CA installations to be /// found, this function clears the set of certificates. -pub fn rescan(cb: *Bundle, gpa: Allocator, io: Io) RescanError!void { +pub fn rescan(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanError!void { switch (builtin.os.tag) { - .linux => return rescanLinux(cb, gpa, io), - .macos => return rescanMac(cb, gpa), - .freebsd, .openbsd => return rescanWithPath(cb, gpa, io, "/etc/ssl/cert.pem"), - .netbsd => return rescanWithPath(cb, gpa, io, "/etc/openssl/certs/ca-certificates.crt"), - .dragonfly => return rescanWithPath(cb, gpa, io, "/usr/local/etc/ssl/cert.pem"), - .illumos => return rescanWithPath(cb, gpa, io, "/etc/ssl/cacert.pem"), - .haiku => return rescanWithPath(cb, gpa, io, "/boot/system/data/ssl/CARootCertificates.pem"), + .linux => return rescanLinux(cb, gpa, io, now), + .macos => return rescanMac(cb, gpa, io, now), + .freebsd, .openbsd => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/cert.pem"), + .netbsd => return rescanWithPath(cb, gpa, io, now, "/etc/openssl/certs/ca-certificates.crt"), + .dragonfly => return rescanWithPath(cb, gpa, io, now, "/usr/local/etc/ssl/cert.pem"), + .illumos => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/cacert.pem"), + .haiku => return rescanWithPath(cb, gpa, io, now, "/boot/system/data/ssl/CARootCertificates.pem"), // https://github.com/SerenityOS/serenity/blob/222acc9d389bc6b490d4c39539761b043a4bfcb0/Ports/ca-certificates/package.sh#L19 - .serenity => return rescanWithPath(cb, gpa, io, "/etc/ssl/certs/ca-certificates.crt"), - .windows => return rescanWindows(cb, gpa), + .serenity => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/certs/ca-certificates.crt"), + .windows => return rescanWindows(cb, gpa, io, now), else => {}, } } @@ -91,7 +91,7 @@ const RescanMacError = @import("Bundle/macos.zig").RescanMacError; const RescanLinuxError = AddCertsFromFilePathError || AddCertsFromDirPathError; -fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void { +fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanLinuxError!void { // Possible certificate files; stop after finding one. const cert_file_paths = [_][]const u8{ "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. @@ -114,7 +114,7 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void { scan: { for (cert_file_paths) |cert_file_path| { - if (addCertsFromFilePathAbsolute(cb, gpa, io, cert_file_path)) |_| { + if (addCertsFromFilePathAbsolute(cb, gpa, io, now, cert_file_path)) |_| { break :scan; } else |err| switch (err) { error.FileNotFound => continue, @@ -123,7 +123,7 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void { } for (cert_dir_paths) |cert_dir_path| { - addCertsFromDirPathAbsolute(cb, gpa, io, cert_dir_path) catch |err| switch (err) { + addCertsFromDirPathAbsolute(cb, gpa, io, now, cert_dir_path) catch |err| switch (err) { error.FileNotFound => continue, else => |e| return e, }; @@ -135,10 +135,10 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void { const RescanWithPathError = AddCertsFromFilePathError; -fn rescanWithPath(cb: *Bundle, gpa: Allocator, io: Io, cert_file_path: []const u8) RescanWithPathError!void { +fn rescanWithPath(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, cert_file_path: []const u8) RescanWithPathError!void { cb.bytes.clearRetainingCapacity(); cb.map.clearRetainingCapacity(); - try addCertsFromFilePathAbsolute(cb, gpa, io, cert_file_path); + try addCertsFromFilePathAbsolute(cb, gpa, io, now, cert_file_path); cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len); } @@ -187,17 +187,18 @@ pub fn addCertsFromDirPathAbsolute( cb: *Bundle, gpa: Allocator, io: Io, + now: Io.Timestamp, abs_dir_path: []const u8, ) AddCertsFromDirPathError!void { assert(fs.path.isAbsolute(abs_dir_path)); var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true }); defer iterable_dir.close(); - return addCertsFromDir(cb, gpa, io, iterable_dir); + return addCertsFromDir(cb, gpa, io, now, iterable_dir); } pub const AddCertsFromDirError = AddCertsFromFilePathError; -pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, iterable_dir: fs.Dir) AddCertsFromDirError!void { +pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp, iterable_dir: fs.Dir) AddCertsFromDirError!void { var it = iterable_dir.iterate(); while (try it.next()) |entry| { switch (entry.kind) { @@ -205,7 +206,7 @@ pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, iterable_dir: fs.Dir else => continue, } - try addCertsFromFilePath(cb, gpa, io, iterable_dir.adaptToNewApi(), entry.name); + try addCertsFromFilePath(cb, gpa, io, now, iterable_dir.adaptToNewApi(), entry.name); } } @@ -215,9 +216,9 @@ pub fn addCertsFromFilePathAbsolute( cb: *Bundle, gpa: Allocator, io: Io, + now: Io.Timestamp, abs_file_path: []const u8, ) AddCertsFromFilePathError!void { - const now = try Io.Clock.real.now(io); var file = try fs.openFileAbsolute(abs_file_path, .{}); defer file.close(); var file_reader = file.reader(io, &.{}); @@ -228,10 +229,10 @@ pub fn addCertsFromFilePath( cb: *Bundle, gpa: Allocator, io: Io, + now: Io.Timestamp, dir: Io.Dir, sub_file_path: []const u8, ) AddCertsFromFilePathError!void { - const now = try Io.Clock.real.now(io); var file = try dir.openFile(io, sub_file_path, .{}); defer file.close(io); var file_reader = file.reader(io, &.{}); @@ -335,5 +336,7 @@ test "scan for OS-provided certificates" { var bundle: Bundle = .{}; defer bundle.deinit(gpa); - try bundle.rescan(gpa, io); + const now = try Io.Clock.real.now(io); + + try bundle.rescan(gpa, io, now); } diff --git a/lib/std/crypto/Certificate/Bundle/macos.zig b/lib/std/crypto/Certificate/Bundle/macos.zig index 5aa842f245..d32f1be8e0 100644 --- a/lib/std/crypto/Certificate/Bundle/macos.zig +++ b/lib/std/crypto/Certificate/Bundle/macos.zig @@ -1,4 +1,5 @@ const std = @import("std"); +const Io = std.Io; const assert = std.debug.assert; const fs = std.fs; const mem = std.mem; @@ -7,7 +8,7 @@ const Bundle = @import("../Bundle.zig"); pub const RescanMacError = Allocator.Error || fs.File.OpenError || fs.File.ReadError || fs.File.SeekError || Bundle.ParseCertError || error{EndOfStream}; -pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void { +pub fn rescanMac(cb: *Bundle, gpa: Allocator, io: Io, now: Io.Timestamp) RescanMacError!void { cb.bytes.clearRetainingCapacity(); cb.map.clearRetainingCapacity(); @@ -16,6 +17,7 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void { "/Library/Keychains/System.keychain", }; + _ = io; // TODO migrate file system to use std.Io for (keychain_paths) |keychain_path| { const bytes = std.fs.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { error.StreamTooLong => return error.FileTooBig, @@ -23,8 +25,8 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void { }; defer gpa.free(bytes); - var reader: std.Io.Reader = .fixed(bytes); - scanReader(cb, gpa, &reader) catch |err| switch (err) { + var reader: Io.Reader = .fixed(bytes); + scanReader(cb, gpa, &reader, now.toSeconds()) catch |err| switch (err) { error.ReadFailed => unreachable, // prebuffered else => |e| return e, }; @@ -33,7 +35,7 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void { cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len); } -fn scanReader(cb: *Bundle, gpa: Allocator, reader: *std.Io.Reader) !void { +fn scanReader(cb: *Bundle, gpa: Allocator, reader: *Io.Reader, now_sec: i64) !void { const db_header = try reader.takeStruct(ApplDbHeader, .big); assert(mem.eql(u8, &db_header.signature, "kych")); @@ -49,8 +51,6 @@ fn scanReader(cb: *Bundle, gpa: Allocator, reader: *std.Io.Reader) !void { table_list[table_idx] = try reader.takeInt(u32, .big); } - const now_sec = std.time.timestamp(); - for (table_list) |table_offset| { reader.seek = db_header.schema_offset + table_offset; diff --git a/lib/std/debug/SelfInfo/MachO.zig b/lib/std/debug/SelfInfo/MachO.zig index a89a2f0fb5..8a0d9f0e1d 100644 --- a/lib/std/debug/SelfInfo/MachO.zig +++ b/lib/std/debug/SelfInfo/MachO.zig @@ -117,11 +117,14 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error error.ReadFailed, error.OutOfMemory, error.Unexpected, + error.Canceled, => |e| return e, + error.UnsupportedRegister, error.UnsupportedAddrSize, error.UnimplementedUserOpcode, => return error.UnsupportedDebugInfo, + error.Overflow, error.EndOfStream, error.StreamTooLong, diff --git a/lib/std/fs.zig b/lib/std/fs.zig index e03d426276..96aa962e67 100644 --- a/lib/std/fs.zig +++ b/lib/std/fs.zig @@ -458,6 +458,8 @@ pub const SelfExePathError = error{ /// On Windows, the volume does not contain a recognized file system. File /// system drivers might not be loaded, or the volume may be corrupt. UnrecognizedVolume, + + Canceled, } || posix.SysCtlError; /// `selfExePath` except allocates the result on the heap. diff --git a/lib/std/http/Client.zig b/lib/std/http/Client.zig index f05d6ff5b1..431f239db3 100644 --- a/lib/std/http/Client.zig +++ b/lib/std/http/Client.zig @@ -35,9 +35,11 @@ tls_buffer_size: if (disable_tls) u0 else usize = if (disable_tls) 0 else std.cr /// traffic over connections created with this `Client`. ssl_key_log: ?*std.crypto.tls.Client.SslKeyLog = null, -/// When this is `true`, the next time this client performs an HTTPS request, -/// it will first rescan the system for root certificates. -next_https_rescan_certs: bool = true, +/// The time used to decide whether certificates are expired. +/// +/// When this is `null`, the next time this client performs an HTTPS request, +/// it will first check the time and rescan the system for root certificates. +now: ?Io.Timestamp = null, /// The pool of connections that can be reused (and currently in use). connection_pool: ConnectionPool = .{}, @@ -295,6 +297,7 @@ pub const Connection = struct { client: std.crypto.tls.Client, connection: Connection, + /// Asserts that `client.now` is non-null. fn create( client: *Client, remote_host: HostName, @@ -320,7 +323,6 @@ pub const Connection = struct { const tls: *Tls = @ptrCast(base); var random_buffer: [176]u8 = undefined; std.crypto.random.bytes(&random_buffer); - const now_ts = if (Io.Clock.real.now(io)) |ts| ts.toSeconds() else |err| return err; tls.* = .{ .connection = .{ .client = client, @@ -333,7 +335,7 @@ pub const Connection = struct { .closing = false, .protocol = .tls, }, - // TODO data race here on ca_bundle if the user sets next_https_rescan_certs to true + // TODO data race here on ca_bundle if the user sets `now` to null .client = std.crypto.tls.Client.init( &tls.connection.stream_reader.interface, &tls.connection.stream_writer.interface, @@ -344,7 +346,7 @@ pub const Connection = struct { .read_buffer = tls_read_buffer, .write_buffer = socket_write_buffer, .entropy = &random_buffer, - .realtime_now_seconds = now_ts, + .realtime_now_seconds = client.now.?.toSeconds(), // This is appropriate for HTTPS because the HTTP headers contain // the content length which is used to detect truncation attacks. .allow_truncation_attacks = true, @@ -1687,14 +1689,15 @@ pub fn request( if (protocol == .tls) { if (disable_tls) unreachable; - if (@atomicLoad(bool, &client.next_https_rescan_certs, .acquire)) { + { client.ca_bundle_mutex.lock(); defer client.ca_bundle_mutex.unlock(); - if (client.next_https_rescan_certs) { - client.ca_bundle.rescan(client.allocator, io) catch + if (client.now == null) { + const now = try Io.Clock.real.now(io); + client.now = now; + client.ca_bundle.rescan(client.allocator, io, now) catch return error.CertificateBundleLoadFailure; - @atomicStore(bool, &client.next_https_rescan_certs, false, .release); } } } diff --git a/lib/std/http/Server.zig b/lib/std/http/Server.zig index b64253f975..084f2f5855 100644 --- a/lib/std/http/Server.zig +++ b/lib/std/http/Server.zig @@ -688,7 +688,7 @@ pub const WebSocket = struct { pub const ReadSmallTextMessageError = error{ ConnectionClose, UnexpectedOpCode, - MessageTooBig, + MessageOversize, MissingMaskBit, ReadFailed, EndOfStream, @@ -717,15 +717,15 @@ pub const WebSocket = struct { _ => return error.UnexpectedOpCode, } - if (!h0.fin) return error.MessageTooBig; + if (!h0.fin) return error.MessageOversize; if (!h1.mask) return error.MissingMaskBit; const len: usize = switch (h1.payload_len) { .len16 => try in.takeInt(u16, .big), - .len64 => std.math.cast(usize, try in.takeInt(u64, .big)) orelse return error.MessageTooBig, + .len64 => std.math.cast(usize, try in.takeInt(u64, .big)) orelse return error.MessageOversize, else => @intFromEnum(h1.payload_len), }; - if (len > in.buffer.len) return error.MessageTooBig; + if (len > in.buffer.len) return error.MessageOversize; const mask: u32 = @bitCast((try in.takeArray(4)).*); const payload = try in.take(len); diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 27b40fcd60..cbf49638a3 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1653,7 +1653,7 @@ pub fn WSASocketW( const rc = ws2_32.WSASocketW(af, socket_type, protocol, protocolInfo, g, dwFlags); if (rc == ws2_32.INVALID_SOCKET) { switch (ws2_32.WSAGetLastError()) { - .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported, .WSAEMFILE => return error.ProcessFdQuotaExceeded, .WSAENOBUFS => return error.SystemResources, .WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 8844a8249e..f62c8c9edd 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -1205,7 +1205,7 @@ pub const WriteError = error{ /// The socket type requires that message be sent atomically, and the size of the message /// to be sent made this impossible. The message is not transmitted. - MessageTooBig, + MessageOversize, } || UnexpectedError; /// Write to a file descriptor. @@ -1287,7 +1287,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { .CONNRESET => return error.ConnectionResetByPeer, .BUSY => return error.DeviceBusy, .NXIO => return error.NoDevice, - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, else => |err| return unexpectedErrno(err), } } @@ -3487,7 +3487,7 @@ pub const SocketError = error{ AccessDenied, /// The implementation does not support the specified address family. - AddressFamilyNotSupported, + AddressFamilyUnsupported, /// Unknown protocol, or protocol family not available. ProtocolFamilyNotAvailable, @@ -3553,7 +3553,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t return fd; }, .ACCES => return error.AccessDenied, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .INVAL => return error.ProtocolFamilyNotAvailable, .MFILE => return error.ProcessFdQuotaExceeded, .NFILE => return error.SystemFdQuotaExceeded, @@ -3593,7 +3593,7 @@ pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]s return socks; }, .ACCES => return error.AccessDenied, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .INVAL => return error.ProtocolFamilyNotAvailable, .MFILE => return error.ProcessFdQuotaExceeded, .NFILE => return error.SystemFdQuotaExceeded, @@ -3676,7 +3676,7 @@ pub const BindError = error{ AddressNotAvailable, /// The address is not valid for the address family of socket. - AddressFamilyNotSupported, + AddressFamilyUnsupported, /// Too many symbolic links were encountered in resolving addr. SymLinkLoop, @@ -3733,7 +3733,7 @@ pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!voi .BADF => unreachable, // always a race condition if this error is returned .INVAL => unreachable, // invalid parameters .NOTSOCK => unreachable, // invalid `sockfd` - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .ADDRNOTAVAIL => return error.AddressNotAvailable, .FAULT => unreachable, // invalid `addr` pointer .LOOP => return error.SymLinkLoop, @@ -4192,7 +4192,7 @@ pub const ConnectError = error{ AddressNotAvailable, /// The passed address didn't have the correct address family in its sa_family field. - AddressFamilyNotSupported, + AddressFamilyUnsupported, /// Insufficient entries in the routing cache. SystemResources, @@ -4247,7 +4247,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne .WSAEWOULDBLOCK => return error.WouldBlock, .WSAEACCES => unreachable, .WSAENOBUFS => return error.SystemResources, - .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported, else => |err| return windows.unexpectedWSAError(err), } return; @@ -4260,7 +4260,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne .PERM => return error.PermissionDenied, .ADDRINUSE => return error.AddressInUse, .ADDRNOTAVAIL => return error.AddressNotAvailable, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .AGAIN, .INPROGRESS => return error.WouldBlock, .ALREADY => return error.ConnectionPending, .BADF => unreachable, // sockfd is not a valid open file descriptor. @@ -4322,7 +4322,7 @@ pub fn getsockoptError(sockfd: fd_t) ConnectError!void { .PERM => return error.PermissionDenied, .ADDRINUSE => return error.AddressInUse, .ADDRNOTAVAIL => return error.AddressNotAvailable, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .AGAIN => return error.SystemResources, .ALREADY => return error.ConnectionPending, .BADF => unreachable, // sockfd is not a valid open file descriptor. @@ -6039,7 +6039,7 @@ pub const SendError = error{ /// The socket type requires that message be sent atomically, and the size of the message /// to be sent made this impossible. The message is not transmitted. - MessageTooBig, + MessageOversize, /// The output queue for a network interface was full. This generally indicates that the /// interface has stopped sending, but may be caused by transient congestion. (Normally, @@ -6066,7 +6066,7 @@ pub const SendError = error{ pub const SendMsgError = SendError || error{ /// The passed address didn't have the correct address family in its sa_family field. - AddressFamilyNotSupported, + AddressFamilyUnsupported, /// Returned when socket is AF.UNIX and the given path has a symlink loop. SymLinkLoop, @@ -6098,10 +6098,10 @@ pub fn sendmsg( .WSAEACCES => return error.AccessDenied, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAECONNRESET => return error.ConnectionResetByPeer, - .WSAEMSGSIZE => return error.MessageTooBig, + .WSAEMSGSIZE => return error.MessageOversize, .WSAENOBUFS => return error.SystemResources, .WSAENOTSOCK => return error.FileDescriptorNotASocket, - .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported, .WSAEDESTADDRREQ => unreachable, // A destination address is required. .WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. .WSAEHOSTUNREACH => return error.NetworkUnreachable, @@ -6133,13 +6133,13 @@ pub fn sendmsg( .INTR => continue, .INVAL => unreachable, // Invalid argument passed. .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, .NOBUFS => return error.SystemResources, .NOMEM => return error.SystemResources, .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .LOOP => return error.SymLinkLoop, .NAMETOOLONG => return error.NameTooLong, .NOENT => return error.FileNotFound, @@ -6178,7 +6178,7 @@ pub const SendToError = SendMsgError || error{ /// Otherwise, the address of the target is given by `dest_addr` with `addrlen` specifying its size. /// /// If the message is too long to pass atomically through the underlying protocol, -/// `SendError.MessageTooBig` is returned, and the message is not transmitted. +/// `SendError.MessageOversize` is returned, and the message is not transmitted. /// /// There is no indication of failure to deliver. /// @@ -6201,10 +6201,10 @@ pub fn sendto( .WSAEACCES => return error.AccessDenied, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAECONNRESET => return error.ConnectionResetByPeer, - .WSAEMSGSIZE => return error.MessageTooBig, + .WSAEMSGSIZE => return error.MessageOversize, .WSAENOBUFS => return error.SystemResources, .WSAENOTSOCK => return error.FileDescriptorNotASocket, - .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, + .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported, .WSAEDESTADDRREQ => unreachable, // A destination address is required. .WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. .WSAEHOSTUNREACH => return error.NetworkUnreachable, @@ -6238,13 +6238,13 @@ pub fn sendto( .INTR => continue, .INVAL => return error.UnreachableAddress, .ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, .NOBUFS => return error.SystemResources, .NOMEM => return error.SystemResources, .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. .PIPE => return error.BrokenPipe, - .AFNOSUPPORT => return error.AddressFamilyNotSupported, + .AFNOSUPPORT => return error.AddressFamilyUnsupported, .LOOP => return error.SymLinkLoop, .NAMETOOLONG => return error.NameTooLong, .NOENT => return error.FileNotFound, @@ -6284,7 +6284,7 @@ pub fn send( flags: u32, ) SendError!usize { return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) { - error.AddressFamilyNotSupported => unreachable, + error.AddressFamilyUnsupported => unreachable, error.SymLinkLoop => unreachable, error.NameTooLong => unreachable, error.FileNotFound => unreachable, @@ -6471,7 +6471,7 @@ pub const RecvFromError = error{ SocketNotBound, /// The UDP message was too big for the buffer and part of it has been discarded - MessageTooBig, + MessageOversize, /// The network subsystem has failed. NetworkDown, @@ -6504,7 +6504,7 @@ pub fn recvfrom( .WSANOTINITIALISED => unreachable, .WSAECONNRESET => return error.ConnectionResetByPeer, .WSAEINVAL => return error.SocketNotBound, - .WSAEMSGSIZE => return error.MessageTooBig, + .WSAEMSGSIZE => return error.MessageOversize, .WSAENETDOWN => return error.NetworkDown, .WSAENOTCONN => return error.SocketUnconnected, .WSAEWOULDBLOCK => return error.WouldBlock, @@ -6575,7 +6575,7 @@ pub fn recvmsg( .NOMEM => return error.SystemResources, .NOTCONN => return error.SocketUnconnected, .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. - .MSGSIZE => return error.MessageTooBig, + .MSGSIZE => return error.MessageOversize, .PIPE => return error.BrokenPipe, .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. .CONNRESET => return error.ConnectionResetByPeer,