-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[libc] add linux specific statfs #85953
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-libc Author: Schrodinger ZHU Yifan (SchrodingerZhu) Changeshttps://man7.org/linux/man-pages/man2/statfs.2.html Full diff: https://github.com/llvm/llvm-project/pull/85953.diff 20 Files Affected:
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));
+}
|
Can you provide |
In order to provide statvfs, I |
fs_type is somewhat also useful in pathconf implementation. How about internalizing statfs64 and exposing statvfs only?
|
https://man7.org/linux/man-pages/man2/statfs.2.html
fixes #85964