| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| //===-- Linux implementation of statvfs -----------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/sys/statvfs/statvfs.h" | ||
| #include "src/__support/common.h" | ||
| #include "src/__support/libc_assert.h" | ||
| #include "src/sys/statvfs/linux/statfs_utils.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, statvfs, | ||
| (const char *__restrict path, | ||
| struct statvfs *__restrict buf)) { | ||
| using namespace statfs_utils; | ||
| cpp::optional<LinuxStatFs> result = linux_statfs(path); | ||
| if (result) { | ||
| LIBC_ASSERT(buf != nullptr); | ||
| *buf = statfs_to_statvfs(*result); | ||
| } | ||
| return result ? 0 : -1; | ||
| } | ||
|
|
||
| } // namespace LIBC_NAMESPACE |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| //===-- Implementation header for statvfs -----------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H | ||
| #define LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H | ||
|
|
||
| #include "llvm-libc-types/struct_statvfs.h" | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
|
|
||
| int statvfs(const char *__restrict path, struct statvfs *__restrict buf); | ||
|
|
||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| #endif // LLVM_LIBC_SRC_SYS_STATVFS_STATVFS_H |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS}) | ||
| add_subdirectory(${LIBC_TARGET_OS}) | ||
| endif() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| add_custom_target(libc_sys_statvfs_unittests) | ||
|
|
||
| add_libc_unittest( | ||
| statvfs_test | ||
| SUITE | ||
| libc_sys_statvfs_unittests | ||
| SRCS | ||
| statvfs_test.cpp | ||
| DEPENDS | ||
| libc.src.errno.errno | ||
| libc.src.sys.statvfs.linux.statfs_utils | ||
| libc.src.sys.statvfs.statvfs | ||
| libc.test.UnitTest.ErrnoSetterMatcher | ||
| ) | ||
|
|
||
| add_libc_unittest( | ||
| fstatvfs_test | ||
| SUITE | ||
| libc_sys_statvfs_unittests | ||
| SRCS | ||
| fstatvfs_test.cpp | ||
| DEPENDS | ||
| libc.src.errno.errno | ||
| libc.src.sys.statvfs.linux.statfs_utils | ||
| libc.src.sys.statvfs.fstatvfs | ||
| libc.src.fcntl.open | ||
| libc.src.unistd.close | ||
| libc.test.UnitTest.ErrnoSetterMatcher | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| #include "llvm-libc-macros/linux/fcntl-macros.h" | ||
| #include "src/fcntl/open.h" | ||
| #include "src/sys/statvfs/fstatvfs.h" | ||
| #include "src/sys/statvfs/linux/statfs_utils.h" | ||
| #include "src/unistd/close.h" | ||
| #include "test/UnitTest/ErrnoSetterMatcher.h" | ||
| #include "test/UnitTest/LibcTest.h" | ||
| #include <linux/magic.h> | ||
| using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
| static int fstatfs(int fd, struct statfs *buf) { | ||
| using namespace statfs_utils; | ||
| if (cpp::optional<LinuxStatFs> result = linux_fstatfs(fd)) { | ||
| *buf = *result; | ||
| return 0; | ||
| } | ||
| return -1; | ||
| } | ||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| struct PathFD { | ||
| int fd; | ||
| explicit PathFD(const char *path) | ||
| : fd(LIBC_NAMESPACE::open(path, O_CLOEXEC | O_PATH)) {} | ||
| ~PathFD() { LIBC_NAMESPACE::close(fd); } | ||
| operator int() const { return fd; } | ||
| }; | ||
|
|
||
| TEST(LlvmLibcSysStatvfsTest, FstatfsBasic) { | ||
| struct statfs buf; | ||
| ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/"), &buf), Succeeds()); | ||
| ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/proc"), &buf), Succeeds()); | ||
| ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC)); | ||
| ASSERT_THAT(LIBC_NAMESPACE::fstatfs(PathFD("/sys"), &buf), Succeeds()); | ||
| ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC)); | ||
| } | ||
|
|
||
| TEST(LlvmLibcSysStatvfsTest, FstatvfsInvalidFD) { | ||
| struct statvfs buf; | ||
| ASSERT_THAT(LIBC_NAMESPACE::fstatvfs(-1, &buf), Fails(EBADF)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| #include "src/sys/statvfs/linux/statfs_utils.h" | ||
| #include "src/sys/statvfs/statvfs.h" | ||
| #include "test/UnitTest/ErrnoSetterMatcher.h" | ||
| #include "test/UnitTest/LibcTest.h" | ||
| #include <linux/magic.h> | ||
| using namespace LIBC_NAMESPACE::testing::ErrnoSetterMatcher; | ||
|
|
||
| namespace LIBC_NAMESPACE { | ||
| static int statfs(const char *path, struct statfs *buf) { | ||
| using namespace statfs_utils; | ||
| if (cpp::optional<LinuxStatFs> result = linux_statfs(path)) { | ||
| *buf = *result; | ||
| return 0; | ||
| } | ||
| return -1; | ||
| } | ||
| } // namespace LIBC_NAMESPACE | ||
|
|
||
| TEST(LlvmLibcSysStatfsTest, StatfsBasic) { | ||
| struct statfs buf; | ||
| ASSERT_THAT(LIBC_NAMESPACE::statfs("/", &buf), Succeeds()); | ||
| ASSERT_THAT(LIBC_NAMESPACE::statfs("/proc", &buf), Succeeds()); | ||
| ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(PROC_SUPER_MAGIC)); | ||
| ASSERT_THAT(LIBC_NAMESPACE::statfs("/sys", &buf), Succeeds()); | ||
| ASSERT_EQ(buf.f_type, static_cast<decltype(buf.f_type)>(SYSFS_MAGIC)); | ||
| } | ||
|
|
||
| TEST(LlvmLibcSysStatfsTest, StatvfsInvalidPath) { | ||
| struct statvfs buf; | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs("", &buf), Fails(ENOENT)); | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs("/nonexistent", &buf), Fails(ENOENT)); | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs("/dev/null/whatever", &buf), | ||
| Fails(ENOTDIR)); | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs(nullptr, &buf), Fails(EFAULT)); | ||
| } | ||
|
|
||
| TEST(LlvmLibcSysStatfsTest, StatvfsNameTooLong) { | ||
| struct statvfs buf; | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs("/", &buf), Succeeds()); | ||
| char *name = static_cast<char *>(__builtin_alloca(buf.f_namemax + 3)); | ||
| name[0] = '/'; | ||
| name[buf.f_namemax + 2] = '\0'; | ||
| for (unsigned i = 1; i < buf.f_namemax + 2; ++i) { | ||
| name[i] = 'a'; | ||
| } | ||
| ASSERT_THAT(LIBC_NAMESPACE::statvfs(name, &buf), Fails(ENAMETOOLONG)); | ||
| } |