[libc-commits] [libc] [libc] Add sys/xattr.h and entrypoints flistxattr, listxattr, and llistxattr. (PR #224357)

Alex Strelnikov via libc-commits libc-commits at lists.llvm.org
Thu Sep 17 11:58:31 PDT 2026


https://github.com/strel-12 updated https://github.com/llvm/llvm-project/pull/224357

>From 1fcdee60011694a46dd6e98a8b8eb8b584f90ca6 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Thu, 17 Sep 2026 16:05:04 +0000
Subject: [PATCH 1/5] Add sys/xattr.h and entrypoints flistxattr, listxattr,
 and llistxattr.

---
 libc/config/linux/aarch64/entrypoints.txt     |   5 +
 libc/config/linux/aarch64/headers.txt         |   1 +
 libc/config/linux/x86_64/entrypoints.txt      |   5 +
 libc/config/linux/x86_64/headers.txt          |   1 +
 libc/include/CMakeLists.txt                   |  10 ++
 libc/include/sys/xattr.yaml                   |  32 ++++
 .../linux/syscall_wrappers/CMakeLists.txt     |  36 +++++
 .../linux/syscall_wrappers/flistxattr.h       |  36 +++++
 .../OSUtil/linux/syscall_wrappers/listxattr.h |  37 +++++
 .../linux/syscall_wrappers/llistxattr.h       |  37 +++++
 libc/src/sys/CMakeLists.txt                   |   1 +
 libc/src/sys/xattr/CMakeLists.txt             |  24 +++
 libc/src/sys/xattr/flistxattr.h               |  27 ++++
 libc/src/sys/xattr/linux/CMakeLists.txt       |  40 +++++
 libc/src/sys/xattr/linux/flistxattr.cpp       |  31 ++++
 libc/src/sys/xattr/linux/listxattr.cpp        |  35 +++++
 libc/src/sys/xattr/linux/llistxattr.cpp       |  35 +++++
 libc/src/sys/xattr/listxattr.h                |  28 ++++
 libc/src/sys/xattr/llistxattr.h               |  28 ++++
 libc/test/src/sys/CMakeLists.txt              |   1 +
 libc/test/src/sys/xattr/CMakeLists.txt        |  66 ++++++++
 libc/test/src/sys/xattr/flistxattr_test.cpp   |  97 ++++++++++++
 libc/test/src/sys/xattr/listxattr_test.cpp    | 141 ++++++++++++++++++
 libc/test/src/sys/xattr/llistxattr_test.cpp   | 138 +++++++++++++++++
 .../src/sys/xattr/testdata/CMakeLists.txt     |   0
 25 files changed, 892 insertions(+)
 create mode 100644 libc/include/sys/xattr.yaml
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
 create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
 create mode 100644 libc/src/sys/xattr/CMakeLists.txt
 create mode 100644 libc/src/sys/xattr/flistxattr.h
 create mode 100644 libc/src/sys/xattr/linux/CMakeLists.txt
 create mode 100644 libc/src/sys/xattr/linux/flistxattr.cpp
 create mode 100644 libc/src/sys/xattr/linux/listxattr.cpp
 create mode 100644 libc/src/sys/xattr/linux/llistxattr.cpp
 create mode 100644 libc/src/sys/xattr/listxattr.h
 create mode 100644 libc/src/sys/xattr/llistxattr.h
 create mode 100644 libc/test/src/sys/xattr/CMakeLists.txt
 create mode 100644 libc/test/src/sys/xattr/flistxattr_test.cpp
 create mode 100644 libc/test/src/sys/xattr/listxattr_test.cpp
 create mode 100644 libc/test/src/sys/xattr/llistxattr_test.cpp
 create mode 100644 libc/test/src/sys/xattr/testdata/CMakeLists.txt

diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 77610d6d06057c..5df64d84c31fa0 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -371,6 +371,11 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.wait.wait4
     libc.src.sys.wait.waitpid
 
+    # sys/xattr.h entrypoints
+    libc.src.sys.xattr.flistxattr
+    libc.src.sys.xattr.listxattr
+    libc.src.sys.xattr.llistxattr
+
     # sys/prctl.h entrypoints
     libc.src.sys.prctl.prctl
 
diff --git a/libc/config/linux/aarch64/headers.txt b/libc/config/linux/aarch64/headers.txt
index 399149d4dde902..bcdfa308695063 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -80,6 +80,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_utsname
     libc.include.sys_vfs
     libc.include.sys_wait
+    libc.include.sys_xattr
     libc.include.syscall
     libc.include.sysexits
     libc.include.syslog
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 65b820e551be64..9e88fe6a592598 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -410,6 +410,11 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.wait.wait4
     libc.src.sys.wait.waitpid
 
+    # sys/xattr.h entrypoints
+    libc.src.sys.xattr.flistxattr
+    libc.src.sys.xattr.listxattr
+    libc.src.sys.xattr.llistxattr
+
     # sys/prctl.h entrypoints
     libc.src.sys.prctl.prctl
 
diff --git a/libc/config/linux/x86_64/headers.txt b/libc/config/linux/x86_64/headers.txt
index 6df2b54216c1f2..02450cbf66cb1d 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -85,6 +85,7 @@ set(TARGET_PUBLIC_HEADERS
     libc.include.sys_utsname
     libc.include.sys_vfs
     libc.include.sys_wait
+    libc.include.sys_xattr
     libc.include.syscall
     libc.include.sysexits
     libc.include.syslog
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index 35b7bdc8c184e1..2afa4cb6c9cb40 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1086,6 +1086,16 @@ add_header_macro(
     .llvm-libc-types.siginfo_t
 )
 
+add_header_macro(
+  sys_xattr
+  ../libc/include/sys/xattr.yaml
+  sys/xattr.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.size_t
+    .llvm-libc-types.ssize_t
+)
+
 file(MAKE_DIRECTORY ${LIBC_INCLUDE_DIR}/net)
 
 add_header_macro(
diff --git a/libc/include/sys/xattr.yaml b/libc/include/sys/xattr.yaml
new file mode 100644
index 00000000000000..b37a65f168d110
--- /dev/null
+++ b/libc/include/sys/xattr.yaml
@@ -0,0 +1,32 @@
+header: sys/xattr.h
+standards:
+  - linux
+macros: []
+types: []
+enums: []
+objects: []
+functions:
+  - name: listxattr
+    standards:
+      - linux
+    return_type: ssize_t
+    arguments:
+      - type: const char *
+      - type: char *
+      - type: size_t
+  - name: llistxattr
+    standards:
+      - linux
+    return_type: ssize_t
+    arguments:
+      - type: const char *
+      - type: char *
+      - type: size_t
+  - name: flistxattr
+    standards:
+      - linux
+    return_type: ssize_t
+    arguments:
+      - type: int
+      - type: char *
+      - type: size_t
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 9512528e9e5e29..c88f46b7cf19bb 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -215,6 +215,30 @@ add_header_library(
     libc.include.sys_syscall
 )
 
+add_header_library(
+  listxattr
+  HDRS
+    listxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)
+
+add_header_library(
+  llistxattr
+  HDRS
+    llistxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)
+
 add_header_library(
   read
   HDRS
@@ -864,6 +888,18 @@ add_header_library(
     libc.include.sys_syscall
 )
 
+add_header_library(
+  flistxattr
+  HDRS
+    flistxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)
+
 add_header_library(
   fsync
   HDRS
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
new file mode 100644
index 00000000000000..36981720dd28cb
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for flistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FLISTXATTR_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FLISTXATTR_H
+
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<ssize_t> flistxattr(int fd, char *list, size_t size) {
+  ssize_t ret = syscall_impl<ssize_t>(SYS_flistxattr, fd, list, size);
+  if (ret < 0)
+    return Error(-static_cast<int>(ret));
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FLISTXATTR_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
new file mode 100644
index 00000000000000..d2bbc62ef31639
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for listxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LISTXATTR_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LISTXATTR_H
+
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<ssize_t> listxattr(const char *path, char *list,
+                                       size_t size) {
+  ssize_t ret = syscall_impl<ssize_t>(SYS_listxattr, path, list, size);
+  if (ret < 0)
+    return Error(-static_cast<int>(ret));
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LISTXATTR_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
new file mode 100644
index 00000000000000..4796fc6d012d43
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
@@ -0,0 +1,37 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Syscall wrapper for llistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LLISTXATTR_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LLISTXATTR_H
+
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h>
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<ssize_t> llistxattr(const char *path, char *list,
+                                        size_t size) {
+  ssize_t ret = syscall_impl<ssize_t>(SYS_llistxattr, path, list, size);
+  if (ret < 0)
+    return Error(-static_cast<int>(ret));
+  return ret;
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_LLISTXATTR_H
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index 4249f72b4d78a2..afc4706c2b1c0b 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -21,3 +21,4 @@ add_subdirectory(uio)
 add_subdirectory(ioctl)
 add_subdirectory(sysmacros)
 add_subdirectory(sysinfo)
+add_subdirectory(xattr)
diff --git a/libc/src/sys/xattr/CMakeLists.txt b/libc/src/sys/xattr/CMakeLists.txt
new file mode 100644
index 00000000000000..d008639bddf0d9
--- /dev/null
+++ b/libc/src/sys/xattr/CMakeLists.txt
@@ -0,0 +1,24 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  flistxattr
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.flistxattr
+)
+
+add_entrypoint_object(
+  listxattr
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.listxattr
+)
+
+add_entrypoint_object(
+  llistxattr
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.llistxattr
+)
diff --git a/libc/src/sys/xattr/flistxattr.h b/libc/src/sys/xattr/flistxattr.h
new file mode 100644
index 00000000000000..cb6cb0d0d4fdb9
--- /dev/null
+++ b/libc/src/sys/xattr/flistxattr.h
@@ -0,0 +1,27 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Function declaration of flistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_FLISTXATTR_H
+#define LLVM_LIBC_SRC_SYS_XATTR_LINUX_FLISTXATTR_H
+
+#include "include/llvm-libc-types/size_t.h"
+#include "include/llvm-libc-types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t flistxattr(int fd, char *_Nullable list, size_t size);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_XATTR_LINUX_FLISTXATTR_H
diff --git a/libc/src/sys/xattr/linux/CMakeLists.txt b/libc/src/sys/xattr/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..8cabd69e2e3f3d
--- /dev/null
+++ b/libc/src/sys/xattr/linux/CMakeLists.txt
@@ -0,0 +1,40 @@
+add_entrypoint_object(
+  flistxattr
+  SRCS
+    flistxattr.cpp
+  HDRS
+    ../flistxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.linux.syscall_wrappers.flistxattr
+    libc.src.__support.common
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+)
+
+add_entrypoint_object(
+  listxattr
+  SRCS
+    listxattr.cpp
+  HDRS
+    ../listxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.linux.syscall_wrappers.listxattr
+    libc.src.__support.common
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+    libc.src.__support.macros.null_check
+)
+
+add_entrypoint_object(
+  llistxattr
+  SRCS
+    llistxattr.cpp
+  HDRS
+    ../llistxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.linux.syscall_wrappers.llistxattr
+    libc.src.__support.common
+    libc.src.__support.libc_errno
+    libc.src.__support.macros.config
+    libc.src.__support.macros.null_check
+)
diff --git a/libc/src/sys/xattr/linux/flistxattr.cpp b/libc/src/sys/xattr/linux/flistxattr.cpp
new file mode 100644
index 00000000000000..68119436aa29e2
--- /dev/null
+++ b/libc/src/sys/xattr/linux/flistxattr.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 of flistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/xattr/flistxattr.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(ssize_t, flistxattr, (int fd, char *list, size_t size)) {
+  ErrorOr<ssize_t> ret = linux_syscalls::flistxattr(fd, list, size);
+  if (!ret) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return *ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/xattr/linux/listxattr.cpp b/libc/src/sys/xattr/linux/listxattr.cpp
new file mode 100644
index 00000000000000..d0ef1558ce75c0
--- /dev/null
+++ b/libc/src/sys/xattr/linux/listxattr.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 of listxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/xattr/listxattr.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/listxattr.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(ssize_t, listxattr,
+                   (const char *path, char *list, size_t size)) {
+  LIBC_CRASH_ON_NULLPTR(path);
+
+  ErrorOr<ssize_t> ret = linux_syscalls::listxattr(path, list, size);
+  if (!ret) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return *ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/xattr/linux/llistxattr.cpp b/libc/src/sys/xattr/linux/llistxattr.cpp
new file mode 100644
index 00000000000000..12d073f19deac7
--- /dev/null
+++ b/libc/src/sys/xattr/linux/llistxattr.cpp
@@ -0,0 +1,35 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 of llistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/xattr/llistxattr.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h"
+#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(ssize_t, llistxattr,
+                   (const char *path, char *list, size_t size)) {
+  LIBC_CRASH_ON_NULLPTR(path);
+
+  ErrorOr<ssize_t> ret = linux_syscalls::llistxattr(path, list, size);
+  if (!ret) {
+    libc_errno = ret.error();
+    return -1;
+  }
+  return *ret;
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/xattr/listxattr.h b/libc/src/sys/xattr/listxattr.h
new file mode 100644
index 00000000000000..76cf26b5717104
--- /dev/null
+++ b/libc/src/sys/xattr/listxattr.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Function declaration of listxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
+#define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
+
+#include "include/llvm-libc-types/size_t.h"
+#include "include/llvm-libc-types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t listxattr(const char *_Nullable path, char *_Nullable list,
+                  size_t size);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
diff --git a/libc/src/sys/xattr/llistxattr.h b/libc/src/sys/xattr/llistxattr.h
new file mode 100644
index 00000000000000..14ce1fdd1311ab
--- /dev/null
+++ b/libc/src/sys/xattr/llistxattr.h
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Function declaration of llistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
+#define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
+
+#include "include/llvm-libc-types/size_t.h"
+#include "include/llvm-libc-types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t llistxattr(const char *_Nullable path, char *_Nullable list,
+                   size_t size);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 17bf10f2b3d079..ff7ed11d09525a 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -20,3 +20,4 @@ add_subdirectory(ioctl)
 add_subdirectory(sem)
 add_subdirectory(sysmacros)
 add_subdirectory(sysinfo)
+add_subdirectory(xattr)
diff --git a/libc/test/src/sys/xattr/CMakeLists.txt b/libc/test/src/sys/xattr/CMakeLists.txt
new file mode 100644
index 00000000000000..3ac896f0c0dcfe
--- /dev/null
+++ b/libc/test/src/sys/xattr/CMakeLists.txt
@@ -0,0 +1,66 @@
+add_custom_target(libc_sys_xattr_unittests)
+
+add_libc_test(
+  flistxattr_test
+  SUITE
+    libc_sys_xattr_unittests
+  SRCS
+    flistxattr_test.cpp
+  DEPENDS
+    libc.hdr.sys_stat_macros
+    libc.include.sys_xattr
+    libc.src.__support.CPP.scope
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.libc_errno
+    libc.src.errno.errno
+    libc.src.fcntl.creat
+    libc.src.sys.xattr.flistxattr
+    libc.src.unistd.close
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
+add_libc_test(
+  listxattr_test
+  SUITE
+    libc_sys_xattr_unittests
+  SRCS
+    listxattr_test.cpp
+  DEPENDS
+    libc.hdr.sys_stat_macros
+    libc.include.sys_xattr
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.libc_errno
+    libc.src.errno.errno
+    libc.src.fcntl.creat
+    libc.src.sys.xattr.listxattr
+    libc.src.unistd.close
+    libc.src.unistd.symlink
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
+add_libc_test(
+  llistxattr_test
+  SUITE
+    libc_sys_xattr_unittests
+  SRCS
+    llistxattr_test.cpp
+  DEPENDS
+    libc.hdr.sys_stat_macros
+    libc.include.sys_xattr
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.libc_errno
+    libc.src.errno.errno
+    libc.src.fcntl.creat
+    libc.src.sys.xattr.llistxattr
+    libc.src.unistd.close
+    libc.src.unistd.symlink
+    libc.src.unistd.unlink
+    libc.test.UnitTest.ErrnoCheckingTest
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+
+add_subdirectory(testdata)
diff --git a/libc/test/src/sys/xattr/flistxattr_test.cpp b/libc/test/src/sys/xattr/flistxattr_test.cpp
new file mode 100644
index 00000000000000..cb9dab84be0ec0
--- /dev/null
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -0,0 +1,97 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unit tests for flistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/sys_stat_macros.h"
+#include "src/__support/CPP/scope.h"
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/libc_errno.h"
+#include "src/fcntl/creat.h"
+#include "src/sys/xattr/flistxattr.h"
+#include "src/unistd/close.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/xattr.h>
+
+namespace {
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcListxattrTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
+using LIBC_NAMESPACE::cpp::string_view;
+
+int recreate_test_file(const char *path) {
+  LIBC_NAMESPACE::unlink(path);
+  LIBC_NAMESPACE::libc_errno = 0;
+  return LIBC_NAMESPACE::creat(path, S_IRWXU);
+}
+
+TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
+  int fd = recreate_test_file("testdata/flistxattr_no_xattrs.txt");
+  ASSERT_ERRNO_SUCCESS();
+  scope_exit close_file(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
+
+  EXPECT_THAT(LIBC_NAMESPACE::flistxattr(fd, nullptr, 0), Succeeds<ssize_t>(0));
+
+  constexpr size_t BUFFER_SIZE = 32;
+  char buffer[BUFFER_SIZE] = {};
+  EXPECT_THAT(LIBC_NAMESPACE::flistxattr(fd, buffer, BUFFER_SIZE),
+              Succeeds<ssize_t>(0));
+}
+
+TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
+  constexpr const char *TEST_FILE_NAME =
+      "testdata/flistxattr_with_user_xattr.txt";
+
+  int fd = recreate_test_file(TEST_FILE_NAME);
+  ASSERT_ERRNO_SUCCESS();
+  scope_exit close_file(
+      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
+
+  string_view XATTR_NAME = "user.test_attr";
+  string_view XATTR_VALUE = "test_value";
+  ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
+                   SYS_fsetxattr, fd, XATTR_NAME.data(), XATTR_VALUE.data(),
+                   XATTR_VALUE.size(),
+                   /* flags = */ 0));
+  size_t xattr_name_null_terminated_len = XATTR_NAME.size() + 1;
+
+  ASSERT_THAT(LIBC_NAMESPACE::flistxattr(fd, nullptr, 0),
+              Succeeds<ssize_t>(xattr_name_null_terminated_len));
+
+  {
+    constexpr size_t BUFFER_SIZE = 32;
+    ASSERT_GE(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    ASSERT_THAT(LIBC_NAMESPACE::flistxattr(fd, buffer, BUFFER_SIZE),
+                Succeeds(xattr_name_null_terminated_len));
+    string_view result_str(buffer, xattr_name_null_terminated_len - 1);
+    EXPECT_EQ(result_str, XATTR_NAME);
+  }
+
+  // Call with insufficient buffer size to check failing errno.
+  {
+    constexpr size_t BUFFER_SIZE = 14;
+    ASSERT_LT(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    EXPECT_THAT(LIBC_NAMESPACE::flistxattr(fd, buffer, BUFFER_SIZE),
+                Fails<ssize_t>(ERANGE));
+  }
+}
+
+} // namespace
diff --git a/libc/test/src/sys/xattr/listxattr_test.cpp b/libc/test/src/sys/xattr/listxattr_test.cpp
new file mode 100644
index 00000000000000..2f0db56885f088
--- /dev/null
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -0,0 +1,141 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unit tests for listxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/xattr/listxattr.h"
+
+#include "hdr/sys_stat_macros.h"
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/libc_errno.h"
+#include "src/fcntl/creat.h"
+#include "src/unistd/close.h"
+#include "src/unistd/symlink.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/xattr.h>
+
+namespace {
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcListxattrTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::string_view;
+
+int recreate_test_file(const char *path) {
+  LIBC_NAMESPACE::unlink(path);
+  LIBC_NAMESPACE::libc_errno = 0;
+  return LIBC_NAMESPACE::creat(path, S_IRWXU);
+}
+
+int recreate_test_symlink(const char *target, const char *linkpath) {
+  LIBC_NAMESPACE::unlink(linkpath);
+  LIBC_NAMESPACE::libc_errno = 0;
+  return LIBC_NAMESPACE::symlink(target, linkpath);
+}
+
+TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
+  constexpr const char *TEST_FILE_NAME = "testdata/listxattr_no_xattrs.txt";
+
+  int fd = recreate_test_file(TEST_FILE_NAME);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+  EXPECT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, nullptr, 0),
+              Succeeds<ssize_t>(0));
+
+  constexpr size_t BUFFER_SIZE = 32;
+  char buffer[BUFFER_SIZE] = {};
+  EXPECT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+              Succeeds<ssize_t>(0));
+}
+
+TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
+  constexpr const char *TEST_FILE_NAME =
+      "testdata/listxattr_with_user_xattr.txt";
+  constexpr const char *TEST_SYMLINK_TARGET = "listxattr_with_user_xattr.txt";
+  constexpr const char *TEST_SYMLINK_NAME = "testdata/listxattr_symlink.txt";
+
+  int fd = recreate_test_file(TEST_FILE_NAME);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+  ASSERT_THAT(recreate_test_symlink(TEST_SYMLINK_TARGET, TEST_SYMLINK_NAME),
+              Succeeds(0));
+
+  string_view XATTR_NAME = "user.test_attr";
+  string_view XATTR_VALUE = "test_value";
+  ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
+                   SYS_setxattr, TEST_FILE_NAME, XATTR_NAME.data(),
+                   XATTR_VALUE.data(), XATTR_VALUE.size(),
+                   /* flags = */ 0));
+  size_t xattr_name_null_terminated_len = XATTR_NAME.size() + 1;
+
+  // Call with the test file path.
+  {
+    ASSERT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, nullptr, 0),
+                Succeeds<ssize_t>(xattr_name_null_terminated_len));
+
+    constexpr size_t BUFFER_SIZE = 32;
+    ASSERT_GE(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    ASSERT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+                Succeeds(xattr_name_null_terminated_len));
+    string_view result_str(buffer, xattr_name_null_terminated_len - 1);
+    EXPECT_EQ(result_str, XATTR_NAME);
+  }
+
+  // Call with the symlink path to verify the correct syscall is used
+  // internally; listxattr instead of llistxattr.
+  {
+    ASSERT_THAT(LIBC_NAMESPACE::listxattr(TEST_SYMLINK_NAME, nullptr, 0),
+                Succeeds<ssize_t>(xattr_name_null_terminated_len));
+
+    constexpr size_t BUFFER_SIZE = 32;
+    ASSERT_GE(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    ASSERT_THAT(
+        LIBC_NAMESPACE::listxattr(TEST_SYMLINK_NAME, buffer, BUFFER_SIZE),
+        Succeeds(xattr_name_null_terminated_len));
+    string_view result_str(buffer, xattr_name_null_terminated_len - 1);
+    EXPECT_EQ(result_str, XATTR_NAME);
+  }
+
+  // Call with insufficient buffer size to check failing errno.
+  {
+    constexpr size_t BUFFER_SIZE = 14;
+    ASSERT_LT(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    EXPECT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+                Fails<ssize_t>(ERANGE));
+  }
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS)
+
+TEST(LlvmLibcListxattrTest, CrashOnNullPath) {
+  EXPECT_DEATH(
+      [] {
+        constexpr size_t BUFFER_SIZE = 32;
+        char buffer[BUFFER_SIZE] = {};
+        LIBC_NAMESPACE::listxattr(nullptr, buffer, BUFFER_SIZE);
+      },
+      WITH_SIGNAL(-1));
+}
+
+#endif // LIBC_ADD_NULL_CHECKS
+
+} // namespace
diff --git a/libc/test/src/sys/xattr/llistxattr_test.cpp b/libc/test/src/sys/xattr/llistxattr_test.cpp
new file mode 100644
index 00000000000000..a4b0c3795322a8
--- /dev/null
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -0,0 +1,138 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Unit tests for llistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hdr/sys_stat_macros.h"
+#include "src/__support/OSUtil/linux/syscall.h"
+#include "src/__support/libc_errno.h"
+#include "src/fcntl/creat.h"
+#include "src/sys/xattr/llistxattr.h"
+#include "src/unistd/close.h"
+#include "src/unistd/symlink.h"
+#include "src/unistd/unlink.h"
+#include "test/UnitTest/ErrnoCheckingTest.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/Test.h"
+
+#include <sys/xattr.h>
+
+namespace {
+
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+using LlvmLibcLlistxattrTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::string_view;
+
+int recreate_test_file(const char *path) {
+  LIBC_NAMESPACE::unlink(path);
+  LIBC_NAMESPACE::libc_errno = 0;
+  return LIBC_NAMESPACE::creat(path, S_IRWXU);
+}
+
+int recreate_test_symlink(const char *target, const char *linkpath) {
+  LIBC_NAMESPACE::unlink(linkpath);
+  LIBC_NAMESPACE::libc_errno = 0;
+  return LIBC_NAMESPACE::symlink(target, linkpath);
+}
+
+TEST_F(LlvmLibcLlistxattrTest, NoExtendedAttributes) {
+  constexpr const char *TEST_FILE_NAME = "testdata/llistxattr_no_xattrs.txt";
+
+  int fd = recreate_test_file(TEST_FILE_NAME);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+  EXPECT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, nullptr, 0),
+              Succeeds<ssize_t>(0));
+
+  constexpr size_t BUFFER_SIZE = 32;
+  char buffer[BUFFER_SIZE] = {};
+  ASSERT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+              Succeeds<ssize_t>(0));
+}
+
+TEST_F(LlvmLibcLlistxattrTest, WithUserExtendedAttribute) {
+  constexpr const char *TEST_FILE_NAME =
+      "testdata/llistxattr_with_user_xattr.txt";
+  constexpr const char *TEST_SYMLINK_TARGET = "llistxattr_with_user_xattr.txt";
+  constexpr const char *TEST_SYMLINK_NAME = "testdata/llistxattr_symlink.txt";
+
+  int fd = recreate_test_file(TEST_FILE_NAME);
+  ASSERT_ERRNO_SUCCESS();
+  ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+  ASSERT_THAT(recreate_test_symlink(TEST_SYMLINK_TARGET, TEST_SYMLINK_NAME),
+              Succeeds(0));
+
+  string_view XATTR_NAME = "user.test_attr";
+  string_view XATTR_VALUE = "test_value";
+  ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
+                   SYS_setxattr, TEST_FILE_NAME, XATTR_NAME.data(),
+                   XATTR_VALUE.data(), XATTR_VALUE.size(),
+                   /* flags = */ 0));
+  size_t xattr_name_null_terminated_len = XATTR_NAME.size() + 1;
+
+  // Call with the test file path.
+  {
+    ASSERT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, nullptr, 0),
+                Succeeds<ssize_t>(xattr_name_null_terminated_len));
+
+    constexpr size_t BUFFER_SIZE = 32;
+    ASSERT_GE(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    ASSERT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+                Succeeds(xattr_name_null_terminated_len));
+    string_view result_str(buffer, xattr_name_null_terminated_len - 1);
+    EXPECT_EQ(result_str, XATTR_NAME);
+  }
+
+  // Call with the symlink path to verify the correct syscall is used
+  // internally; llistxattr instead of listxattr.
+  {
+    EXPECT_THAT(LIBC_NAMESPACE::llistxattr(TEST_SYMLINK_NAME, nullptr, 0),
+                Succeeds<ssize_t>(0));
+
+    constexpr size_t BUFFER_SIZE = 32;
+    ASSERT_GE(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    EXPECT_THAT(
+        LIBC_NAMESPACE::llistxattr(TEST_SYMLINK_NAME, buffer, BUFFER_SIZE),
+        Succeeds<ssize_t>(0));
+  }
+
+  // Call with insufficient buffer size to check failing errno.
+  {
+    constexpr size_t BUFFER_SIZE = 14;
+    ASSERT_LT(BUFFER_SIZE, xattr_name_null_terminated_len);
+
+    char buffer[BUFFER_SIZE] = {};
+    EXPECT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, buffer, BUFFER_SIZE),
+                Fails<ssize_t>(ERANGE));
+  }
+}
+
+#if defined(LIBC_ADD_NULL_CHECKS)
+
+TEST(LlvmLibcLlistxattrTest, CrashOnNullPath) {
+  EXPECT_DEATH(
+      [] {
+        constexpr size_t BUFFER_SIZE = 32;
+        char buffer[BUFFER_SIZE] = {};
+        LIBC_NAMESPACE::llistxattr(nullptr, buffer, BUFFER_SIZE);
+      },
+      WITH_SIGNAL(-1));
+}
+
+#endif // LIBC_ADD_NULL_CHECKS
+
+} // namespace
diff --git a/libc/test/src/sys/xattr/testdata/CMakeLists.txt b/libc/test/src/sys/xattr/testdata/CMakeLists.txt
new file mode 100644
index 00000000000000..e69de29bb2d1d6

