std: fix macos compilation errors

This commit is contained in:
Andrew Kelley 2025-10-15 19:31:28 -07:00
parent f7d47aed47
commit 031044b399
12 changed files with 138 additions and 104 deletions

View File

@ -1469,7 +1469,7 @@ fn pwrite(userdata: ?*anyopaque, file: Io.File, buffer: []const u8, offset: std.
.OVERFLOW => return error.Unseekable, .OVERFLOW => return error.Unseekable,
.BUSY => return error.DeviceBusy, .BUSY => return error.DeviceBusy,
.CONNRESET => return error.ConnectionResetByPeer, .CONNRESET => return error.ConnectionResetByPeer,
.MSGSIZE => return error.MessageTooBig, .MSGSIZE => return error.MessageOversize,
else => |err| return std.posix.unexpectedErrno(err), else => |err| return std.posix.unexpectedErrno(err),
} }
} }

View File

@ -966,7 +966,7 @@ fn dirStatPathPosix(
try t.checkCancel(); try t.checkCancel();
var stat = std.mem.zeroes(posix.Stat); var stat = std.mem.zeroes(posix.Stat);
switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &stat, flags))) { switch (posix.errno(fstatat_sym(dir.handle, sub_path_posix, &stat, flags))) {
.SUCCESS => return statFromPosix(stat), .SUCCESS => return statFromPosix(&stat),
.INTR => continue, .INTR => continue,
.INVAL => |err| return errnoBug(err), .INVAL => |err| return errnoBug(err),
.BADF => |err| return errnoBug(err), // Always a race condition. .BADF => |err| return errnoBug(err), // Always a race condition.
@ -1166,8 +1166,9 @@ fn dirCreateFilePosix(
if (has_flock_open_flags and flags.lock_nonblocking) { if (has_flock_open_flags and flags.lock_nonblocking) {
var fl_flags: usize = while (true) { var fl_flags: usize = while (true) {
try t.checkCancel(); try t.checkCancel();
switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0));
.SUCCESS => break, switch (posix.errno(rc)) {
.SUCCESS => break @intCast(rc),
.INTR => continue, .INTR => continue,
else => |err| return posix.unexpectedErrno(err), else => |err| return posix.unexpectedErrno(err),
} }
@ -1295,8 +1296,9 @@ fn dirOpenFile(
if (has_flock_open_flags and flags.lock_nonblocking) { if (has_flock_open_flags and flags.lock_nonblocking) {
var fl_flags: usize = while (true) { var fl_flags: usize = while (true) {
try t.checkCancel(); try t.checkCancel();
switch (posix.errno(posix.system.fcntl(fd, posix.F.GETFL, 0))) { const rc = posix.system.fcntl(fd, posix.F.GETFL, @as(usize, 0));
.SUCCESS => break, switch (posix.errno(rc)) {
.SUCCESS => break @intCast(rc),
.INTR => continue, .INTR => continue,
else => |err| return posix.unexpectedErrno(err), 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), .sec = std.math.maxInt(sec_type),
.nsec = std.math.maxInt(nsec_type), .nsec = std.math.maxInt(nsec_type),
}; };
break :t timestampToPosix(d.duration.nanoseconds); break :t timestampToPosix(d.raw.toNanoseconds());
}; };
while (true) { while (true) {
try t.checkCancel(); try t.checkCancel();
@ -1850,6 +1852,7 @@ fn netListenUnix(
error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported, error.ProtocolUnsupportedBySystem => return error.AddressFamilyUnsupported,
error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported, error.ProtocolUnsupportedByAddressFamily => return error.AddressFamilyUnsupported,
error.SocketModeUnsupported => return error.AddressFamilyUnsupported, error.SocketModeUnsupported => return error.AddressFamilyUnsupported,
error.OptionUnsupported => return error.Unexpected,
else => |e| return e, else => |e| return e,
}; };
errdefer posix.close(socket_fd); errdefer posix.close(socket_fd);
@ -2037,7 +2040,10 @@ fn netConnectUnix(
) net.UnixAddress.ConnectError!net.Socket.Handle { ) net.UnixAddress.ConnectError!net.Socket.Handle {
if (!net.has_unix_sockets) return error.AddressFamilyUnsupported; if (!net.has_unix_sockets) return error.AddressFamilyUnsupported;
const t: *Threaded = @ptrCast(@alignCast(userdata)); 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); errdefer posix.close(socket_fd);
var storage: UnixAddress = undefined; var storage: UnixAddress = undefined;
const addr_len = addressUnixToPosix(address, &storage); 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 mode = posixSocketMode(options.mode);
const protocol = posixProtocol(options.protocol); const protocol = posixProtocol(options.protocol);
const socket_fd = while (true) { const socket_fd = while (true) {
@ -2209,7 +2230,7 @@ fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.
.NOTCONN => return error.SocketUnconnected, .NOTCONN => return error.SocketUnconnected,
.CONNRESET => return error.ConnectionResetByPeer, .CONNRESET => return error.ConnectionResetByPeer,
.TIMEDOUT => return error.Timeout, .TIMEDOUT => return error.Timeout,
.PIPE => return error.BrokenPipe, .PIPE => return error.SocketUnconnected,
.NETDOWN => return error.NetworkDown, .NETDOWN => return error.NetworkDown,
else => |err| return posix.unexpectedErrno(err), else => |err| return posix.unexpectedErrno(err),
} }
@ -2253,29 +2274,29 @@ fn netSendOne(
flags: u32, flags: u32,
) net.Socket.SendError!void { ) net.Socket.SendError!void {
var addr: PosixAddress = undefined; var addr: PosixAddress = undefined;
var iovec: posix.iovec = .{ .base = @constCast(message.data_ptr), .len = message.data_len }; var iovec: posix.iovec_const = .{ .base = @constCast(message.data_ptr), .len = message.data_len };
const msg: posix.msghdr = .{ const msg: posix.msghdr_const = .{
.name = &addr.any, .name = &addr.any,
.namelen = addressToPosix(message.address, &addr), .namelen = addressToPosix(message.address, &addr),
.iov = iovec[0..1], .iov = (&iovec)[0..1],
.iovlen = 1, .iovlen = 1,
.control = @constCast(message.control.ptr), .control = @constCast(message.control.ptr),
.controllen = message.control.len, .controllen = @intCast(message.control.len),
.flags = 0, .flags = 0,
}; };
while (true) { while (true) {
try t.checkCancel(); try t.checkCancel();
const rc = posix.system.sendmsg(handle, msg, flags); const rc = posix.system.sendmsg(handle, &msg, flags);
if (is_windows) { if (is_windows) {
if (rc == windows.ws2_32.SOCKET_ERROR) { if (rc == windows.ws2_32.SOCKET_ERROR) {
switch (windows.ws2_32.WSAGetLastError()) { switch (windows.ws2_32.WSAGetLastError()) {
.WSAEACCES => return error.AccessDenied, .WSAEACCES => return error.AccessDenied,
.WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable,
.WSAECONNRESET => return error.ConnectionResetByPeer, .WSAECONNRESET => return error.ConnectionResetByPeer,
.WSAEMSGSIZE => return error.MessageTooBig, .WSAEMSGSIZE => return error.MessageOversize,
.WSAENOBUFS => return error.SystemResources, .WSAENOBUFS => return error.SystemResources,
.WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAENOTSOCK => return error.FileDescriptorNotASocket,
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported,
.WSAEDESTADDRREQ => unreachable, // A destination address is required. .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. .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, .WSAEHOSTUNREACH => return error.NetworkUnreachable,
@ -2285,7 +2306,6 @@ fn netSendOne(
.WSAENETUNREACH => return error.NetworkUnreachable, .WSAENETUNREACH => return error.NetworkUnreachable,
.WSAENOTCONN => return error.SocketUnconnected, .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. .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. .WSANOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function.
else => |err| return windows.unexpectedWSAError(err), else => |err| return windows.unexpectedWSAError(err),
} }
@ -2299,28 +2319,24 @@ fn netSendOne(
message.data_len = @intCast(rc); message.data_len = @intCast(rc);
return; return;
}, },
.INTR => continue,
.ACCES => return error.AccessDenied, .ACCES => return error.AccessDenied,
.AGAIN => return error.WouldBlock,
.ALREADY => return error.FastOpenAlreadyInProgress, .ALREADY => return error.FastOpenAlreadyInProgress,
.BADF => |err| return errnoBug(err), .BADF => |err| return errnoBug(err),
.CONNRESET => return error.ConnectionResetByPeer, .CONNRESET => return error.ConnectionResetByPeer,
.DESTADDRREQ => |err| return errnoBug(err), .DESTADDRREQ => |err| return errnoBug(err),
.FAULT => |err| return errnoBug(err), .FAULT => |err| return errnoBug(err),
.INTR => continue,
.INVAL => |err| return errnoBug(err), .INVAL => |err| return errnoBug(err),
.ISCONN => |err| return errnoBug(err), .ISCONN => |err| return errnoBug(err),
.MSGSIZE => return error.MessageTooBig, .MSGSIZE => return error.MessageOversize,
.NOBUFS => return error.SystemResources, .NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources, .NOMEM => return error.SystemResources,
.NOTSOCK => |err| return errnoBug(err), .NOTSOCK => |err| return errnoBug(err),
.OPNOTSUPP => |err| return errnoBug(err), .OPNOTSUPP => |err| return errnoBug(err),
.PIPE => return error.BrokenPipe, .PIPE => return error.SocketUnconnected,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.LOOP => return error.SymLinkLoop, .HOSTUNREACH => return error.HostUnreachable,
.NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound,
.NOTDIR => return error.NotDir,
.HOSTUNREACH => return error.NetworkUnreachable,
.NETUNREACH => return error.NetworkUnreachable, .NETUNREACH => return error.NetworkUnreachable,
.NOTCONN => return error.SocketUnconnected, .NOTCONN => return error.SocketUnconnected,
.NETDOWN => return error.NetworkDown, .NETDOWN => return error.NetworkDown,
@ -2447,7 +2463,7 @@ fn netReceive(
.iov = (&iov)[0..1], .iov = (&iov)[0..1],
.iovlen = 1, .iovlen = 1,
.control = message.control.ptr, .control = message.control.ptr,
.controllen = message.control.len, .controllen = @intCast(message.control.len),
.flags = undefined, .flags = undefined,
}; };
@ -2465,7 +2481,7 @@ fn netReceive(
.trunc = (msg.flags & posix.MSG.TRUNC) != 0, .trunc = (msg.flags & posix.MSG.TRUNC) != 0,
.ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0, .ctrunc = (msg.flags & posix.MSG.CTRUNC) != 0,
.oob = (msg.flags & posix.MSG.OOB) != 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; message_i += 1;
@ -2605,6 +2621,7 @@ fn netInterfaceNameResolve(
error.ProtocolUnsupportedBySystem => return error.Unexpected, error.ProtocolUnsupportedBySystem => return error.Unexpected,
error.ProtocolUnsupportedByAddressFamily => return error.Unexpected, error.ProtocolUnsupportedByAddressFamily => return error.Unexpected,
error.SocketModeUnsupported => return error.Unexpected, error.SocketModeUnsupported => return error.Unexpected,
error.OptionUnsupported => return error.Unexpected,
else => |e| return e, else => |e| return e,
}; };
defer posix.close(sock_fd); 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; var any_ip6 = false;
for (rc.nameservers(), &ip4_mapped) |*ns, *m| { for (rc.nameservers(), ip4_mapped) |*ns, *m| {
m.* = .{ .ip6 = .fromAny(ns.*) }; m.* = .{ .ip6 = .fromAny(ns.*) };
any_ip6 = any_ip6 or ns.* == .ip6; any_ip6 = any_ip6 or ns.* == .ip6;
} }
@ -3101,7 +3119,7 @@ fn lookupDns(
}; };
defer socket.close(t_io); 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 queries = queries_buffer[0..nq];
const answers = answers_buffer[0..queries.len]; const answers = answers_buffer[0..queries.len];
var answers_remaining = answers.len; var answers_remaining = answers.len;

View File

@ -209,6 +209,9 @@ pub const IpAddress = union(enum) {
ProtocolUnsupportedBySystem, ProtocolUnsupportedBySystem,
ProtocolUnsupportedByAddressFamily, ProtocolUnsupportedByAddressFamily,
SocketModeUnsupported, SocketModeUnsupported,
/// One of the `ListenOptions` is not supported by the Io
/// implementation.
OptionUnsupported,
} || Io.UnexpectedError || Io.Cancelable; } || Io.UnexpectedError || Io.Cancelable;
pub const ListenOptions = struct { pub const ListenOptions = struct {
@ -1057,6 +1060,9 @@ pub const Socket = struct {
/// Local end has been shut down on a connection-oriented socket, or /// Local end has been shut down on a connection-oriented socket, or
/// the socket was never connected. /// the socket was never connected.
SocketUnconnected, SocketUnconnected,
/// An attempt was made to send to a network/broadcast address as
/// though it was a unicast address.
AccessDenied,
} || Io.UnexpectedError || Io.Cancelable; } || Io.UnexpectedError || Io.Cancelable;
/// Transfers `data` to `dest`, connectionless, in one packet. /// Transfers `data` to `dest`, connectionless, in one packet.
@ -1167,7 +1173,6 @@ pub const Stream = struct {
pub const Error = error{ pub const Error = error{
SystemResources, SystemResources,
BrokenPipe,
ConnectionResetByPeer, ConnectionResetByPeer,
Timeout, Timeout,
SocketUnconnected, SocketUnconnected,
@ -1233,7 +1238,7 @@ pub const Stream = struct {
pub const Error = std.posix.SendMsgError || error{ pub const Error = std.posix.SendMsgError || error{
ConnectionResetByPeer, ConnectionResetByPeer,
SocketNotBound, SocketNotBound,
MessageTooBig, MessageOversize,
NetworkDown, NetworkDown,
SystemResources, SystemResources,
SocketUnconnected, SocketUnconnected,

View File

@ -4104,7 +4104,7 @@ pub const msghdr = switch (native_os) {
.visionos, .visionos,
.watchos, .watchos,
.serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82 .serenity, // https://github.com/SerenityOS/serenity/blob/ac44ec5ebc707f9dd0c3d4759a1e17e91db5d74f/Kernel/API/POSIX/sys/socket.h#L74-L82
=> private.posix_msghdr, => posix_msghdr,
else => void, else => void,
}; };

View File

@ -70,18 +70,18 @@ pub const RescanError = RescanLinuxError || RescanMacError || RescanWithPathErro
/// file system standard locations for certificates. /// file system standard locations for certificates.
/// For operating systems that do not have standard CA installations to be /// For operating systems that do not have standard CA installations to be
/// found, this function clears the set of certificates. /// 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) { switch (builtin.os.tag) {
.linux => return rescanLinux(cb, gpa, io), .linux => return rescanLinux(cb, gpa, io, now),
.macos => return rescanMac(cb, gpa), .macos => return rescanMac(cb, gpa, io, now),
.freebsd, .openbsd => return rescanWithPath(cb, gpa, io, "/etc/ssl/cert.pem"), .freebsd, .openbsd => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/cert.pem"),
.netbsd => return rescanWithPath(cb, gpa, io, "/etc/openssl/certs/ca-certificates.crt"), .netbsd => return rescanWithPath(cb, gpa, io, now, "/etc/openssl/certs/ca-certificates.crt"),
.dragonfly => return rescanWithPath(cb, gpa, io, "/usr/local/etc/ssl/cert.pem"), .dragonfly => return rescanWithPath(cb, gpa, io, now, "/usr/local/etc/ssl/cert.pem"),
.illumos => return rescanWithPath(cb, gpa, io, "/etc/ssl/cacert.pem"), .illumos => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/cacert.pem"),
.haiku => return rescanWithPath(cb, gpa, io, "/boot/system/data/ssl/CARootCertificates.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 // 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"), .serenity => return rescanWithPath(cb, gpa, io, now, "/etc/ssl/certs/ca-certificates.crt"),
.windows => return rescanWindows(cb, gpa), .windows => return rescanWindows(cb, gpa, io, now),
else => {}, else => {},
} }
} }
@ -91,7 +91,7 @@ const RescanMacError = @import("Bundle/macos.zig").RescanMacError;
const RescanLinuxError = AddCertsFromFilePathError || AddCertsFromDirPathError; 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. // Possible certificate files; stop after finding one.
const cert_file_paths = [_][]const u8{ const cert_file_paths = [_][]const u8{
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. "/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: { scan: {
for (cert_file_paths) |cert_file_path| { 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; break :scan;
} else |err| switch (err) { } else |err| switch (err) {
error.FileNotFound => continue, error.FileNotFound => continue,
@ -123,7 +123,7 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void {
} }
for (cert_dir_paths) |cert_dir_path| { 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, error.FileNotFound => continue,
else => |e| return e, else => |e| return e,
}; };
@ -135,10 +135,10 @@ fn rescanLinux(cb: *Bundle, gpa: Allocator, io: Io) RescanLinuxError!void {
const RescanWithPathError = AddCertsFromFilePathError; 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.bytes.clearRetainingCapacity();
cb.map.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); cb.bytes.shrinkAndFree(gpa, cb.bytes.items.len);
} }
@ -187,17 +187,18 @@ pub fn addCertsFromDirPathAbsolute(
cb: *Bundle, cb: *Bundle,
gpa: Allocator, gpa: Allocator,
io: Io, io: Io,
now: Io.Timestamp,
abs_dir_path: []const u8, abs_dir_path: []const u8,
) AddCertsFromDirPathError!void { ) AddCertsFromDirPathError!void {
assert(fs.path.isAbsolute(abs_dir_path)); assert(fs.path.isAbsolute(abs_dir_path));
var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true }); var iterable_dir = try fs.openDirAbsolute(abs_dir_path, .{ .iterate = true });
defer iterable_dir.close(); defer iterable_dir.close();
return addCertsFromDir(cb, gpa, io, iterable_dir); return addCertsFromDir(cb, gpa, io, now, iterable_dir);
} }
pub const AddCertsFromDirError = AddCertsFromFilePathError; 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(); var it = iterable_dir.iterate();
while (try it.next()) |entry| { while (try it.next()) |entry| {
switch (entry.kind) { switch (entry.kind) {
@ -205,7 +206,7 @@ pub fn addCertsFromDir(cb: *Bundle, gpa: Allocator, io: Io, iterable_dir: fs.Dir
else => continue, 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, cb: *Bundle,
gpa: Allocator, gpa: Allocator,
io: Io, io: Io,
now: Io.Timestamp,
abs_file_path: []const u8, abs_file_path: []const u8,
) AddCertsFromFilePathError!void { ) AddCertsFromFilePathError!void {
const now = try Io.Clock.real.now(io);
var file = try fs.openFileAbsolute(abs_file_path, .{}); var file = try fs.openFileAbsolute(abs_file_path, .{});
defer file.close(); defer file.close();
var file_reader = file.reader(io, &.{}); var file_reader = file.reader(io, &.{});
@ -228,10 +229,10 @@ pub fn addCertsFromFilePath(
cb: *Bundle, cb: *Bundle,
gpa: Allocator, gpa: Allocator,
io: Io, io: Io,
now: Io.Timestamp,
dir: Io.Dir, dir: Io.Dir,
sub_file_path: []const u8, sub_file_path: []const u8,
) AddCertsFromFilePathError!void { ) AddCertsFromFilePathError!void {
const now = try Io.Clock.real.now(io);
var file = try dir.openFile(io, sub_file_path, .{}); var file = try dir.openFile(io, sub_file_path, .{});
defer file.close(io); defer file.close(io);
var file_reader = file.reader(io, &.{}); var file_reader = file.reader(io, &.{});
@ -335,5 +336,7 @@ test "scan for OS-provided certificates" {
var bundle: Bundle = .{}; var bundle: Bundle = .{};
defer bundle.deinit(gpa); defer bundle.deinit(gpa);
try bundle.rescan(gpa, io); const now = try Io.Clock.real.now(io);
try bundle.rescan(gpa, io, now);
} }

View File

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const Io = std.Io;
const assert = std.debug.assert; const assert = std.debug.assert;
const fs = std.fs; const fs = std.fs;
const mem = std.mem; 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 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.bytes.clearRetainingCapacity();
cb.map.clearRetainingCapacity(); cb.map.clearRetainingCapacity();
@ -16,6 +17,7 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {
"/Library/Keychains/System.keychain", "/Library/Keychains/System.keychain",
}; };
_ = io; // TODO migrate file system to use std.Io
for (keychain_paths) |keychain_path| { for (keychain_paths) |keychain_path| {
const bytes = std.fs.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) { const bytes = std.fs.cwd().readFileAlloc(keychain_path, gpa, .limited(std.math.maxInt(u32))) catch |err| switch (err) {
error.StreamTooLong => return error.FileTooBig, error.StreamTooLong => return error.FileTooBig,
@ -23,8 +25,8 @@ pub fn rescanMac(cb: *Bundle, gpa: Allocator) RescanMacError!void {
}; };
defer gpa.free(bytes); defer gpa.free(bytes);
var reader: std.Io.Reader = .fixed(bytes); var reader: Io.Reader = .fixed(bytes);
scanReader(cb, gpa, &reader) catch |err| switch (err) { scanReader(cb, gpa, &reader, now.toSeconds()) catch |err| switch (err) {
error.ReadFailed => unreachable, // prebuffered error.ReadFailed => unreachable, // prebuffered
else => |e| return e, 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); 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); const db_header = try reader.takeStruct(ApplDbHeader, .big);
assert(mem.eql(u8, &db_header.signature, "kych")); 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); table_list[table_idx] = try reader.takeInt(u32, .big);
} }
const now_sec = std.time.timestamp();
for (table_list) |table_offset| { for (table_list) |table_offset| {
reader.seek = db_header.schema_offset + table_offset; reader.seek = db_header.schema_offset + table_offset;

View File

@ -117,11 +117,14 @@ pub fn unwindFrame(si: *SelfInfo, gpa: Allocator, context: *UnwindContext) Error
error.ReadFailed, error.ReadFailed,
error.OutOfMemory, error.OutOfMemory,
error.Unexpected, error.Unexpected,
error.Canceled,
=> |e| return e, => |e| return e,
error.UnsupportedRegister, error.UnsupportedRegister,
error.UnsupportedAddrSize, error.UnsupportedAddrSize,
error.UnimplementedUserOpcode, error.UnimplementedUserOpcode,
=> return error.UnsupportedDebugInfo, => return error.UnsupportedDebugInfo,
error.Overflow, error.Overflow,
error.EndOfStream, error.EndOfStream,
error.StreamTooLong, error.StreamTooLong,

View File

@ -458,6 +458,8 @@ pub const SelfExePathError = error{
/// On Windows, the volume does not contain a recognized file system. File /// On Windows, the volume does not contain a recognized file system. File
/// system drivers might not be loaded, or the volume may be corrupt. /// system drivers might not be loaded, or the volume may be corrupt.
UnrecognizedVolume, UnrecognizedVolume,
Canceled,
} || posix.SysCtlError; } || posix.SysCtlError;
/// `selfExePath` except allocates the result on the heap. /// `selfExePath` except allocates the result on the heap.

View File

@ -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`. /// traffic over connections created with this `Client`.
ssl_key_log: ?*std.crypto.tls.Client.SslKeyLog = null, ssl_key_log: ?*std.crypto.tls.Client.SslKeyLog = null,
/// When this is `true`, the next time this client performs an HTTPS request, /// The time used to decide whether certificates are expired.
/// it will first rescan the system for root certificates. ///
next_https_rescan_certs: bool = true, /// 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). /// The pool of connections that can be reused (and currently in use).
connection_pool: ConnectionPool = .{}, connection_pool: ConnectionPool = .{},
@ -295,6 +297,7 @@ pub const Connection = struct {
client: std.crypto.tls.Client, client: std.crypto.tls.Client,
connection: Connection, connection: Connection,
/// Asserts that `client.now` is non-null.
fn create( fn create(
client: *Client, client: *Client,
remote_host: HostName, remote_host: HostName,
@ -320,7 +323,6 @@ pub const Connection = struct {
const tls: *Tls = @ptrCast(base); const tls: *Tls = @ptrCast(base);
var random_buffer: [176]u8 = undefined; var random_buffer: [176]u8 = undefined;
std.crypto.random.bytes(&random_buffer); std.crypto.random.bytes(&random_buffer);
const now_ts = if (Io.Clock.real.now(io)) |ts| ts.toSeconds() else |err| return err;
tls.* = .{ tls.* = .{
.connection = .{ .connection = .{
.client = client, .client = client,
@ -333,7 +335,7 @@ pub const Connection = struct {
.closing = false, .closing = false,
.protocol = .tls, .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( .client = std.crypto.tls.Client.init(
&tls.connection.stream_reader.interface, &tls.connection.stream_reader.interface,
&tls.connection.stream_writer.interface, &tls.connection.stream_writer.interface,
@ -344,7 +346,7 @@ pub const Connection = struct {
.read_buffer = tls_read_buffer, .read_buffer = tls_read_buffer,
.write_buffer = socket_write_buffer, .write_buffer = socket_write_buffer,
.entropy = &random_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 // This is appropriate for HTTPS because the HTTP headers contain
// the content length which is used to detect truncation attacks. // the content length which is used to detect truncation attacks.
.allow_truncation_attacks = true, .allow_truncation_attacks = true,
@ -1687,14 +1689,15 @@ pub fn request(
if (protocol == .tls) { if (protocol == .tls) {
if (disable_tls) unreachable; if (disable_tls) unreachable;
if (@atomicLoad(bool, &client.next_https_rescan_certs, .acquire)) { {
client.ca_bundle_mutex.lock(); client.ca_bundle_mutex.lock();
defer client.ca_bundle_mutex.unlock(); defer client.ca_bundle_mutex.unlock();
if (client.next_https_rescan_certs) { if (client.now == null) {
client.ca_bundle.rescan(client.allocator, io) catch const now = try Io.Clock.real.now(io);
client.now = now;
client.ca_bundle.rescan(client.allocator, io, now) catch
return error.CertificateBundleLoadFailure; return error.CertificateBundleLoadFailure;
@atomicStore(bool, &client.next_https_rescan_certs, false, .release);
} }
} }
} }

View File

@ -688,7 +688,7 @@ pub const WebSocket = struct {
pub const ReadSmallTextMessageError = error{ pub const ReadSmallTextMessageError = error{
ConnectionClose, ConnectionClose,
UnexpectedOpCode, UnexpectedOpCode,
MessageTooBig, MessageOversize,
MissingMaskBit, MissingMaskBit,
ReadFailed, ReadFailed,
EndOfStream, EndOfStream,
@ -717,15 +717,15 @@ pub const WebSocket = struct {
_ => return error.UnexpectedOpCode, _ => return error.UnexpectedOpCode,
} }
if (!h0.fin) return error.MessageTooBig; if (!h0.fin) return error.MessageOversize;
if (!h1.mask) return error.MissingMaskBit; if (!h1.mask) return error.MissingMaskBit;
const len: usize = switch (h1.payload_len) { const len: usize = switch (h1.payload_len) {
.len16 => try in.takeInt(u16, .big), .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), 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 mask: u32 = @bitCast((try in.takeArray(4)).*);
const payload = try in.take(len); const payload = try in.take(len);

View File

@ -1653,7 +1653,7 @@ pub fn WSASocketW(
const rc = ws2_32.WSASocketW(af, socket_type, protocol, protocolInfo, g, dwFlags); const rc = ws2_32.WSASocketW(af, socket_type, protocol, protocolInfo, g, dwFlags);
if (rc == ws2_32.INVALID_SOCKET) { if (rc == ws2_32.INVALID_SOCKET) {
switch (ws2_32.WSAGetLastError()) { switch (ws2_32.WSAGetLastError()) {
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported,
.WSAEMFILE => return error.ProcessFdQuotaExceeded, .WSAEMFILE => return error.ProcessFdQuotaExceeded,
.WSAENOBUFS => return error.SystemResources, .WSAENOBUFS => return error.SystemResources,
.WSAEPROTONOSUPPORT => return error.ProtocolNotSupported, .WSAEPROTONOSUPPORT => return error.ProtocolNotSupported,

View File

@ -1205,7 +1205,7 @@ pub const WriteError = error{
/// The socket type requires that message be sent atomically, and the size of the message /// 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. /// to be sent made this impossible. The message is not transmitted.
MessageTooBig, MessageOversize,
} || UnexpectedError; } || UnexpectedError;
/// Write to a file descriptor. /// Write to a file descriptor.
@ -1287,7 +1287,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
.CONNRESET => return error.ConnectionResetByPeer, .CONNRESET => return error.ConnectionResetByPeer,
.BUSY => return error.DeviceBusy, .BUSY => return error.DeviceBusy,
.NXIO => return error.NoDevice, .NXIO => return error.NoDevice,
.MSGSIZE => return error.MessageTooBig, .MSGSIZE => return error.MessageOversize,
else => |err| return unexpectedErrno(err), else => |err| return unexpectedErrno(err),
} }
} }
@ -3487,7 +3487,7 @@ pub const SocketError = error{
AccessDenied, AccessDenied,
/// The implementation does not support the specified address family. /// The implementation does not support the specified address family.
AddressFamilyNotSupported, AddressFamilyUnsupported,
/// Unknown protocol, or protocol family not available. /// Unknown protocol, or protocol family not available.
ProtocolFamilyNotAvailable, ProtocolFamilyNotAvailable,
@ -3553,7 +3553,7 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
return fd; return fd;
}, },
.ACCES => return error.AccessDenied, .ACCES => return error.AccessDenied,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.INVAL => return error.ProtocolFamilyNotAvailable, .INVAL => return error.ProtocolFamilyNotAvailable,
.MFILE => return error.ProcessFdQuotaExceeded, .MFILE => return error.ProcessFdQuotaExceeded,
.NFILE => return error.SystemFdQuotaExceeded, .NFILE => return error.SystemFdQuotaExceeded,
@ -3593,7 +3593,7 @@ pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]s
return socks; return socks;
}, },
.ACCES => return error.AccessDenied, .ACCES => return error.AccessDenied,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.INVAL => return error.ProtocolFamilyNotAvailable, .INVAL => return error.ProtocolFamilyNotAvailable,
.MFILE => return error.ProcessFdQuotaExceeded, .MFILE => return error.ProcessFdQuotaExceeded,
.NFILE => return error.SystemFdQuotaExceeded, .NFILE => return error.SystemFdQuotaExceeded,
@ -3676,7 +3676,7 @@ pub const BindError = error{
AddressNotAvailable, AddressNotAvailable,
/// The address is not valid for the address family of socket. /// The address is not valid for the address family of socket.
AddressFamilyNotSupported, AddressFamilyUnsupported,
/// Too many symbolic links were encountered in resolving addr. /// Too many symbolic links were encountered in resolving addr.
SymLinkLoop, 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 .BADF => unreachable, // always a race condition if this error is returned
.INVAL => unreachable, // invalid parameters .INVAL => unreachable, // invalid parameters
.NOTSOCK => unreachable, // invalid `sockfd` .NOTSOCK => unreachable, // invalid `sockfd`
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.ADDRNOTAVAIL => return error.AddressNotAvailable, .ADDRNOTAVAIL => return error.AddressNotAvailable,
.FAULT => unreachable, // invalid `addr` pointer .FAULT => unreachable, // invalid `addr` pointer
.LOOP => return error.SymLinkLoop, .LOOP => return error.SymLinkLoop,
@ -4192,7 +4192,7 @@ pub const ConnectError = error{
AddressNotAvailable, AddressNotAvailable,
/// The passed address didn't have the correct address family in its sa_family field. /// The passed address didn't have the correct address family in its sa_family field.
AddressFamilyNotSupported, AddressFamilyUnsupported,
/// Insufficient entries in the routing cache. /// Insufficient entries in the routing cache.
SystemResources, SystemResources,
@ -4247,7 +4247,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne
.WSAEWOULDBLOCK => return error.WouldBlock, .WSAEWOULDBLOCK => return error.WouldBlock,
.WSAEACCES => unreachable, .WSAEACCES => unreachable,
.WSAENOBUFS => return error.SystemResources, .WSAENOBUFS => return error.SystemResources,
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported,
else => |err| return windows.unexpectedWSAError(err), else => |err| return windows.unexpectedWSAError(err),
} }
return; return;
@ -4260,7 +4260,7 @@ pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) Conne
.PERM => return error.PermissionDenied, .PERM => return error.PermissionDenied,
.ADDRINUSE => return error.AddressInUse, .ADDRINUSE => return error.AddressInUse,
.ADDRNOTAVAIL => return error.AddressNotAvailable, .ADDRNOTAVAIL => return error.AddressNotAvailable,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.AGAIN, .INPROGRESS => return error.WouldBlock, .AGAIN, .INPROGRESS => return error.WouldBlock,
.ALREADY => return error.ConnectionPending, .ALREADY => return error.ConnectionPending,
.BADF => unreachable, // sockfd is not a valid open file descriptor. .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, .PERM => return error.PermissionDenied,
.ADDRINUSE => return error.AddressInUse, .ADDRINUSE => return error.AddressInUse,
.ADDRNOTAVAIL => return error.AddressNotAvailable, .ADDRNOTAVAIL => return error.AddressNotAvailable,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.AGAIN => return error.SystemResources, .AGAIN => return error.SystemResources,
.ALREADY => return error.ConnectionPending, .ALREADY => return error.ConnectionPending,
.BADF => unreachable, // sockfd is not a valid open file descriptor. .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 /// 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. /// 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 /// 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, /// 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{ pub const SendMsgError = SendError || error{
/// The passed address didn't have the correct address family in its sa_family field. /// 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. /// Returned when socket is AF.UNIX and the given path has a symlink loop.
SymLinkLoop, SymLinkLoop,
@ -6098,10 +6098,10 @@ pub fn sendmsg(
.WSAEACCES => return error.AccessDenied, .WSAEACCES => return error.AccessDenied,
.WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable,
.WSAECONNRESET => return error.ConnectionResetByPeer, .WSAECONNRESET => return error.ConnectionResetByPeer,
.WSAEMSGSIZE => return error.MessageTooBig, .WSAEMSGSIZE => return error.MessageOversize,
.WSAENOBUFS => return error.SystemResources, .WSAENOBUFS => return error.SystemResources,
.WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAENOTSOCK => return error.FileDescriptorNotASocket,
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported,
.WSAEDESTADDRREQ => unreachable, // A destination address is required. .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. .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, .WSAEHOSTUNREACH => return error.NetworkUnreachable,
@ -6133,13 +6133,13 @@ pub fn sendmsg(
.INTR => continue, .INTR => continue,
.INVAL => unreachable, // Invalid argument passed. .INVAL => unreachable, // Invalid argument passed.
.ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified .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, .NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources, .NOMEM => return error.SystemResources,
.NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. .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. .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
.PIPE => return error.BrokenPipe, .PIPE => return error.BrokenPipe,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.LOOP => return error.SymLinkLoop, .LOOP => return error.SymLinkLoop,
.NAMETOOLONG => return error.NameTooLong, .NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound, .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. /// 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, /// 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. /// There is no indication of failure to deliver.
/// ///
@ -6201,10 +6201,10 @@ pub fn sendto(
.WSAEACCES => return error.AccessDenied, .WSAEACCES => return error.AccessDenied,
.WSAEADDRNOTAVAIL => return error.AddressNotAvailable, .WSAEADDRNOTAVAIL => return error.AddressNotAvailable,
.WSAECONNRESET => return error.ConnectionResetByPeer, .WSAECONNRESET => return error.ConnectionResetByPeer,
.WSAEMSGSIZE => return error.MessageTooBig, .WSAEMSGSIZE => return error.MessageOversize,
.WSAENOBUFS => return error.SystemResources, .WSAENOBUFS => return error.SystemResources,
.WSAENOTSOCK => return error.FileDescriptorNotASocket, .WSAENOTSOCK => return error.FileDescriptorNotASocket,
.WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, .WSAEAFNOSUPPORT => return error.AddressFamilyUnsupported,
.WSAEDESTADDRREQ => unreachable, // A destination address is required. .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. .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, .WSAEHOSTUNREACH => return error.NetworkUnreachable,
@ -6238,13 +6238,13 @@ pub fn sendto(
.INTR => continue, .INTR => continue,
.INVAL => return error.UnreachableAddress, .INVAL => return error.UnreachableAddress,
.ISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified .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, .NOBUFS => return error.SystemResources,
.NOMEM => return error.SystemResources, .NOMEM => return error.SystemResources,
.NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. .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. .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
.PIPE => return error.BrokenPipe, .PIPE => return error.BrokenPipe,
.AFNOSUPPORT => return error.AddressFamilyNotSupported, .AFNOSUPPORT => return error.AddressFamilyUnsupported,
.LOOP => return error.SymLinkLoop, .LOOP => return error.SymLinkLoop,
.NAMETOOLONG => return error.NameTooLong, .NAMETOOLONG => return error.NameTooLong,
.NOENT => return error.FileNotFound, .NOENT => return error.FileNotFound,
@ -6284,7 +6284,7 @@ pub fn send(
flags: u32, flags: u32,
) SendError!usize { ) SendError!usize {
return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) { return sendto(sockfd, buf, flags, null, 0) catch |err| switch (err) {
error.AddressFamilyNotSupported => unreachable, error.AddressFamilyUnsupported => unreachable,
error.SymLinkLoop => unreachable, error.SymLinkLoop => unreachable,
error.NameTooLong => unreachable, error.NameTooLong => unreachable,
error.FileNotFound => unreachable, error.FileNotFound => unreachable,
@ -6471,7 +6471,7 @@ pub const RecvFromError = error{
SocketNotBound, SocketNotBound,
/// The UDP message was too big for the buffer and part of it has been discarded /// The UDP message was too big for the buffer and part of it has been discarded
MessageTooBig, MessageOversize,
/// The network subsystem has failed. /// The network subsystem has failed.
NetworkDown, NetworkDown,
@ -6504,7 +6504,7 @@ pub fn recvfrom(
.WSANOTINITIALISED => unreachable, .WSANOTINITIALISED => unreachable,
.WSAECONNRESET => return error.ConnectionResetByPeer, .WSAECONNRESET => return error.ConnectionResetByPeer,
.WSAEINVAL => return error.SocketNotBound, .WSAEINVAL => return error.SocketNotBound,
.WSAEMSGSIZE => return error.MessageTooBig, .WSAEMSGSIZE => return error.MessageOversize,
.WSAENETDOWN => return error.NetworkDown, .WSAENETDOWN => return error.NetworkDown,
.WSAENOTCONN => return error.SocketUnconnected, .WSAENOTCONN => return error.SocketUnconnected,
.WSAEWOULDBLOCK => return error.WouldBlock, .WSAEWOULDBLOCK => return error.WouldBlock,
@ -6575,7 +6575,7 @@ pub fn recvmsg(
.NOMEM => return error.SystemResources, .NOMEM => return error.SystemResources,
.NOTCONN => return error.SocketUnconnected, .NOTCONN => return error.SocketUnconnected,
.NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
.MSGSIZE => return error.MessageTooBig, .MSGSIZE => return error.MessageOversize,
.PIPE => return error.BrokenPipe, .PIPE => return error.BrokenPipe,
.OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. .OPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
.CONNRESET => return error.ConnectionResetByPeer, .CONNRESET => return error.ConnectionResetByPeer,