1 use crate::FileTime;
2 use libc::{time_t, timespec};
3 use std::fs;
4 use std::os::unix::prelude::*;
5 
6 cfg_if::cfg_if! {
7     if #[cfg(target_os = "linux")] {
8         mod utimes;
9         mod linux;
10         pub use self::linux::*;
11     } else if #[cfg(target_os = "android")] {
12         mod android;
13         pub use self::android::*;
14     } else if #[cfg(target_os = "macos")] {
15         mod utimes;
16         mod macos;
17         pub use self::macos::*;
18     } else if #[cfg(any(target_os = "solaris",
19                         target_os = "illumos",
20                         target_os = "emscripten",
21                         target_os = "freebsd",
22                         target_os = "netbsd",
23                         target_os = "openbsd",
24                         target_os = "haiku"))] {
25         mod utimensat;
26         pub use self::utimensat::*;
27     } else {
28         mod utimes;
29         pub use self::utimes::*;
30     }
31 }
32 
33 #[allow(dead_code)]
to_timespec(ft: &Option<FileTime>) -> timespec34 fn to_timespec(ft: &Option<FileTime>) -> timespec {
35     cfg_if::cfg_if! {
36         if #[cfg(target_os = "macos")] {
37             // https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/sys/stat.h#L541
38             const UTIME_OMIT: i64 = -2;
39         } else if #[cfg(target_os = "openbsd")] {
40             // https://github.com/openbsd/src/blob/master/sys/sys/stat.h#L189
41             const UTIME_OMIT: i64 = -1;
42         } else {
43             const UTIME_OMIT: i64 = 1_073_741_822;
44         }
45     }
46 
47     if let &Some(ft) = ft {
48         timespec {
49             tv_sec: ft.seconds() as time_t,
50             tv_nsec: ft.nanoseconds() as _,
51         }
52     } else {
53         timespec {
54             tv_sec: 0,
55             tv_nsec: UTIME_OMIT as _,
56         }
57     }
58 }
59 
from_last_modification_time(meta: &fs::Metadata) -> FileTime60 pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
61     FileTime {
62         seconds: meta.mtime(),
63         nanos: meta.mtime_nsec() as u32,
64     }
65 }
66 
from_last_access_time(meta: &fs::Metadata) -> FileTime67 pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
68     FileTime {
69         seconds: meta.atime(),
70         nanos: meta.atime_nsec() as u32,
71     }
72 }
73 
from_creation_time(meta: &fs::Metadata) -> Option<FileTime>74 pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
75     macro_rules! birthtim {
76         ($(($e:expr, $i:ident)),*) => {
77             #[cfg(any($(target_os = $e),*))]
78             fn imp(meta: &fs::Metadata) -> Option<FileTime> {
79                 $(
80                     #[cfg(target_os = $e)]
81                     use std::os::$i::fs::MetadataExt;
82                 )*
83                 Some(FileTime {
84                     seconds: meta.st_birthtime(),
85                     nanos: meta.st_birthtime_nsec() as u32,
86                 })
87             }
88 
89             #[cfg(all($(not(target_os = $e)),*))]
90             fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
91                 None
92             }
93         }
94     }
95 
96     birthtim! {
97         ("bitrig", bitrig),
98         ("freebsd", freebsd),
99         ("ios", ios),
100         ("macos", macos),
101         ("openbsd", openbsd)
102     }
103 
104     imp(meta)
105 }
106