>From 89e332de29db5ace396572898e4b2396880b2bdd Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Thu, 17 Sep 2026 16:17:18 +0000
Subject: [PATCH 2/5] Remove declaration nonnull and unneeded include.

---
 libc/src/sys/xattr/flistxattr.h             | 2 +-
 libc/src/sys/xattr/listxattr.h              | 3 +--
 libc/src/sys/xattr/llistxattr.h             | 3 +--
 libc/test/src/sys/xattr/flistxattr_test.cpp | 2 --
 libc/test/src/sys/xattr/listxattr_test.cpp  | 5 +----
 libc/test/src/sys/xattr/llistxattr_test.cpp | 2 --
 6 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/libc/src/sys/xattr/flistxattr.h b/libc/src/sys/xattr/flistxattr.h
index cb6cb0d0d4fdb9..5a12ac81025ca5 100644
--- a/libc/src/sys/xattr/flistxattr.h
+++ b/libc/src/sys/xattr/flistxattr.h
@@ -20,7 +20,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-ssize_t flistxattr(int fd, char *_Nullable list, size_t size);
+ssize_t flistxattr(int fd, char *list, size_t size);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/sys/xattr/listxattr.h b/libc/src/sys/xattr/listxattr.h
index 76cf26b5717104..e451f9b341b05d 100644
--- a/libc/src/sys/xattr/listxattr.h
+++ b/libc/src/sys/xattr/listxattr.h
@@ -20,8 +20,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-ssize_t listxattr(const char *_Nullable path, char *_Nullable list,
-                  size_t size);
+ssize_t listxattr(const char *path, char *list, size_t size);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/src/sys/xattr/llistxattr.h b/libc/src/sys/xattr/llistxattr.h
index 14ce1fdd1311ab..f286f4641802fc 100644
--- a/libc/src/sys/xattr/llistxattr.h
+++ b/libc/src/sys/xattr/llistxattr.h
@@ -20,8 +20,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-ssize_t llistxattr(const char *_Nullable path, char *_Nullable list,
-                   size_t size);
+ssize_t llistxattr(const char *path, char *list, size_t size);
 
 } // namespace LIBC_NAMESPACE_DECL
 
