From 3c1f35247d107ad3669216fc09e75d66fa146363 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 28 Jul 2022 00:36:18 +0200 Subject: [PATCH] unix: implement recvmsgRaw and sendmsgN on aix This allows using RecvmsgBuffers and SendmsgBuffers on aix in x/net. For golang/go#54099 Change-Id: Ib21c59244c9d74b826f4fc8ba3314e3602fd9a8a Reviewed-on: https://go-review.googlesource.com/c/sys/+/419396 Reviewed-by: Cherry Mui Reviewed-by: Ian Lance Taylor Run-TryBot: Tobias Klauser Auto-Submit: Tobias Klauser TryBot-Result: Gopher Robot --- unix/syscall_aix.go | 57 ++++++++++++++++++++++++++++++++++++--- unix/syscall_unix_test.go | 4 --- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/unix/syscall_aix.go b/unix/syscall_aix.go index ac579c60f..e2a30e88c 100644 --- a/unix/syscall_aix.go +++ b/unix/syscall_aix.go @@ -218,13 +218,62 @@ func Accept(fd int) (nfd int, sa Sockaddr, err error) { } func recvmsgRaw(fd int, iov []Iovec, oob []byte, flags int, rsa *RawSockaddrAny) (n, oobn int, recvflags int, err error) { - // Recvmsg not implemented on AIX - return -1, -1, -1, ENOSYS + var msg Msghdr + msg.Name = (*byte)(unsafe.Pointer(rsa)) + msg.Namelen = uint32(SizeofSockaddrAny) + var dummy byte + if len(oob) > 0 { + // receive at least one normal byte + if emptyIovecs(iov) { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } + if n, err = recvmsg(fd, &msg, flags); n == -1 { + return + } + oobn = int(msg.Controllen) + recvflags = int(msg.Flags) + return } func sendmsgN(fd int, iov []Iovec, oob []byte, ptr unsafe.Pointer, salen _Socklen, flags int) (n int, err error) { - // SendmsgN not implemented on AIX - return -1, ENOSYS + var msg Msghdr + msg.Name = (*byte)(unsafe.Pointer(ptr)) + msg.Namelen = uint32(salen) + var dummy byte + var empty bool + if len(oob) > 0 { + // send at least one normal byte + empty := emptyIovecs(iov) + if empty { + var iova [1]Iovec + iova[0].Base = &dummy + iova[0].SetLen(1) + iov = iova[:] + } + msg.Control = (*byte)(unsafe.Pointer(&oob[0])) + msg.SetControllen(len(oob)) + } + if len(iov) > 0 { + msg.Iov = &iov[0] + msg.SetIovlen(len(iov)) + } + if n, err = sendmsg(fd, &msg, flags); err != nil { + return 0, err + } + if len(oob) > 0 && empty { + n = 0 + } + return n, nil } func anyToSockaddr(fd int, rsa *RawSockaddrAny) (Sockaddr, error) { diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go index c20afbef6..f2c0ed8fa 100644 --- a/unix/syscall_unix_test.go +++ b/unix/syscall_unix_test.go @@ -957,10 +957,6 @@ func TestSend(t *testing.T) { } func TestSendmsgBuffers(t *testing.T) { - if runtime.GOOS == "aix" { - t.Skipf("SendmsgBuffers not supported on %s", runtime.GOOS) - } - fds, err := unix.Socketpair(unix.AF_LOCAL, unix.SOCK_STREAM, 0) if err != nil { t.Fatal(err)