98 lines · c
1//===-- Convert Statfs to Statvfs -------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H10#define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H11 12#include "include/llvm-libc-types/struct_statvfs.h"13#include "src/__support/CPP/optional.h"14#include "src/__support/OSUtil/syscall.h"15#include "src/__support/libc_errno.h"16#include "src/__support/macros/attributes.h"17#include "src/__support/macros/config.h"18#include <asm/statfs.h>19#include <sys/syscall.h>20namespace LIBC_NAMESPACE_DECL {21 22namespace statfs_utils {23#ifdef SYS_statfs6424using LinuxStatFs = statfs64;25#else26using LinuxStatFs = statfs;27#endif28 29// Linux kernel set an additional flag to f_flags. Libc should mask it out.30LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020;31 32LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) {33 // The kernel syscall routine checks the validity of the path before filling34 // the statfs structure. So, it is possible that the result is not initialized35 // after the syscall. Since the struct is trvial, the compiler will generate36 // pattern filling for the struct.37 LinuxStatFs result;38 // On 32-bit platforms, original statfs cannot handle large file systems.39 // In such cases, SYS_statfs64 is defined and should be used.40#ifdef SYS_statfs6441 int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result);42#else43 int ret = syscall_impl<int>(SYS_statfs, path, &result);44#endif45 if (ret < 0) {46 libc_errno = -ret;47 return cpp::nullopt;48 }49 result.f_flags &= ~ST_VALID;50 return result;51}52 53LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) {54 // The kernel syscall routine checks the validity of the path before filling55 // the statfs structure. So, it is possible that the result is not initialized56 // after the syscall. Since the struct is trvial, the compiler will generate57 // pattern filling for the struct.58 LinuxStatFs result;59 // On 32-bit platforms, original fstatfs cannot handle large file systems.60 // In such cases, SYS_fstatfs64 is defined and should be used.61#ifdef SYS_fstatfs6462 int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result);63#else64 int ret = syscall_impl<int>(SYS_fstatfs, fd, &result);65#endif66 if (ret < 0) {67 libc_errno = -ret;68 return cpp::nullopt;69 }70 result.f_flags &= ~ST_VALID;71 return result;72}73 74// must use 'struct' tag to refer to type 'statvfs' in this scope. There will be75// a function in the same namespace with the same name. For consistency, we use76// struct prefix for all statvfs/statfs related types.77LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {78 struct statvfs out;79 out.f_bsize = in.f_bsize;80 out.f_frsize = in.f_frsize;81 out.f_blocks = static_cast<decltype(out.f_blocks)>(in.f_blocks);82 out.f_bfree = static_cast<decltype(out.f_bfree)>(in.f_bfree);83 out.f_bavail = static_cast<decltype(out.f_bavail)>(in.f_bavail);84 out.f_files = static_cast<decltype(out.f_files)>(in.f_files);85 out.f_ffree = static_cast<decltype(out.f_ffree)>(in.f_ffree);86 out.f_favail = static_cast<decltype(out.f_favail)>(in.f_ffree);87 out.f_fsid = in.f_fsid.val[0];88 if constexpr (sizeof(decltype(out.f_fsid)) == sizeof(uint64_t))89 out.f_fsid |= static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32;90 out.f_flag = in.f_flags;91 out.f_namemax = in.f_namelen;92 return out;93}94} // namespace statfs_utils95} // namespace LIBC_NAMESPACE_DECL96 97#endif // LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H98