]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | #![allow(bad_style)] |
2 | ||
3 | use std::fs::{self, OpenOptions}; | |
4 | use std::io; | |
5 | use std::os::windows::prelude::*; | |
6 | use std::path::Path; | |
7 | ||
8 | use FileTime; | |
9 | ||
10 | pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { | |
11 | set_file_times_w(p, atime, mtime, OpenOptions::new()) | |
12 | } | |
13 | ||
14 | pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { | |
15 | use std::os::windows::fs::OpenOptionsExt; | |
16 | const FILE_FLAG_OPEN_REPARSE_POINT: u32 = 0x00200000; | |
17 | ||
18 | let mut options = OpenOptions::new(); | |
19 | options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT); | |
20 | set_file_times_w(p, atime, mtime, options) | |
21 | } | |
22 | ||
23 | pub fn set_file_times_w(p: &Path, | |
24 | atime: FileTime, | |
25 | mtime: FileTime, | |
26 | mut options: OpenOptions) -> io::Result<()> { | |
27 | type BOOL = i32; | |
28 | type HANDLE = *mut u8; | |
29 | type DWORD = u32; | |
30 | ||
31 | #[repr(C)] | |
32 | struct FILETIME { | |
33 | dwLowDateTime: u32, | |
34 | dwHighDateTime: u32, | |
35 | } | |
36 | ||
37 | extern "system" { | |
38 | fn SetFileTime(hFile: HANDLE, | |
39 | lpCreationTime: *const FILETIME, | |
40 | lpLastAccessTime: *const FILETIME, | |
41 | lpLastWriteTime: *const FILETIME) -> BOOL; | |
42 | } | |
43 | ||
44 | let f = try!(options.write(true).open(p)); | |
45 | let atime = to_filetime(&atime); | |
46 | let mtime = to_filetime(&mtime); | |
47 | return unsafe { | |
48 | let ret = SetFileTime(f.as_raw_handle() as *mut _, | |
49 | 0 as *const _, | |
50 | &atime, &mtime); | |
51 | if ret != 0 { | |
52 | Ok(()) | |
53 | } else { | |
54 | Err(io::Error::last_os_error()) | |
55 | } | |
56 | }; | |
57 | ||
58 | fn to_filetime(ft: &FileTime) -> FILETIME { | |
59 | let intervals = ft.seconds() * (1_000_000_000 / 100) + | |
83c7162d | 60 | ((ft.nanoseconds() as i64) / 100); |
ea8adc8c XL |
61 | FILETIME { |
62 | dwLowDateTime: intervals as DWORD, | |
63 | dwHighDateTime: (intervals >> 32) as DWORD, | |
64 | } | |
65 | } | |
66 | } | |
67 | ||
68 | pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime { | |
69 | from_intervals(meta.last_write_time()) | |
70 | } | |
71 | ||
72 | pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime { | |
73 | from_intervals(meta.last_access_time()) | |
74 | } | |
75 | ||
76 | pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> { | |
77 | Some(from_intervals(meta.creation_time())) | |
78 | } | |
79 | ||
80 | fn from_intervals(ticks: u64) -> FileTime { | |
81 | // Windows write times are in 100ns intervals, so do a little math to | |
82 | // get it into the right representation. | |
83 | FileTime { | |
83c7162d | 84 | seconds: (ticks / (1_000_000_000 / 100)) as i64, |
ea8adc8c XL |
85 | nanos: ((ticks % (1_000_000_000 / 100)) * 100) as u32, |
86 | } | |
87 | } |