xref: /llvm-project/libc/src/sys/statvfs/linux/statfs_utils.h (revision 7e37d021022b0786a704a89abae2014692158b2f)
105dc5d92SSchrodinger ZHU Yifan //===-- Convert Statfs to Statvfs -------------------------------*- C++ -*-===//
205dc5d92SSchrodinger ZHU Yifan //
305dc5d92SSchrodinger ZHU Yifan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
405dc5d92SSchrodinger ZHU Yifan // See https://llvm.org/LICENSE.txt for license information.
505dc5d92SSchrodinger ZHU Yifan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
605dc5d92SSchrodinger ZHU Yifan //
705dc5d92SSchrodinger ZHU Yifan //===----------------------------------------------------------------------===//
805dc5d92SSchrodinger ZHU Yifan 
905dc5d92SSchrodinger ZHU Yifan #ifndef LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
1005dc5d92SSchrodinger ZHU Yifan #define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
1105dc5d92SSchrodinger ZHU Yifan 
12*7e37d021SJoseph Huber #include "include/llvm-libc-types/struct_statvfs.h"
1305dc5d92SSchrodinger ZHU Yifan #include "src/__support/CPP/optional.h"
1405dc5d92SSchrodinger ZHU Yifan #include "src/__support/OSUtil/syscall.h"
1505dc5d92SSchrodinger ZHU Yifan #include "src/__support/macros/attributes.h"
165ff3ff33SPetr Hosek #include "src/__support/macros/config.h"
1705dc5d92SSchrodinger ZHU Yifan #include "src/errno/libc_errno.h"
1805dc5d92SSchrodinger ZHU Yifan #include <asm/statfs.h>
1905dc5d92SSchrodinger ZHU Yifan #include <sys/syscall.h>
205ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL {
2105dc5d92SSchrodinger ZHU Yifan 
2205dc5d92SSchrodinger ZHU Yifan namespace statfs_utils {
2305dc5d92SSchrodinger ZHU Yifan #ifdef SYS_statfs64
2405dc5d92SSchrodinger ZHU Yifan using LinuxStatFs = statfs64;
2505dc5d92SSchrodinger ZHU Yifan #else
2605dc5d92SSchrodinger ZHU Yifan using LinuxStatFs = statfs;
2705dc5d92SSchrodinger ZHU Yifan #endif
2805dc5d92SSchrodinger ZHU Yifan 
2905dc5d92SSchrodinger ZHU Yifan // Linux kernel set an additional flag to f_flags. Libc should mask it out.
3005dc5d92SSchrodinger ZHU Yifan LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020;
3105dc5d92SSchrodinger ZHU Yifan 
3205dc5d92SSchrodinger ZHU Yifan LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) {
3305dc5d92SSchrodinger ZHU Yifan   // The kernel syscall routine checks the validity of the path before filling
3405dc5d92SSchrodinger ZHU Yifan   // the statfs structure. So, it is possible that the result is not initialized
3505dc5d92SSchrodinger ZHU Yifan   // after the syscall. Since the struct is trvial, the compiler will generate
3605dc5d92SSchrodinger ZHU Yifan   // pattern filling for the struct.
3705dc5d92SSchrodinger ZHU Yifan   LinuxStatFs result;
3805dc5d92SSchrodinger ZHU Yifan   // On 32-bit platforms, original statfs cannot handle large file systems.
3905dc5d92SSchrodinger ZHU Yifan   // In such cases, SYS_statfs64 is defined and should be used.
4005dc5d92SSchrodinger ZHU Yifan #ifdef SYS_statfs64
4105dc5d92SSchrodinger ZHU Yifan   int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result);
4205dc5d92SSchrodinger ZHU Yifan #else
4305dc5d92SSchrodinger ZHU Yifan   int ret = syscall_impl<int>(SYS_statfs, path, &result);
4405dc5d92SSchrodinger ZHU Yifan #endif
4505dc5d92SSchrodinger ZHU Yifan   if (ret < 0) {
4605dc5d92SSchrodinger ZHU Yifan     libc_errno = -ret;
4705dc5d92SSchrodinger ZHU Yifan     return cpp::nullopt;
4805dc5d92SSchrodinger ZHU Yifan   }
4905dc5d92SSchrodinger ZHU Yifan   result.f_flags &= ~ST_VALID;
5005dc5d92SSchrodinger ZHU Yifan   return result;
5105dc5d92SSchrodinger ZHU Yifan }
5205dc5d92SSchrodinger ZHU Yifan 
5305dc5d92SSchrodinger ZHU Yifan LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) {
5405dc5d92SSchrodinger ZHU Yifan   // The kernel syscall routine checks the validity of the path before filling
5505dc5d92SSchrodinger ZHU Yifan   // the statfs structure. So, it is possible that the result is not initialized
5605dc5d92SSchrodinger ZHU Yifan   // after the syscall. Since the struct is trvial, the compiler will generate
5705dc5d92SSchrodinger ZHU Yifan   // pattern filling for the struct.
5805dc5d92SSchrodinger ZHU Yifan   LinuxStatFs result;
5905dc5d92SSchrodinger ZHU Yifan   // On 32-bit platforms, original fstatfs cannot handle large file systems.
6005dc5d92SSchrodinger ZHU Yifan   // In such cases, SYS_fstatfs64 is defined and should be used.
6105dc5d92SSchrodinger ZHU Yifan #ifdef SYS_fstatfs64
6205dc5d92SSchrodinger ZHU Yifan   int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result);
6305dc5d92SSchrodinger ZHU Yifan #else
6405dc5d92SSchrodinger ZHU Yifan   int ret = syscall_impl<int>(SYS_fstatfs, fd, &result);
6505dc5d92SSchrodinger ZHU Yifan #endif
6605dc5d92SSchrodinger ZHU Yifan   if (ret < 0) {
6705dc5d92SSchrodinger ZHU Yifan     libc_errno = -ret;
6805dc5d92SSchrodinger ZHU Yifan     return cpp::nullopt;
6905dc5d92SSchrodinger ZHU Yifan   }
7005dc5d92SSchrodinger ZHU Yifan   result.f_flags &= ~ST_VALID;
7105dc5d92SSchrodinger ZHU Yifan   return result;
7205dc5d92SSchrodinger ZHU Yifan }
7305dc5d92SSchrodinger ZHU Yifan 
7405dc5d92SSchrodinger ZHU Yifan // must use 'struct' tag to refer to type 'statvfs' in this scope. There will be
7505dc5d92SSchrodinger ZHU Yifan // a function in the same namespace with the same name. For consistency, we use
7605dc5d92SSchrodinger ZHU Yifan // struct prefix for all statvfs/statfs related types.
7705dc5d92SSchrodinger ZHU Yifan LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {
7805dc5d92SSchrodinger ZHU Yifan   struct statvfs out;
7905dc5d92SSchrodinger ZHU Yifan   out.f_bsize = in.f_bsize;
8005dc5d92SSchrodinger ZHU Yifan   out.f_frsize = in.f_frsize;
81c1f1aab5SMikhail R. Gadelha   out.f_blocks = static_cast<decltype(out.f_blocks)>(in.f_blocks);
82c1f1aab5SMikhail R. Gadelha   out.f_bfree = static_cast<decltype(out.f_bfree)>(in.f_bfree);
83c1f1aab5SMikhail R. Gadelha   out.f_bavail = static_cast<decltype(out.f_bavail)>(in.f_bavail);
84c1f1aab5SMikhail R. Gadelha   out.f_files = static_cast<decltype(out.f_files)>(in.f_files);
85c1f1aab5SMikhail R. Gadelha   out.f_ffree = static_cast<decltype(out.f_ffree)>(in.f_ffree);
86c1f1aab5SMikhail R. Gadelha   out.f_favail = static_cast<decltype(out.f_favail)>(in.f_ffree);
87c1f1aab5SMikhail R. Gadelha   out.f_fsid = in.f_fsid.val[0];
88c1f1aab5SMikhail R. Gadelha   if constexpr (sizeof(decltype(out.f_fsid)) == sizeof(uint64_t))
89c1f1aab5SMikhail R. Gadelha     out.f_fsid |= static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32;
9005dc5d92SSchrodinger ZHU Yifan   out.f_flag = in.f_flags;
9105dc5d92SSchrodinger ZHU Yifan   out.f_namemax = in.f_namelen;
9205dc5d92SSchrodinger ZHU Yifan   return out;
9305dc5d92SSchrodinger ZHU Yifan }
9405dc5d92SSchrodinger ZHU Yifan } // namespace statfs_utils
955ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL
9605dc5d92SSchrodinger ZHU Yifan 
9705dc5d92SSchrodinger ZHU Yifan #endif // LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
98