compio_driver/sys/pal/unix/stat/mod.rs
1use super::*;
2
3/// File metadata returned by the stat operations.
4///
5/// It bundles the raw platform [`Stat`] together with the file creation (birth)
6/// time. On Linux the birth time is not part of `struct stat`; it comes from
7/// `statx` instead, so it has to be carried separately. On the BSDs and Apple
8/// platforms it is extracted from the `st_birthtime` field of [`Stat`].
9#[derive(Clone, Copy)]
10pub struct FileAttr {
11 /// The raw `stat` result.
12 pub stat: Stat,
13 /// Creation (birth) time as `(seconds, nanoseconds)` since the Unix epoch,
14 /// or [`None`] when the platform/filesystem does not report it.
15 pub created: Option<(i64, i64)>,
16}
17
18impl FileAttr {
19 /// Build from a plain [`Stat`], extracting the birth time from the
20 /// `st_birthtime` field when the platform stores it there.
21 pub fn from_stat(stat: Stat) -> Self {
22 Self {
23 created: stat_created(&stat),
24 stat,
25 }
26 }
27}
28
29#[cfg(st_birthtime)]
30fn stat_created(stat: &Stat) -> Option<(i64, i64)> {
31 Some((stat.st_birthtime as _, stat.st_birthtime_nsec as _))
32}
33
34#[cfg(not(st_birthtime))]
35fn stat_created(_stat: &Stat) -> Option<(i64, i64)> {
36 // On Linux `struct stat` has no birth time; it is obtained from `statx`.
37 None
38}
39
40cfg_select! {
41 linux_all => {
42 mod_use![linux];
43 }
44 _ => {
45 pub fn stat<Fd: AsFd>(dirfd: Fd, path: &CStr, follow_symlink: bool) -> io::Result<FileAttr> {
46 use rustix::fs::{fstat, statat};
47
48 let stat = if path.is_empty() {
49 fstat(dirfd)?
50 } else {
51 let flags = if follow_symlink {
52 AtFlags::empty()
53 } else {
54 AtFlags::SYMLINK_NOFOLLOW
55 };
56 statat(dirfd, path, flags)?
57 };
58 Ok(FileAttr::from_stat(stat))
59 }
60 }
61}