1#![no_std]
8#![cfg(target_os = "linux")]
9#![deny(warnings)]
10
11use libc::syscall;
12use libc::{c_char, c_int, c_uint};
13
14#[repr(C)]
23#[derive(Clone, Copy, Debug)]
24pub struct statx_timestamp {
25 pub tv_sec: i64,
26 pub tv_nsec: u32,
27 __reserved: i32,
28}
29
30#[repr(C)]
66#[derive(Clone, Copy, Debug)]
67pub struct statx {
68 pub stx_mask: u32,
71 pub stx_blksize: u32,
73 pub stx_attributes: u64,
75
76 pub stx_nlink: u32,
79 pub stx_uid: u32,
81 pub stx_gid: u32,
83 pub stx_mode: u16,
85 __spare0: [u16; 1],
86
87 pub stx_ino: u64,
90 pub stx_size: u64,
92 pub stx_blocks: u64,
94 pub stx_attributes_mask: u64,
96
97 pub stx_atime: statx_timestamp, pub stx_btime: statx_timestamp, pub stx_ctime: statx_timestamp, pub stx_mtime: statx_timestamp, pub stx_rdev_major: u32,
106 pub stx_rdev_minor: u32,
107 pub stx_dev_major: u32,
109 pub stx_dev_minor: u32,
110
111 __spare2: [u64; 14],
114 }
116
117mod syscall;
118pub use syscall::SYS_statx;
119
120pub const AT_FDCWD: c_int = -100;
122pub const AT_SYMLINK_NOFOLLOW: c_int = 0x100;
123pub const AT_REMOVEDIR: c_int = 0x200;
124pub const AT_SYMLINK_FOLLOW: c_int = 0x400;
125pub const AT_NO_AUTOMOUNT: c_int = 0x800;
126pub const AT_EMPTY_PATH: c_int = 0x1000;
127
128pub const AT_STATX_SYNC_AS_STAT: c_int = 0x0000;
129pub const AT_STATX_FORCE_SYNC: c_int = 0x2000;
130pub const AT_STATX_SYNC_TYPE: c_int = 0x6000;
131pub const AT_STATX_DONT_SYNC: c_int = 0x4000;
132
133pub const STATX_TYPE: c_uint = 0x0000_0001;
134pub const STATX_MODE: c_uint = 0x0000_0002;
135pub const STATX_NLINK: c_uint = 0x0000_0004;
136pub const STATX_UID: c_uint = 0x0000_0008;
137pub const STATX_GID: c_uint = 0x0000_0010;
138pub const STATX_ATIME: c_uint = 0x0000_0020;
139pub const STATX_MTIME: c_uint = 0x0000_0040;
140pub const STATX_CTIME: c_uint = 0x0000_0080;
141pub const STATX_INO: c_uint = 0x0000_0100;
142pub const STATX_SIZE: c_uint = 0x0000_0200;
143pub const STATX_BLOCKS: c_uint = 0x0000_0400;
144pub const STATX_BASIC_STATS: c_uint = 0x0000_07ff;
145pub const STATX_BTIME: c_uint = 0x0000_0800;
146pub const STATX_ALL: c_uint = 0x0000_0fff;
147pub const STATX__RESERVED: c_uint = 0x8000_0000;
148
149pub const STATX_ATTR_COMPRESSED: c_int = 0x0000_0004;
152pub const STATX_ATTR_IMMUTABLE: c_int = 0x0000_0010;
153pub const STATX_ATTR_APPEND: c_int = 0x0000_0020;
154pub const STATX_ATTR_NODUMP: c_int = 0x0000_0040;
155pub const STATX_ATTR_ENCRYPTED: c_int = 0x0000_0800;
156
157pub const STATX_ATTR_AUTOMOUNT: c_int = 0x0000_1000;
158
159pub unsafe fn statx(
164 dirfd: c_int,
165 pathname: *const c_char,
166 flags: c_int,
167 mask: c_uint,
168 statxbuf: *mut statx,
169) -> c_int {
170 syscall(SYS_statx, dirfd, pathname, flags, mask, statxbuf) as c_int
171}
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn check_struct_layout() {
179 use core::mem::size_of;
180 use memoffset::offset_of;
181
182 assert_eq!(size_of::<statx>(), 0x100);
183 assert_eq!(size_of::<statx_timestamp>(), 16);
184
185 assert_eq!(offset_of!(statx, stx_mask), 0);
186 assert_eq!(offset_of!(statx, stx_nlink), 0x10);
187 assert_eq!(offset_of!(statx, stx_ino), 0x20);
188 assert_eq!(offset_of!(statx, stx_atime), 0x40);
189 assert_eq!(offset_of!(statx, stx_rdev_major), 0x80);
190 assert_eq!(offset_of!(statx, __spare2), 0x90);
191 }
192}