Skip to main content

c/
statvfs.rs

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