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(any(target_os = "macos",
37                      target_os = "illumos",
38                      target_os = "freebsd"))] {
39             // https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/sys/stat.h#L541
40             // https://github.com/illumos/illumos-gate/blob/master/usr/src/boot/sys/sys/stat.h#L312
41             // https://svnweb.freebsd.org/base/head/sys/sys/stat.h?view=markup#l359
42             const UTIME_OMIT: i64 = -2;
43         } else if #[cfg(target_os = "openbsd")] {
44             // https://github.com/openbsd/src/blob/master/sys/sys/stat.h#L189
45             const UTIME_OMIT: i64 = -1;
46         } else if #[cfg(target_os = "haiku")] {
47             // https://git.haiku-os.org/haiku/tree/headers/posix/sys/stat.h?#n106
48             const UTIME_OMIT: i64 = 1000000001;
49         } else {
50             // http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/stat.h?annotate=1.68.30.1
51             // https://github.com/emscripten-core/emscripten/blob/master/system/include/libc/sys/stat.h#L71
52             const UTIME_OMIT: i64 = 1_073_741_822;
53         }
54     }
55 
56     if let &Some(ft) = ft {
57         timespec {
58             tv_sec: ft.seconds() as time_t,
59             tv_nsec: ft.nanoseconds() as _,
60         }
61     } else {
62         timespec {
63             tv_sec: 0,
64             tv_nsec: UTIME_OMIT as _,
65         }
66     }
67 }
68 
from_last_modification_time(meta: &fs::Metadata) -> FileTime69 pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
70     FileTime {
71         seconds: meta.mtime(),
72         nanos: meta.mtime_nsec() as u32,
73     }
74 }
75 
from_last_access_time(meta: &fs::Metadata) -> FileTime76 pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
77     FileTime {
78         seconds: meta.atime(),
79         nanos: meta.atime_nsec() as u32,
80     }
81 }
82 
from_creation_time(meta: &fs::Metadata) -> Option<FileTime>83 pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
84     macro_rules! birthtim {
85         ($(($e:expr, $i:ident)),*) => {
86             #[cfg(any($(target_os = $e),*))]
87             fn imp(meta: &fs::Metadata) -> Option<FileTime> {
88                 $(
89                     #[cfg(target_os = $e)]
90                     use std::os::$i::fs::MetadataExt;
91                 )*
92                 Some(FileTime {
93                     seconds: meta.st_birthtime(),
94                     nanos: meta.st_birthtime_nsec() as u32,
95                 })
96             }
97 
98             #[cfg(all($(not(target_os = $e)),*))]
99             fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
100                 None
101             }
102         }
103     }
104 
105     birthtim! {
106         ("bitrig", bitrig),
107         ("freebsd", freebsd),
108         ("ios", ios),
109         ("macos", macos),
110         ("openbsd", openbsd)
111     }
112 
113     imp(meta)
114 }
115