| 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,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 | } |
| 10653 | 10648 | ||
| 10654 | fn posixConnectUnix( | 10649 | fn 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 | } |
| 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 | fn openSocketWsa( | 11219 | fn 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 | }; |
| 1191 | 1220 | ||
| 1192 | /// An open socket connection with a network protocol that guarantees | 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,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 client | 1755 | // 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)); |
| 1759 | 1759 | ||
| 1760 | // test accept completion | 1760 | // 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" { |
| 1865 | 1865 | ||
| 1866 | // connect | 1866 | // 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); |
| 1870 | 1870 | ||
| 1871 | // accept completion | 1871 | // 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 | // connect | 1900 | // 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 error | 1904 | // 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 | // connect | 1950 | // 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); |
| 1954 | 1954 | ||
| 1955 | // accept completion | 1955 | // accept completion |
| ... | @@ -1964,7 +1964,7 @@ test "accept_multishot_direct" { | ... | @@ -1964,7 +1964,7 @@ test "accept_multishot_direct" { |
| 1964 | { | 1964 | { |
| 1965 | // connect | 1965 | // 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 error | 1969 | // 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 | |||
| 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,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 is | 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 | //! `std.process`. | 5 | //! `std.process`. |
| 6 | //! | 6 | //! |
| 7 | //! These APIs are generally lowered to libc function calls if and only if libc | 7 | //! 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 WASI | 8 | //! 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 | |||
| 17 | const builtin = @import("builtin"); | 10 | const builtin = @import("builtin"); |
| 18 | const native_os = builtin.os.tag; | 11 | const native_os = builtin.os.tag; |
| 19 | 12 | ||
| 20 | const std = @import("std.zig"); | 13 | const std = @import("std.zig"); |
| 21 | const Io = std.Io; | 14 | const Io = std.Io; |
| 22 | const mem = std.mem; | 15 | const mem = std.mem; |
| 23 | const fs = std.fs; | ||
| 24 | const max_path_bytes = std.fs.max_path_bytes; | ||
| 25 | const maxInt = std.math.maxInt; | 16 | const maxInt = std.math.maxInt; |
| 26 | const cast = std.math.cast; | 17 | const cast = std.math.cast; |
| 27 | const assert = std.debug.assert; | 18 | const 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; |
| 122 | pub const STDOUT_FILENO = system.STDOUT_FILENO; | 113 | pub const STDOUT_FILENO = system.STDOUT_FILENO; |
| 123 | pub const SYS = system.SYS; | 114 | pub const SYS = system.SYS; |
| 124 | pub const Sigaction = system.Sigaction; | 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 | pub const Stat = switch (native_os) { | 122 | pub 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 | } |
| 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 | pub const GetSockNameError = error{ | 512 | pub 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 | } |
| 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 | pub const FanotifyInitError = error{ | 554 | pub 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 | } |
| 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 | pub fn getSelfPhdrs() []std.elf.ElfN.Phdr { | 790 | pub 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" { |
| 273 | 273 | ||
| 274 | // Note: The test assumes createFile opens the file with CLOEXEC | 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 | 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 stack | 561 | .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 family | 568 | // whole Darwin family |
| 568 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { | 569 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => { |
| 569 | // "hw.memsize" returns uint64_t | 570 | // "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 stack | 575 | .FAULT => unreachable, |
| 575 | error.UnknownName => unreachable, // constant, known good value | 576 | .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)); |
| 262 | 262 | ||
| 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 stack | 265 | .FAULT => unreachable, |
| 266 | error.UnknownName => unreachable, // constant, known good value | 266 | .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 | } | ||
| 269 | 271 | ||
| 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"); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const Io = std.Io; | 4 | const Io = std.Io; |
| 5 | const posix = std.posix; | ||
| 5 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 6 | const mem = std.mem; | 7 | const mem = std.mem; |
| 7 | const testing = std.testing; | 8 | const testing = std.testing; |
| ... | @@ -399,12 +400,14 @@ test "detect" { | ... | @@ -399,12 +400,14 @@ test "detect" { |
| 399 | pub fn detectNativeCpuAndFeatures() ?Target.Cpu { | 400 | pub 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 stack | 405 | .FAULT => unreachable, // segmentation fault |
| 405 | error.UnknownName => unreachable, // constant, known good value | 406 | .PERM => unreachable, // only when setting values, |
| 406 | error.Unexpected => unreachable, // EFAULT: stack should be safe, EISDIR/ENOTDIR: constant, known good value | 407 | .NOMEM => unreachable, // memory already on the stack |
| 407 | }; | 408 | .NOENT => unreachable, // constant, known good value |
| 409 | else => unreachable, | ||
| 410 | } | ||
| 408 | 411 | ||
| 409 | const current_arch = builtin.cpu.arch; | 412 | const current_arch = builtin.cpu.arch; |
| 410 | switch (current_arch) { | 413 | switch (current_arch) { |