1 extern crate libc;
2
3 use std::ffi::CString;
4 use std::fs;
5 use std::io;
6 use std::os::unix::prelude::*;
7 use std::path::Path;
8
9 use self::libc::{c_int, c_char, timeval, time_t, suseconds_t, c_long};
10 use self::libc::{timespec};
11
12 use FileTime;
13
14 cfg_if! {
15 if #[cfg(target_os = "linux")] {
16 mod linux;
17 pub use self::linux::*;
18 } else if #[cfg(any(target_os = "android",
19 target_os = "solaris",
20 target_os = "netbsd",
21 target_os = "openbsd"))] {
22 mod utimensat;
23 pub use self::utimensat::*;
24 } else {
25 mod utimes;
26 pub use self::utimes::*;
27 }
28 }
29
30 #[allow(dead_code)]
utimes(p: &Path, atime: FileTime, mtime: FileTime, utimes: unsafe extern fn(*const c_char, *const timeval) -> c_int) -> io::Result<()>31 fn utimes(p: &Path,
32 atime: FileTime,
33 mtime: FileTime,
34 utimes: unsafe extern fn(*const c_char, *const timeval) -> c_int)
35 -> io::Result<()>
36 {
37 let times = [to_timeval(&atime), to_timeval(&mtime)];
38 let p = try!(CString::new(p.as_os_str().as_bytes()));
39 return if unsafe { utimes(p.as_ptr() as *const _, times.as_ptr()) == 0 } {
40 Ok(())
41 } else {
42 Err(io::Error::last_os_error())
43 };
44
45 fn to_timeval(ft: &FileTime) -> timeval {
46 timeval {
47 tv_sec: ft.seconds() as time_t,
48 tv_usec: (ft.nanoseconds() / 1000) as suseconds_t,
49 }
50 }
51 }
52
53 #[allow(dead_code)]
utimensat(p: &Path, atime: FileTime, mtime: FileTime, f: unsafe extern fn(c_int, *const c_char, *const timespec, c_int) -> c_int, flags: c_int) -> io::Result<()>54 fn utimensat(p: &Path,
55 atime: FileTime,
56 mtime: FileTime,
57 f: unsafe extern fn(c_int, *const c_char, *const timespec, c_int) -> c_int,
58 flags: c_int)
59 -> io::Result<()>
60 {
61 let times = [to_timespec(&atime), to_timespec(&mtime)];
62 let p = try!(CString::new(p.as_os_str().as_bytes()));
63 let rc = unsafe {
64 f(libc::AT_FDCWD, p.as_ptr() as *const _, times.as_ptr(), flags)
65 };
66 return if rc == 0 {
67 Ok(())
68 } else {
69 Err(io::Error::last_os_error())
70 };
71
72 fn to_timespec(ft: &FileTime) -> timespec {
73 timespec {
74 tv_sec: ft.seconds() as time_t,
75 tv_nsec: ft.nanoseconds() as c_long,
76 }
77 }
78 }
79
from_last_modification_time(meta: &fs::Metadata) -> FileTime80 pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
81 FileTime {
82 seconds: meta.mtime() as u64,
83 nanos: meta.mtime_nsec() as u32,
84 }
85 }
86
from_last_access_time(meta: &fs::Metadata) -> FileTime87 pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
88 FileTime {
89 seconds: meta.atime() as u64,
90 nanos: meta.atime_nsec() as u32,
91 }
92 }
93
from_creation_time(meta: &fs::Metadata) -> Option<FileTime>94 pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
95 macro_rules! birthtim {
96 ($(($e:expr, $i:ident)),*) => {
97 #[cfg(any($(target_os = $e),*))]
98 fn imp(meta: &fs::Metadata) -> Option<FileTime> {
99 $(
100 #[cfg(target_os = $e)]
101 use std::os::$i::fs::MetadataExt;
102 )*
103 Some(FileTime {
104 seconds: meta.st_birthtime() as u64,
105 nanos: meta.st_birthtime_nsec() as u32,
106 })
107 }
108
109 #[cfg(all($(not(target_os = $e)),*))]
110 fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
111 None
112 }
113 }
114 }
115
116 birthtim! {
117 ("bitrig", bitrig),
118 ("freebsd", freebsd),
119 ("ios", ios),
120 ("macos", macos),
121 ("openbsd", openbsd)
122 }
123
124 imp(meta)
125 }
126