authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 14:30:25+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-30 14:30:25+01:00
logaa38f07c5173f9722ebfb933058a2a032c2badf3
treebc76f81dda9c9031cafa963e8fc723b6e41ce688
parentb9819fce69e0f208e9e20071071a40863fbdb8a9
parent6a3226c43cd63fd331c3f4340d4331a8875138e3

Merge pull request 'add `std.Io.net.Socket.createPair` + handful of `std.posix` removals' (#31056) from std.posix-removals into master

Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31056

10 files changed, 221 insertions(+), 466 deletions(-)

lib/std/Io.zig+1
...@@ -688,6 +688,7 @@ pub const VTable = struct {...@@ -688,6 +688,7 @@ pub const VTable = struct {
688 netConnectIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream,688 netConnectIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream,
689 netListenUnix: *const fn (?*anyopaque, *const net.UnixAddress, net.UnixAddress.ListenOptions) net.UnixAddress.ListenError!net.Socket.Handle,689 netListenUnix: *const fn (?*anyopaque, *const net.UnixAddress, net.UnixAddress.ListenOptions) net.UnixAddress.ListenError!net.Socket.Handle,
690 netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle,690 netConnectUnix: *const fn (?*anyopaque, *const net.UnixAddress) net.UnixAddress.ConnectError!net.Socket.Handle,
691 netSocketCreatePair: *const fn (?*anyopaque, net.Socket.CreatePairOptions) net.Socket.CreatePairError![2]net.Socket,
691 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },692 netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize },
692 netReceive: *const fn (?*anyopaque, net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, net.ReceiveFlags, Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize },693 netReceive: *const fn (?*anyopaque, net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, net.ReceiveFlags, Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize },
693 /// Returns 0 on end of stream.694 /// Returns 0 on end of stream.
lib/std/Io/Threaded.zig+127-79
...@@ -1684,6 +1684,7 @@ pub fn io(t: *Threaded) Io {...@@ -1684,6 +1684,7 @@ pub fn io(t: *Threaded) Io {
1684 .windows => netConnectUnixWindows,1684 .windows => netConnectUnixWindows,
1685 else => netConnectUnixPosix,1685 else => netConnectUnixPosix,
1686 },1686 },
1687 .netSocketCreatePair = netSocketCreatePair,
1687 .netClose = netClose,1688 .netClose = netClose,
1688 .netShutdown = switch (native_os) {1689 .netShutdown = switch (native_os) {
1689 .windows => netShutdownWindows,1690 .windows => netShutdownWindows,
...@@ -1824,6 +1825,7 @@ pub fn ioBasic(t: *Threaded) Io {...@@ -1824,6 +1825,7 @@ pub fn ioBasic(t: *Threaded) Io {
1824 .netAccept = netAcceptUnavailable,1825 .netAccept = netAcceptUnavailable,
1825 .netBindIp = netBindIpUnavailable,1826 .netBindIp = netBindIpUnavailable,
1826 .netConnectIp = netConnectIpUnavailable,1827 .netConnectIp = netConnectIpUnavailable,
1828 .netSocketCreatePair = netSocketCreatePairUnavailable,
1827 .netConnectUnix = netConnectUnixUnavailable,1829 .netConnectUnix = netConnectUnixUnavailable,
1828 .netClose = netCloseUnavailable,1830 .netClose = netCloseUnavailable,
1829 .netShutdown = netShutdownUnavailable,1831 .netShutdown = netShutdownUnavailable,
...@@ -10612,43 +10614,36 @@ fn posixConnect(...@@ -10612,43 +10614,36 @@ fn posixConnect(
10612 addr_len: posix.socklen_t,10614 addr_len: posix.socklen_t,
10613) !void {10615) !void {
10614 const syscall: Syscall = try .start();10616 const syscall: Syscall = try .start();
10615 while (true) {10617 while (true) switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) {
10616 switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) {10618 .SUCCESS => {
10617 .SUCCESS => {10619 syscall.finish();
10618 syscall.finish();10620 return;
10619 return;10621 },
10620 },10622 .INTR => {
10621 .INTR => {10623 try syscall.checkCancel();
10622 try syscall.checkCancel();10624 continue;
10623 continue;10625 },
10624 },10626 .ADDRNOTAVAIL => return syscall.fail(error.AddressUnavailable),
10625 else => |e| {10627 .AFNOSUPPORT => return syscall.fail(error.AddressFamilyUnsupported),
10626 syscall.finish();10628 .AGAIN, .INPROGRESS => return syscall.fail(error.WouldBlock),
10627 switch (e) {10629 .ALREADY => return syscall.fail(error.ConnectionPending),
10628 .ADDRNOTAVAIL => return error.AddressUnavailable,10630 .CONNREFUSED => return syscall.fail(error.ConnectionRefused),
10629 .AFNOSUPPORT => return error.AddressFamilyUnsupported,10631 .CONNRESET => return syscall.fail(error.ConnectionResetByPeer),
10630 .AGAIN, .INPROGRESS => return error.WouldBlock,10632 .HOSTUNREACH => return syscall.fail(error.HostUnreachable),
10631 .ALREADY => return error.ConnectionPending,10633 .NETUNREACH => return syscall.fail(error.NetworkUnreachable),
10632 .BADF => |err| return errnoBug(err), // File descriptor used after closed.10634 .TIMEDOUT => return syscall.fail(error.Timeout),
10633 .CONNREFUSED => return error.ConnectionRefused,10635 .ACCES => return syscall.fail(error.AccessDenied),
10634 .CONNRESET => return error.ConnectionResetByPeer,10636 .NETDOWN => return syscall.fail(error.NetworkDown),
10635 .FAULT => |err| return errnoBug(err),10637 .BADF => |err| return syscall.errnoBug(err), // File descriptor used after closed.
10636 .ISCONN => |err| return errnoBug(err),10638 .CONNABORTED => |err| return syscall.errnoBug(err),
10637 .HOSTUNREACH => return error.HostUnreachable,10639 .FAULT => |err| return syscall.errnoBug(err),
10638 .NETUNREACH => return error.NetworkUnreachable,10640 .ISCONN => |err| return syscall.errnoBug(err),
10639 .NOTSOCK => |err| return errnoBug(err),10641 .NOENT => |err| return syscall.errnoBug(err),
10640 .PROTOTYPE => |err| return errnoBug(err),10642 .NOTSOCK => |err| return syscall.errnoBug(err),
10641 .TIMEDOUT => return error.Timeout,10643 .PERM => |err| return syscall.errnoBug(err),
10642 .CONNABORTED => |err| return errnoBug(err),10644 .PROTOTYPE => |err| return syscall.errnoBug(err),
10643 .ACCES => return error.AccessDenied,10645 else => |err| return syscall.unexpectedErrno(err),
10644 .PERM => |err| return errnoBug(err),10646 };
10645 .NOENT => |err| return errnoBug(err),
10646 .NETDOWN => return error.NetworkDown,
10647 else => |err| return posix.unexpectedErrno(err),
10648 }
10649 },
10650 }
10651 }
10652}10647}
1065310648
10654fn posixConnectUnix(10649fn posixConnectUnix(
...@@ -11106,46 +11101,31 @@ fn openSocketPosix(...@@ -11106,46 +11101,31 @@ fn openSocketPosix(
11106}!posix.socket_t {11101}!posix.socket_t {
11107 const mode = posixSocketMode(options.mode);11102 const mode = posixSocketMode(options.mode);
11108 const protocol = posixProtocol(options.protocol);11103 const protocol = posixProtocol(options.protocol);
11104 const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC;
11109 const syscall: Syscall = try .start();11105 const syscall: Syscall = try .start();
11110 const socket_fd = while (true) {11106 const socket_fd = while (true) {
11111 const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC;11107 const rc = posix.system.socket(family, flags, protocol);
11112 const socket_rc = posix.system.socket(family, flags, protocol);11108 switch (posix.errno(rc)) {
11113 switch (posix.errno(socket_rc)) {
11114 .SUCCESS => {11109 .SUCCESS => {
11115 const fd: posix.fd_t = @intCast(socket_rc);
11116 errdefer posix.close(fd);
11117 if (socket_flags_unsupported) while (true) {
11118 try syscall.checkCancel();
11119 switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) {
11120 .SUCCESS => break,
11121 .INTR => continue,
11122 else => |err| {
11123 syscall.finish();
11124 return posix.unexpectedErrno(err);
11125 },
11126 }
11127 };
11128 syscall.finish();11110 syscall.finish();
11111 const fd: posix.fd_t = @intCast(rc);
11112 errdefer posix.close(fd);
11113 if (socket_flags_unsupported) try setCloexec(fd);
11129 break fd;11114 break fd;
11130 },11115 },
11131 .INTR => {11116 .INTR => {
11132 try syscall.checkCancel();11117 try syscall.checkCancel();
11133 continue;11118 continue;
11134 },11119 },
11135 else => |e| {11120 .AFNOSUPPORT => return syscall.fail(error.AddressFamilyUnsupported),
11136 syscall.finish();11121 .INVAL => return syscall.fail(error.ProtocolUnsupportedBySystem),
11137 switch (e) {11122 .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded),
11138 .AFNOSUPPORT => return error.AddressFamilyUnsupported,11123 .NFILE => return syscall.fail(error.SystemFdQuotaExceeded),
11139 .INVAL => return error.ProtocolUnsupportedBySystem,11124 .NOBUFS => return syscall.fail(error.SystemResources),
11140 .MFILE => return error.ProcessFdQuotaExceeded,11125 .NOMEM => return syscall.fail(error.SystemResources),
11141 .NFILE => return error.SystemFdQuotaExceeded,11126 .PROTONOSUPPORT => return syscall.fail(error.ProtocolUnsupportedByAddressFamily),
11142 .NOBUFS => return error.SystemResources,11127 .PROTOTYPE => return syscall.fail(error.SocketModeUnsupported),
11143 .NOMEM => return error.SystemResources,11128 else => |err| return syscall.unexpectedErrno(err),
11144 .PROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily,
11145 .PROTOTYPE => return error.SocketModeUnsupported,
11146 else => |err| return posix.unexpectedErrno(err),
11147 }
11148 },
11149 }11129 }
11150 };11130 };
11151 errdefer posix.close(socket_fd);11131 errdefer posix.close(socket_fd);
...@@ -11158,6 +11138,84 @@ fn openSocketPosix(...@@ -11158,6 +11138,84 @@ fn openSocketPosix(
11158 return socket_fd;11138 return socket_fd;
11159}11139}
1116011140
11141fn setCloexec(fd: posix.fd_t) error{ Canceled, Unexpected }!void {
11142 const syscall: Syscall = try .start();
11143 while (true) switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) {
11144 .SUCCESS => return syscall.finish(),
11145 .INTR => {
11146 try syscall.checkCancel();
11147 continue;
11148 },
11149 else => |err| return syscall.unexpectedErrno(err),
11150 };
11151}
11152
11153fn netSocketCreatePair(
11154 userdata: ?*anyopaque,
11155 options: net.Socket.CreatePairOptions,
11156) net.Socket.CreatePairError![2]net.Socket {
11157 const t: *Threaded = @ptrCast(@alignCast(userdata));
11158 _ = t;
11159 if (!have_networking) return error.OperationUnsupported;
11160 if (@TypeOf(posix.system.socketpair) == void) return error.OperationUnsupported;
11161 if (native_os == .haiku) @panic("TODO");
11162
11163 const family: posix.sa_family_t = switch (options.family) {
11164 .ip4 => posix.AF.INET,
11165 .ip6 => posix.AF.INET6,
11166 };
11167 const mode = posixSocketMode(options.mode);
11168 const protocol = posixProtocol(options.protocol);
11169 const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC;
11170
11171 var sockets: [2]posix.socket_t = undefined;
11172 const syscall: Syscall = try .start();
11173 while (true) switch (posix.errno(posix.system.socketpair(family, flags, protocol, &sockets))) {
11174 .SUCCESS => {
11175 syscall.finish();
11176 errdefer {
11177 posix.close(sockets[0]);
11178 posix.close(sockets[1]);
11179 }
11180 if (socket_flags_unsupported) {
11181 try setCloexec(sockets[0]);
11182 try setCloexec(sockets[1]);
11183 }
11184 var storages: [2]PosixAddress = undefined;
11185 var addr_lens: [2]posix.socklen_t = .{ @sizeOf(PosixAddress), @sizeOf(PosixAddress) };
11186 try posixGetSockName(sockets[0], &storages[0].any, &addr_lens[0]);
11187 try posixGetSockName(sockets[1], &storages[1].any, &addr_lens[1]);
11188 return .{
11189 .{ .handle = sockets[0], .address = addressFromPosix(&storages[0]) },
11190 .{ .handle = sockets[1], .address = addressFromPosix(&storages[1]) },
11191 };
11192 },
11193 .INTR => {
11194 try syscall.checkCancel();
11195 continue;
11196 },
11197 .ACCES => return syscall.fail(error.AccessDenied),
11198 .AFNOSUPPORT => return syscall.fail(error.AddressFamilyUnsupported),
11199 .INVAL => return syscall.fail(error.ProtocolUnsupportedBySystem),
11200 .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded),
11201 .NFILE => return syscall.fail(error.SystemFdQuotaExceeded),
11202 .NOBUFS => return syscall.fail(error.SystemResources),
11203 .NOMEM => return syscall.fail(error.SystemResources),
11204 .PROTONOSUPPORT => return syscall.fail(error.ProtocolUnsupportedByAddressFamily),
11205 .PROTOTYPE => return syscall.fail(error.SocketModeUnsupported),
11206 else => |err| return syscall.unexpectedErrno(err),
11207 };
11208}
11209
11210fn netSocketCreatePairUnavailable(
11211 userdata: ?*anyopaque,
11212 options: net.Socket.CreatePairOptions,
11213) net.Socket.CreatePairError![2]net.Socket {
11214 _ = userdata;
11215 _ = options;
11216 return error.OperationUnsupported;
11217}
11218
11161fn openSocketWsa(11219fn openSocketWsa(
11162 t: *Threaded,11220 t: *Threaded,
11163 family: posix.sa_family_t,11221 family: posix.sa_family_t,
...@@ -11216,20 +11274,10 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve...@@ -11216,20 +11274,10 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve
11216 posix.system.accept(listen_fd, &storage.any, &addr_len);11274 posix.system.accept(listen_fd, &storage.any, &addr_len);
11217 switch (posix.errno(rc)) {11275 switch (posix.errno(rc)) {
11218 .SUCCESS => {11276 .SUCCESS => {
11277 syscall.finish();
11219 const fd: posix.fd_t = @intCast(rc);11278 const fd: posix.fd_t = @intCast(rc);
11220 errdefer posix.close(fd);11279 errdefer posix.close(fd);
11221 if (!have_accept4) while (true) {11280 if (!have_accept4) try setCloexec(fd);
11222 try syscall.checkCancel();
11223 switch (posix.errno(posix.system.fcntl(fd, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)))) {
11224 .SUCCESS => break,
11225 .INTR => continue,
11226 else => |err| {
11227 syscall.finish();
11228 return posix.unexpectedErrno(err);
11229 },
11230 }
11231 };
11232 syscall.finish();
11233 break fd;11281 break fd;
11234 },11282 },
11235 .INTR => {11283 .INTR => {
lib/std/Io/net.zig+29
...@@ -1187,6 +1187,35 @@ pub const Socket = struct {...@@ -1187,6 +1187,35 @@ pub const Socket = struct {
1187 ) struct { ?ReceiveTimeoutError, usize } {1187 ) struct { ?ReceiveTimeoutError, usize } {
1188 return io.vtable.netReceive(io.userdata, s.handle, message_buffer, data_buffer, flags, timeout);1188 return io.vtable.netReceive(io.userdata, s.handle, message_buffer, data_buffer, flags, timeout);
1189 }1189 }
1190
1191 pub const CreatePairError = error{
1192 OperationUnsupported,
1193 AccessDenied,
1194 AddressFamilyUnsupported,
1195 ProtocolUnsupportedBySystem,
1196 /// The per-process limit on the number of open file descriptors has been reached.
1197 ProcessFdQuotaExceeded,
1198 /// The system-wide limit on the total number of open files has been reached.
1199 SystemFdQuotaExceeded,
1200 /// Insufficient memory is available. The socket cannot be created
1201 /// until sufficient resources are freed.
1202 SystemResources,
1203 ProtocolUnsupportedByAddressFamily,
1204 SocketModeUnsupported,
1205 } || Io.UnexpectedError || Io.Cancelable;
1206
1207 pub const CreatePairOptions = struct {
1208 family: IpAddress.Family = .ip4,
1209 mode: Mode = .stream,
1210 protocol: ?Protocol = null,
1211 };
1212
1213 /// Create a set of two sockets that are connected to each other.
1214 ///
1215 /// Also known as "socketpair".
1216 pub fn createPair(io: Io, options: CreatePairOptions) CreatePairError![2]Socket {
1217 return io.vtable.netSocketCreatePair(io.userdata, options);
1218 }
1190};1219};
11911220
1192/// An open socket connection with a network protocol that guarantees1221/// An open socket connection with a network protocol that guarantees
lib/std/Thread.zig+9-6
...@@ -809,12 +809,15 @@ const PosixThreadImpl = struct {...@@ -809,12 +809,15 @@ const PosixThreadImpl = struct {
809 else => {809 else => {
810 var count: c_int = undefined;810 var count: c_int = undefined;
811 var count_len: usize = @sizeOf(c_int);811 var count_len: usize = @sizeOf(c_int);
812 const name = if (comptime target.os.tag.isDarwin()) "hw.logicalcpu" else "hw.ncpu";812 const name = comptime if (target.os.tag.isDarwin()) "hw.logicalcpu" else "hw.ncpu";
813 posix.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) {813 switch (posix.errno(posix.system.sysctlbyname(name, &count, &count_len, null, 0))) {
814 error.UnknownName => unreachable,814 .SUCCESS => return @intCast(count),
815 else => |e| return e,815 .FAULT => unreachable,
816 };816 .PERM => return error.PermissionDenied,
817 return @as(usize, @intCast(count));817 .NOMEM => return error.SystemResources,
818 .NOENT => unreachable,
819 else => |err| return posix.unexpectedErrno(err),
820 }
818 },821 },
819 }822 }
820 }823 }
lib/std/os/linux/IoUring/test.zig+12-5
...@@ -1755,7 +1755,7 @@ test "accept multishot" {...@@ -1755,7 +1755,7 @@ test "accept multishot" {
1755 // connect client1755 // connect client
1756 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1756 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1757 errdefer posix.close(client);1757 errdefer posix.close(client);
1758 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1758 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
17591759
1760 // test accept completion1760 // test accept completion
1761 var cqe = try ring.copy_cqe();1761 var cqe = try ring.copy_cqe();
...@@ -1865,7 +1865,7 @@ test "accept_direct" {...@@ -1865,7 +1865,7 @@ test "accept_direct" {
18651865
1866 // connect1866 // connect
1867 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1867 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1868 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1868 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1869 defer posix.close(client);1869 defer posix.close(client);
18701870
1871 // accept completion1871 // accept completion
...@@ -1899,7 +1899,7 @@ test "accept_direct" {...@@ -1899,7 +1899,7 @@ test "accept_direct" {
1899 try testing.expectEqual(@as(u32, 1), try ring.submit());1899 try testing.expectEqual(@as(u32, 1), try ring.submit());
1900 // connect1900 // connect
1901 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1901 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1902 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1902 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1903 defer posix.close(client);1903 defer posix.close(client);
1904 // completion with error1904 // completion with error
1905 const cqe_accept = try ring.copy_cqe();1905 const cqe_accept = try ring.copy_cqe();
...@@ -1949,7 +1949,7 @@ test "accept_multishot_direct" {...@@ -1949,7 +1949,7 @@ test "accept_multishot_direct" {
1949 for (registered_fds) |_| {1949 for (registered_fds) |_| {
1950 // connect1950 // connect
1951 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1951 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1952 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1952 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1953 defer posix.close(client);1953 defer posix.close(client);
19541954
1955 // accept completion1955 // accept completion
...@@ -1964,7 +1964,7 @@ test "accept_multishot_direct" {...@@ -1964,7 +1964,7 @@ test "accept_multishot_direct" {
1964 {1964 {
1965 // connect1965 // connect
1966 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);1966 const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0);
1967 try posix.connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));1967 try connect(client, addrAny(&address), @sizeOf(linux.sockaddr.in));
1968 defer posix.close(client);1968 defer posix.close(client);
1969 // completion with error1969 // completion with error
1970 const cqe_accept = try ring.copy_cqe();1970 const cqe_accept = try ring.copy_cqe();
...@@ -2734,3 +2734,10 @@ fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize {...@@ -2734,3 +2734,10 @@ fn send(sockfd: posix.socket_t, buf: []const u8, flags: u32) !usize {
2734 else => return error.SendFailed,2734 else => return error.SendFailed,
2735 }2735 }
2736}2736}
2737
2738fn connect(sock: posix.socket_t, sock_addr: *const posix.sockaddr, len: posix.socklen_t) !void {
2739 switch (posix.errno(posix.system.connect(sock, sock_addr, len))) {
2740 .SUCCESS => return,
2741 else => return error.ConnectFailed,
2742 }
2743}
lib/std/posix.zig+7-347
...@@ -1,27 +1,18 @@...@@ -1,27 +1,18 @@
1//! POSIX API layer.1//! POSIX API layer.
2//!2//!
3//! This is more cross platform than using OS-specific APIs, however, it is3//! This is more cross platform than using OS-specific APIs, however, it is
4//! lower-level and less portable than other namespaces such as `std.fs` and4//! lower-level and less portable than other namespaces such as `std.Io` and
5//! `std.process`.5//! `std.process`.
6//!6//!
7//! These APIs are generally lowered to libc function calls if and only if libc7//! These APIs are generally lowered to libc function calls if and only if libc
8//! is linked. Most operating systems other than Windows, Linux, and WASI8//! is linked. Most operating systems other than Windows, Linux, and WASI
9//! require always linking libc because they use it as the stable syscall ABI.9//! require always linking libc because they use it as the stable syscall ABI.
10//!
11//! Operating systems that are not POSIX-compliant are sometimes supported by
12//! this API layer; sometimes not. Generally, an implementation will be
13//! provided only if such implementation is straightforward on that operating
14//! system. Otherwise, programmers are expected to use OS-specific logic to
15//! deal with the exception.
16
17const builtin = @import("builtin");10const builtin = @import("builtin");
18const native_os = builtin.os.tag;11const native_os = builtin.os.tag;
1912
20const std = @import("std.zig");13const std = @import("std.zig");
21const Io = std.Io;14const Io = std.Io;
22const mem = std.mem;15const mem = std.mem;
23const fs = std.fs;
24const max_path_bytes = std.fs.max_path_bytes;
25const maxInt = std.math.maxInt;16const maxInt = std.math.maxInt;
26const cast = std.math.cast;17const cast = std.math.cast;
27const assert = std.debug.assert;18const assert = std.debug.assert;
...@@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO;...@@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO;
122pub const STDOUT_FILENO = system.STDOUT_FILENO;113pub const STDOUT_FILENO = system.STDOUT_FILENO;
123pub const SYS = system.SYS;114pub const SYS = system.SYS;
124pub const Sigaction = system.Sigaction;115pub const Sigaction = system.Sigaction;
116/// Windows has no concept of `stat`.
117///
118/// On Linux, the `stat` bits/wrappers are removed due to having to maintain
119/// the different varying stat structs per target and libc, leading to runtime
120/// errors. Users targeting Linux should add a comptime check and use statx,
121/// similar to how `Io.File.stat` does.
125pub const Stat = switch (native_os) {122pub const Stat = switch (native_os) {
126 // Has no concept of `stat`.
127 .windows => void,123 .windows => void,
128 // The `stat` bits/wrappers are removed due to having to maintain the
129 // different varying `struct stat`s per target and libc, leading to runtime
130 // errors.
131 //
132 // Users targeting linux should add a comptime check and use `statx`,
133 // similar to how `std.fs.File.stat` does.
134 .linux => void,124 .linux => void,
135 else => system.Stat,125 else => system.Stat,
136};126};
...@@ -519,152 +509,6 @@ pub fn getppid() pid_t {...@@ -519,152 +509,6 @@ pub fn getppid() pid_t {
519 return system.getppid();509 return system.getppid();
520}510}
521511
522pub const SocketError = error{
523 /// Permission to create a socket of the specified type and/or
524 /// pro‐tocol is denied.
525 AccessDenied,
526
527 /// The implementation does not support the specified address family.
528 AddressFamilyUnsupported,
529
530 /// Unknown protocol, or protocol family not available.
531 ProtocolFamilyNotAvailable,
532
533 /// The per-process limit on the number of open file descriptors has been reached.
534 ProcessFdQuotaExceeded,
535
536 /// The system-wide limit on the total number of open files has been reached.
537 SystemFdQuotaExceeded,
538
539 /// Insufficient memory is available. The socket cannot be created until sufficient
540 /// resources are freed.
541 SystemResources,
542
543 /// The protocol type or the specified protocol is not supported within this domain.
544 ProtocolNotSupported,
545
546 /// The socket type is not supported by the protocol.
547 SocketTypeNotSupported,
548} || UnexpectedError;
549
550pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]socket_t {
551 // Note to the future: we could provide a shim here for e.g. windows which
552 // creates a listening socket, then creates a second socket and connects it
553 // to the listening socket, and then returns the two.
554 if (@TypeOf(system.socketpair) == void)
555 @compileError("socketpair() not supported by this OS");
556
557 // I'm not really sure if haiku supports flags here. I'm following the
558 // existing filter here from pipe2(), because it sure seems like it
559 // supports flags there too, but haiku can be hard to understand.
560 const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku;
561 const filtered_sock_type = if (!have_sock_flags)
562 socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC)
563 else
564 socket_type;
565 var socks: [2]socket_t = undefined;
566 const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks);
567 switch (errno(rc)) {
568 .SUCCESS => {
569 errdefer close(socks[0]);
570 errdefer close(socks[1]);
571 if (!have_sock_flags) {
572 try setSockFlags(socks[0], socket_type);
573 try setSockFlags(socks[1], socket_type);
574 }
575 return socks;
576 },
577 .ACCES => return error.AccessDenied,
578 .AFNOSUPPORT => return error.AddressFamilyUnsupported,
579 .INVAL => return error.ProtocolFamilyNotAvailable,
580 .MFILE => return error.ProcessFdQuotaExceeded,
581 .NFILE => return error.SystemFdQuotaExceeded,
582 .NOBUFS => return error.SystemResources,
583 .NOMEM => return error.SystemResources,
584 .PROTONOSUPPORT => return error.ProtocolNotSupported,
585 .PROTOTYPE => return error.SocketTypeNotSupported,
586 else => |err| return unexpectedErrno(err),
587 }
588}
589
590fn setSockFlags(sock: socket_t, flags: u32) !void {
591 if ((flags & SOCK.CLOEXEC) != 0) {
592 if (native_os == .windows) {
593 // TODO: Find out if this is supported for sockets
594 } else {
595 var fd_flags = fcntl(sock, F.GETFD, 0) catch |err| switch (err) {
596 error.FileBusy => unreachable,
597 error.Locked => unreachable,
598 error.PermissionDenied => unreachable,
599 error.DeadLock => unreachable,
600 error.LockedRegionLimitExceeded => unreachable,
601 else => |e| return e,
602 };
603 fd_flags |= FD_CLOEXEC;
604 _ = fcntl(sock, F.SETFD, fd_flags) catch |err| switch (err) {
605 error.FileBusy => unreachable,
606 error.Locked => unreachable,
607 error.PermissionDenied => unreachable,
608 error.DeadLock => unreachable,
609 error.LockedRegionLimitExceeded => unreachable,
610 else => |e| return e,
611 };
612 }
613 }
614 if ((flags & SOCK.NONBLOCK) != 0) {
615 if (native_os == .windows) {
616 var mode: c_ulong = 1;
617 if (windows.ws2_32.ioctlsocket(sock, windows.ws2_32.FIONBIO, &mode) == windows.ws2_32.SOCKET_ERROR) {
618 switch (windows.ws2_32.WSAGetLastError()) {
619 .NOTINITIALISED => unreachable,
620 .ENETDOWN => return error.NetworkDown,
621 .ENOTSOCK => return error.FileDescriptorNotASocket,
622 // TODO: handle more errors
623 else => |err| return windows.unexpectedWSAError(err),
624 }
625 }
626 } else {
627 var fl_flags = fcntl(sock, F.GETFL, 0) catch |err| switch (err) {
628 error.FileBusy => unreachable,
629 error.Locked => unreachable,
630 error.PermissionDenied => unreachable,
631 error.DeadLock => unreachable,
632 error.LockedRegionLimitExceeded => unreachable,
633 else => |e| return e,
634 };
635 fl_flags |= 1 << @bitOffsetOf(O, "NONBLOCK");
636 _ = fcntl(sock, F.SETFL, fl_flags) catch |err| switch (err) {
637 error.FileBusy => unreachable,
638 error.Locked => unreachable,
639 error.PermissionDenied => unreachable,
640 error.DeadLock => unreachable,
641 error.LockedRegionLimitExceeded => unreachable,
642 else => |e| return e,
643 };
644 }
645 }
646}
647
648pub const EventFdError = error{
649 SystemResources,
650 ProcessFdQuotaExceeded,
651 SystemFdQuotaExceeded,
652} || UnexpectedError;
653
654pub fn eventfd(initval: u32, flags: u32) EventFdError!i32 {
655 const rc = system.eventfd(initval, flags);
656 switch (errno(rc)) {
657 .SUCCESS => return @intCast(rc),
658 else => |err| return unexpectedErrno(err),
659
660 .INVAL => unreachable, // invalid parameters
661 .MFILE => return error.ProcessFdQuotaExceeded,
662 .NFILE => return error.SystemFdQuotaExceeded,
663 .NODEV => return error.SystemResources,
664 .NOMEM => return error.SystemResources,
665 }
666}
667
668pub const GetSockNameError = error{512pub const GetSockNameError = error{
669 /// Insufficient resources were available in the system to perform the operation.513 /// Insufficient resources were available in the system to perform the operation.
670 SystemResources,514 SystemResources,
...@@ -707,123 +551,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock...@@ -707,123 +551,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock
707 }551 }
708}552}
709553
710pub const ConnectError = std.Io.net.IpAddress.ConnectError || std.Io.net.UnixAddress.ConnectError;
711
712pub fn connect(sock: socket_t, sock_addr: *const sockaddr, len: socklen_t) ConnectError!void {
713 if (native_os == .windows) {
714 @compileError("use std.Io instead");
715 }
716
717 while (true) {
718 switch (errno(system.connect(sock, sock_addr, len))) {
719 .SUCCESS => return,
720 .ACCES => return error.AccessDenied,
721 .PERM => return error.PermissionDenied,
722 .ADDRNOTAVAIL => return error.AddressUnavailable,
723 .AFNOSUPPORT => return error.AddressFamilyUnsupported,
724 .AGAIN, .INPROGRESS => return error.WouldBlock,
725 .ALREADY => return error.ConnectionPending,
726 .BADF => unreachable, // sockfd is not a valid open file descriptor.
727 .CONNREFUSED => return error.ConnectionRefused,
728 .CONNRESET => return error.ConnectionResetByPeer,
729 .FAULT => unreachable, // The socket structure address is outside the user's address space.
730 .INTR => continue,
731 .ISCONN => @panic("AlreadyConnected"), // The socket is already connected.
732 .HOSTUNREACH => return error.NetworkUnreachable,
733 .NETUNREACH => return error.NetworkUnreachable,
734 .NOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
735 .PROTOTYPE => unreachable, // The socket type does not support the requested communications protocol.
736 .TIMEDOUT => return error.Timeout,
737 .NOENT => return error.FileNotFound, // Returned when socket is AF.UNIX and the given path does not exist.
738 .CONNABORTED => unreachable, // Tried to reuse socket that previously received error.ConnectionRefused.
739 else => |err| return unexpectedErrno(err),
740 }
741 }
742}
743
744pub const FStatError = std.Io.File.StatError;
745
746/// Return information about a file descriptor.
747pub fn fstat(fd: fd_t) FStatError!Stat {
748 if (native_os == .wasi and !builtin.link_libc) {
749 @compileError("unsupported OS");
750 }
751
752 var stat = mem.zeroes(Stat);
753 switch (errno(system.fstat(fd, &stat))) {
754 .SUCCESS => return stat,
755 .INVAL => unreachable,
756 .BADF => unreachable, // Always a race condition.
757 .NOMEM => return error.SystemResources,
758 .ACCES => return error.AccessDenied,
759 else => |err| return unexpectedErrno(err),
760 }
761}
762
763pub const INotifyInitError = error{
764 ProcessFdQuotaExceeded,
765 SystemFdQuotaExceeded,
766 SystemResources,
767} || UnexpectedError;
768
769/// initialize an inotify instance
770pub fn inotify_init1(flags: u32) INotifyInitError!i32 {
771 const rc = system.inotify_init1(flags);
772 switch (errno(rc)) {
773 .SUCCESS => return @intCast(rc),
774 .INVAL => unreachable,
775 .MFILE => return error.ProcessFdQuotaExceeded,
776 .NFILE => return error.SystemFdQuotaExceeded,
777 .NOMEM => return error.SystemResources,
778 else => |err| return unexpectedErrno(err),
779 }
780}
781
782pub const INotifyAddWatchError = error{
783 AccessDenied,
784 NameTooLong,
785 FileNotFound,
786 SystemResources,
787 UserResourceLimitReached,
788 NotDir,
789 WatchAlreadyExists,
790} || UnexpectedError;
791
792/// add a watch to an initialized inotify instance
793pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INotifyAddWatchError!i32 {
794 const pathname_c = try toPosixPath(pathname);
795 return inotify_add_watchZ(inotify_fd, &pathname_c, mask);
796}
797
798/// Same as `inotify_add_watch` except pathname is null-terminated.
799pub fn inotify_add_watchZ(inotify_fd: i32, pathname: [*:0]const u8, mask: u32) INotifyAddWatchError!i32 {
800 const rc = system.inotify_add_watch(inotify_fd, pathname, mask);
801 switch (errno(rc)) {
802 .SUCCESS => return @intCast(rc),
803 .ACCES => return error.AccessDenied,
804 .BADF => unreachable,
805 .FAULT => unreachable,
806 .INVAL => unreachable,
807 .NAMETOOLONG => return error.NameTooLong,
808 .NOENT => return error.FileNotFound,
809 .NOMEM => return error.SystemResources,
810 .NOSPC => return error.UserResourceLimitReached,
811 .NOTDIR => return error.NotDir,
812 .EXIST => return error.WatchAlreadyExists,
813 else => |err| return unexpectedErrno(err),
814 }
815}
816
817/// remove an existing watch from an inotify instance
818pub fn inotify_rm_watch(inotify_fd: i32, wd: i32) void {
819 switch (errno(system.inotify_rm_watch(inotify_fd, wd))) {
820 .SUCCESS => return,
821 .BADF => unreachable,
822 .INVAL => unreachable,
823 else => unreachable,
824 }
825}
826
827pub const FanotifyInitError = error{554pub const FanotifyInitError = error{
828 ProcessFdQuotaExceeded,555 ProcessFdQuotaExceeded,
829 SystemFdQuotaExceeded,556 SystemFdQuotaExceeded,
...@@ -1060,73 +787,6 @@ pub fn sysctl(...@@ -1060,73 +787,6 @@ pub fn sysctl(
1060 }787 }
1061}788}
1062789
1063pub const SysCtlByNameError = error{
1064 PermissionDenied,
1065 SystemResources,
1066 UnknownName,
1067} || UnexpectedError;
1068
1069pub fn sysctlbynameZ(
1070 name: [*:0]const u8,
1071 oldp: ?*anyopaque,
1072 oldlenp: ?*usize,
1073 newp: ?*anyopaque,
1074 newlen: usize,
1075) SysCtlByNameError!void {
1076 if (native_os == .wasi) {
1077 @compileError("sysctl not supported on WASI");
1078 }
1079 if (native_os == .haiku) {
1080 @compileError("sysctl not supported on Haiku");
1081 }
1082
1083 switch (errno(system.sysctlbyname(name, oldp, oldlenp, newp, newlen))) {
1084 .SUCCESS => return,
1085 .FAULT => unreachable,
1086 .PERM => return error.PermissionDenied,
1087 .NOMEM => return error.SystemResources,
1088 .NOENT => return error.UnknownName,
1089 else => |err| return unexpectedErrno(err),
1090 }
1091}
1092
1093pub fn gettimeofday(tv: ?*timeval, tz: ?*timezone) void {
1094 switch (errno(system.gettimeofday(tv, tz))) {
1095 .SUCCESS => return,
1096 .INVAL => unreachable,
1097 else => unreachable,
1098 }
1099}
1100
1101pub const FcntlError = error{
1102 PermissionDenied,
1103 FileBusy,
1104 ProcessFdQuotaExceeded,
1105 Locked,
1106 DeadLock,
1107 LockedRegionLimitExceeded,
1108} || UnexpectedError;
1109
1110pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize {
1111 while (true) {
1112 const rc = system.fcntl(fd, cmd, arg);
1113 switch (errno(rc)) {
1114 .SUCCESS => return @intCast(rc),
1115 .INTR => continue,
1116 .AGAIN, .ACCES => return error.Locked,
1117 .BADF => unreachable,
1118 .BUSY => return error.FileBusy,
1119 .INVAL => unreachable, // invalid parameters
1120 .PERM => return error.PermissionDenied,
1121 .MFILE => return error.ProcessFdQuotaExceeded,
1122 .NOTDIR => unreachable, // invalid parameter
1123 .DEADLK => return error.DeadLock,
1124 .NOLCK => return error.LockedRegionLimitExceeded,
1125 else => |err| return unexpectedErrno(err),
1126 }
1127 }
1128}
1129
1130pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {790pub fn getSelfPhdrs() []std.elf.ElfN.Phdr {
1131 const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;791 const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval;
1132 assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr));792 assert(getauxval(std.elf.AT_PHENT) == @sizeOf(std.elf.ElfN.Phdr));
lib/std/posix/test.zig+5-5
...@@ -273,17 +273,17 @@ test "fcntl" {...@@ -273,17 +273,17 @@ test "fcntl" {
273273
274 // Note: The test assumes createFile opens the file with CLOEXEC274 // Note: The test assumes createFile opens the file with CLOEXEC
275 {275 {
276 const flags = try posix.fcntl(file.handle, posix.F.GETFD, 0);276 const flags = posix.system.fcntl(file.handle, posix.F.GETFD, @as(usize, 0));
277 try expect((flags & posix.FD_CLOEXEC) != 0);277 try expect((flags & posix.FD_CLOEXEC) != 0);
278 }278 }
279 {279 {
280 _ = try posix.fcntl(file.handle, posix.F.SETFD, 0);280 _ = posix.system.fcntl(file.handle, posix.F.SETFD, @as(usize, 0));
281 const flags = try posix.fcntl(file.handle, posix.F.GETFD, 0);281 const flags = posix.system.fcntl(file.handle, posix.F.GETFD, @as(usize, 0));
282 try expect((flags & posix.FD_CLOEXEC) == 0);282 try expect((flags & posix.FD_CLOEXEC) == 0);
283 }283 }
284 {284 {
285 _ = try posix.fcntl(file.handle, posix.F.SETFD, posix.FD_CLOEXEC);285 _ = posix.system.fcntl(file.handle, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC));
286 const flags = try posix.fcntl(file.handle, posix.F.GETFD, 0);286 const flags = posix.system.fcntl(file.handle, posix.F.GETFD, @as(usize, 0));
287 try expect((flags & posix.FD_CLOEXEC) != 0);287 try expect((flags & posix.FD_CLOEXEC) != 0);
288 }288 }
289}289}
lib/std/process.zig+14-12
...@@ -556,26 +556,28 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {...@@ -556,26 +556,28 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 {
556 const name = if (native_os == .netbsd) "hw.physmem64" else "hw.physmem";556 const name = if (native_os == .netbsd) "hw.physmem64" else "hw.physmem";
557 var physmem: c_ulong = undefined;557 var physmem: c_ulong = undefined;
558 var len: usize = @sizeOf(c_ulong);558 var len: usize = @sizeOf(c_ulong);
559 posix.sysctlbynameZ(name, &physmem, &len, null, 0) catch |err| switch (err) {559 switch (posix.errno(posix.system.sysctlbyname(name, &physmem, &len, null, 0))) {
560 error.PermissionDenied => unreachable, // only when setting values,560 .SUCCESS => return @intCast(physmem),
561 error.SystemResources => unreachable, // memory already on the stack561 .FAULT => unreachable,
562 error.UnknownName => unreachable,562 .PERM => unreachable, // only when setting values
563 .NOMEM => unreachable, // memory already on the stack
564 .NOENT => unreachable,
563 else => return error.UnknownTotalSystemMemory,565 else => return error.UnknownTotalSystemMemory,
564 };566 }
565 return @intCast(physmem);
566 },567 },
567 // whole Darwin family568 // whole Darwin family
568 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {569 .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => {
569 // "hw.memsize" returns uint64_t570 // "hw.memsize" returns uint64_t
570 var physmem: u64 = undefined;571 var physmem: u64 = undefined;
571 var len: usize = @sizeOf(u64);572 var len: usize = @sizeOf(u64);
572 posix.sysctlbynameZ("hw.memsize", &physmem, &len, null, 0) catch |err| switch (err) {573 switch (posix.errno(posix.system.sysctlbyname("hw.memsize", &physmem, &len, null, 0))) {
573 error.PermissionDenied => unreachable, // only when setting values,574 .SUCCESS => return physmem,
574 error.SystemResources => unreachable, // memory already on the stack575 .FAULT => unreachable,
575 error.UnknownName => unreachable, // constant, known good value576 .PERM => unreachable, // only when setting values
577 .NOMEM => unreachable, // memory already on the stack
578 .NOENT => unreachable, // constant, known good value
576 else => return error.UnknownTotalSystemMemory,579 else => return error.UnknownTotalSystemMemory,
577 };580 }
578 return physmem;
579 },581 },
580 .openbsd => {582 .openbsd => {
581 const mib: [2]c_int = [_]c_int{583 const mib: [2]c_int = [_]c_int{
lib/std/zig/system.zig+8-6
...@@ -260,12 +260,14 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target {...@@ -260,12 +260,14 @@ pub fn resolveTargetQuery(io: Io, query: Target.Query) DetectError!Target {
260 var value: u32 = undefined;260 var value: u32 = undefined;
261 var len: usize = @sizeOf(@TypeOf(value));261 var len: usize = @sizeOf(@TypeOf(value));
262262
263 posix.sysctlbynameZ(key, &value, &len, null, 0) catch |err| switch (err) {263 switch (posix.errno(posix.system.sysctlbyname(key, &value, &len, null, 0))) {
264 error.PermissionDenied => unreachable, // only when setting values,264 .SUCCESS => {},
265 error.SystemResources => unreachable, // memory already on the stack265 .FAULT => unreachable,
266 error.UnknownName => unreachable, // constant, known good value266 .PERM => unreachable, // only when setting values,
267 error.Unexpected => return error.OSVersionDetectionFail,267 .NOMEM => unreachable, // memory already on the stack
268 };268 .NOENT => unreachable, // constant, known good value
269 else => return error.OSVersionDetectionFail,
270 }
269271
270 switch (builtin.target.os.tag) {272 switch (builtin.target.os.tag) {
271 .freebsd => {273 .freebsd => {
lib/std/zig/system/darwin/macos.zig+9-6
...@@ -2,6 +2,7 @@ const builtin = @import("builtin");...@@ -2,6 +2,7 @@ const builtin = @import("builtin");
22
3const std = @import("std");3const std = @import("std");
4const Io = std.Io;4const Io = std.Io;
5const posix = std.posix;
5const assert = std.debug.assert;6const assert = std.debug.assert;
6const mem = std.mem;7const mem = std.mem;
7const testing = std.testing;8const testing = std.testing;
...@@ -399,12 +400,14 @@ test "detect" {...@@ -399,12 +400,14 @@ test "detect" {
399pub fn detectNativeCpuAndFeatures() ?Target.Cpu {400pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
400 var cpu_family: std.c.CPUFAMILY = undefined;401 var cpu_family: std.c.CPUFAMILY = undefined;
401 var len: usize = @sizeOf(std.c.CPUFAMILY);402 var len: usize = @sizeOf(std.c.CPUFAMILY);
402 std.posix.sysctlbynameZ("hw.cpufamily", &cpu_family, &len, null, 0) catch |err| switch (err) {403 switch (posix.errno(posix.system.sysctlbyname("hw.cpufamily", &cpu_family, &len, null, 0))) {
403 error.PermissionDenied => unreachable, // only when setting values,404 .SUCCESS => {},
404 error.SystemResources => unreachable, // memory already on the stack405 .FAULT => unreachable, // segmentation fault
405 error.UnknownName => unreachable, // constant, known good value406 .PERM => unreachable, // only when setting values,
406 error.Unexpected => unreachable, // EFAULT: stack should be safe, EISDIR/ENOTDIR: constant, known good value407 .NOMEM => unreachable, // memory already on the stack
407 };408 .NOENT => unreachable, // constant, known good value
409 else => unreachable,
410 }
408411
409 const current_arch = builtin.cpu.arch;412 const current_arch = builtin.cpu.arch;
410 switch (current_arch) {413 switch (current_arch) {