Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 05dc5d9

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

File tree

22 files changed

+495
-0
lines changed

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
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//===-- Linux implementation of 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+
#include "src/sys/statvfs/statvfs.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, statvfs,
17+
(const char *__restrict path,
18+
struct statvfs *__restrict buf)) {
19+
using namespace statfs_utils;
20+
cpp::optional<LinuxStatFs> result = linux_statfs(path);
21+
if (result) {
22+
LIBC_ASSERT(buf != nullptr);
23+
*buf = statfs_to_statvfs(*result);
24+
}
25+
return result ? 0 : -1;
26+
}
27+
28+
} // namespace LIBC_NAMESPACE

‎libc/src/sys/statvfs/statvfs.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//===-- Implementation header for 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_STATVFS_H
10+
#define LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H
11+
12+
#include "llvm-libc-types/struct_statvfs.h"
13+
14+
namespace LIBC_NAMESPACE {
15+
16+
int statvfs(const char *__restrict path, struct statvfs *__restrict buf);
17+
18+
} // namespace LIBC_NAMESPACE
19+
20+
#endif // LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H

‎libc/test/src/sys/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_subdirectory(select)
55
add_subdirectory(sendfile)
66
add_subdirectory(socket)
77
add_subdirectory(stat)
8+
add_subdirectory(statvfs)
89
add_subdirectory(utsname)
910
add_subdirectory(wait)
1011
add_subdirectory(prctl)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${LIBC_TARGET_OS})
3+
endif()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
add_custom_target(libc_sys_statvfs_unittests)
2+
3+
add_libc_unittest(
4+
statvfs_test
5+
SUITE
6+
libc_sys_statvfs_unittests
7+
SRCS
8+
statvfs_test.cpp
9+
DEPENDS
10+
libc.src.errno.errno
11+
libc.src.sys.statvfs.linux.statfs_utils
12+
libc.src.sys.statvfs.statvfs
13+
libc.test.UnitTest.ErrnoSetterMatcher
14+
)
15+
16+
add_libc_unittest(
17+
fstatvfs_test
18+
SUITE
19+
libc_sys_statvfs_unittests
20+
SRCS
21+
fstatvfs_test.cpp
22+
DEPENDS
23+
libc.src.errno.errno
24+
libc.src.sys.statvfs.linux.statfs_utils
25+
libc.src.sys.statvfs.fstatvfs
26+
libc.src.fcntl.open
27+
libc.src.unistd.close
28+
libc.test.UnitTest.ErrnoSetterMatcher
29+
)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "llvm-libc-macros/linux/fcntl-macros.h"
2+
#include "src/fcntl/open.h"
3+
#include "src/sys/statvfs/fstatvfs.h"
4+
#include "src/sys/statvfs/linux/statfs_utils.h"
5+
#include "src/unistd/close.h"
6+
#include "test/UnitTest/ErrnoSetterMatcher.h"
7+
#include "test/UnitTest/LibcTest.h"
8+
#include <linux/magic.h>
9+
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
10+
11+
namespace LIBC_NAMESPACE {
12+
static int fstatfs(int fd, struct statfs *buf) {
13+
using namespace statfs_utils;
14+
if (cpp::optional<LinuxStatFs> result = linux_fstatfs(fd)) {
15+
*buf = *result;
16+
return 0;
17+
}
18+
return -1;
19+
}
20+
} // namespace LIBC_NAMESPACE
21+
22+
struct PathFD {
23+
int fd;
24+
explicit PathFD(const char *path)
25+
: fd(LIBC_NAMESPACE::open(path, O_CLOEXEC | O_PATH)) {}
26+
~PathFD() { LIBC_NAMESPACE::close(fd); }
27+
operator int() const { return fd; }
28+
};
29+
30+
TEST(LlvmLibcSysStatvfsTest, FstatfsBasic) {
31+
struct statfs buf;
32+
ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/"), &buf), Succeeds());
33+
ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/proc"), &buf), Succeeds());
34+
ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC));
35+
ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/sys"), &buf), Succeeds());
36+
ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC));
37+
}
38+
39+
TEST(LlvmLibcSysStatvfsTest, FstatvfsInvalidFD) {
40+
struct statvfs buf;
41+
ASSERT_THAT(LIBC_NAMESPACE::fstatvfs(-1, &buf), Fails(EBADF));
42+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#include "src/sys/statvfs/linux/statfs_utils.h"
2+
#include "src/sys/statvfs/statvfs.h"
3+
#include "test/UnitTest/ErrnoSetterMatcher.h"
4+
#include "test/UnitTest/LibcTest.h"
5+
#include <linux/magic.h>
6+
using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher;
7+
8+
namespace LIBC_NAMESPACE {
9+
static int statfs(const char *path, struct statfs *buf) {
10+
using namespace statfs_utils;
11+
if (cpp::optional<LinuxStatFs> result = linux_statfs(path)) {
12+
*buf = *result;
13+
return 0;
14+
}
15+
return -1;
16+
}
17+
} // namespace LIBC_NAMESPACE
18+
19+
TEST(LlvmLibcSysStatfsTest, StatfsBasic) {
20+
struct statfs buf;
21+
ASSERT_THAT(LIBC_NAMESPACE::statfs("/", &buf), Succeeds());
22+
ASSERT_THAT(LIBC_NAMESPACE::statfs("/proc", &buf), Succeeds());
23+
ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC));
24+
ASSERT_THAT(LIBC_NAMESPACE::statfs("/sys", &buf), Succeeds());
25+
ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC));
26+
}
27+
28+
TEST(LlvmLibcSysStatfsTest, StatvfsInvalidPath) {
29+
struct statvfs buf;
30+
ASSERT_THAT(LIBC_NAMESPACE::statvfs("", &buf), Fails(ENOENT));
31+
ASSERT_THAT(LIBC_NAMESPACE::statvfs("/nonexistent", &buf), Fails(ENOENT));
32+
ASSERT_THAT(LIBC_NAMESPACE::statvfs("/dev/null/whatever", &buf),
33+
Fails(ENOTDIR));
34+
ASSERT_THAT(LIBC_NAMESPACE::statvfs(nullptr, &buf), Fails(EFAULT));
35+
}
36+
37+
TEST(LlvmLibcSysStatfsTest, StatvfsNameTooLong) {
38+
struct statvfs buf;
39+
ASSERT_THAT(LIBC_NAMESPACE::statvfs("/", &buf), Succeeds());
40+
char *name = static_cast<char *>(__builtin_alloca(buf.f_namemax + 3));
41+
name[0] = '/';
42+
name[buf.f_namemax + 2] = '\0';
43+
for (unsigned i = 1; i < buf.f_namemax + 2; ++i) {
44+
name[i] = 'a';
45+
}
46+
ASSERT_THAT(LIBC_NAMESPACE::statvfs(name, &buf), Fails(ENAMETOOLONG));
47+
}

0 commit comments

Comments
 (0)
Please sign in to comment.