• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
10 #define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
11 
12 #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/macros/attributes.h"
16 #include "src/errno/libc_errno.h"
17 #include <asm/statfs.h>
18 #include <sys/syscall.h>
19 namespace LIBC_NAMESPACE {
20 
21 namespace statfs_utils {
22 #ifdef SYS_statfs64
23 using LinuxStatFs = statfs64;
24 #else
25 using LinuxStatFs = statfs;
26 #endif
27 
28 // Linux kernel set an additional flag to f_flags. Libc should mask it out.
29 LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020;
30 
linux_statfs(const char * path)31 LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) {
32   // The kernel syscall routine checks the validity of the path before filling
33   // the statfs structure. So, it is possible that the result is not initialized
34   // after the syscall. Since the struct is trvial, the compiler will generate
35   // pattern filling for the struct.
36   LinuxStatFs result;
37   // On 32-bit platforms, original statfs cannot handle large file systems.
38   // In such cases, SYS_statfs64 is defined and should be used.
39 #ifdef SYS_statfs64
40   int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result);
41 #else
42   int ret = syscall_impl<int>(SYS_statfs, path, &result);
43 #endif
44   if (ret < 0) {
45     libc_errno = -ret;
46     return cpp::nullopt;
47   }
48   result.f_flags &= ~ST_VALID;
49   return result;
50 }
51 
linux_fstatfs(int fd)52 LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) {
53   // The kernel syscall routine checks the validity of the path before filling
54   // the statfs structure. So, it is possible that the result is not initialized
55   // after the syscall. Since the struct is trvial, the compiler will generate
56   // pattern filling for the struct.
57   LinuxStatFs result;
58   // On 32-bit platforms, original fstatfs cannot handle large file systems.
59   // In such cases, SYS_fstatfs64 is defined and should be used.
60 #ifdef SYS_fstatfs64
61   int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result);
62 #else
63   int ret = syscall_impl<int>(SYS_fstatfs, fd, &result);
64 #endif
65   if (ret < 0) {
66     libc_errno = -ret;
67     return cpp::nullopt;
68   }
69   result.f_flags &= ~ST_VALID;
70   return result;
71 }
72 
73 // must use 'struct' tag to refer to type 'statvfs' in this scope. There will be
74 // a function in the same namespace with the same name. For consistency, we use
75 // struct prefix for all statvfs/statfs related types.
statfs_to_statvfs(const LinuxStatFs & in)76 LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {
77   struct statvfs out;
78   out.f_bsize = in.f_bsize;
79   out.f_frsize = in.f_frsize;
80   out.f_blocks = in.f_blocks;
81   out.f_bfree = in.f_bfree;
82   out.f_bavail = in.f_bavail;
83   out.f_files = in.f_files;
84   out.f_ffree = in.f_ffree;
85   out.f_favail = in.f_ffree;
86   out.f_fsid = in.f_fsid.val[0] |
87                static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32;
88   out.f_flag = in.f_flags;
89   out.f_namemax = in.f_namelen;
90   return out;
91 }
92 } // namespace statfs_utils
93 } // namespace LIBC_NAMESPACE
94 
95 #endif // LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
96