[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