Commit 79313d844f
lib/std/c.zig
@@ -10599,6 +10599,12 @@ pub const socket = switch (native_os) {
else => private.socket,
};
+pub const socketpair = switch (native_os) {
+ // https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/#unsupported\unavailable:
+ .windows => void,
+ else => private.socketpair,
+};
+
pub const stat = switch (native_os) {
.macos => switch (native_arch) {
.x86_64 => private.@"stat$INODE64",
@@ -10740,7 +10746,6 @@ pub extern "c" fn uname(buf: *utsname) c_int;
pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;
pub extern "c" fn shutdown(socket: fd_t, how: c_int) c_int;
pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
-pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
pub extern "c" fn getpeername(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
@@ -11429,6 +11434,7 @@ const private = struct {
extern "c" fn sigismember(set: ?*const sigset_t, signo: c_int) c_int;
extern "c" fn sigprocmask(how: c_int, noalias set: ?*const sigset_t, noalias oset: ?*sigset_t) c_int;
extern "c" fn socket(domain: c_uint, sock_type: c_uint, protocol: c_uint) c_int;
+ extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
extern "c" fn stat(noalias path: [*:0]const u8, noalias buf: *Stat) c_int;
extern "c" fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) c_int;
extern "c" fn sysconf(sc: c_int) c_long;
lib/std/posix.zig
@@ -3671,6 +3671,46 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
}
}
+pub fn socketpair(domain: u32, socket_type: u32, protocol: u32) SocketError![2]socket_t {
+ // Note to the future: we could provide a shim here for e.g. windows which
+ // creates a listening socket, then creates a second socket and connects it
+ // to the listening socket, and then returns the two.
+ if (@TypeOf(system.socketpair) == void)
+ @compileError("socketpair() not supported by this OS");
+
+ // I'm not really sure if haiku supports flags here. I'm following the
+ // existing filter here from pipe2(), because it sure seems like it
+ // supports flags there too, but haiku can be hard to understand.
+ const have_sock_flags = !builtin.target.os.tag.isDarwin() and native_os != .haiku;
+ const filtered_sock_type = if (!have_sock_flags)
+ socket_type & ~@as(u32, SOCK.NONBLOCK | SOCK.CLOEXEC)
+ else
+ socket_type;
+ var socks: [2]socket_t = undefined;
+ const rc = system.socketpair(domain, filtered_sock_type, protocol, &socks);
+ switch (errno(rc)) {
+ .SUCCESS => {
+ errdefer close(socks[0]);
+ errdefer close(socks[1]);
+ if (!have_sock_flags) {
+ try setSockFlags(socks[0], socket_type);
+ try setSockFlags(socks[1], socket_type);
+ }
+ return socks;
+ },
+ .ACCES => return error.AccessDenied,
+ .AFNOSUPPORT => return error.AddressFamilyNotSupported,
+ .INVAL => return error.ProtocolFamilyNotAvailable,
+ .MFILE => return error.ProcessFdQuotaExceeded,
+ .NFILE => return error.SystemFdQuotaExceeded,
+ .NOBUFS => return error.SystemResources,
+ .NOMEM => return error.SystemResources,
+ .PROTONOSUPPORT => return error.ProtocolNotSupported,
+ .PROTOTYPE => return error.SocketTypeNotSupported,
+ else => |err| return unexpectedErrno(err),
+ }
+}
+
pub const ShutdownError = error{
ConnectionAborted,