diff --git a/libc/test/src/sys/xattr/flistxattr_test.cpp b/libc/test/src/sys/xattr/flistxattr_test.cpp
index cb9dab84be0ec0..c5279f4e144a67 100644
--- a/libc/test/src/sys/xattr/flistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -23,8 +23,6 @@
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <sys/xattr.h>
-
 namespace {
 
 using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
diff --git a/libc/test/src/sys/xattr/listxattr_test.cpp b/libc/test/src/sys/xattr/listxattr_test.cpp
index 2f0db56885f088..e41786f2c6ffd7 100644
--- a/libc/test/src/sys/xattr/listxattr_test.cpp
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -11,12 +11,11 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "src/sys/xattr/listxattr.h"
-
 #include "hdr/sys_stat_macros.h"
 #include "src/__support/OSUtil/linux/syscall.h"
 #include "src/__support/libc_errno.h"
 #include "src/fcntl/creat.h"
+#include "src/sys/xattr/listxattr.h"
 #include "src/unistd/close.h"
 #include "src/unistd/symlink.h"
 #include "src/unistd/unlink.h"
@@ -24,8 +23,6 @@
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <sys/xattr.h>
-
 namespace {
 
 using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
diff --git a/libc/test/src/sys/xattr/llistxattr_test.cpp b/libc/test/src/sys/xattr/llistxattr_test.cpp
index a4b0c3795322a8..dbeee0a350e03b 100644
--- a/libc/test/src/sys/xattr/llistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -23,8 +23,6 @@
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include <sys/xattr.h>
-
 namespace {
 
 using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;

>From aff67ccb95fa6b75ee4d42ae37e62785b559eeef Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Thu, 17 Sep 2026 18:05:02 +0000
Subject: [PATCH 3/5] Address review comments.

---
 .../linux/syscall_wrappers/CMakeLists.txt     | 24 +++++++++----------
 .../linux/syscall_wrappers/flistxattr.h       |  5 +---
 .../OSUtil/linux/syscall_wrappers/listxattr.h |  5 +---
 .../linux/syscall_wrappers/llistxattr.h       |  5 +---
 libc/test/src/sys/xattr/flistxattr_test.cpp   |  7 +++---
 libc/test/src/sys/xattr/listxattr_test.cpp    | 14 ++++++-----
 libc/test/src/sys/xattr/llistxattr_test.cpp   | 14 ++++++-----
 7 files changed, 35 insertions(+), 39 deletions(-)

diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index a26721003f2fbf..10df669103e780 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -215,6 +215,18 @@ add_header_library(
     libc.include.sys_syscall
 )
 
+add_header_library(
+  flistxattr
+  HDRS
+    flistxattr.h
+  DEPENDS
+    libc.src.__support.OSUtil.osutil
+    libc.src.__support.common
+    libc.src.__support.error_or
+    libc.src.__support.macros.config
+    libc.include.sys_syscall
+)
+
 add_header_library(
   listxattr
   HDRS
@@ -904,18 +916,6 @@ add_header_library(
     libc.include.sys_syscall
 )
 
-add_header_library(
-  flistxattr
-  HDRS
-    flistxattr.h
-  DEPENDS
-    libc.src.__support.OSUtil.osutil
-    libc.src.__support.common
-    libc.src.__support.error_or
-    libc.src.__support.macros.config
-    libc.include.sys_syscall
-)
-
 add_header_library(
   flock
   HDRS
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
index 36981720dd28cb..73cddc21b9507b 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
@@ -24,10 +24,7 @@ namespace LIBC_NAMESPACE_DECL {
 namespace linux_syscalls {
 
 LIBC_INLINE ErrorOr<ssize_t> flistxattr(int fd, char *list, size_t size) {
-  ssize_t ret = syscall_impl<ssize_t>(SYS_flistxattr, fd, list, size);
-  if (ret < 0)
-    return Error(-static_cast<int>(ret));
-  return ret;
+  return syscall_checked<ssize_t>(SYS_flistxattr, fd, list, size);
 }
 
 } // namespace linux_syscalls
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
index d2bbc62ef31639..77d002b496bab4 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
@@ -25,10 +25,7 @@ namespace linux_syscalls {
 
 LIBC_INLINE ErrorOr<ssize_t> listxattr(const char *path, char *list,
                                        size_t size) {
-  ssize_t ret = syscall_impl<ssize_t>(SYS_listxattr, path, list, size);
-  if (ret < 0)
-    return Error(-static_cast<int>(ret));
-  return ret;
+  return syscall_checked<ssize_t>(SYS_listxattr, path, list, size);
 }
 
 } // namespace linux_syscalls
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
index 4796fc6d012d43..09fc80b301520c 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
@@ -25,10 +25,7 @@ namespace linux_syscalls {
 
 LIBC_INLINE ErrorOr<ssize_t> llistxattr(const char *path, char *list,
                                         size_t size) {
-  ssize_t ret = syscall_impl<ssize_t>(SYS_llistxattr, path, list, size);
-  if (ret < 0)
-    return Error(-static_cast<int>(ret));
-  return ret;
+  return syscall_checked<ssize_t>(SYS_llistxattr, path, list, size);
 }
 
 } // namespace linux_syscalls
diff --git a/libc/test/src/sys/xattr/flistxattr_test.cpp b/libc/test/src/sys/xattr/flistxattr_test.cpp
index c5279f4e144a67..3d1ba88738d3df 100644
--- a/libc/test/src/sys/xattr/flistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -37,7 +37,8 @@ int recreate_test_file(const char *path) {
 }
 
 TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
-  int fd = recreate_test_file("testdata/flistxattr_no_xattrs.txt");
+  int fd = recreate_test_file(
+      libc_make_test_file_path("testdata/flistxattr_no_xattrs.txt"));
   ASSERT_ERRNO_SUCCESS();
   scope_exit close_file(
       [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
@@ -51,8 +52,8 @@ TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
 }
 
 TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
-  constexpr const char *TEST_FILE_NAME =
-      "testdata/flistxattr_with_user_xattr.txt";
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/flistxattr_with_user_xattr.txt");
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
diff --git a/libc/test/src/sys/xattr/listxattr_test.cpp b/libc/test/src/sys/xattr/listxattr_test.cpp
index e41786f2c6ffd7..e45f5ddecf41ad 100644
--- a/libc/test/src/sys/xattr/listxattr_test.cpp
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -42,7 +42,8 @@ int recreate_test_symlink(const char *target, const char *linkpath) {
 }
 
 TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
-  constexpr const char *TEST_FILE_NAME = "testdata/listxattr_no_xattrs.txt";
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/listxattr_no_xattrs.txt");
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
@@ -58,10 +59,11 @@ TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
 }
 
 TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
-  constexpr const char *TEST_FILE_NAME =
-      "testdata/listxattr_with_user_xattr.txt";
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/listxattr_with_user_xattr.txt");
   constexpr const char *TEST_SYMLINK_TARGET = "listxattr_with_user_xattr.txt";
-  constexpr const char *TEST_SYMLINK_NAME = "testdata/listxattr_symlink.txt";
+  const LIBC_NAMESPACE::CString TEST_SYMLINK_NAME =
+      libc_make_test_file_path("testdata/listxattr_symlink.txt");
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
@@ -73,8 +75,8 @@ TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
   string_view XATTR_NAME = "user.test_attr";
   string_view XATTR_VALUE = "test_value";
   ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
-                   SYS_setxattr, TEST_FILE_NAME, XATTR_NAME.data(),
-                   XATTR_VALUE.data(), XATTR_VALUE.size(),
+                   SYS_setxattr, static_cast<const char *>(TEST_FILE_NAME),
+                   XATTR_NAME.data(), XATTR_VALUE.data(), XATTR_VALUE.size(),
                    /* flags = */ 0));
   size_t xattr_name_null_terminated_len = XATTR_NAME.size() + 1;
 
diff --git a/libc/test/src/sys/xattr/llistxattr_test.cpp b/libc/test/src/sys/xattr/llistxattr_test.cpp
index dbeee0a350e03b..622f932abf178b 100644
--- a/libc/test/src/sys/xattr/llistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -42,7 +42,8 @@ int recreate_test_symlink(const char *target, const char *linkpath) {
 }
 
 TEST_F(LlvmLibcLlistxattrTest, NoExtendedAttributes) {
-  constexpr const char *TEST_FILE_NAME = "testdata/llistxattr_no_xattrs.txt";
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/llistxattr_no_xattrs.txt");
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
@@ -58,10 +59,11 @@ TEST_F(LlvmLibcLlistxattrTest, NoExtendedAttributes) {
 }
 
 TEST_F(LlvmLibcLlistxattrTest, WithUserExtendedAttribute) {
-  constexpr const char *TEST_FILE_NAME =
-      "testdata/llistxattr_with_user_xattr.txt";
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/llistxattr_with_user_xattr.txt");
   constexpr const char *TEST_SYMLINK_TARGET = "llistxattr_with_user_xattr.txt";
-  constexpr const char *TEST_SYMLINK_NAME = "testdata/llistxattr_symlink.txt";
+  const LIBC_NAMESPACE::CString TEST_SYMLINK_NAME =
+      libc_make_test_file_path("testdata/llistxattr_symlink.txt");
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
@@ -73,8 +75,8 @@ TEST_F(LlvmLibcLlistxattrTest, WithUserExtendedAttribute) {
   string_view XATTR_NAME = "user.test_attr";
   string_view XATTR_VALUE = "test_value";
   ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
-                   SYS_setxattr, TEST_FILE_NAME, XATTR_NAME.data(),
-                   XATTR_VALUE.data(), XATTR_VALUE.size(),
+                   SYS_setxattr, static_cast<const char *>(TEST_FILE_NAME),
+                   XATTR_NAME.data(), XATTR_VALUE.data(), XATTR_VALUE.size(),
                    /* flags = */ 0));
   size_t xattr_name_null_terminated_len = XATTR_NAME.size() + 1;
 

>From e69c41696126f833426109fe402d64ae95d0be54 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Thu, 17 Sep 2026 18:10:49 +0000
Subject: [PATCH 4/5] Try add missing include for aarch64 test failures.

---
 libc/test/src/sys/xattr/flistxattr_test.cpp | 1 +
 libc/test/src/sys/xattr/listxattr_test.cpp  | 1 +
 libc/test/src/sys/xattr/llistxattr_test.cpp | 1 +
 3 files changed, 3 insertions(+)

diff --git a/libc/test/src/sys/xattr/flistxattr_test.cpp b/libc/test/src/sys/xattr/flistxattr_test.cpp
index 3d1ba88738d3df..1a9c0a7d0b9272 100644
--- a/libc/test/src/sys/xattr/flistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -22,6 +22,7 @@
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
+#include <sys/syscall.h>
 
 namespace {
 
diff --git a/libc/test/src/sys/xattr/listxattr_test.cpp b/libc/test/src/sys/xattr/listxattr_test.cpp
index e45f5ddecf41ad..0664b178400d78 100644
--- a/libc/test/src/sys/xattr/listxattr_test.cpp
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -22,6 +22,7 @@
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
+#include <sys/syscall.h>
 
 namespace {
 
diff --git a/libc/test/src/sys/xattr/llistxattr_test.cpp b/libc/test/src/sys/xattr/llistxattr_test.cpp
index 622f932abf178b..73f20dc477a3e6 100644
--- a/libc/test/src/sys/xattr/llistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -22,6 +22,7 @@
 #include "test/UnitTest/ErrnoCheckingTest.h"
 #include "test/UnitTest/ErrnoSetterMatcher.h"
 #include "test/UnitTest/Test.h"
+#include <sys/syscall.h>
 
 namespace {
 

>From 71de2e2de904274cd0c74e653c02eb89335b48a8 Mon Sep 17 00:00:00 2001
From: Alex Strelnikov <strel at google.com>
Date: Thu, 17 Sep 2026 18:58:05 +0000
Subject: [PATCH 5/5] Address review comments.

---
 libc/include/sys/xattr.yaml                 |  4 +++-
 libc/src/sys/xattr/flistxattr.h             |  4 ++--
 libc/src/sys/xattr/listxattr.h              |  4 ++--
 libc/src/sys/xattr/llistxattr.h             |  4 ++--
 libc/test/src/sys/xattr/CMakeLists.txt      |  2 ++
 libc/test/src/sys/xattr/flistxattr_test.cpp | 17 +++++++++++------
 libc/test/src/sys/xattr/listxattr_test.cpp  |  9 +++++++++
 libc/test/src/sys/xattr/llistxattr_test.cpp |  9 +++++++++
 8 files changed, 40 insertions(+), 13 deletions(-)

diff --git a/libc/include/sys/xattr.yaml b/libc/include/sys/xattr.yaml
index b37a65f168d110..5f8b6174af025a 100644
--- a/libc/include/sys/xattr.yaml
+++ b/libc/include/sys/xattr.yaml
@@ -2,7 +2,9 @@ header: sys/xattr.h
 standards:
   - linux
 macros: []
-types: []
+types:
+  - type_name: size_t
+  - type_name: ssize_t
 enums: []
 objects: []
 functions:
diff --git a/libc/src/sys/xattr/flistxattr.h b/libc/src/sys/xattr/flistxattr.h
index 5a12ac81025ca5..6493a413fc4479 100644
--- a/libc/src/sys/xattr/flistxattr.h
+++ b/libc/src/sys/xattr/flistxattr.h
@@ -14,8 +14,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_FLISTXATTR_H
 #define LLVM_LIBC_SRC_SYS_XATTR_LINUX_FLISTXATTR_H
 
-#include "include/llvm-libc-types/size_t.h"
-#include "include/llvm-libc-types/ssize_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
 #include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/xattr/listxattr.h b/libc/src/sys/xattr/listxattr.h
index e451f9b341b05d..535c8e6ce9186e 100644
--- a/libc/src/sys/xattr/listxattr.h
+++ b/libc/src/sys/xattr/listxattr.h
@@ -14,8 +14,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
 #define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
 
-#include "include/llvm-libc-types/size_t.h"
-#include "include/llvm-libc-types/ssize_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
 #include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/src/sys/xattr/llistxattr.h b/libc/src/sys/xattr/llistxattr.h
index f286f4641802fc..8dabae04fd93a0 100644
--- a/libc/src/sys/xattr/llistxattr.h
+++ b/libc/src/sys/xattr/llistxattr.h
@@ -14,8 +14,8 @@
 #ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
 #define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
 
-#include "include/llvm-libc-types/size_t.h"
-#include "include/llvm-libc-types/ssize_t.h"
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
 #include "src/__support/macros/config.h"
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/src/sys/xattr/CMakeLists.txt b/libc/test/src/sys/xattr/CMakeLists.txt
index 3ac896f0c0dcfe..240cb2cc9c7a7a 100644
--- a/libc/test/src/sys/xattr/CMakeLists.txt
+++ b/libc/test/src/sys/xattr/CMakeLists.txt
@@ -30,6 +30,7 @@ add_libc_test(
   DEPENDS
     libc.hdr.sys_stat_macros
     libc.include.sys_xattr
+    libc.src.__support.CPP.scope
     libc.src.__support.OSUtil.osutil
     libc.src.__support.libc_errno
     libc.src.errno.errno
@@ -51,6 +52,7 @@ add_libc_test(
   DEPENDS
     libc.hdr.sys_stat_macros
     libc.include.sys_xattr
+    libc.src.__support.CPP.scope
     libc.src.__support.OSUtil.osutil
     libc.src.__support.libc_errno
     libc.src.errno.errno
diff --git a/libc/test/src/sys/xattr/flistxattr_test.cpp b/libc/test/src/sys/xattr/flistxattr_test.cpp
index 1a9c0a7d0b9272..474d0ae81d5599 100644
--- a/libc/test/src/sys/xattr/flistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -38,11 +38,14 @@ int recreate_test_file(const char *path) {
 }
 
 TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
-  int fd = recreate_test_file(
-      libc_make_test_file_path("testdata/flistxattr_no_xattrs.txt"));
+  const LIBC_NAMESPACE::CString TEST_FILE_NAME =
+      libc_make_test_file_path("testdata/flistxattr_no_xattrs.txt");
+  int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
-  scope_exit close_file(
-      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+  });
 
   EXPECT_THAT(LIBC_NAMESPACE::flistxattr(fd, nullptr, 0), Succeeds<ssize_t>(0));
 
@@ -58,8 +61,10 @@ TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
 
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
-  scope_exit close_file(
-      [&] { ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0)); });
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+  });
 
   string_view XATTR_NAME = "user.test_attr";
   string_view XATTR_VALUE = "test_value";
diff --git a/libc/test/src/sys/xattr/listxattr_test.cpp b/libc/test/src/sys/xattr/listxattr_test.cpp
index 0664b178400d78..da72fd0602fcfa 100644
--- a/libc/test/src/sys/xattr/listxattr_test.cpp
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "hdr/sys_stat_macros.h"
+#include "src/__support/CPP/scope.h"
 #include "src/__support/OSUtil/linux/syscall.h"
 #include "src/__support/libc_errno.h"
 #include "src/fcntl/creat.h"
@@ -28,6 +29,7 @@ namespace {
 
 using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
 using LlvmLibcListxattrTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
 using LIBC_NAMESPACE::cpp::string_view;
 
 int recreate_test_file(const char *path) {
@@ -49,6 +51,9 @@ TEST_F(LlvmLibcListxattrTest, NoExtendedAttributes) {
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
   ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+  });
 
   EXPECT_THAT(LIBC_NAMESPACE::listxattr(TEST_FILE_NAME, nullptr, 0),
               Succeeds<ssize_t>(0));
@@ -72,6 +77,10 @@ TEST_F(LlvmLibcListxattrTest, WithUserExtendedAttribute) {
 
   ASSERT_THAT(recreate_test_symlink(TEST_SYMLINK_TARGET, TEST_SYMLINK_NAME),
               Succeeds(0));
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_SYMLINK_NAME), Succeeds(0));
+  });
 
   string_view XATTR_NAME = "user.test_attr";
   string_view XATTR_VALUE = "test_value";
diff --git a/libc/test/src/sys/xattr/llistxattr_test.cpp b/libc/test/src/sys/xattr/llistxattr_test.cpp
index 73f20dc477a3e6..bddb5516d4cd33 100644
--- a/libc/test/src/sys/xattr/llistxattr_test.cpp
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "hdr/sys_stat_macros.h"
+#include "src/__support/CPP/scope.h"
 #include "src/__support/OSUtil/linux/syscall.h"
 #include "src/__support/libc_errno.h"
 #include "src/fcntl/creat.h"
@@ -28,6 +29,7 @@ namespace {
 
 using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
 using LlvmLibcLlistxattrTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
+using LIBC_NAMESPACE::cpp::scope_exit;
 using LIBC_NAMESPACE::cpp::string_view;
 
 int recreate_test_file(const char *path) {
@@ -49,6 +51,9 @@ TEST_F(LlvmLibcLlistxattrTest, NoExtendedAttributes) {
   int fd = recreate_test_file(TEST_FILE_NAME);
   ASSERT_ERRNO_SUCCESS();
   ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+  });
 
   EXPECT_THAT(LIBC_NAMESPACE::llistxattr(TEST_FILE_NAME, nullptr, 0),
               Succeeds<ssize_t>(0));
@@ -72,6 +77,10 @@ TEST_F(LlvmLibcLlistxattrTest, WithUserExtendedAttribute) {
 
   ASSERT_THAT(recreate_test_symlink(TEST_SYMLINK_TARGET, TEST_SYMLINK_NAME),
               Succeeds(0));
+  scope_exit cleanup([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_FILE_NAME), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::unlink(TEST_SYMLINK_NAME), Succeeds(0));
+  });
 
   string_view XATTR_NAME = "user.test_attr";
   string_view XATTR_VALUE = "test_value";



More information about the libc-commits mailing list