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