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 = "aix" , |
19 | target_os = "solaris" , |
20 | target_os = "illumos" , |
21 | target_os = "emscripten" , |
22 | target_os = "freebsd" , |
23 | target_os = "netbsd" , |
24 | target_os = "openbsd" , |
25 | target_os = "haiku" ))] { |
26 | mod utimensat; |
27 | pub use self::utimensat::*; |
28 | } else { |
29 | mod utimes; |
30 | pub use self::utimes::*; |
31 | } |
32 | } |
33 | |
34 | #[allow (dead_code)] |
35 | fn to_timespec(ft: &Option<FileTime>) -> timespec { |
36 | cfg_if::cfg_if! { |
37 | if #[cfg(any(target_os = "macos" , |
38 | target_os = "illumos" , |
39 | target_os = "freebsd" ))] { |
40 | // https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/sys/stat.h#L541 |
41 | // https://github.com/illumos/illumos-gate/blob/master/usr/src/boot/sys/sys/stat.h#L312 |
42 | // https://svnweb.freebsd.org/base/head/sys/sys/stat.h?view=markup#l359 |
43 | const UTIME_OMIT: i64 = -2; |
44 | } else if #[cfg(target_os = "openbsd" )] { |
45 | // https://github.com/openbsd/src/blob/master/sys/sys/stat.h#L189 |
46 | const UTIME_OMIT: i64 = -1; |
47 | } else if #[cfg(target_os = "haiku" )] { |
48 | // https://git.haiku-os.org/haiku/tree/headers/posix/sys/stat.h?#n106 |
49 | const UTIME_OMIT: i64 = 1000000001; |
50 | } else if #[cfg(target_os = "aix" )] { |
51 | // AIX hasn't disclosed system header files yet. |
52 | // https://github.com/golang/go/blob/master/src/cmd/vendor/golang.org/x/sys/unix/zerrors_aix_ppc64.go#L1007 |
53 | const UTIME_OMIT: i64 = -3; |
54 | } else { |
55 | // http://cvsweb.netbsd.org/bsdweb.cgi/src/sys/sys/stat.h?annotate=1.68.30.1 |
56 | // https://github.com/emscripten-core/emscripten/blob/master/system/include/libc/sys/stat.h#L71 |
57 | const UTIME_OMIT: i64 = 1_073_741_822; |
58 | } |
59 | } |
60 | |
61 | let mut ts: timespec = unsafe { std::mem::zeroed() }; |
62 | if let &Some(ft) = ft { |
63 | ts.tv_sec = ft.seconds() as time_t; |
64 | ts.tv_nsec = ft.nanoseconds() as _; |
65 | } else { |
66 | ts.tv_sec = 0; |
67 | ts.tv_nsec = UTIME_OMIT as _; |
68 | } |
69 | |
70 | ts |
71 | } |
72 | |
73 | pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { |
74 | FileTime { |
75 | seconds: meta.mtime(), |
76 | nanos: meta.mtime_nsec() as u32, |
77 | } |
78 | } |
79 | |
80 | pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { |
81 | FileTime { |
82 | seconds: meta.atime(), |
83 | nanos: meta.atime_nsec() as u32, |
84 | } |
85 | } |
86 | |
87 | pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> { |
88 | macro_rules! birthtim { |
89 | ($(($e:expr, $i:ident)),*) => { |
90 | #[cfg(any($(target_os = $e),*))] |
91 | fn imp(meta: &fs::Metadata) -> Option<FileTime> { |
92 | $( |
93 | #[cfg(target_os = $e)] |
94 | use std::os::$i::fs::MetadataExt; |
95 | )* |
96 | Some(FileTime { |
97 | seconds: meta.st_birthtime(), |
98 | nanos: meta.st_birthtime_nsec() as u32, |
99 | }) |
100 | } |
101 | |
102 | #[cfg(all($(not(target_os = $e)),*))] |
103 | fn imp(_meta: &fs::Metadata) -> Option<FileTime> { |
104 | None |
105 | } |
106 | } |
107 | } |
108 | |
109 | birthtim! { |
110 | ("bitrig" , bitrig), |
111 | ("freebsd" , freebsd), |
112 | ("ios" , ios), |
113 | ("macos" , macos), |
114 | ("openbsd" , openbsd) |
115 | } |
116 | |
117 | imp(meta) |
118 | } |
119 | |