Skip to content

[libc] add statvfs/fstatvfs #86169

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions libc/config/linux/api.td
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,7 @@ def SetJmpAPI : PublicAPI<"setjmp.h"> {
def SearchAPI : PublicAPI<"search.h"> {
let Types = ["ACTION", "ENTRY", "struct hsearch_data"];
}

def SysStatvfsAPI : PublicAPI<"sys/statvfs.h"> {
let Types = ["fsblkcnt_t", "fsfilcnt_t", "struct statvfs"];
}
4 changes: 4 additions & 0 deletions libc/config/linux/x86_64/entrypoints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ set(TARGET_LIBC_ENTRYPOINTS
libc.src.sys.stat.mkdirat
libc.src.sys.stat.stat

# sys/statvfs.h
libc.src.sys.statvfs.statvfs
libc.src.sys.statvfs.fstatvfs

# sys/utsname.h entrypoints
libc.src.sys.utsname.uname

Expand Down
9 changes: 9 additions & 0 deletions libc/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,15 @@ add_gen_header(
.llvm-libc-types.struct_sockaddr_un
)

add_gen_header(
sys_statvfs
DEF_FILE sys/statvfs.h.def
GEN_HDR sys/statvfs.h
DEPENDS
.llvm_libc_common_h
.llvm-libc-types.struct_statvfs
)

add_gen_header(
sys_syscall
DEF_FILE sys/syscall.h.def
Expand Down
10 changes: 10 additions & 0 deletions libc/include/llvm-libc-types/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,13 @@ add_header(
DEPENDS
libc.include.llvm-libc-macros.float_macros
)
add_header(fsblkcnt_t HDR fsblkcnt_t.h)
add_header(fsfilcnt_t HDR fsfilcnt_t.h)
add_header(
struct_statvfs
HDR
struct_statvfs.h
DEPENDS
.fsblkcnt_t
.fsfilcnt_t
)
14 changes: 14 additions & 0 deletions libc/include/llvm-libc-types/fsblkcnt_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//===-- Definition of fsblkcnt_t type -------------------------------------===//
//
// 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_TYPES_FSBLKCNT_T_H
#define LLVM_LIBC_TYPES_FSBLKCNT_T_H

typedef __SIZE_TYPE__ fsblkcnt_t;

#endif // LLVM_LIBC_TYPES_FSBLKCNT_T_H
14 changes: 14 additions & 0 deletions libc/include/llvm-libc-types/fsfilcnt_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//===-- Definition of fsfilcnt_t type -------------------------------------===//
//
// 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_TYPES_FSFILCNT_T_H
#define LLVM_LIBC_TYPES_FSFILCNT_T_H

typedef __SIZE_TYPE__ fsfilcnt_t;

#endif // LLVM_LIBC_TYPES_FSFILCNT_T_H
29 changes: 29 additions & 0 deletions libc/include/llvm-libc-types/struct_statvfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===-- Definition of type struct 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
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIBC_TYPES_STRUCT_STATVFS_H
#define LLVM_LIBC_TYPES_STRUCT_STATVFS_H

#include <llvm-libc-types/fsblkcnt_t.h>
#include <llvm-libc-types/fsfilcnt_t.h>

struct statvfs {
unsigned long f_bsize; /* Filesystem block size */
unsigned long f_frsize; /* Fragment size */
fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */
fsblkcnt_t f_bfree; /* Number of free blocks */
fsblkcnt_t f_bavail; /* Number of free blocks for unprivileged users */
fsfilcnt_t f_files; /* Number of inodes */
fsfilcnt_t f_ffree; /* Number of free inodes */
fsfilcnt_t f_favail; /* Number of free inodes for unprivileged users */
unsigned long f_fsid; /* Filesystem ID */
unsigned long f_flag; /* Mount flags */
unsigned long f_namemax; /* Maximum filename length */
};

#endif // LLVM_LIBC_TYPES_STRUCT_STATVFS_H
16 changes: 16 additions & 0 deletions libc/include/sys/statvfs.h.def
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===-- POSIX header statvfs.h --------------------------------------------===//
//
// 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_SYS_STATVFS_H
#define LLVM_LIBC_SYS_STATVFS_H

#include <__llvm-libc-common.h>

%%public_api()

#endif // LLVM_LIBC_SYS_STATVFS_H
30 changes: 30 additions & 0 deletions libc/spec/posix.td
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ def ConstStructSockAddrPtr : ConstType<StructSockAddrPtr>;

def StructSockAddrUn : NamedType<"struct sockaddr_un">;

def StructStatvfs : NamedType<"struct statvfs">;
def StructStatvfsPtr : PtrType<StructStatvfs>;
def RestrictedStructStatvfsPtr : RestrictedPtrType<StructStatvfs>;

def POSIX : StandardSpec<"POSIX"> {
PtrType CharPtr = PtrType<CharType>;
RestrictedPtrType RestrictedCharPtr = RestrictedPtrType<CharType>;
Expand Down Expand Up @@ -888,6 +892,31 @@ def POSIX : StandardSpec<"POSIX"> {
]
>;

HeaderSpec SysStatvfs = HeaderSpec<
"sys/statvfs.h",
[], // Macros
[StructStatvfs], // Types
[], // Enumerations
[
FunctionSpec<
"statvfs",
RetValSpec<IntType>,
[
ArgSpec<ConstRestrictedCharPtr>,
ArgSpec<RestrictedStructStatvfsPtr>
]
>,
FunctionSpec<
"fstatvfs",
RetValSpec<IntType>,
[
ArgSpec<IntType>,
ArgSpec<StructStatvfsPtr>
]
>,
] // Functions
>;

NamedType StructUtsName = NamedType<"struct utsname">;
PtrType StructUtsNamePtr = PtrType<StructUtsName>;
HeaderSpec SysUtsName = HeaderSpec<
Expand Down Expand Up @@ -1505,6 +1534,7 @@ def POSIX : StandardSpec<"POSIX"> {
SysSelect,
SysSocket,
SysStat,
SysStatvfs,
SysTypes,
SysUtsName,
SysWait,
Expand Down
1 change: 1 addition & 0 deletions libc/src/sys/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ add_subdirectory(select)
add_subdirectory(socket)
add_subdirectory(sendfile)
add_subdirectory(stat)
add_subdirectory(statvfs)
add_subdirectory(utsname)
add_subdirectory(wait)
add_subdirectory(prctl)
17 changes: 17 additions & 0 deletions libc/src/sys/statvfs/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
endif()

add_entrypoint_object(
statvfs
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.statvfs
)

add_entrypoint_object(
fstatvfs
ALIAS
DEPENDS
.${LIBC_TARGET_OS}.fstatvfs
)
20 changes: 20 additions & 0 deletions libc/src/sys/statvfs/fstatvfs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//===-- Implementation header for fstatvfs ----------------------*- 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_FSTATVFS_H
#define LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H

#include "llvm-libc-types/struct_statvfs.h"

namespace LIBC_NAMESPACE {

int fstatvfs(int fd, struct statvfs *buf);

} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_SYS_STATVFS_FSTATVFS_H
36 changes: 36 additions & 0 deletions libc/src/sys/statvfs/linux/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
add_header_library(
statfs_utils
HDRS
statfs_utils.h
DEPENDS
libc.src.errno.errno
libc.src.__support.OSUtil.osutil
libc.src.__support.common
libc.src.__support.CPP.optional
libc.include.sys_syscall
)

add_entrypoint_object(
statvfs
SRCS
statvfs.cpp
HDRS
../statvfs.h
DEPENDS
libc.src.__support.libc_assert
libc.include.llvm-libc-types.struct_statvfs
.statfs_utils
)

add_entrypoint_object(
fstatvfs
SRCS
fstatvfs.cpp
HDRS
../fstatvfs.h
DEPENDS
libc.src.__support.libc_assert
libc.include.llvm-libc-types.struct_statvfs
.statfs_utils
)

26 changes: 26 additions & 0 deletions libc/src/sys/statvfs/linux/fstatvfs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Linux implementation of fstatvfs ----------------------------------===//
//
// 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/fstatvfs.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, fstatvfs, (int fd, struct statvfs *buf)) {
using namespace statfs_utils;
cpp::optional<LinuxStatFs> result = linux_fstatfs(fd);
if (result) {
LIBC_ASSERT(buf != nullptr);
*buf = statfs_to_statvfs(*result);
}
return result ? 0 : -1;
}

} // namespace LIBC_NAMESPACE
95 changes: 95 additions & 0 deletions libc/src/sys/statvfs/linux/statfs_utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
//===-- Convert Statfs to 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_LINUX_STATFS_TO_STATVFS_H
#define LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H

#include "llvm-libc-types/struct_statvfs.h"
#include "src/__support/CPP/optional.h"
#include "src/__support/OSUtil/syscall.h"
#include "src/__support/macros/attributes.h"
#include "src/errno/libc_errno.h"
#include <asm/statfs.h>
#include <sys/syscall.h>
namespace LIBC_NAMESPACE {

namespace statfs_utils {
#ifdef SYS_statfs64
using LinuxStatFs = statfs64;
#else
using LinuxStatFs = statfs;
#endif

// Linux kernel set an additional flag to f_flags. Libc should mask it out.
LIBC_INLINE_VAR constexpr decltype(LinuxStatFs::f_flags) ST_VALID = 0x0020;

LIBC_INLINE cpp::optional<LinuxStatFs> linux_statfs(const char *path) {
// The kernel syscall routine checks the validity of the path before filling
// the statfs structure. So, it is possible that the result is not initialized
// after the syscall. Since the struct is trvial, the compiler will generate
// pattern filling for the struct.
LinuxStatFs result;
// On 32-bit platforms, original statfs cannot handle large file systems.
// In such cases, SYS_statfs64 is defined and should be used.
#ifdef SYS_statfs64
int ret = syscall_impl<int>(SYS_statfs64, path, sizeof(result), &result);
#else
int ret = syscall_impl<int>(SYS_statfs, path, &result);
#endif
if (ret < 0) {
libc_errno = -ret;
return cpp::nullopt;
}
result.f_flags &= ~ST_VALID;
return result;
}

LIBC_INLINE cpp::optional<LinuxStatFs> linux_fstatfs(int fd) {
// The kernel syscall routine checks the validity of the path before filling
// the statfs structure. So, it is possible that the result is not initialized
// after the syscall. Since the struct is trvial, the compiler will generate
// pattern filling for the struct.
LinuxStatFs result;
// On 32-bit platforms, original fstatfs cannot handle large file systems.
// In such cases, SYS_fstatfs64 is defined and should be used.
#ifdef SYS_fstatfs64
int ret = syscall_impl<int>(SYS_fstatfs64, fd, sizeof(result), &result);
#else
int ret = syscall_impl<int>(SYS_fstatfs, fd, &result);
#endif
if (ret < 0) {
libc_errno = -ret;
return cpp::nullopt;
}
result.f_flags &= ~ST_VALID;
return result;
}

// must use 'struct' tag to refer to type 'statvfs' in this scope. There will be
// a function in the same namespace with the same name. For consistency, we use
// struct prefix for all statvfs/statfs related types.
LIBC_INLINE struct statvfs statfs_to_statvfs(const LinuxStatFs &in) {
struct statvfs out;
out.f_bsize = in.f_bsize;
out.f_frsize = in.f_frsize;
out.f_blocks = in.f_blocks;
out.f_bfree = in.f_bfree;
out.f_bavail = in.f_bavail;
out.f_files = in.f_files;
out.f_ffree = in.f_ffree;
out.f_favail = in.f_ffree;
out.f_fsid = in.f_fsid.val[0] |
static_cast<decltype(out.f_fsid)>(in.f_fsid.val[1]) << 32;
out.f_flag = in.f_flags;
out.f_namemax = in.f_namelen;
return out;
}
} // namespace statfs_utils
} // namespace LIBC_NAMESPACE

#endif // LLVM_LIBC_SRC_SYS_STATVFS_LINUX_STATFS_TO_STATVFS_H
Loading