| author | |
| committer | |
| log | 6a3226c43cd63fd331c3f4340d4331a8875138e3 |
| tree | bc76f81dda9c9031cafa963e8fc723b6e41ce688 |
| parent | 0c67d9ebdec86a5faac9336c9ed912d798050e17 |
and remove the following from std.posix:
- socketpair
- fcntl5 files changed, 162 insertions(+), 239 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/posix.zig-155| ... | @@ -509,132 +509,6 @@ pub fn getppid() pid_t { | ... | @@ -509,132 +509,6 @@ pub fn getppid() pid_t { |
| 509 | return system.getppid(); | 509 | return system.getppid(); |
| 510 | } | 510 | } |
| 511 | 511 | ||
| 512 | pub const SocketError = error{ | ||
| 513 | /// Permission to create a socket of the specified type and/or | ||
| 514 | /// pro‐tocol is denied. | ||
| 515 | AccessDenied, | ||
| 516 | |||
| 517 | /// The implementation does not support the specified address family. | ||
| 518 | AddressFamilyUnsupported, | ||
| 519 | |||
| 520 | /// Unknown protocol, or protocol family not available. | ||
| 521 | ProtocolFamilyNotAvailable, | ||
| 522 | |||
| 523 | /// The per-process limit on the number of open file descriptors has been reached. | ||
| 524 | ProcessFdQuotaExceeded, | ||
| 525 | |||
| 526 | /// The system-wide limit on the total number of open files has been reached. | ||
| 527 | SystemFdQuotaExceeded, | ||
| 528 | |||
| 529 | /// Insufficient memory is available. The socket cannot be created until sufficient | ||
| 530 | /// resources are freed. | ||
| 531 | SystemResources, | ||
| 532 | |||
| 533 | /// The protocol type or the specified protocol is not supported within this domain. | ||
| 534 | ProtocolNotSupported, | ||
| 535 | |||
| 536 | /// The socket type is not supported by the protocol. | ||
| 537 | SocketTypeNotSupported, | ||
| 538 | } || UnexpectedError; | ||
| 539 | |||
| 540 | pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]socket_t { | ||
| 541 | // Note to the future: we could provide a shim here for e.g. windows which | ||
| 542 | // creates a listening socket, then creates a second socket and connects it | ||
| 543 | // to the listening socket, and then returns the two. | ||
| 544 | if (@TypeOf(system.socketpair) == void) | ||
| 545 | @compileError("socketpair() not supported by this OS"); | ||
| 546 | |||
| 547 | // I'm not really sure if haiku supports flags here. I'm following the | ||
| 548 | // existing filter here from pipe2(), because it sure seems like it | ||
| 549 | // supports flags there too, but haiku can be hard to understand. | ||
| 550 | const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku; | ||
| 551 | const filtered_sock_type = if (!have_sock_flags) | ||
| 552 | socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC) | ||
| 553 | else | ||
| 554 | socket_type; | ||
| 555 | var socks: [2]socket_t = undefined; | ||
| 556 | const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks); | ||
| 557 | switch (errno(rc)) { | ||
| 558 | .SUCCESS => { | ||
| 559 | errdefer close(socks[0]); | ||
| 560 | errdefer close(socks[1]); | ||
| 561 | if (!have_sock_flags) { | ||
| 562 | try setSockFlags(socks[0], socket_type); | ||
| 563 | try setSockFlags(socks[1], socket_type); | ||
| 564 | } | ||
| 565 | return socks; | ||
| 566 | }, | ||
| 567 | .ACCES => return error.AccessDenied, | ||
| 568 | .AFNOSUPPORT => return error.AddressFamilyUnsupported, | ||
| 569 | .INVAL => return error.ProtocolFamilyNotAvailable, | ||
| 570 | .MFILE => return error.ProcessFdQuotaExceeded, | ||
| 571 | .NFILE => return error.SystemFdQuotaExceeded, | ||
| 572 | .NOBUFS => return error.SystemResources, | ||
| 573 | .NOMEM => return error.SystemResources, | ||
| 574 | .PROTONOSUPPORT => return error.ProtocolNotSupported, | ||
| 575 | .PROTOTYPE => return error.SocketTypeNotSupported, | ||
| 576 | else => |err| return unexpectedErrno(err), | ||
| 577 | } | ||
| 578 | } | ||
| 579 | |||
| 580 | fn setSockFlags(sock: socket_t, flags: u32) !void { | ||
| 581 | if ((flags & SOCK.CLOEXEC) != 0) { | ||
| 582 | if (native_os == .windows) { | ||
| 583 | // TODO: Find out if this is supported for sockets | ||
| 584 | } else { | ||
| 585 | var fd_flags = fcntl(sock, F.GETFD, 0) catch |err| switch (err) { | ||
| 586 | error.FileBusy => unreachable, | ||
| 587 | error.Locked => unreachable, | ||
| 588 | error.PermissionDenied => unreachable, | ||
| 589 | error.DeadLock => unreachable, | ||
| 590 | error.LockedRegionLimitExceeded => unreachable, | ||
| 591 | else => |e| return e, | ||
| 592 | }; | ||
| 593 | fd_flags |= FD_CLOEXEC; | ||
| 594 | _ = fcntl(sock, F.SETFD, fd_flags) catch |err| switch (err) { | ||
| 595 | error.FileBusy => unreachable, | ||
| 596 | error.Locked => unreachable, | ||
| 597 | error.PermissionDenied => unreachable, | ||
| 598 | error.DeadLock => unreachable, | ||
| 599 | error.LockedRegionLimitExceeded => unreachable, | ||
| 600 | else => |e| return e, | ||
| 601 | }; | ||
| 602 | } | ||
| 603 | } | ||
| 604 | if ((flags & SOCK.NONBLOCK) != 0) { | ||
| 605 | if (native_os == .windows) { | ||
| 606 | var mode: c_ulong = 1; | ||
| 607 | if (windows.ws2_32.ioctlsocket(sock, windows.ws2_32.FIONBIO, &mode) == windows.ws2_32.SOCKET_ERROR) { | ||
| 608 | switch (windows.ws2_32.WSAGetLastError()) { | ||
| 609 | .NOTINITIALISED => unreachable, | ||
| 610 | .ENETDOWN => return error.NetworkDown, | ||
| 611 | .ENOTSOCK => return error.FileDescriptorNotASocket, | ||
| 612 | // TODO: handle more errors | ||
| 613 | else => |err| return windows.unexpectedWSAError(err), | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } else { | ||
| 617 | var fl_flags = fcntl(sock, F.GETFL, 0) catch |err| switch (err) { | ||
| 618 | error.FileBusy => unreachable, | ||
| 619 | error.Locked => unreachable, | ||
| 620 | error.PermissionDenied => unreachable, | ||
| 621 | error.DeadLock => unreachable, | ||
| 622 | error.LockedRegionLimitExceeded => unreachable, | ||
| 623 | else => |e| return e, | ||
| 624 | }; | ||
| 625 | fl_flags |= 1 << @bitOffsetOf(O, "NONBLOCK"); | ||
| 626 | _ = fcntl(sock, F.SETFL, fl_flags) catch |err| switch (err) { | ||
| 627 | error.FileBusy => unreachable, | ||
| 628 | error.Locked => unreachable, | ||
| 629 | error.PermissionDenied => unreachable, | ||
| 630 | error.DeadLock => unreachable, | ||
| 631 | error.LockedRegionLimitExceeded => unreachable, | ||
| 632 | else => |e| return e, | ||
| 633 | }; | ||
| 634 | } | ||
| 635 | } | ||
| 636 | } | ||
| 637 | |||
| 638 | pub const GetSockNameError = error{ | 512 | pub const GetSockNameError = error{ |
| 639 | /// Insufficient resources were available in the system to perform the operation. | 513 | /// Insufficient resources were available in the system to perform the operation. |
| 640 | SystemResources, | 514 | SystemResources, |
| ... | @@ -913,35 +787,6 @@ pub fn sysctl( | ... | @@ -913,35 +787,6 @@ pub fn sysctl( |
| 913 | } | 787 | } |
| 914 | } | 788 | } |
| 915 | 789 | ||
| 916 | pub const FcntlError = error{ | ||
| 917 | PermissionDenied, | ||
| 918 | FileBusy, | ||
| 919 | ProcessFdQuotaExceeded, | ||
| 920 | Locked, | ||
| 921 | DeadLock, | ||
| 922 | LockedRegionLimitExceeded, | ||
| 923 | } || UnexpectedError; | ||
| 924 | |||
| 925 | pub fn fcntl(fd: fd_t, cmd: i32, arg: usize) FcntlError!usize { | ||
| 926 | while (true) { | ||
| 927 | const rc = system.fcntl(fd, cmd, arg); | ||
| 928 | switch (errno(rc)) { | ||
| 929 | .SUCCESS => return @intCast(rc), | ||
| 930 | .INTR => continue, | ||
| 931 | .AGAIN, .ACCES => return error.Locked, | ||
| 932 | .BADF => unreachable, | ||
| 933 | .BUSY => return error.FileBusy, | ||
| 934 | .INVAL => unreachable, // invalid parameters | ||
| 935 | .PERM => return error.PermissionDenied, | ||
| 936 | .MFILE => return error.ProcessFdQuotaExceeded, | ||
| 937 | .NOTDIR => unreachable, // invalid parameter | ||
| 938 | .DEADLK => return error.DeadLock, | ||
| 939 | .NOLCK => return error.LockedRegionLimitExceeded, | ||
| 940 | else => |err| return unexpectedErrno(err), | ||
| 941 | } | ||
| 942 | } | ||
| 943 | } | ||
| 944 | |||
| 945 | pub fn getSelfPhdrs() []std.elf.ElfN.Phdr { | 790 | pub fn getSelfPhdrs() []std.elf.ElfN.Phdr { |
| 946 | 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; |
| 947 | 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 | } |