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