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