[libc-commits] [libc] [libc] add linux specific statfs (PR #85953)

Schrodinger ZHU Yifan via libc-commits libc-commits at lists.llvm.org
Wed Mar 20 08:49:42 PDT 2024


https://github.com/SchrodingerZhu created https://github.com/llvm/llvm-project/pull/85953

https://man7.org/linux/man-pages/man2/statfs.2.html

>From 2bf3d04f88312cb68684c3dc6bf6919b2d951a35 Mon Sep 17 00:00:00 2001
From: Schrodinger ZHU Yifan <yifanzhu at rochester.edu>
Date: Wed, 20 Mar 2024 11:48:54 -0400
Subject: [PATCH] [libc] add linux specific statfs

---
 libc/config/linux/api.td                      |  4 ++
 libc/config/linux/x86_64/entrypoints.txt      |  4 ++
 libc/include/CMakeLists.txt                   | 18 +++++++
 libc/include/llvm-libc-types/CMakeLists.txt   |  1 +
 libc/include/llvm-libc-types/struct_statfs.h  | 19 +++++++
 libc/include/sys/statfs.h.def                 | 16 ++++++
 libc/include/sys/vfs.h.def                    | 22 ++++++++
 libc/spec/linux.td                            | 54 +++++++++++++++++++
 libc/src/sys/CMakeLists.txt                   |  1 +
 libc/src/sys/statfs/CMakeLists.txt            | 17 ++++++
 libc/src/sys/statfs/fstatfs.h                 | 20 +++++++
 libc/src/sys/statfs/linux/CMakeLists.txt      | 25 +++++++++
 libc/src/sys/statfs/linux/fstatfs.cpp         | 27 ++++++++++
 libc/src/sys/statfs/linux/statfs.cpp          | 27 ++++++++++
 libc/src/sys/statfs/statfs.h                  | 20 +++++++
 libc/test/src/sys/CMakeLists.txt              |  1 +
 libc/test/src/sys/statfs/CMakeLists.txt       |  3 ++
 libc/test/src/sys/statfs/linux/CMakeLists.txt | 26 +++++++++
 .../src/sys/statfs/linux/fstatfs_test.cpp     | 35 ++++++++++++
 .../test/src/sys/statfs/linux/statfs_test.cpp | 40 ++++++++++++++
 20 files changed, 380 insertions(+)
 create mode 100644 libc/include/llvm-libc-types/struct_statfs.h
 create mode 100644 libc/include/sys/statfs.h.def
 create mode 100644 libc/include/sys/vfs.h.def
 create mode 100644 libc/src/sys/statfs/CMakeLists.txt
 create mode 100644 libc/src/sys/statfs/fstatfs.h
 create mode 100644 libc/src/sys/statfs/linux/CMakeLists.txt
 create mode 100644 libc/src/sys/statfs/linux/fstatfs.cpp
 create mode 100644 libc/src/sys/statfs/linux/statfs.cpp
 create mode 100644 libc/src/sys/statfs/statfs.h
 create mode 100644 libc/test/src/sys/statfs/CMakeLists.txt
 create mode 100644 libc/test/src/sys/statfs/linux/CMakeLists.txt
 create mode 100644 libc/test/src/sys/statfs/linux/fstatfs_test.cpp
 create mode 100644 libc/test/src/sys/statfs/linux/statfs_test.cpp

diff --git a/libc/config/linux/api.td b/libc/config/linux/api.td
index e9e82c5d478945..1869b8a4b751f8 100644
--- a/libc/config/linux/api.td
+++ b/libc/config/linux/api.td
@@ -262,3 +262,7 @@ def SetJmpAPI : PublicAPI<"setjmp.h"> {
 def SearchAPI : PublicAPI<"search.h"> {
   let Types = ["ACTION", "ENTRY", "struct hsearch_data"];
 }
+
+def SysStatfsAPI : PublicAPI<"sys/statfs.h"> {
+  let Types = ["struct statfs"];
+}
diff --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index e8cf11266624a7..a1901725e36344 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -253,6 +253,10 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.sys.stat.mkdirat
     libc.src.sys.stat.stat
 
+    # sys/statfs.h and sys/vfs.h entrypoints
+    libc.src.sys.statfs.statfs
+    libc.src.sys.statfs.fstatfs
+
     # sys/utsname.h entrypoints
     libc.src.sys.utsname.uname
 
diff --git a/libc/include/CMakeLists.txt b/libc/include/CMakeLists.txt
index b2cb10459c53e3..21ec1d1458dd4b 100644
--- a/libc/include/CMakeLists.txt
+++ b/libc/include/CMakeLists.txt
@@ -498,6 +498,24 @@ add_gen_header(
     .llvm-libc-types.struct_sockaddr_un
 )
 
+add_gen_header(
+  sys_statfs
+  DEF_FILE sys/statfs.h.def
+  GEN_HDR sys/statfs.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.struct_statfs
+)
+
+add_gen_header(
+  sys_vfs
+  DEF_FILE sys/vfs.h.def
+  GEN_HDR sys/vfs.h
+  DEPENDS
+    .llvm_libc_common_h
+    .llvm-libc-types.struct_statfs
+)
+
 add_gen_header(
   sys_syscall
   DEF_FILE sys/syscall.h.def
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index 7fef976d7b3250..24a62ccbdd8fdc 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -106,3 +106,4 @@ add_header(
   DEPENDS
     libc.include.llvm-libc-macros.float_macros
 )
+add_header(struct_statfs HDR struct_statfs.h)
diff --git a/libc/include/llvm-libc-types/struct_statfs.h b/libc/include/llvm-libc-types/struct_statfs.h
new file mode 100644
index 00000000000000..bac51cc6e3ac3a
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_statfs.h
@@ -0,0 +1,19 @@
+//===-- Definition of type struct statfs ----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_STATFS_H
+#define LLVM_LIBC_TYPES_STRUCT_STATFS_H
+
+// Statfs is not specified by POSIX, rather it is OS specific. So, we include
+// UAPI header to provide its definition.
+
+#ifdef __linux__
+#include <asm/statfs.h>
+#endif
+
+#endif // LLVM_LIBC_TYPES_STRUCT_STATFS_H
diff --git a/libc/include/sys/statfs.h.def b/libc/include/sys/statfs.h.def
new file mode 100644
index 00000000000000..9ad15f4f337cc5
--- /dev/null
+++ b/libc/include/sys/statfs.h.def
@@ -0,0 +1,16 @@
+//===-- Linux header statfs.h ---------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SYS_STATFS_H
+#define LLVM_LIBC_SYS_STATFS_H
+
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif // LLVM_LIBC_SYS_STATFS_H
diff --git a/libc/include/sys/vfs.h.def b/libc/include/sys/vfs.h.def
new file mode 100644
index 00000000000000..abf30067759458
--- /dev/null
+++ b/libc/include/sys/vfs.h.def
@@ -0,0 +1,22 @@
+//===-- Linux header vfs.h ------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SYS_VFS_H
+#define LLVM_LIBC_SYS_VFS_H
+
+#ifdef __linux__
+// On Linux, sys/vfs.h is just a compat layer for sys/statfs.h
+#include <sys/statfs.h>
+#else
+#include <__llvm-libc-common.h>
+
+%%public_api()
+
+#endif
+
+#endif // LLVM_LIBC_SYS_VFS_H
diff --git a/libc/spec/linux.td b/libc/spec/linux.td
index f91f55ddac7846..b6733f546b4d96 100644
--- a/libc/spec/linux.td
+++ b/libc/spec/linux.td
@@ -2,6 +2,8 @@ def StructEpollEvent : NamedType<"struct epoll_event">;
 def StructEpollEventPtr : PtrType<StructEpollEvent>;
 
 def StructEpollData : NamedType<"struct epoll_data">;
+def StructStatfs : NamedType<"struct statfs">;
+def StructStatfsPtr : PtrType<StructStatfs>;
 
 def Linux : StandardSpec<"Linux"> {
   HeaderSpec Errno = HeaderSpec<
@@ -264,6 +266,56 @@ def Linux : StandardSpec<"Linux"> {
       ]
   >;
 
+  HeaderSpec SysStatfs = HeaderSpec<
+    "sys/statfs.h",
+    [], // Macros
+    [StructStatfs], // Types
+    [], // Enumerations
+    [
+      FunctionSpec<
+        "statfs",
+        RetValSpec<IntType>,
+        [
+          ArgSpec<ConstCharPtr>,
+          ArgSpec<StructStatfsPtr>
+        ]
+      >,
+      FunctionSpec<
+        "fstatfs",
+        RetValSpec<IntType>,
+        [
+          ArgSpec<IntType>,
+          ArgSpec<StructStatfsPtr>
+        ]
+      >,
+    ]  // Functions
+  >;
+
+  HeaderSpec SysVfs = HeaderSpec<
+    "sys/vfs.h",
+    [], // Macros
+    [StructStatfs], // Types
+    [], // Enumerations
+    [
+      FunctionSpec<
+        "statfs",
+        RetValSpec<IntType>,
+        [
+          ArgSpec<ConstCharPtr>,
+          ArgSpec<StructStatfsPtr>
+        ]
+      >,
+      FunctionSpec<
+        "fstatfs",
+        RetValSpec<IntType>,
+        [
+          ArgSpec<IntType>,
+          ArgSpec<StructStatfsPtr>
+        ]
+      >,
+    ]  // Functions
+  >;
+
   let Headers = [
     Errno,
     SysEpoll,
@@ -272,5 +324,7 @@ def Linux : StandardSpec<"Linux"> {
     SysRandom,
     SysTime,
     Signal,
+    SysStatfs,
+    SysVfs,
   ];
 }
diff --git a/libc/src/sys/CMakeLists.txt b/libc/src/sys/CMakeLists.txt
index 57ea7b4beaca1b..8ea56db1b90ebc 100644
--- a/libc/src/sys/CMakeLists.txt
+++ b/libc/src/sys/CMakeLists.txt
@@ -7,6 +7,7 @@ add_subdirectory(select)
 add_subdirectory(socket)
 add_subdirectory(sendfile)
 add_subdirectory(stat)
+add_subdirectory(statfs)
 add_subdirectory(utsname)
 add_subdirectory(wait)
 add_subdirectory(prctl)
diff --git a/libc/src/sys/statfs/CMakeLists.txt b/libc/src/sys/statfs/CMakeLists.txt
new file mode 100644
index 00000000000000..7db6450b2aa319
--- /dev/null
+++ b/libc/src/sys/statfs/CMakeLists.txt
@@ -0,0 +1,17 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+endif()
+
+add_entrypoint_object(
+  statfs
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.statfs
+)
+
+add_entrypoint_object(
+  fstatfs
+  ALIAS
+  DEPENDS
+    .${LIBC_TARGET_OS}.fstatfs
+)
diff --git a/libc/src/sys/statfs/fstatfs.h b/libc/src/sys/statfs/fstatfs.h
new file mode 100644
index 00000000000000..461e0594b240e0
--- /dev/null
+++ b/libc/src/sys/statfs/fstatfs.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for fstatfs -----------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_STATFS_FSTATFS_H
+#define LLVM_LIBC_SRC_SYS_STATFS_FSTATFS_H
+
+#include "llvm-libc-types/struct_statfs.h"
+
+namespace LIBC_NAMESPACE {
+
+int fstatfs(int fd, struct statfs *buf);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_STATFS_FSTATFS_H
diff --git a/libc/src/sys/statfs/linux/CMakeLists.txt b/libc/src/sys/statfs/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..d19f786bca90df
--- /dev/null
+++ b/libc/src/sys/statfs/linux/CMakeLists.txt
@@ -0,0 +1,25 @@
+add_entrypoint_object(
+  statfs
+  SRCS
+    statfs.cpp
+  HDRS
+    ../statfs.h
+  DEPENDS
+    libc.include.llvm-libc-types.struct_statfs
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
+
+add_entrypoint_object(
+  fstatfs
+  SRCS
+    fstatfs.cpp
+  HDRS
+    ../fstatfs.h
+  DEPENDS
+    libc.include.llvm-libc-types.struct_statfs
+    libc.include.sys_syscall
+    libc.src.__support.OSUtil.osutil
+    libc.src.errno.errno
+)
\ No newline at end of file
diff --git a/libc/src/sys/statfs/linux/fstatfs.cpp b/libc/src/sys/statfs/linux/fstatfs.cpp
new file mode 100644
index 00000000000000..bfe7fd3f0094c4
--- /dev/null
+++ b/libc/src/sys/statfs/linux/fstatfs.cpp
@@ -0,0 +1,27 @@
+//===-- Linux implementation of fstatfs -----------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/statfs/fstatfs.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, fstatfs, (int fd, struct statfs *buf)) {
+  int ret = syscall_impl<int>(SYS_fstatfs, fd, buf);
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/statfs/linux/statfs.cpp b/libc/src/sys/statfs/linux/statfs.cpp
new file mode 100644
index 00000000000000..c604f0687889a0
--- /dev/null
+++ b/libc/src/sys/statfs/linux/statfs.cpp
@@ -0,0 +1,27 @@
+//===-- Linux implementation of statfs ------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/sys/statfs/statfs.h"
+#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "src/__support/common.h"
+
+#include "src/errno/libc_errno.h"
+#include <sys/syscall.h> // For syscall numbers.
+
+namespace LIBC_NAMESPACE {
+
+LLVM_LIBC_FUNCTION(int, statfs, (const char *path, struct statfs *buf)) {
+  int ret = syscall_impl<int>(SYS_statfs, path, buf);
+  if (ret < 0) {
+    libc_errno = -ret;
+    return -1;
+  }
+  return 0;
+}
+
+} // namespace LIBC_NAMESPACE
diff --git a/libc/src/sys/statfs/statfs.h b/libc/src/sys/statfs/statfs.h
new file mode 100644
index 00000000000000..b8bab907e58415
--- /dev/null
+++ b/libc/src/sys/statfs/statfs.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for statfs ------------------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_SYS_STATFS_STATFS_H
+#define LLVM_LIBC_SRC_SYS_STATFS_STATFS_H
+
+#include "llvm-libc-types/struct_statfs.h"
+
+namespace LIBC_NAMESPACE {
+
+int statfs(const char *path, struct statfs *buf);
+
+} // namespace LIBC_NAMESPACE
+
+#endif // LLVM_LIBC_SRC_SYS_STATFS_STATFS_H
diff --git a/libc/test/src/sys/CMakeLists.txt b/libc/test/src/sys/CMakeLists.txt
index 7f228e709046d0..047ba33a9a4334 100644
--- a/libc/test/src/sys/CMakeLists.txt
+++ b/libc/test/src/sys/CMakeLists.txt
@@ -5,6 +5,7 @@ add_subdirectory(select)
 add_subdirectory(sendfile)
 add_subdirectory(socket)
 add_subdirectory(stat)
+add_subdirectory(statfs)
 add_subdirectory(utsname)
 add_subdirectory(wait)
 add_subdirectory(prctl)
diff --git a/libc/test/src/sys/statfs/CMakeLists.txt b/libc/test/src/sys/statfs/CMakeLists.txt
new file mode 100644
index 00000000000000..b4bbe81c92ff2e
--- /dev/null
+++ b/libc/test/src/sys/statfs/CMakeLists.txt
@@ -0,0 +1,3 @@
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
+  add_subdirectory(${LIBC_TARGET_OS})
+endif()
diff --git a/libc/test/src/sys/statfs/linux/CMakeLists.txt b/libc/test/src/sys/statfs/linux/CMakeLists.txt
new file mode 100644
index 00000000000000..09650a0e45eb9d
--- /dev/null
+++ b/libc/test/src/sys/statfs/linux/CMakeLists.txt
@@ -0,0 +1,26 @@
+add_custom_target(libc_sys_statfs_unittests)
+add_libc_unittest(
+  statfs_test
+  SUITE
+    libc_sys_statfs_unittests
+  SRCS
+    statfs_test.cpp
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.sys.statfs.statfs
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
+add_libc_unittest(
+  fstatfs_test
+  SUITE
+    libc_sys_statfs_unittests
+  SRCS
+    fstatfs_test.cpp
+  DEPENDS
+    libc.src.errno.errno
+    libc.src.sys.statfs.fstatfs
+    libc.src.fcntl.open
+    libc.src.unistd.close
+    libc.src.__support.CPP.string_view
+    libc.test.UnitTest.ErrnoSetterMatcher
+)
diff --git a/libc/test/src/sys/statfs/linux/fstatfs_test.cpp b/libc/test/src/sys/statfs/linux/fstatfs_test.cpp
new file mode 100644
index 00000000000000..374045a36eba5f
--- /dev/null
+++ b/libc/test/src/sys/statfs/linux/fstatfs_test.cpp
@@ -0,0 +1,35 @@
+#include "src/__support/CPP/string_view.h"
+#include "src/fcntl/open.h"
+#include "src/sys/statfs/fstatfs.h"
+#include "src/unistd/close.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/LibcTest.h"
+#include "test/UnitTest/Test.h"
+#include <linux/magic.h>
+#include <llvm-libc-macros/linux/fcntl-macros.h>
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+struct PathFD {
+  int fd;
+  explicit PathFD(LIBC_NAMESPACE::cpp::string_view path)
+      : fd(LIBC_NAMESPACE::open(path.data(), O_CLOEXEC | O_PATH)) {}
+  ~PathFD() { LIBC_NAMESPACE::close(fd); }
+  operator int() const { return fd; }
+};
+
+TEST(LlvmLibcSysStatfsTest, FstatfsBasic) {
+  statfs buf[1];
+  ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/"), buf), Succeeds());
+  ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/proc"), buf), Succeeds());
+  ASSERT_EQ(buf->f_type, static_cast<__kernel_long_t>(PROC_SUPER_MAGIC));
+  ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/sys"), buf), Succeeds());
+  ASSERT_EQ(buf->f_type, static_cast<__kernel_long_t>(SYSFS_MAGIC));
+}
+
+TEST(LlvmLibcSysStatfsTest, FstatfsNullBuffer) {
+  ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/"), nullptr), Fails(EFAULT));
+}
+
+TEST(LlvmLibcSysStatfsTest, FstatfsInvalidFD) {
+  ASSERT_THAT(LIBC_NAMESPACE::fstatfs(-1, nullptr), Fails(EBADF));
+}
diff --git a/libc/test/src/sys/statfs/linux/statfs_test.cpp b/libc/test/src/sys/statfs/linux/statfs_test.cpp
new file mode 100644
index 00000000000000..bca07667781683
--- /dev/null
+++ b/libc/test/src/sys/statfs/linux/statfs_test.cpp
@@ -0,0 +1,40 @@
+#include "src/sys/statfs/statfs.h"
+#include "test/UnitTest/ErrnoSetterMatcher.h"
+#include "test/UnitTest/LibcTest.h"
+#include "test/UnitTest/Test.h"
+#include <linux/magic.h>
+using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
+
+TEST(LlvmLibcSysStatfsTest, StatfsBasic) {
+  statfs buf[1];
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/", buf), Succeeds());
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/proc", buf), Succeeds());
+  ASSERT_EQ(buf->f_type, static_cast<__kernel_long_t>(PROC_SUPER_MAGIC));
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/sys", buf), Succeeds());
+  ASSERT_EQ(buf->f_type, static_cast<__kernel_long_t>(SYSFS_MAGIC));
+}
+
+TEST(LlvmLibcSysStatfsTest, InvalidPath) {
+  statfs buf[1];
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("", buf), Fails(ENOENT));
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/nonexistent", buf), Fails(ENOENT));
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/dev/null/whatever", buf),
+              Fails(ENOTDIR));
+  ASSERT_THAT(LIBC_NAMESPACE::statfs(nullptr, buf), Fails(EFAULT));
+}
+
+TEST(LlvmLibcSysStatfsTest, StatfsNullBuffer) {
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/", nullptr), Fails(EFAULT));
+}
+
+TEST(LlvmLibcSysStatfsTest, NameTooLong) {
+  statfs buf[1];
+  ASSERT_THAT(LIBC_NAMESPACE::statfs("/", buf), Succeeds());
+  char *name = static_cast<char *>(__builtin_alloca(buf->f_namelen + 3));
+  name[0] = '/';
+  name[buf->f_namelen + 2] = '\0';
+  for (unsigned i = 1; i < buf->f_namelen + 2; ++i) {
+    name[i] = 'a';
+  }
+  ASSERT_THAT(LIBC_NAMESPACE::statfs(name, buf), Fails(ENAMETOOLONG));
+}



More information about the libc-commits mailing list