statx_sys/
lib.rs

1//! # Bindings to `statx` syscall.
2//!
3//! Note that `statx()` was added to Linux in kernel 4.11 .
4//!
5//! # See also
6//! <http://man7.org/linux/man-pages/man2/statx.2.html>
7#![no_std]
8#![cfg(target_os = "linux")]
9#![deny(warnings)]
10
11use libc::syscall;
12use libc::{c_char, c_int, c_uint};
13
14/// Timestamp structure for the timestamps in struct statx.
15///
16/// tv_sec holds the number of seconds before (negative) or after (positive)
17/// 00:00:00 1st January 1970 UTC.
18///
19/// tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
20///
21/// __reserved is held in case we need a yet finer resolution.
22#[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/// Structures for the extended file attribute retrieval system call
31/// (statx()).
32///
33/// The caller passes a mask of what they're specifically interested in as a
34/// parameter to statx().  What statx() actually got will be indicated in
35/// st_mask upon return.
36///
37/// For each bit in the mask argument:
38///
39/// - if the datum is not supported:
40///
41///   - the bit will be cleared, and
42///
43///   - the datum will be set to an appropriate fabricated value if one is
44///     available (eg. CIFS can take a default uid and gid), otherwise
45///
46///   - the field will be cleared;
47///
48/// - otherwise, if explicitly requested:
49///
50///   - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
51///     set or if the datum is considered out of date, and
52///
53///   - the field will be filled in and the bit will be set;
54///
55/// - otherwise, if not requested, but available in approximate form without any
56///   effort, it will be filled in anyway, and the bit will be set upon return
57///   (it might not be up to date, however, and no attempt will be made to
58///   synchronise the internal state first);
59///
60/// - otherwise the field and the bit will be cleared before returning.
61///
62/// Items in STATX_BASIC_STATS may be marked unavailable on return, but they
63/// will have values installed for compatibility purposes so that stat() and
64/// co. can be emulated in userspace.
65#[repr(C)]
66#[derive(Clone, Copy, Debug)]
67pub struct statx {
68    // 0x00
69    /// What results were written \[uncond]
70    pub stx_mask: u32,
71    /// Preferred general I/O size \[uncond]
72    pub stx_blksize: u32,
73    /// Flags conveying information about the file \[uncond]
74    pub stx_attributes: u64,
75
76    // 0x10
77    /// Number of hard links
78    pub stx_nlink: u32,
79    /// User ID of owner
80    pub stx_uid: u32,
81    /// Group ID of owner
82    pub stx_gid: u32,
83    /// File mode
84    pub stx_mode: u16,
85    __spare0: [u16; 1],
86
87    // 0x20
88    /// Inode number
89    pub stx_ino: u64,
90    /// File size
91    pub stx_size: u64,
92    /// Number of 512-byte blocks allocated
93    pub stx_blocks: u64,
94    /// Mask to show what's supported in stx_attributes
95    pub stx_attributes_mask: u64,
96
97    // 0x40
98    pub stx_atime: statx_timestamp, /* Last access time */
99    pub stx_btime: statx_timestamp, /* File creation time */
100    pub stx_ctime: statx_timestamp, /* Last attribute change time */
101    pub stx_mtime: statx_timestamp, /* Last data modification time */
102
103    /* 0x80 */
104    /// Device ID of special file \[if bdev/cdev]
105    pub stx_rdev_major: u32,
106    pub stx_rdev_minor: u32,
107    /// ID of device containing file \[uncond]
108    pub stx_dev_major: u32,
109    pub stx_dev_minor: u32,
110
111    // 0x90
112    /// Spare space for future expansion
113    __spare2: [u64; 14],
114    // 0x100
115}
116
117mod syscall;
118pub use syscall::SYS_statx;
119
120// Flags
121pub 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
149// File attributes.
150
151pub 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
159/// statx - get file status (extended)
160///
161/// See also:
162/// <http://man7.org/linux/man-pages/man2/statx.2.html>
163pub 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}