Skip to main content

c/
statvfs.rs

1// Copyright (c) 2026 Meng Zhuo
2// SPDX-License-Identifier: BSD-3-Clause
3
4#[repr(C)]
5struct kernel_statfs {
6    f_type: c_ulong,
7    f_bsize: c_ulong,
8    f_blocks: u64,
9    f_bfree: u64,
10    f_bavail: u64,
11    f_files: u64,
12    f_ffree: u64,
13    f_fsid: [c_int; 2],
14    f_namelen: c_ulong,
15    f_frsize: c_ulong,
16    f_flags: c_ulong,
17    f_spare: [c_ulong; 4],
18}
19
20#[repr(C)]
21pub struct statvfs {
22    pub f_bsize: c_ulong,
23    pub f_frsize: c_ulong,
24    pub f_blocks: u64,
25    pub f_bfree: u64,
26    pub f_bavail: u64,
27    pub f_files: u64,
28    pub f_ffree: u64,
29    pub f_favail: u64,
30    pub f_fsid: c_ulong,
31    pub f_flag: c_ulong,
32    pub f_namemax: c_ulong,
33    pub f_type: c_uint,
34    __reserved: [c_int; 5],
35}
36
37pub const ST_RDONLY: c_ulong = 1;
38pub const ST_NOSUID: c_ulong = 2;
39pub const ST_NODEV: c_ulong = 4;
40pub const ST_NOEXEC: c_ulong = 8;
41pub const ST_SYNCHRONOUS: c_ulong = 16;
42pub const ST_MANDLOCK: c_ulong = 64;
43pub const ST_WRITE: c_ulong = 128;
44pub const ST_APPEND: c_ulong = 256;
45pub const ST_IMMUTABLE: c_ulong = 512;
46pub const ST_NOATIME: c_ulong = 1024;
47pub const ST_NODIRATIME: c_ulong = 2048;
48pub const ST_RELATIME: c_ulong = 4096;
49
50// ponytail: SYS_statfs(137) vs SYS_statfs64(305) identical on x86_64
51#[inline]
52unsafe fn sys_statfs(path: *const c_char, buf: *mut kernel_statfs) -> i64 {
53    <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64)
54}
55
56#[inline]
57unsafe fn sys_fstatfs(fd: c_int, buf: *mut kernel_statfs) -> i64 {
58    <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64)
59}
60
61unsafe fn fixup(out: *mut statvfs, kbuf: *const kernel_statfs) {
62    core::ptr::write_bytes(out, 0, 1);
63    (*out).f_bsize = (*kbuf).f_bsize;
64    (*out).f_frsize = if (*kbuf).f_frsize != 0 { (*kbuf).f_frsize } else { (*kbuf).f_bsize };
65    (*out).f_blocks = (*kbuf).f_blocks;
66    (*out).f_bfree = (*kbuf).f_bfree;
67    (*out).f_bavail = (*kbuf).f_bavail;
68    (*out).f_files = (*kbuf).f_files;
69    (*out).f_ffree = (*kbuf).f_ffree;
70    (*out).f_favail = (*kbuf).f_ffree;
71    (*out).f_fsid = (*kbuf).f_fsid[0] as c_ulong;
72    (*out).f_flag = (*kbuf).f_flags;
73    (*out).f_namemax = (*kbuf).f_namelen;
74    (*out).f_type = (*kbuf).f_type as c_uint;
75}
76
77#[no_mangle]
78pub unsafe extern "C" fn statvfs(path: *const c_char, buf: *mut statvfs) -> c_int {
79    let mut kbuf: kernel_statfs = core::mem::zeroed();
80    let r = sys_statfs(path, &mut kbuf);
81    if r < 0 {
82        ERRNO!() = (-r) as c_int;
83        return -1;
84    }
85    fixup(buf, &kbuf);
86    0
87}
88
89#[no_mangle]
90pub unsafe extern "C" fn fstatvfs(fd: c_int, buf: *mut statvfs) -> c_int {
91    let mut kbuf: kernel_statfs = core::mem::zeroed();
92    let r = sys_fstatfs(fd, &mut kbuf);
93    if r < 0 {
94        ERRNO!() = (-r) as c_int;
95        return -1;
96    }
97    fixup(buf, &kbuf);
98    0
99}