Skip to content

Commit 05dc5d9

Browse files
[libc] add statvfs/fstatvfs (#86169)
fixes #86449
1 parent 05840c8 commit 05dc5d9

22 files changed

+495
-0
lines changed

libc/config/linux/api.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,7 @@ def SetJmpAPI : PublicAPI<"setjmp.h"> {
262262
def SearchAPI : PublicAPI<"search.h"> {
263263
let Types = ["ACTION", "ENTRY", "struct hsearch_data"];
264264
}
265+
266+
def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> {
267+
let Types = ["fsblkcnt_t", "fsfilcnt_t", "struct statvfs"];
268+
}

libc/config/linux/x86_64/entrypoints.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ set(TARGET_LIBC_ENTRYPOINTS
257257
libc.src.sys.stat.mkdirat
258258
libc.src.sys.stat.stat
259259

260+
# sys/statvfs.h
261+
libc.src.sys.statvfs.statvfs
262+
libc.src.sys.statvfs.fstatvfs
263+
260264
# sys/utsname.h entrypoints
261265
libc.src.sys.utsname.uname
262266

libc/include/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,15 @@ add_gen_header(
498498
.llvm-libc-types.struct_sockaddr_un
499499
)
500500

501+
add_gen_header(
502+
sys_statvfs
503+
DEF_FILE sys/statvfs.h.def
504+
GEN_HDR sys/statvfs.h
505+
DEPENDS
506+
.llvm_libc_common_h
507+
.llvm-libc-types.struct_statvfs
508+
)
509+
501510
add_gen_header(
502511
sys_syscall
503512
DEF_FILE sys/syscall.h.def

libc/include/llvm-libc-types/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,13 @@ add_header(
106106
DEPENDS
107107
libc.include.llvm-libc-macros.float_macros
108108
)
109+
add_header(fsblkcnt_t HDR fsblkcnt_t.h)
110+
add_header(fsfilcnt_t HDR fsfilcnt_t.h)
111+
add_header(
112+
struct_statvfs
113+
HDR
114+
struct_statvfs.h
115+
DEPENDS
116+
.fsblkcnt_t
117+
.fsfilcnt_t
118+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===-- Definition of fsblkcnt_t type -------------------------------------===//
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_TYPES_FSBLKCNT_T_H
10+
#define LLVM_LIBC_TYPES_FSBLKCNT_T_H
11+
12+
typedef __SIZE_TYPE__ fsblkcnt_t;
13+
14+
#endif // LLVM_LIBC_TYPES_FSBLKCNT_T_H
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//===-- Definition of fsfilcnt_t type -------------------------------------===//
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_TYPES_FSFILCNT_T_H
10+
#define LLVM_LIBC_TYPES_FSFILCNT_T_H
11+
12+
typedef __SIZE_TYPE__ fsfilcnt_t;
13+
14+
#endif // LLVM_LIBC_TYPES_FSFILCNT_T_H
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//===-- Definition of type struct statvfs ---------------------------------===//
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_TYPES_STRUCT_STATVFS_H
10+
#define LLVM_LIBC_TYPES_STRUCT_STATVFS_H
11+
12+
#include <llvm-libc-types/fsblkcnt_t.h>
13+
#include <llvm-libc-types/fsfilcnt_t.h>
14+
15+
struct statvfs {
16+
unsigned long f_bsize; /* Filesystem block size */
17+
unsigned long f_frsize; /* Fragment size */
18+
fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */
19+
fsblkcnt_t f_bfree; /* Number of free blocks */
20+
fsblkcnt_t f_bavail; /* Number of free blocks for unprivileged users */
21+
fsfilcnt_t f_files; /* Number of inodes */
22+
fsfilcnt_t f_ffree; /* Number of free inodes */
23+
fsfilcnt_t f_favail; /* Number of free inodes for unprivileged users */
24+
unsigned long f_fsid; /* Filesystem ID */
25+
unsigned long f_flag; /* Mount flags */
26+
unsigned long f_namemax; /* Maximum filename length */
27+
};
28+
29+
#endif // LLVM_LIBC_TYPES_STRUCT_STATVFS_H

libc/include/sys/statvfs.h.def

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//===-- POSIX header statvfs.h --------------------------------------------===//
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_SYS_STATVFS_H
10+
#define LLVM_LIBC_SYS_STATVFS_H
11+
12+
#include <__llvm-libc-common.h>
13+
14+
%%public_api()
15+
16+
#endif // LLVM_LIBC_SYS_STATVFS_H

libc/spec/posix.td

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>;
8686

8787
def StructSockAddrUn : NamedType<"struct sockaddr_un">;
8888

89+
def StructStatvfs : NamedType<"struct statvfs">;
90+
def StructStatvfsPtr : PtrType<StructStatvfs>;
91+
def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>;
92+
8993
def POSIX : StandardSpec<"POSIX"> {
9094
PtrType CharPtr = PtrType<CharType>;
9195
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
@@ -888,6 +892,31 @@ def POSIX : StandardSpec<"POSIX"> {
888892
]
889893
>;
890894

895+
HeaderSpec SysStatvfs = HeaderSpec<
896+
"sys/statvfs.h",
897+
[], // Macros
898+
[StructStatvfs], // Types
899+
[], // Enumerations
900+
[
901+
FunctionSpec<
902+
"statvfs",
903+
RetValSpec<IntType>,
904+
[
905+
ArgSpec<ConstRestrictedCharPtr>,
906+
ArgSpec<RestrictedStructStatvfsPtr>
907+
]
908+
>,
909+
FunctionSpec<
910+
"fstatvfs",
911+
RetValSpec<IntType>,
912+
[
913+
ArgSpec<IntType>,
914+
ArgSpec<StructStatvfsPtr>
915+
]
916+
>,
917+
] // Functions
918+
>;
919+
891920
NamedType StructUtsName = NamedType<"struct utsname">;
892921
PtrType StructUtsNamePtr = PtrType<StructUtsName>;
893922
HeaderSpec SysUtsName = HeaderSpec<
@@ -1505,6 +1534,7 @@ def POSIX : StandardSpec<"POSIX"> {
15051534
SysSelect,
15061535
SysSocket,
15071536
SysStat,
1537+
SysStatvfs,
15081538
SysTypes,
15091539
SysUtsName,
15101540
SysWait,

libc/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ add_subdirectory(select)
77
add_subdirectory(socket)
88
add_subdirectory(sendfile)
99
add_subdirectory(stat)
10+
add_subdirectory(statvfs)
1011
add_subdirectory(utsname)
1112
add_subdirectory(wait)
1213
add_subdirectory(prctl)

libc/src/sys/statvfs/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
endif()
4+
5+
add_entrypoint_object(
6+
statvfs
7+
ALIAS
8+
DEPENDS
9+
.${LIBC_TARGET_OS}.statvfs
10+
)
11+
12+
add_entrypoint_object(
13+
fstatvfs
14+
ALIAS
15+
DEPENDS
16+
.${LIBC_TARGET_OS}.fstatvfs
17+
)

libc/src/sys/statvfs/fstatvfs.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for fstatvfs ----------------------*- 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_FSTATVFS_H
10+
#define LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H
11+
12+
#include "llvm-libc-types/struct_statvfs.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int fstatvfs(int fd, struct statvfs *buf);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
add_header_library(
2+
statfs_utils
3+
HDRS
4+
statfs_utils.h
5+
DEPENDS
6+
libc.src.errno.errno
7+
libc.src.__support.OSUtil.osutil
8+
libc.src.__support.common
9+
libc.src.__support.CPP.optional
10+
libc.include.sys_syscall
11+
)
12+
13+
add_entrypoint_object(
14+
statvfs
15+
SRCS
16+
statvfs.cpp
17+
HDRS
18+
../statvfs.h
19+
DEPENDS
20+
libc.src.__support.libc_assert
21+
libc.include.llvm-libc-types.struct_statvfs
22+
.statfs_utils
23+
)
24+
25+
add_entrypoint_object(
26+
fstatvfs
27+
SRCS
28+
fstatvfs.cpp
29+
HDRS
30+
../fstatvfs.h
31+
DEPENDS
32+
libc.src.__support.libc_assert
33+
libc.include.llvm-libc-types.struct_statvfs
34+
.statfs_utils
35+
)
36+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===-- Linux implementation of fstatvfs ----------------------------------===//
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+
#include "src/sys/statvfs/fstatvfs.h"
10+
#include "src/__support/common.h"
11+
#include "src/__support/libc_assert.h"
12+
#include "src/sys/statvfs/linux/statfs_utils.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
LLVM_LIBC_FUNCTION(int, fstatvfs, (int fd, struct statvfs *buf)) {
17+
using namespace statfs_utils;
18+
cpp::optional<LinuxStatFs> result = linux_fstatfs(fd);
19+
if (result) {
20+
LIBC_ASSERT(buf != nullptr);
21+
*buf = statfs_to_statvfs(*result);
22+
}
23+
return result ? 0 : -1;
24+
}
25+
26+
} // namespace LIBC_NAMESPACE
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
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+
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+
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.
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

0 commit comments

Comments
 (0)