[libc-commits] [libc] [libc] Implement sockatmark (PR #205400)
Pavel Labath via libc-commits
libc-commits at lists.llvm.org
Wed Jun 24 03:03:00 PDT 2026
https://github.com/labath updated https://github.com/llvm/llvm-project/pull/205400
>From e26a46a40bdedcab24303d35c29c259419501b8c Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Thu, 18 Jun 2026 03:45:12 +0000
Subject: [PATCH 1/2] [libc] Implement sockatmark
This patch implements sockatmark as a simple wrapper around
ioctl(SIOCATMARK).
I don't test it with actual out of band data, as that requires a TCP connection,
which is more complicated to set up.
Assisted by Gemini.
---
libc/config/linux/aarch64/entrypoints.txt | 1 +
libc/config/linux/riscv/entrypoints.txt | 1 +
libc/config/linux/x86_64/entrypoints.txt | 1 +
libc/include/sys/socket.yaml | 6 +++
libc/src/sys/socket/CMakeLists.txt | 7 +++
libc/src/sys/socket/linux/CMakeLists.txt | 14 +++++
libc/src/sys/socket/linux/sockatmark.cpp | 33 ++++++++++++
libc/src/sys/socket/sockatmark.h | 25 +++++++++
libc/test/src/sys/socket/linux/CMakeLists.txt | 18 +++++++
.../src/sys/socket/linux/sockatmark_test.cpp | 54 +++++++++++++++++++
10 files changed, 160 insertions(+)
create mode 100644 libc/src/sys/socket/linux/sockatmark.cpp
create mode 100644 libc/src/sys/socket/sockatmark.h
create mode 100644 libc/test/src/sys/socket/linux/sockatmark_test.cpp
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 251913fd57b99..8ccf16c370f70 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -303,6 +303,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.socket.sendto
libc.src.sys.socket.setsockopt
libc.src.sys.socket.shutdown
+ libc.src.sys.socket.sockatmark
libc.src.sys.socket.socket
libc.src.sys.socket.socketpair
# TODO: These functions are not compatible with 64-bit musl. They need to
diff --git a/libc/config/linux/riscv/entrypoints.txt b/libc/config/linux/riscv/entrypoints.txt
index a9839b44a0042..3e2be93df3dbb 100644
--- a/libc/config/linux/riscv/entrypoints.txt
+++ b/libc/config/linux/riscv/entrypoints.txt
@@ -303,6 +303,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.socket.sendto
libc.src.sys.socket.setsockopt
libc.src.sys.socket.shutdown
+ libc.src.sys.socket.sockatmark
libc.src.sys.socket.socket
libc.src.sys.socket.socketpair
# TODO: These functions are not compatible with 64-bit musl. They need to
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 037c8b50c352e..6f2d4f11d27aa 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -333,6 +333,7 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.socket.sendto
libc.src.sys.socket.setsockopt
libc.src.sys.socket.shutdown
+ libc.src.sys.socket.sockatmark
libc.src.sys.socket.socket
libc.src.sys.socket.socketpair
# TODO: These functions are not compatible with 64-bit musl. They need to
diff --git a/libc/include/sys/socket.yaml b/libc/include/sys/socket.yaml
index 18b8b9e750aa7..fb121fa805f3b 100644
--- a/libc/include/sys/socket.yaml
+++ b/libc/include/sys/socket.yaml
@@ -178,6 +178,12 @@ functions:
arguments:
- type: int
- type: int
+ - name: sockatmark
+ standards:
+ - posix
+ return_type: int
+ arguments:
+ - type: int
- name: socket
standards:
- posix
diff --git a/libc/src/sys/socket/CMakeLists.txt b/libc/src/sys/socket/CMakeLists.txt
index 45c0aee6f6f3b..2806bb0a752ff 100644
--- a/libc/src/sys/socket/CMakeLists.txt
+++ b/libc/src/sys/socket/CMakeLists.txt
@@ -142,3 +142,10 @@ add_entrypoint_object(
DEPENDS
.${LIBC_TARGET_OS}.shutdown
)
+
+add_entrypoint_object(
+ sockatmark
+ ALIAS
+ DEPENDS
+ .${LIBC_TARGET_OS}.sockatmark
+)
diff --git a/libc/src/sys/socket/linux/CMakeLists.txt b/libc/src/sys/socket/linux/CMakeLists.txt
index 82a7554f80107..06015d5f65b9a 100644
--- a/libc/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/src/sys/socket/linux/CMakeLists.txt
@@ -276,3 +276,17 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
libc.src.errno.errno
)
+
+add_entrypoint_object(
+ sockatmark
+ SRCS
+ sockatmark.cpp
+ HDRS
+ ../sockatmark.h
+ DEPENDS
+ libc.hdr.sys_ioctl_macros
+ libc.include.sys_socket
+ libc.src.__support.common
+ libc.src.__support.OSUtil.linux.syscall_wrappers.ioctl
+ libc.src.errno.errno
+)
diff --git a/libc/src/sys/socket/linux/sockatmark.cpp b/libc/src/sys/socket/linux/sockatmark.cpp
new file mode 100644
index 0000000000000..9ae896c8b9892
--- /dev/null
+++ b/libc/src/sys/socket/linux/sockatmark.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Linux implementation of sockatmark.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/socket/sockatmark.h"
+#include "hdr/sys_ioctl_macros.h" // For SIOCATMARK.
+#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, sockatmark, (int sockfd)) {
+ int mark = 0;
+ ErrorOr<int> result = linux_syscalls::ioctl(sockfd, SIOCATMARK, &mark);
+ if (!result.has_value()) {
+ libc_errno = result.error();
+ return -1;
+ }
+
+ return mark;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/socket/sockatmark.h b/libc/src/sys/socket/sockatmark.h
new file mode 100644
index 0000000000000..a3e1e2046fae8
--- /dev/null
+++ b/libc/src/sys/socket/sockatmark.h
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Implementation header for sockatmark.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_SOCKET_SOCKATMARK_H
+#define LLVM_LIBC_SRC_SYS_SOCKET_SOCKATMARK_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int sockatmark(int sockfd);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_SOCKET_SOCKATMARK_H
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index fc02db4aec7a0..76585f6b9129d 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -149,6 +149,24 @@ add_libc_unittest(
libc.test.UnitTest.ErrnoSetterMatcher
)
+add_libc_unittest(
+ sockatmark_test
+ SUITE
+ libc_sys_socket_unittests
+ SRCS
+ sockatmark_test.cpp
+ DEPENDS
+ libc.hdr.sys_socket_macros
+ libc.src.errno.errno
+ libc.src.sys.socket.sockatmark
+ libc.src.sys.socket.socketpair
+ libc.src.unistd.close
+ libc.src.unistd.pipe
+ libc.src.__support.CPP.scope
+ libc.test.UnitTest.ErrnoCheckingTest
+ libc.test.UnitTest.ErrnoSetterMatcher
+)
+
add_libc_unittest(
sockname_test
SUITE
diff --git a/libc/test/src/sys/socket/linux/sockatmark_test.cpp b/libc/test/src/sys/socket/linux/sockatmark_test.cpp
new file mode 100644
index 0000000000000..249bd298f4832
--- /dev/null
+++ b/libc/test/src/sys/socket/linux/sockatmark_test.cpp
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Unittests for sockatmark.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/sys_socket_macros.h" // For AF_UNIX and SOCK_DGRAM
+#include "src/__support/CPP/scope.h"
+#include "src/sys/socket/sockatmark.h"
+#include "src/sys/socket/socketpair.h"
+#include "src/unistd/close.h"
+#include "src/unistd/pipe.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
+using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
+using LlvmLibcSockatmarkTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
+
+TEST_F(LlvmLibcSockatmarkTest, SocketpairReturnsFalse) {
+ int sockpair[2] = {-1, -1};
+ ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_DGRAM, 0, sockpair),
+ Succeeds(0));
+ scope_exit close_sockpair([&] {
+ ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[0]), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::close(sockpair[1]), Succeeds(0));
+ });
+
+ ASSERT_THAT(LIBC_NAMESPACE::sockatmark(sockpair[0]), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::sockatmark(sockpair[1]), Succeeds(0));
+}
+
+TEST_F(LlvmLibcSockatmarkTest, InvalidFdFails) {
+ ASSERT_THAT(LIBC_NAMESPACE::sockatmark(-1), Fails(EBADF));
+}
+
+TEST_F(LlvmLibcSockatmarkTest, NonSocketFdFails) {
+ int pipefd[2] = {-1, -1};
+ ASSERT_THAT(LIBC_NAMESPACE::pipe(pipefd), Succeeds(0));
+ scope_exit close_pipe([&] {
+ ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[0]), Succeeds(0));
+ ASSERT_THAT(LIBC_NAMESPACE::close(pipefd[1]), Succeeds(0));
+ });
+
+ ASSERT_THAT(LIBC_NAMESPACE::sockatmark(pipefd[0]), Fails(ENOTTY));
+}
>From 48bfed73956ecd60e1f680bc84cbd711bce0c29f Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Wed, 24 Jun 2026 10:00:59 +0000
Subject: [PATCH 2/2] format, fix "missing SIOCATMARK" errors
---
libc/src/sys/socket/linux/sockatmark.cpp | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/libc/src/sys/socket/linux/sockatmark.cpp b/libc/src/sys/socket/linux/sockatmark.cpp
index 9ae896c8b9892..2f864b64d3270 100644
--- a/libc/src/sys/socket/linux/sockatmark.cpp
+++ b/libc/src/sys/socket/linux/sockatmark.cpp
@@ -12,11 +12,14 @@
//===----------------------------------------------------------------------===//
#include "src/sys/socket/sockatmark.h"
-#include "hdr/sys_ioctl_macros.h" // For SIOCATMARK.
#include "src/__support/OSUtil/linux/syscall_wrappers/ioctl.h"
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
+// For SIOCATMARK. Can't use hdr/sys_ioctl_macros, as not all system library
+// versions define it.
+#include <linux/sockios.h> // For SIOCATMARK.
+
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, sockatmark, (int sockfd)) {
More information about the libc-commits
mailing list