[libc-commits] [libc] b65f5ac - [libc] Add sys/xattr.h and entrypoints flistxattr, listxattr, and llistxattr. (#224357)
via libc-commits
libc-commits at lists.llvm.org
Fri Sep 18 07:04:00 PDT 2026
Author: Alex Strelnikov
Date: 2026-09-18T10:03:54-04:00
New Revision: b65f5aca2ba2ca10611c9b5fb6f80bc34619362d
URL: https://github.com/llvm/llvm-project/commit/b65f5aca2ba2ca10611c9b5fb6f80bc34619362d
DIFF: https://github.com/llvm/llvm-project/commit/b65f5aca2ba2ca10611c9b5fb6f80bc34619362d.diff
LOG: [libc] Add sys/xattr.h and entrypoints flistxattr, listxattr, and llistxattr. (#224357)
The header is non-POSIX, and the entrypoints, as described in
https://man7.org/linux/man-pages/man2/listxattr.2.html, have
Linux-specific signatures. BSD defines `listxattr` and `flistxattr`, but
with an additional parameter.
Assisted-by: Automated tooling, human reviewed.
Added:
libc/include/sys/xattr.yaml
libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
libc/src/sys/xattr/CMakeLists.txt
libc/src/sys/xattr/flistxattr.h
libc/src/sys/xattr/linux/CMakeLists.txt
libc/src/sys/xattr/linux/flistxattr.cpp
libc/src/sys/xattr/linux/listxattr.cpp
libc/src/sys/xattr/linux/llistxattr.cpp
libc/src/sys/xattr/listxattr.h
libc/src/sys/xattr/llistxattr.h
libc/test/src/sys/xattr/CMakeLists.txt
libc/test/src/sys/xattr/flistxattr_test.cpp
libc/test/src/sys/xattr/listxattr_test.cpp
libc/test/src/sys/xattr/llistxattr_test.cpp
libc/test/src/sys/xattr/testdata/CMakeLists.txt
Modified:
libc/config/linux/aarch64/entrypoints.txt
libc/config/linux/aarch64/headers.txt
libc/config/linux/x86_64/entrypoints.txt
libc/config/linux/x86_64/headers.txt
libc/include/CMakeLists.txt
libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
libc/src/sys/CMakeLists.txt
libc/test/src/sys/CMakeLists.txt
Removed:
################################################################################
diff --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index f87ba3437fb6c..fe1c2965f778b 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -384,6 +384,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 0e7854bd5c29d..4317f3e7bd18e 100644
--- a/libc/config/linux/aarch64/headers.txt
+++ b/libc/config/linux/aarch64/headers.txt
@@ -81,6 +81,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 8b77efa648c43..f21d48d6ef9e7 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -423,6 +423,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 d01bb7b6a40f2..ea327ad0386da 100644
--- a/libc/config/linux/x86_64/headers.txt
+++ b/libc/config/linux/x86_64/headers.txt
@@ -86,6 +86,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 4a1158401d6ed..a45026de31ee5 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -1097,6 +1097,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 0000000000000..5f8b6174af025
--- /dev/null
+++ b/libc/include/sys/xattr.yaml
@@ -0,0 +1,34 @@
+header: sys/xattr.h
+standards:
+ - linux
+macros: []
+types:
+ - type_name: size_t
+ - type_name: ssize_t
+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 95abcfa59d3de..f5f28f51f49f6 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -215,6 +215,42 @@ 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
+ 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
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 0000000000000..73cddc21b9507
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/flistxattr.h
@@ -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
+/// 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) {
+ return syscall_checked<ssize_t>(SYS_flistxattr, fd, list, size);
+}
+
+} // 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 0000000000000..77d002b496bab
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/listxattr.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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) {
+ return syscall_checked<ssize_t>(SYS_listxattr, path, list, size);
+}
+
+} // 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 0000000000000..09fc80b301520
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/llistxattr.h
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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) {
+ return syscall_checked<ssize_t>(SYS_llistxattr, path, list, size);
+}
+
+} // 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 cd7f7bea24058..3ac5b92a2a7c1 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -22,3 +22,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 0000000000000..d008639bddf0d
--- /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 0000000000000..6493a413fc447
--- /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 "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t flistxattr(int fd, char *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 0000000000000..0d80394c7f8f1
--- /dev/null
+++ b/libc/src/sys/xattr/linux/CMakeLists.txt
@@ -0,0 +1,43 @@
+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
+ libc.src.errno.errno
+)
+
+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
+ libc.src.errno.errno
+)
+
+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
+ libc.src.errno.errno
+)
diff --git a/libc/src/sys/xattr/linux/flistxattr.cpp b/libc/src/sys/xattr/linux/flistxattr.cpp
new file mode 100644
index 0000000000000..68119436aa29e
--- /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 0000000000000..d0ef1558ce75c
--- /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 0000000000000..12d073f19deac
--- /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 0000000000000..535c8e6ce9186
--- /dev/null
+++ b/libc/src/sys/xattr/listxattr.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 listxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
+#define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LISTXATTR_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t listxattr(const char *path, char *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 0000000000000..8dabae04fd93a
--- /dev/null
+++ b/libc/src/sys/xattr/llistxattr.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 llistxattr.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
+#define LLVM_LIBC_SRC_SYS_XATTR_LINUX_LLISTXATTR_H
+
+#include "hdr/types/size_t.h"
+#include "hdr/types/ssize_t.h"
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+ssize_t llistxattr(const char *path, char *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 f944fdcc9e86f..1e2905b07eb85 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -21,3 +21,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 0000000000000..240cb2cc9c7a7
--- /dev/null
+++ b/libc/test/src/sys/xattr/CMakeLists.txt
@@ -0,0 +1,68 @@
+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.CPP.scope
+ 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.CPP.scope
+ 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 0000000000000..474d0ae81d559
--- /dev/null
+++ b/libc/test/src/sys/xattr/flistxattr_test.cpp
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/syscall.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) {
+ 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 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));
+
+ 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) {
+ 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();
+ 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";
+ 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 0000000000000..da72fd0602fcf
--- /dev/null
+++ b/libc/test/src/sys/xattr/listxattr_test.cpp
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "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/listxattr.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/syscall.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);
+}
+
+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) {
+ 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();
+ 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));
+
+ 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) {
+ 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";
+ 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();
+ ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+ 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";
+ ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
+ 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;
+
+ // 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 0000000000000..bddb5516d4cd3
--- /dev/null
+++ b/libc/test/src/sys/xattr/llistxattr_test.cpp
@@ -0,0 +1,148 @@
+//===----------------------------------------------------------------------===//
+//
+// 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/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/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/syscall.h>
+
+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) {
+ 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) {
+ 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();
+ 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));
+
+ 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) {
+ 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";
+ 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();
+ ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
+
+ 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";
+ ASSERT_EQ(0, LIBC_NAMESPACE::syscall_impl<int>(
+ 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;
+
+ // 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 0000000000000..e69de29bb2d1d
More information about the libc-commits
mailing list