[libc-commits] [libc] [libc] Refactor statfs Linux syscalls and provide 'struct statfs' (PR #212930)
Alexey Samsonov via libc-commits
libc-commits at lists.llvm.org
Thu Jul 30 07:18:39 PDT 2026
https://github.com/vonosmas updated https://github.com/llvm/llvm-project/pull/212930
>From b31f286d37916c0961a9660783caa7a12ea557b2 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Thu, 30 Jul 2026 05:16:23 +0000
Subject: [PATCH 1/4] [libc] Refactor statfs Linux syscalls and provide 'struct
statfs'
---
libc/hdr/types/CMakeLists.txt | 8 +++
libc/hdr/types/struct_statfs.h | 27 ++++++++
libc/include/llvm-libc-types/CMakeLists.txt | 10 +++
libc/include/llvm-libc-types/fsid_t.h | 21 ++++++
libc/include/llvm-libc-types/struct_statfs.h | 36 ++++++++++
.../linux/syscall_wrappers/CMakeLists.txt | 26 +++++++
.../OSUtil/linux/syscall_wrappers/fstatfs.h | 38 +++++++++++
.../OSUtil/linux/syscall_wrappers/statfs.h | 38 +++++++++++
libc/src/sys/statvfs/linux/CMakeLists.txt | 10 +--
libc/src/sys/statvfs/linux/fstatvfs.cpp | 16 +++--
libc/src/sys/statvfs/linux/statfs_utils.h | 67 +++----------------
libc/src/sys/statvfs/linux/statvfs.cpp | 16 +++--
libc/src/unistd/linux/CMakeLists.txt | 11 ++-
libc/src/unistd/linux/fpathconf.cpp | 16 +++--
libc/src/unistd/linux/pathconf.cpp | 14 ++--
libc/src/unistd/linux/pathconf_utils.cpp | 11 ++-
libc/src/unistd/linux/pathconf_utils.h | 4 +-
17 files changed, 271 insertions(+), 98 deletions(-)
create mode 100644 libc/hdr/types/struct_statfs.h
create mode 100644 libc/include/llvm-libc-types/fsid_t.h
create mode 100644 libc/include/llvm-libc-types/struct_statfs.h
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
create mode 100644 libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
diff --git a/libc/hdr/types/CMakeLists.txt b/libc/hdr/types/CMakeLists.txt
index 0c926050221f4..4715d98bf7556 100644
--- a/libc/hdr/types/CMakeLists.txt
+++ b/libc/hdr/types/CMakeLists.txt
@@ -177,6 +177,14 @@ add_proxy_header_library(
libc.include.llvm-libc-types.struct_stat
)
+add_proxy_header_library(
+ struct_statfs
+ HDRS
+ struct_statfs.h
+ FULL_BUILD_DEPENDS
+ libc.include.llvm-libc-types.struct_statfs
+)
+
add_proxy_header_library(
struct_winsize
HDRS
diff --git a/libc/hdr/types/struct_statfs.h b/libc/hdr/types/struct_statfs.h
new file mode 100644
index 0000000000000..e19d52add80e4
--- /dev/null
+++ b/libc/hdr/types/struct_statfs.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
+/// Proxy header for struct statfs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_HDR_TYPES_STRUCT_STATFS_H
+#define LLVM_LIBC_HDR_TYPES_STRUCT_STATFS_H
+
+#ifdef LIBC_FULL_BUILD
+
+#include "include/llvm-libc-types/struct_statfs.h"
+
+#else // Overlay mode
+
+#include <sys/statfs.h>
+
+#endif // LIBC_FULL_BUILD
+
+#endif // LLVM_LIBC_HDR_TYPES_STRUCT_STATFS_H
diff --git a/libc/include/llvm-libc-types/CMakeLists.txt b/libc/include/llvm-libc-types/CMakeLists.txt
index aae93bd905e36..edc36c34932aa 100644
--- a/libc/include/llvm-libc-types/CMakeLists.txt
+++ b/libc/include/llvm-libc-types/CMakeLists.txt
@@ -307,6 +307,16 @@ DEPENDS
.fsblkcnt_t
.fsfilcnt_t
)
+add_header(fsid_t HDR fsid_t.h)
+add_header(
+ struct_statfs
+HDR
+ struct_statfs.h
+DEPENDS
+ .fsblkcnt_t
+ .fsfilcnt_t
+ .fsid_t
+)
add_header(locale_t HDR locale_t.h)
add_header(struct_lconv HDR struct_lconv.h)
add_header(int_hk_t HDR int_hk_t.h)
diff --git a/libc/include/llvm-libc-types/fsid_t.h b/libc/include/llvm-libc-types/fsid_t.h
new file mode 100644
index 0000000000000..f7fd52e976bbd
--- /dev/null
+++ b/libc/include/llvm-libc-types/fsid_t.h
@@ -0,0 +1,21 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+/// Definition of fsid_t type.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_FSID_T_H
+#define LLVM_LIBC_TYPES_FSID_T_H
+
+typedef struct {
+ int __val[2];
+} fsid_t;
+
+#endif // LLVM_LIBC_TYPES_FSID_T_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 0000000000000..e5acd01267238
--- /dev/null
+++ b/libc/include/llvm-libc-types/struct_statfs.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
+/// Definition of type struct statfs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_TYPES_STRUCT_STATFS_H
+#define LLVM_LIBC_TYPES_STRUCT_STATFS_H
+
+#include "fsblkcnt_t.h"
+#include "fsfilcnt_t.h"
+#include "fsid_t.h"
+
+struct statfs {
+ unsigned long f_type;
+ unsigned long f_bsize;
+ fsblkcnt_t f_blocks;
+ fsblkcnt_t f_bfree;
+ fsblkcnt_t f_bavail;
+ fsfilcnt_t f_files;
+ fsfilcnt_t f_ffree;
+ fsid_t f_fsid;
+ unsigned long f_namelen;
+ unsigned long f_frsize;
+ unsigned long f_flags;
+ unsigned long f_spare[4];
+};
+
+#endif // LLVM_LIBC_TYPES_STRUCT_STATFS_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
index 7d5f94513d0de..a45641483bbef 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/CMakeLists.txt
@@ -901,3 +901,29 @@ add_header_library(
libc.src.__support.macros.config
libc.include.sys_syscall
)
+
+add_header_library(
+ statfs
+ HDRS
+ statfs.h
+ DEPENDS
+ libc.hdr.types.struct_statfs
+ 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(
+ fstatfs
+ HDRS
+ fstatfs.h
+ DEPENDS
+ libc.hdr.types.struct_statfs
+ libc.src.__support.OSUtil.osutil
+ libc.src.__support.common
+ libc.src.__support.error_or
+ libc.src.__support.macros.config
+ libc.include.sys_syscall
+)
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
new file mode 100644
index 0000000000000..4df0c3628d9dc
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 fstatfs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FSTATFS_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FSTATFS_H
+
+#include "hdr/types/struct_statfs.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> fstatfs(int fd, struct statfs *buf) {
+#ifdef SYS_fstatfs64
+ return syscall_checked<int>(SYS_fstatfs64, fd, sizeof(*buf), buf);
+#else
+ return syscall_checked<int>(SYS_fstatfs, fd, buf);
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_FSTATFS_H
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
new file mode 100644
index 0000000000000..a39db6bf516c4
--- /dev/null
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 statfs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATFS_H
+#define LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATFS_H
+
+#include "hdr/types/struct_statfs.h"
+#include "src/__support/OSUtil/linux/syscall.h" // For syscall_checked
+#include "src/__support/common.h"
+#include "src/__support/error_or.h"
+#include "src/__support/macros/config.h"
+#include <sys/syscall.h> // For syscall numbers
+
+namespace LIBC_NAMESPACE_DECL {
+namespace linux_syscalls {
+
+LIBC_INLINE ErrorOr<int> statfs(const char *path, struct statfs *buf) {
+#ifdef SYS_statfs64
+ return syscall_checked<int>(SYS_statfs64, path, sizeof(*buf), buf);
+#else
+ return syscall_checked<int>(SYS_statfs, path, buf);
+#endif
+}
+
+} // namespace linux_syscalls
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC___SUPPORT_OSUTIL_SYSCALL_WRAPPERS_STATFS_H
diff --git a/libc/src/sys/statvfs/linux/CMakeLists.txt b/libc/src/sys/statvfs/linux/CMakeLists.txt
index 2953717e70392..950962c47c941 100644
--- a/libc/src/sys/statvfs/linux/CMakeLists.txt
+++ b/libc/src/sys/statvfs/linux/CMakeLists.txt
@@ -3,11 +3,9 @@ add_header_library(
HDRS
statfs_utils.h
DEPENDS
- libc.src.errno.errno
- libc.src.__support.OSUtil.osutil
+ libc.hdr.types.struct_statfs
+ libc.hdr.stdint_proxy
libc.src.__support.common
- libc.src.__support.CPP.optional
- libc.include.sys_syscall
libc.include.sys_statvfs
)
@@ -19,6 +17,8 @@ add_entrypoint_object(
../statvfs.h
DEPENDS
libc.src.__support.libc_assert
+ libc.src.errno.errno
+ libc.src.__support.OSUtil.linux.syscall_wrappers.statfs
libc.include.sys_statvfs
.statfs_utils
)
@@ -31,6 +31,8 @@ add_entrypoint_object(
../fstatvfs.h
DEPENDS
libc.src.__support.libc_assert
+ libc.src.errno.errno
+ libc.src.__support.OSUtil.linux.syscall_wrappers.fstatfs
libc.include.sys_statvfs
.statfs_utils
)
diff --git a/libc/src/sys/statvfs/linux/fstatvfs.cpp b/libc/src/sys/statvfs/linux/fstatvfs.cpp
index 1a2fc04a1dff9..49d4cb818c966 100644
--- a/libc/src/sys/statvfs/linux/fstatvfs.cpp
+++ b/libc/src/sys/statvfs/linux/fstatvfs.cpp
@@ -7,8 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/sys/statvfs/fstatvfs.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/sys/statvfs/linux/statfs_utils.h"
@@ -16,12 +18,16 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, fstatvfs, (int fd, struct statvfs *buf)) {
using namespace statfs_utils;
- cpp::optional<LinuxStatFs> result = linux_fstatfs(fd);
- if (result) {
- LIBC_ASSERT(buf != nullptr);
- *buf = statfs_to_statvfs(*result);
+ struct statfs result;
+ auto error_or_ret = linux_syscalls::fstatfs(fd, &result);
+ if (!error_or_ret) {
+ libc_errno = error_or_ret.error();
+ return -1;
}
- return result ? 0 : -1;
+ result.f_flags &= ~ST_VALID;
+ LIBC_ASSERT(buf != nullptr);
+ *buf = statfs_to_statvfs(result);
+ return 0;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/sys/statvfs/linux/statfs_utils.h b/libc/src/sys/statvfs/linux/statfs_utils.h
index 8ee4de288ef61..90beb1f568c85 100644
--- a/libc/src/sys/statvfs/linux/statfs_utils.h
+++ b/libc/src/sys/statvfs/linux/statfs_utils.h
@@ -9,73 +9,22 @@
#ifndef LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
#define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
+#include "hdr/types/struct_statfs.h"
#include "include/llvm-libc-types/struct_statvfs.h"
-#include "src/__support/CPP/optional.h"
-#include "src/__support/OSUtil/syscall.h"
-#include "src/__support/libc_errno.h"
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/config.h"
-#include <asm/statfs.h>
-#include <sys/syscall.h>
-namespace LIBC_NAMESPACE_DECL {
+namespace LIBC_NAMESPACE_DECL {
namespace statfs_utils {
-#ifdef SYS_statfs64
-using LinuxStatFs = statfs64;
-#else
-using LinuxStatFs = statfs;
-#endif
// Linux kernel set an additional flag to f_flags. Libc should mask it out.
-LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020;
-
-LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) {
- // The kernel syscall routine checks the validity of the path before filling
- // the statfs structure. So, it is possible that the result is not initialized
- // after the syscall. Since the struct is trvial, the compiler will generate
- // pattern filling for the struct.
- LinuxStatFs result;
- // On 32-bit platforms, original statfs cannot handle large file systems.
- // In such cases, SYS_statfs64 is defined and should be used.
-#ifdef SYS_statfs64
- int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result);
-#else
- int ret = syscall_impl<int>(SYS_statfs, path, &result);
-#endif
- if (ret < 0) {
- libc_errno = -ret;
- return cpp::nullopt;
- }
- result.f_flags &= ~ST_VALID;
- return result;
-}
-
-LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) {
- // The kernel syscall routine checks the validity of the path before filling
- // the statfs structure. So, it is possible that the result is not initialized
- // after the syscall. Since the struct is trvial, the compiler will generate
- // pattern filling for the struct.
- LinuxStatFs result;
- // On 32-bit platforms, original fstatfs cannot handle large file systems.
- // In such cases, SYS_fstatfs64 is defined and should be used.
-#ifdef SYS_fstatfs64
- int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result);
-#else
- int ret = syscall_impl<int>(SYS_fstatfs, fd, &result);
-#endif
- if (ret < 0) {
- libc_errno = -ret;
- return cpp::nullopt;
- }
- result.f_flags &= ~ST_VALID;
- return result;
-}
+LIBC_INLINE_VAR constexpr long ST_VALID = 0x0020;
// must use 'struct' tag to refer to type 'statvfs' in this scope. There will be
// a function in the same namespace with the same name. For consistency, we use
// struct prefix for all statvfs/statfs related types.
-LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {
- struct statvfs out;
+LIBC_INLINE struct statvfs statfs_to_statvfs(const struct statfs &in) {
+ struct statvfs out{};
out.f_bsize = in.f_bsize;
out.f_frsize = in.f_frsize;
out.f_blocks = static_cast<decltype(out.f_blocks)>(in.f_blocks);
@@ -84,10 +33,10 @@ LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {
out.f_files = static_cast<decltype(out.f_files)>(in.f_files);
out.f_ffree = static_cast<decltype(out.f_ffree)>(in.f_ffree);
out.f_favail = static_cast<decltype(out.f_favail)>(in.f_ffree);
- out.f_fsid = in.f_fsid.val[0];
+ out.f_fsid = in.f_fsid.__val[0];
if constexpr (sizeof(decltype(out.f_fsid)) == sizeof(uint64_t))
- out.f_fsid |= static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32;
- out.f_flag = in.f_flags;
+ out.f_fsid |= static_cast<decltype(out.f_fsid)>(in.f_fsid.__val[1]) << 32;
+ out.f_flag = in.f_flags & ~ST_VALID;
out.f_namemax = in.f_namelen;
return out;
}
diff --git a/libc/src/sys/statvfs/linux/statvfs.cpp b/libc/src/sys/statvfs/linux/statvfs.cpp
index fc3c75a260ce0..c02de91a26f78 100644
--- a/libc/src/sys/statvfs/linux/statvfs.cpp
+++ b/libc/src/sys/statvfs/linux/statvfs.cpp
@@ -7,8 +7,10 @@
//===----------------------------------------------------------------------===//
#include "src/sys/statvfs/statvfs.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/statfs.h"
#include "src/__support/common.h"
#include "src/__support/libc_assert.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
#include "src/sys/statvfs/linux/statfs_utils.h"
@@ -18,12 +20,16 @@ LLVM_LIBC_FUNCTION(int, statvfs,
(const char *__restrict path,
struct statvfs *__restrict buf)) {
using namespace statfs_utils;
- cpp::optional<LinuxStatFs> result = linux_statfs(path);
- if (result) {
- LIBC_ASSERT(buf != nullptr);
- *buf = statfs_to_statvfs(*result);
+ struct statfs result;
+ auto error_or_ret = linux_syscalls::statfs(path, &result);
+ if (!error_or_ret) {
+ libc_errno = error_or_ret.error();
+ return -1;
}
- return result ? 0 : -1;
+ result.f_flags &= ~ST_VALID;
+ LIBC_ASSERT(buf != nullptr);
+ *buf = statfs_to_statvfs(result);
+ return 0;
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/CMakeLists.txt b/libc/src/unistd/linux/CMakeLists.txt
index 49520c1dcf265..7e7a551d9539e 100644
--- a/libc/src/unistd/linux/CMakeLists.txt
+++ b/libc/src/unistd/linux/CMakeLists.txt
@@ -156,8 +156,8 @@ add_entrypoint_object(
../fpathconf.h
DEPENDS
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.hdr.types.struct_statfs
+ libc.src.__support.OSUtil.linux.syscall_wrappers.fstatfs
libc.src.errno.errno
libc.src.unistd.linux.pathconf_utils
)
@@ -394,8 +394,8 @@ add_entrypoint_object(
../pathconf.h
DEPENDS
libc.include.unistd
- libc.include.sys_syscall
- libc.src.__support.OSUtil.osutil
+ libc.hdr.types.struct_statfs
+ libc.src.__support.OSUtil.linux.syscall_wrappers.statfs
libc.src.errno.errno
libc.src.unistd.linux.pathconf_utils
)
@@ -409,9 +409,8 @@ add_object_library(
DEPENDS
libc.hdr.limits_macros
libc.hdr.unistd_macros
- libc.src.__support.OSUtil.osutil
libc.src.errno.errno
- libc.src.sys.statvfs.linux.statfs_utils
+ libc.hdr.types.struct_statfs
)
add_entrypoint_object(
diff --git a/libc/src/unistd/linux/fpathconf.cpp b/libc/src/unistd/linux/fpathconf.cpp
index 8e0c8bcdfc22f..1a613d7c820df 100644
--- a/libc/src/unistd/linux/fpathconf.cpp
+++ b/libc/src/unistd/linux/fpathconf.cpp
@@ -7,19 +7,23 @@
//===----------------------------------------------------------------------===//
#include "src/unistd/fpathconf.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
+#include "hdr/types/struct_statfs.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h"
#include "src/__support/common.h"
+#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/sys/statvfs/linux/statfs_utils.h"
#include "src/unistd/linux/pathconf_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long, fpathconf, (int fd, int name)) {
- if (cpp::optional<statfs_utils::LinuxStatFs> result =
- statfs_utils::linux_fstatfs(fd))
- return pathconfig(result.value(), name);
- return -1;
+ struct statfs result;
+ auto error_or_ret = linux_syscalls::fstatfs(fd, &result);
+ if (!error_or_ret) {
+ libc_errno = error_or_ret.error();
+ return -1;
+ }
+ return pathconfig(result, name);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/pathconf.cpp b/libc/src/unistd/linux/pathconf.cpp
index 7dde857c1cfd8..d3146882831da 100644
--- a/libc/src/unistd/linux/pathconf.cpp
+++ b/libc/src/unistd/linux/pathconf.cpp
@@ -7,18 +7,22 @@
//===----------------------------------------------------------------------===//
#include "src/unistd/pathconf.h"
+#include "hdr/types/struct_statfs.h"
+#include "src/__support/OSUtil/linux/syscall_wrappers/statfs.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/sys/statvfs/linux/statfs_utils.h"
#include "src/unistd/linux/pathconf_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(long, pathconf, (const char *path, int name)) {
- if (cpp::optional<statfs_utils::LinuxStatFs> result =
- statfs_utils::linux_statfs(path))
- return pathconfig(result.value(), name);
- return -1;
+ struct statfs result;
+ auto error_or_ret = linux_syscalls::statfs(path, &result);
+ if (!error_or_ret) {
+ libc_errno = error_or_ret.error();
+ return -1;
+ }
+ return pathconfig(result, name);
}
} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/unistd/linux/pathconf_utils.cpp b/libc/src/unistd/linux/pathconf_utils.cpp
index 9a62e31fd1880..511be724f8862 100644
--- a/libc/src/unistd/linux/pathconf_utils.cpp
+++ b/libc/src/unistd/linux/pathconf_utils.cpp
@@ -12,11 +12,10 @@
#include "hdr/limits_macros.h"
#include "hdr/unistd_macros.h"
-#include "src/__support/OSUtil/syscall.h" // For internal syscall function.
#include "src/__support/common.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
-#include "src/sys/statvfs/linux/statfs_utils.h"
+#include "src/unistd/linux/pathconf_utils.h"
// other linux specific includes
#include <linux/bfs_fs.h>
@@ -30,7 +29,7 @@
namespace LIBC_NAMESPACE_DECL {
-long filesizebits(const statfs_utils::LinuxStatFs &s) {
+long filesizebits(const ::statfs &s) {
switch (s.f_type) {
case JFFS2_SUPER_MAGIC:
case MSDOS_SUPER_MAGIC:
@@ -40,7 +39,7 @@ long filesizebits(const statfs_utils::LinuxStatFs &s) {
return 64;
}
-long link_max(const statfs_utils::LinuxStatFs &s) {
+long link_max(const ::statfs &s) {
switch (s.f_type) {
case EXT2_SUPER_MAGIC:
return 32000;
@@ -56,7 +55,7 @@ long link_max(const statfs_utils::LinuxStatFs &s) {
return LINK_MAX;
}
-long symlinks(const statfs_utils::LinuxStatFs &s) {
+long symlinks(const ::statfs &s) {
switch (s.f_type) {
case ADFS_SUPER_MAGIC:
case BFS_MAGIC:
@@ -69,7 +68,7 @@ long symlinks(const statfs_utils::LinuxStatFs &s) {
return 1;
}
-long pathconfig(const statfs_utils::LinuxStatFs &s, int name) {
+long pathconfig(const ::statfs &s, int name) {
switch (name) {
case _PC_LINK_MAX:
return link_max(s);
diff --git a/libc/src/unistd/linux/pathconf_utils.h b/libc/src/unistd/linux/pathconf_utils.h
index 8487802c09dca..4302b391e9587 100644
--- a/libc/src/unistd/linux/pathconf_utils.h
+++ b/libc/src/unistd/linux/pathconf_utils.h
@@ -9,12 +9,12 @@
#ifndef LLVM_LIBC_SRC_UNISTD_PATHCONF_UTILS_H
#define LLVM_LIBC_SRC_UNISTD_PATHCONF_UTILS_H
+#include "hdr/types/struct_statfs.h"
#include "src/__support/macros/config.h"
-#include "src/sys/statvfs/linux/statfs_utils.h"
namespace LIBC_NAMESPACE_DECL {
-long pathconfig(const statfs_utils::LinuxStatFs &s, int name);
+long pathconfig(const ::statfs &s, int name);
} // namespace LIBC_NAMESPACE_DECL
>From e5dd0731ea8ec9a48f1b0c72f8a96dcbddb43c42 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Thu, 30 Jul 2026 05:27:01 +0000
Subject: [PATCH 2/4] slight fix for statvfs/fstatvfs entrypoints
---
libc/src/sys/statvfs/linux/CMakeLists.txt | 2 ++
libc/src/sys/statvfs/linux/fstatvfs.cpp | 7 +++----
libc/src/sys/statvfs/linux/statvfs.cpp | 7 +++----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/libc/src/sys/statvfs/linux/CMakeLists.txt b/libc/src/sys/statvfs/linux/CMakeLists.txt
index 950962c47c941..a00d5a039406b 100644
--- a/libc/src/sys/statvfs/linux/CMakeLists.txt
+++ b/libc/src/sys/statvfs/linux/CMakeLists.txt
@@ -18,6 +18,7 @@ add_entrypoint_object(
DEPENDS
libc.src.__support.libc_assert
libc.src.errno.errno
+ libc.src.__support.macros.null_check
libc.src.__support.OSUtil.linux.syscall_wrappers.statfs
libc.include.sys_statvfs
.statfs_utils
@@ -32,6 +33,7 @@ add_entrypoint_object(
DEPENDS
libc.src.__support.libc_assert
libc.src.errno.errno
+ libc.src.__support.macros.null_check
libc.src.__support.OSUtil.linux.syscall_wrappers.fstatfs
libc.include.sys_statvfs
.statfs_utils
diff --git a/libc/src/sys/statvfs/linux/fstatvfs.cpp b/libc/src/sys/statvfs/linux/fstatvfs.cpp
index 49d4cb818c966..6f3d8b0714b83 100644
--- a/libc/src/sys/statvfs/linux/fstatvfs.cpp
+++ b/libc/src/sys/statvfs/linux/fstatvfs.cpp
@@ -12,21 +12,20 @@
#include "src/__support/libc_assert.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/sys/statvfs/linux/statfs_utils.h"
namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, fstatvfs, (int fd, struct statvfs *buf)) {
- using namespace statfs_utils;
+ LIBC_CRASH_ON_NULLPTR(buf);
struct statfs result;
auto error_or_ret = linux_syscalls::fstatfs(fd, &result);
if (!error_or_ret) {
libc_errno = error_or_ret.error();
return -1;
}
- result.f_flags &= ~ST_VALID;
- LIBC_ASSERT(buf != nullptr);
- *buf = statfs_to_statvfs(result);
+ *buf = statfs_utils::statfs_to_statvfs(result);
return 0;
}
diff --git a/libc/src/sys/statvfs/linux/statvfs.cpp b/libc/src/sys/statvfs/linux/statvfs.cpp
index c02de91a26f78..75cd54d22e389 100644
--- a/libc/src/sys/statvfs/linux/statvfs.cpp
+++ b/libc/src/sys/statvfs/linux/statvfs.cpp
@@ -12,6 +12,7 @@
#include "src/__support/libc_assert.h"
#include "src/__support/libc_errno.h"
#include "src/__support/macros/config.h"
+#include "src/__support/macros/null_check.h"
#include "src/sys/statvfs/linux/statfs_utils.h"
namespace LIBC_NAMESPACE_DECL {
@@ -19,16 +20,14 @@ namespace LIBC_NAMESPACE_DECL {
LLVM_LIBC_FUNCTION(int, statvfs,
(const char *__restrict path,
struct statvfs *__restrict buf)) {
- using namespace statfs_utils;
+ LIBC_CRASH_ON_NULLPTR(buf);
struct statfs result;
auto error_or_ret = linux_syscalls::statfs(path, &result);
if (!error_or_ret) {
libc_errno = error_or_ret.error();
return -1;
}
- result.f_flags &= ~ST_VALID;
- LIBC_ASSERT(buf != nullptr);
- *buf = statfs_to_statvfs(result);
+ *buf = statfs_utils::statfs_to_statvfs(result);
return 0;
}
>From 455c9bf1adf310de9b7bd50ac7466a0573214e20 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Thu, 30 Jul 2026 05:39:03 +0000
Subject: [PATCH 3/4] Use 'struct statfs' properly
---
libc/src/unistd/linux/pathconf_utils.cpp | 8 ++++----
libc/src/unistd/linux/pathconf_utils.h | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/libc/src/unistd/linux/pathconf_utils.cpp b/libc/src/unistd/linux/pathconf_utils.cpp
index 511be724f8862..52e59c3794ffd 100644
--- a/libc/src/unistd/linux/pathconf_utils.cpp
+++ b/libc/src/unistd/linux/pathconf_utils.cpp
@@ -29,7 +29,7 @@
namespace LIBC_NAMESPACE_DECL {
-long filesizebits(const ::statfs &s) {
+long filesizebits(const struct statfs &s) {
switch (s.f_type) {
case JFFS2_SUPER_MAGIC:
case MSDOS_SUPER_MAGIC:
@@ -39,7 +39,7 @@ long filesizebits(const ::statfs &s) {
return 64;
}
-long link_max(const ::statfs &s) {
+long link_max(const struct statfs &s) {
switch (s.f_type) {
case EXT2_SUPER_MAGIC:
return 32000;
@@ -55,7 +55,7 @@ long link_max(const ::statfs &s) {
return LINK_MAX;
}
-long symlinks(const ::statfs &s) {
+long symlinks(const struct statfs &s) {
switch (s.f_type) {
case ADFS_SUPER_MAGIC:
case BFS_MAGIC:
@@ -68,7 +68,7 @@ long symlinks(const ::statfs &s) {
return 1;
}
-long pathconfig(const ::statfs &s, int name) {
+long pathconfig(const struct statfs &s, int name) {
switch (name) {
case _PC_LINK_MAX:
return link_max(s);
diff --git a/libc/src/unistd/linux/pathconf_utils.h b/libc/src/unistd/linux/pathconf_utils.h
index 4302b391e9587..b1fd3db5a99e6 100644
--- a/libc/src/unistd/linux/pathconf_utils.h
+++ b/libc/src/unistd/linux/pathconf_utils.h
@@ -14,7 +14,7 @@
namespace LIBC_NAMESPACE_DECL {
-long pathconfig(const ::statfs &s, int name);
+long pathconfig(const struct statfs &s, int name);
} // namespace LIBC_NAMESPACE_DECL
>From 486e10d173929acb6b28d4db582cbb3c71182201 Mon Sep 17 00:00:00 2001
From: Alexey Samsonov <vonosmas at gmail.com>
Date: Thu, 30 Jul 2026 14:18:18 +0000
Subject: [PATCH 4/4] Add asserts and comments per review feedback.
---
libc/include/llvm-libc-types/struct_statfs.h | 3 +++
libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h | 5 +++++
libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h | 5 +++++
3 files changed, 13 insertions(+)
diff --git a/libc/include/llvm-libc-types/struct_statfs.h b/libc/include/llvm-libc-types/struct_statfs.h
index e5acd01267238..2767d44507177 100644
--- a/libc/include/llvm-libc-types/struct_statfs.h
+++ b/libc/include/llvm-libc-types/struct_statfs.h
@@ -18,6 +18,9 @@
#include "fsfilcnt_t.h"
#include "fsid_t.h"
+// NOTE: This structure may have different layouts on architectures we don't
+// fully support (e.g. s390 or MIPS).
+
struct statfs {
unsigned long f_type;
unsigned long f_bsize;
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
index 4df0c3628d9dc..39c48bd012060 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/fstatfs.h
@@ -26,8 +26,13 @@ namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> fstatfs(int fd, struct statfs *buf) {
#ifdef SYS_fstatfs64
+ static_assert(sizeof(statfs::f_blocks) == 8,
+ "Can only be used with 64-bit version of the struct");
return syscall_checked<int>(SYS_fstatfs64, fd, sizeof(*buf), buf);
#else
+ static_assert(
+ sizeof(statfs::f_blocks) == sizeof(long),
+ "The fallback is unsafe on 32-bit platforms with 64-bit f_blocks.");
return syscall_checked<int>(SYS_fstatfs, fd, buf);
#endif
}
diff --git a/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h b/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
index a39db6bf516c4..1c1cbd4ec4ee0 100644
--- a/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
+++ b/libc/src/__support/OSUtil/linux/syscall_wrappers/statfs.h
@@ -26,8 +26,13 @@ namespace linux_syscalls {
LIBC_INLINE ErrorOr<int> statfs(const char *path, struct statfs *buf) {
#ifdef SYS_statfs64
+ static_assert(sizeof(statfs::f_blocks) == 8,
+ "Can only be used with 64-bit version of the struct");
return syscall_checked<int>(SYS_statfs64, path, sizeof(*buf), buf);
#else
+ static_assert(
+ sizeof(statfs::f_blocks) == sizeof(long),
+ "The fallback is unsafe on 32-bit platforms with 64-bit f_blocks.");
return syscall_checked<int>(SYS_statfs, path, buf);
#endif
}
More information about the libc-commits
mailing list