| author | |
| committer | |
| log | aa38f07c5173f9722ebfb933058a2a032c2badf3 |
| tree | bc76f81dda9c9031cafa963e8fc723b6e41ce688 |
| parent | b9819fce69e0f208e9e20071071a40863fbdb8a9 |
| parent | 6a3226c43cd63fd331c3f4340d4331a8875138e3 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/3105610 files changed, 221 insertions(+), 466 deletions(-)
lib/std/Io.zig+1| ... | ... | @@ -688,6 +688,7 @@ pub const VTable = struct { |
| 688 | 688 | netConnectIp: *const fn (?*anyopaque, address: *const net.IpAddress, options: net.IpAddress.ConnectOptions) net.IpAddress.ConnectError!net.Stream, |
| 689 | 689 | netListenUnix: *const fn (?*anyopaque, *const net.UnixAddress, net.UnixAddress.ListenOptions) net.UnixAddress.ListenError!net.Socket.Handle, |
| 690 | 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 | 692 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, |
| 692 | 693 | netReceive: *const fn (?*anyopaque, net.Socket.Handle, message_buffer: []net.IncomingMessage, data_buffer: []u8, net.ReceiveFlags, Timeout) struct { ?net.Socket.ReceiveTimeoutError, usize }, |
| 693 | 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 | 1684 | .windows => netConnectUnixWindows, |
| 1685 | 1685 | else => netConnectUnixPosix, |
| 1686 | 1686 | }, |
| 1687 | .netSocketCreatePair = netSocketCreatePair, | |
| 1687 | 1688 | .netClose = netClose, |
| 1688 | 1689 | .netShutdown = switch (native_os) { |
| 1689 | 1690 | .windows => netShutdownWindows, |
| ... | ... | @@ -1824,6 +1825,7 @@ pub fn ioBasic(t: *Threaded) Io { |
| 1824 | 1825 | .netAccept = netAcceptUnavailable, |
| 1825 | 1826 | .netBindIp = netBindIpUnavailable, |
| 1826 | 1827 | .netConnectIp = netConnectIpUnavailable, |
| 1828 | .netSocketCreatePair = netSocketCreatePairUnavailable, | |
| 1827 | 1829 | .netConnectUnix = netConnectUnixUnavailable, |
| 1828 | 1830 | .netClose = netCloseUnavailable, |
| 1829 | 1831 | .netShutdown = netShutdownUnavailable, |
| ... | ... | @@ -10612,43 +10614,36 @@ fn posixConnect( |
| 10612 | 10614 | addr_len: posix.socklen_t, |
| 10613 | 10615 | ) !void { |
| 10614 | 10616 | const syscall: Syscall = try .start(); |
| 10615 | while (true) { | |
| 10616 | switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { | |
| 10617 | .SUCCESS => { | |
| 10618 | syscall.finish(); | |
| 10619 | return; | |
| 10620 | }, | |
| 10621 | .INTR => { | |
| 10622 | try syscall.checkCancel(); | |
| 10623 | continue; | |
| 10624 | }, | |
| 10625 | else => |e| { | |
| 10626 | syscall.finish(); | |
| 10627 | switch (e) { | |
| 10628 | .ADDRNOTAVAIL => return error.AddressUnavailable, | |
| 10629 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, | |
| 10630 | .AGAIN, .INPROGRESS => return error.WouldBlock, | |
| 10631 | .ALREADY => return error.ConnectionPending, | |
| 10632 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. | |
| 10633 | .CONNREFUSED => return error.ConnectionRefused, | |
| 10634 | .CONNRESET => return error.ConnectionResetByPeer, | |
| 10635 | .FAULT => |err| return errnoBug(err), | |
| 10636 | .ISCONN => |err| return errnoBug(err), | |
| 10637 | .HOSTUNREACH => return error.HostUnreachable, | |
| 10638 | .NETUNREACH => return error.NetworkUnreachable, | |
| 10639 | .NOTSOCK => |err| return errnoBug(err), | |
| 10640 | .PROTOTYPE => |err| return errnoBug(err), | |
| 10641 | .TIMEDOUT => return error.Timeout, | |
| 10642 | .CONNABORTED => |err| return errnoBug(err), | |
| 10643 | .ACCES => return error.AccessDenied, | |
| 10644 | .PERM => |err| return errnoBug(err), | |
| 10645 | .NOENT => |err| return errnoBug(err), | |
| 10646 | .NETDOWN => return error.NetworkDown, | |
| 10647 | else => |err| return posix.unexpectedErrno(err), | |
| 10648 | } | |
| 10649 | }, | |
| 10650 | } | |
| 10651 | } | |
| 10617 | while (true) switch (posix.errno(posix.system.connect(socket_fd, addr, addr_len))) { | |
| 10618 | .SUCCESS => { | |
| 10619 | syscall.finish(); | |
| 10620 | return; | |
| 10621 | }, | |
| 10622 | .INTR => { | |
| 10623 | try syscall.checkCancel(); | |
| 10624 | continue; | |
| 10625 | }, | |
| 10626 | .ADDRNOTAVAIL => return syscall.fail(error.AddressUnavailable), | |
| 10627 | .AFNOSUPPORT => return syscall.fail(error.AddressFamilyUnsupported), | |
| 10628 | .AGAIN, .INPROGRESS => return syscall.fail(error.WouldBlock), | |
| 10629 | .ALREADY => return syscall.fail(error.ConnectionPending), | |
| 10630 | .CONNREFUSED => return syscall.fail(error.ConnectionRefused), | |
| 10631 | .CONNRESET => return syscall.fail(error.ConnectionResetByPeer), | |
| 10632 | .HOSTUNREACH => return syscall.fail(error.HostUnreachable), | |
| 10633 | .NETUNREACH => return syscall.fail(error.NetworkUnreachable), | |
| 10634 | .TIMEDOUT => return syscall.fail(error.Timeout), | |
| 10635 | .ACCES => return syscall.fail(error.AccessDenied), | |
| 10636 | .NETDOWN => return syscall.fail(error.NetworkDown), | |
| 10637 | .BADF => |err| return syscall.errnoBug(err), // File descriptor used after closed. | |
| 10638 | .CONNABORTED => |err| return syscall.errnoBug(err), | |
| 10639 | .FAULT => |err| return syscall.errnoBug(err), | |
| 10640 | .ISCONN => |err| return syscall.errnoBug(err), | |
| 10641 | .NOENT => |err| return syscall.errnoBug(err), | |
| 10642 | .NOTSOCK => |err| return syscall.errnoBug(err), | |
| 10643 | .PERM => |err| return syscall.errnoBug(err), | |
| 10644 | .PROTOTYPE => |err| return syscall.errnoBug(err), | |
| 10645 | else => |err| return syscall.unexpectedErrno(err), | |
| 10646 | }; | |
| 10652 | 10647 | } |
| 10653 | 10648 | |
| 10654 | 10649 | fn posixConnectUnix( |
| ... | ... | @@ -11106,46 +11101,31 @@ fn openSocketPosix( |
| 11106 | 11101 | }!posix.socket_t { |
| 11107 | 11102 | const mode = posixSocketMode(options.mode); |
| 11108 | 11103 | const protocol = posixProtocol(options.protocol); |
| 11104 | const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; | |
| 11109 | 11105 | const syscall: Syscall = try .start(); |
| 11110 | 11106 | const socket_fd = while (true) { |
| 11111 | const flags: u32 = mode | if (socket_flags_unsupported) 0 else posix.SOCK.CLOEXEC; | |
| 11112 | const socket_rc = posix.system.socket(family, flags, protocol); | |
| 11113 | switch (posix.errno(socket_rc)) { | |
| 11107 | const rc = posix.system.socket(family, flags, protocol); | |
| 11108 | switch (posix.errno(rc)) { | |
| 11114 | 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 | 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 | 11114 | break fd; |
| 11130 | 11115 | }, |
| 11131 | 11116 | .INTR => { |
| 11132 | 11117 | try syscall.checkCancel(); |
| 11133 | 11118 | continue; |
| 11134 | 11119 | }, |
| 11135 | else => |e| { | |
| 11136 | syscall.finish(); | |
| 11137 | switch (e) { | |
| 11138 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, | |
| 11139 | .INVAL => return error.ProtocolUnsupportedBySystem, | |
| 11140 | .MFILE => return error.ProcessFdQuotaExceeded, | |
| 11141 | .NFILE => return error.SystemFdQuotaExceeded, | |
| 11142 | .NOBUFS => return error.SystemResources, | |
| 11143 | .NOMEM => return error.SystemResources, | |
| 11144 | .PROTONOSUPPORT => return error.ProtocolUnsupportedByAddressFamily, | |
| 11145 | .PROTOTYPE => return error.SocketModeUnsupported, | |
| 11146 | else => |err| return posix.unexpectedErrno(err), | |
| 11147 | } | |
| 11148 | }, | |
| 11120 | .AFNOSUPPORT => return syscall.fail(error.AddressFamilyUnsupported), | |
| 11121 | .INVAL => return syscall.fail(error.ProtocolUnsupportedBySystem), | |
| 11122 | .MFILE => return syscall.fail(error.ProcessFdQuotaExceeded), | |
| 11123 | .NFILE => return syscall.fail(error.SystemFdQuotaExceeded), | |
| 11124 | .NOBUFS => return syscall.fail(error.SystemResources), | |
| 11125 | .NOMEM => return syscall.fail(error.SystemResources), | |
| 11126 | .PROTONOSUPPORT => return syscall.fail(error.ProtocolUnsupportedByAddressFamily), | |
| 11127 | .PROTOTYPE => return syscall.fail(error.SocketModeUnsupported), | |
| 11128 | else => |err| return syscall.unexpectedErrno(err), | |
| 11149 | 11129 | } |
| 11150 | 11130 | }; |
| 11151 | 11131 | errdefer posix.close(socket_fd); |
| ... | ... | @@ -11158,6 +11138,84 @@ fn openSocketPosix( |
| 11158 | 11138 | return socket_fd; |
| 11159 | 11139 | } |
| 11160 | 11140 | |
| 11141 | fn 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 | ||
| 11153 | fn 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 | ||
| 11210 | fn 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 | ||
| 11161 | 11219 | fn openSocketWsa( |
| 11162 | 11220 | t: *Threaded, |
| 11163 | 11221 | family: posix.sa_family_t, |
| ... | ... | @@ -11216,20 +11274,10 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve |
| 11216 | 11274 | posix.system.accept(listen_fd, &storage.any, &addr_len); |
| 11217 | 11275 | switch (posix.errno(rc)) { |
| 11218 | 11276 | .SUCCESS => { |
| 11277 | syscall.finish(); | |
| 11219 | 11278 | const fd: posix.fd_t = @intCast(rc); |
| 11220 | 11279 | errdefer posix.close(fd); |
| 11221 | if (!have_accept4) while (true) { | |
| 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(); | |
| 11280 | if (!have_accept4) try setCloexec(fd); | |
| 11233 | 11281 | break fd; |
| 11234 | 11282 | }, |
| 11235 | 11283 | .INTR => { |
lib/std/Io/net.zig+29| ... | ... | @@ -1187,6 +1187,35 @@ pub const Socket = struct { |
| 1187 | 1187 | ) struct { ?ReceiveTimeoutError, usize } { |
| 1188 | 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 | }; |
| 1191 | 1220 | |
| 1192 | 1221 | /// An open socket connection with a network protocol that guarantees |
lib/std/Thread.zig+9-6| ... | ... | @@ -809,12 +809,15 @@ const PosixThreadImpl = struct { |
| 809 | 809 | else => { |
| 810 | 810 | var count: c_int = undefined; |
| 811 | 811 | var count_len: usize = @sizeOf(c_int); |
| 812 | const name = if (comptime target.os.tag.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; | |
| 813 | posix.sysctlbynameZ(name, &count, &count_len, null, 0) catch |err| switch (err) { | |
| 814 | error.UnknownName => unreachable, | |
| 815 | else => |e| return e, | |
| 816 | }; | |
| 817 | return @as(usize, @intCast(count)); | |
| 812 | const name = comptime if (target.os.tag.isDarwin()) "hw.logicalcpu" else "hw.ncpu"; | |
| 813 | switch (posix.errno(posix.system.sysctlbyname(name, &count, &count_len, null, 0))) { | |
| 814 | .SUCCESS => return @intCast(count), | |
| 815 | .FAULT => unreachable, | |
| 816 | .PERM => return error.PermissionDenied, | |
| 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 | 1755 | // connect client |
| 1756 | 1756 | const client = try socket(address.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, 0); |
| 1757 | 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)); | |
| 1759 | 1759 | |
| 1760 | 1760 | // test accept completion |
| 1761 | 1761 | var cqe = try ring.copy_cqe(); |
| ... | ... | @@ -1865,7 +1865,7 @@ test "accept_direct" { |
| 1865 | 1865 | |
| 1866 | 1866 | // connect |
| 1867 | 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 | 1869 | defer posix.close(client); |
| 1870 | 1870 | |
| 1871 | 1871 | // accept completion |
| ... | ... | @@ -1899,7 +1899,7 @@ test "accept_direct" { |
| 1899 | 1899 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| 1900 | 1900 | // connect |
| 1901 | 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 | 1903 | defer posix.close(client); |
| 1904 | 1904 | // completion with error |
| 1905 | 1905 | const cqe_accept = try ring.copy_cqe(); |
| ... | ... | @@ -1949,7 +1949,7 @@ test "accept_multishot_direct" { |
| 1949 | 1949 | for (registered_fds) |_| { |
| 1950 | 1950 | // connect |
| 1951 | 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 | 1953 | defer posix.close(client); |
| 1954 | 1954 | |
| 1955 | 1955 | // accept completion |
| ... | ... | @@ -1964,7 +1964,7 @@ test "accept_multishot_direct" { |
| 1964 | 1964 | { |
| 1965 | 1965 | // connect |
| 1966 | 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 | 1968 | defer posix.close(client); |
| 1969 | 1969 | // completion with error |
| 1970 | 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 | 2734 | else => return error.SendFailed, |
| 2735 | 2735 | } |
| 2736 | 2736 | } |
| 2737 | ||
| 2738 | fn 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 | 1 | //! POSIX API layer. |
| 2 | 2 | //! |
| 3 | 3 | //! 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` and | |
| 4 | //! lower-level and less portable than other namespaces such as `std.Io` and | |
| 5 | 5 | //! `std.process`. |
| 6 | 6 | //! |
| 7 | 7 | //! These APIs are generally lowered to libc function calls if and only if libc |
| 8 | 8 | //! is linked. Most operating systems other than Windows, Linux, and WASI |
| 9 | 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 | ||
| 17 | 10 | const builtin = @import("builtin"); |
| 18 | 11 | const native_os = builtin.os.tag; |
| 19 | 12 | |
| 20 | 13 | const std = @import("std.zig"); |
| 21 | 14 | const Io = std.Io; |
| 22 | 15 | const mem = std.mem; |
| 23 | const fs = std.fs; | |
| 24 | const max_path_bytes = std.fs.max_path_bytes; | |
| 25 | 16 | const maxInt = std.math.maxInt; |
| 26 | 17 | const cast = std.math.cast; |
| 27 | 18 | const assert = std.debug.assert; |
| ... | ... | @@ -122,15 +113,14 @@ pub const STDIN_FILENO = system.STDIN_FILENO; |
| 122 | 113 | pub const STDOUT_FILENO = system.STDOUT_FILENO; |
| 123 | 114 | pub const SYS = system.SYS; |
| 124 | 115 | pub 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. | |
| 125 | 122 | pub const Stat = switch (native_os) { |
| 126 | // Has no concept of `stat`. | |
| 127 | 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 | 124 | .linux => void, |
| 135 | 125 | else => system.Stat, |
| 136 | 126 | }; |
| ... | ... | @@ -519,152 +509,6 @@ pub fn getppid() pid_t { |
| 519 | 509 | return system.getppid(); |
| 520 | 510 | } |
| 521 | 511 | |
| 522 | pub 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 | ||
| 550 | pub 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 | ||
| 590 | fn 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 | ||
| 648 | pub const EventFdError = error{ | |
| 649 | SystemResources, | |
| 650 | ProcessFdQuotaExceeded, | |
| 651 | SystemFdQuotaExceeded, | |
| 652 | } || UnexpectedError; | |
| 653 | ||
| 654 | pub 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 | ||
| 668 | 512 | pub const GetSockNameError = error{ |
| 669 | 513 | /// Insufficient resources were available in the system to perform the operation. |
| 670 | 514 | SystemResources, |
| ... | ... | @@ -707,123 +551,6 @@ pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock |
| 707 | 551 | } |
| 708 | 552 | } |
| 709 | 553 | |
| 710 | pub const ConnectError = std.Io.net.IpAddress.ConnectError || std.Io.net.UnixAddress.ConnectError; | |
| 711 | ||
| 712 | pub 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 | ||
| 744 | pub const FStatError = std.Io.File.StatError; | |
| 745 | ||
| 746 | /// Return information about a file descriptor. | |
| 747 | pub 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 | ||
| 763 | pub const INotifyInitError = error{ | |
| 764 | ProcessFdQuotaExceeded, | |
| 765 | SystemFdQuotaExceeded, | |
| 766 | SystemResources, | |
| 767 | } || UnexpectedError; | |
| 768 | ||
| 769 | /// initialize an inotify instance | |
| 770 | pub 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 | ||
| 782 | pub 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 | |
| 793 | pub 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. | |
| 799 | pub 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 | |
| 818 | pub 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 | ||
| 827 | 554 | pub const FanotifyInitError = error{ |
| 828 | 555 | ProcessFdQuotaExceeded, |
| 829 | 556 | SystemFdQuotaExceeded, |
| ... | ... | @@ -1060,73 +787,6 @@ pub fn sysctl( |
| 1060 | 787 | } |
| 1061 | 788 | } |
| 1062 | 789 | |
| 1063 | pub const SysCtlByNameError = error{ | |
| 1064 | PermissionDenied, | |
| 1065 | SystemResources, | |
| 1066 | UnknownName, | |
| 1067 | } || UnexpectedError; | |
| 1068 | ||
| 1069 | pub 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 | ||
| 1093 | pub 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 | ||
| 1101 | pub const FcntlError = error{ | |
| 1102 | PermissionDenied, | |
| 1103 | FileBusy, | |
| 1104 | ProcessFdQuotaExceeded, | |
| 1105 | Locked, | |
| 1106 | DeadLock, | |
| 1107 | LockedRegionLimitExceeded, | |
| 1108 | } || UnexpectedError; | |
| 1109 | ||
| 1110 | pub 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 | ||
| 1130 | 790 | pub fn getSelfPhdrs() []std.elf.ElfN.Phdr { |
| 1131 | 791 | const getauxval = if (builtin.link_libc) std.c.getauxval else std.os.linux.getauxval; |
| 1132 | 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 | 273 | |
| 274 | 274 | // 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 | 277 | try expect((flags & posix.FD_CLOEXEC) != 0); |
| 278 | 278 | } |
| 279 | 279 | { |
| 280 | _ = try posix.fcntl(file.handle, posix.F.SETFD, 0); | |
| 281 | const flags = try posix.fcntl(file.handle, posix.F.GETFD, 0); | |
| 280 | _ = posix.system.fcntl(file.handle, posix.F.SETFD, @as(usize, 0)); | |
| 281 | const flags = posix.system.fcntl(file.handle, posix.F.GETFD, @as(usize, 0)); | |
| 282 | 282 | try expect((flags & posix.FD_CLOEXEC) == 0); |
| 283 | 283 | } |
| 284 | 284 | { |
| 285 | _ = try posix.fcntl(file.handle, posix.F.SETFD, posix.FD_CLOEXEC); | |
| 286 | const flags = try posix.fcntl(file.handle, posix.F.GETFD, 0); | |
| 285 | _ = posix.system.fcntl(file.handle, posix.F.SETFD, @as(usize, posix.FD_CLOEXEC)); | |
| 286 | const flags = posix.system.fcntl(file.handle, posix.F.GETFD, @as(usize, 0)); | |
| 287 | 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 | 556 | const name = if (native_os == .netbsd) "hw.physmem64" else "hw.physmem"; |
| 557 | 557 | var physmem: c_ulong = undefined; |
| 558 | 558 | var len: usize = @sizeOf(c_ulong); |
| 559 | posix.sysctlbynameZ(name, &physmem, &len, null, 0) catch |err| switch (err) { | |
| 560 | error.PermissionDenied => unreachable, // only when setting values, | |
| 561 | error.SystemResources => unreachable, // memory already on the stack | |
| 562 | error.UnknownName => unreachable, | |
| 559 | switch (posix.errno(posix.system.sysctlbyname(name, &physmem, &len, null, 0))) { | |
| 560 | .SUCCESS => return @intCast(physmem), | |
| 561 | .FAULT => unreachable, | |
| 562 | .PERM => unreachable, // only when setting values | |
| 563 | .NOMEM => unreachable, // memory already on the stack | |
| 564 | .NOENT => unreachable, | |
| 563 | 565 | else => return error.UnknownTotalSystemMemory, |
| 564 | }; | |
| 565 | return @intCast(physmem); | |
| 566 | } | |
| 566 | 567 | }, |
| 567 | 568 | // whole Darwin family |
| 568 | 569 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { |
| 569 | 570 | // "hw.memsize" returns uint64_t |
| 570 | 571 | var physmem: u64 = undefined; |
| 571 | 572 | var len: usize = @sizeOf(u64); |
| 572 | posix.sysctlbynameZ("hw.memsize", &physmem, &len, null, 0) catch |err| switch (err) { | |
| 573 | error.PermissionDenied => unreachable, // only when setting values, | |
| 574 | error.SystemResources => unreachable, // memory already on the stack | |
| 575 | error.UnknownName => unreachable, // constant, known good value | |
| 573 | switch (posix.errno(posix.system.sysctlbyname("hw.memsize", &physmem, &len, null, 0))) { | |
| 574 | .SUCCESS => return physmem, | |
| 575 | .FAULT => unreachable, | |
| 576 | .PERM => unreachable, // only when setting values | |
| 577 | .NOMEM => unreachable, // memory already on the stack | |
| 578 | .NOENT => unreachable, // constant, known good value | |
| 576 | 579 | else => return error.UnknownTotalSystemMemory, |
| 577 | }; | |
| 578 | return physmem; | |
| 580 | } | |
| 579 | 581 | }, |
| 580 | 582 | .openbsd => { |
| 581 | 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 | 260 | var value: u32 = undefined; |
| 261 | 261 | var len: usize = @sizeOf(@TypeOf(value)); |
| 262 | 262 | |
| 263 | posix.sysctlbynameZ(key, &value, &len, null, 0) catch |err| switch (err) { | |
| 264 | error.PermissionDenied => unreachable, // only when setting values, | |
| 265 | error.SystemResources => unreachable, // memory already on the stack | |
| 266 | error.UnknownName => unreachable, // constant, known good value | |
| 267 | error.Unexpected => return error.OSVersionDetectionFail, | |
| 268 | }; | |
| 263 | switch (posix.errno(posix.system.sysctlbyname(key, &value, &len, null, 0))) { | |
| 264 | .SUCCESS => {}, | |
| 265 | .FAULT => unreachable, | |
| 266 | .PERM => unreachable, // only when setting values, | |
| 267 | .NOMEM => unreachable, // memory already on the stack | |
| 268 | .NOENT => unreachable, // constant, known good value | |
| 269 | else => return error.OSVersionDetectionFail, | |
| 270 | } | |
| 269 | 271 | |
| 270 | 272 | switch (builtin.target.os.tag) { |
| 271 | 273 | .freebsd => { |
lib/std/zig/system/darwin/macos.zig+9-6| ... | ... | @@ -2,6 +2,7 @@ const builtin = @import("builtin"); |
| 2 | 2 | |
| 3 | 3 | const std = @import("std"); |
| 4 | 4 | const Io = std.Io; |
| 5 | const posix = std.posix; | |
| 5 | 6 | const assert = std.debug.assert; |
| 6 | 7 | const mem = std.mem; |
| 7 | 8 | const testing = std.testing; |
| ... | ... | @@ -399,12 +400,14 @@ test "detect" { |
| 399 | 400 | pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 400 | 401 | var cpu_family: std.c.CPUFAMILY = undefined; |
| 401 | 402 | var len: usize = @sizeOf(std.c.CPUFAMILY); |
| 402 | std.posix.sysctlbynameZ("hw.cpufamily", &cpu_family, &len, null, 0) catch |err| switch (err) { | |
| 403 | error.PermissionDenied => unreachable, // only when setting values, | |
| 404 | error.SystemResources => unreachable, // memory already on the stack | |
| 405 | error.UnknownName => unreachable, // constant, known good value | |
| 406 | error.Unexpected => unreachable, // EFAULT: stack should be safe, EISDIR/ENOTDIR: constant, known good value | |
| 407 | }; | |
| 403 | switch (posix.errno(posix.system.sysctlbyname("hw.cpufamily", &cpu_family, &len, null, 0))) { | |
| 404 | .SUCCESS => {}, | |
| 405 | .FAULT => unreachable, // segmentation fault | |
| 406 | .PERM => unreachable, // only when setting values, | |
| 407 | .NOMEM => unreachable, // memory already on the stack | |
| 408 | .NOENT => unreachable, // constant, known good value | |
| 409 | else => unreachable, | |
| 410 | } | |
| 408 | 411 | |
| 409 | 412 | const current_arch = builtin.cpu.arch; |
| 410 | 413 | switch (current_arch) { |