100 lines
2.9 KiB
Rust
100 lines
2.9 KiB
Rust
use crate::FileTime;
|
|
use std::fs::{self, File, OpenOptions};
|
|
use std::io;
|
|
use std::os::windows::prelude::*;
|
|
use std::path::Path;
|
|
use std::ptr;
|
|
use windows_sys::Win32::Foundation::{FILETIME, HANDLE};
|
|
use windows_sys::Win32::Storage::FileSystem::*;
|
|
|
|
pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
|
|
let f = OpenOptions::new()
|
|
.write(true)
|
|
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
|
|
.open(p)?;
|
|
set_file_handle_times(&f, Some(atime), Some(mtime))
|
|
}
|
|
|
|
pub fn set_file_mtime(p: &Path, mtime: FileTime) -> io::Result<()> {
|
|
let f = OpenOptions::new()
|
|
.write(true)
|
|
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
|
|
.open(p)?;
|
|
set_file_handle_times(&f, None, Some(mtime))
|
|
}
|
|
|
|
pub fn set_file_atime(p: &Path, atime: FileTime) -> io::Result<()> {
|
|
let f = OpenOptions::new()
|
|
.write(true)
|
|
.custom_flags(FILE_FLAG_BACKUP_SEMANTICS)
|
|
.open(p)?;
|
|
set_file_handle_times(&f, Some(atime), None)
|
|
}
|
|
|
|
pub fn set_file_handle_times(
|
|
f: &File,
|
|
atime: Option<FileTime>,
|
|
mtime: Option<FileTime>,
|
|
) -> io::Result<()> {
|
|
let atime = atime.map(to_filetime);
|
|
let mtime = mtime.map(to_filetime);
|
|
return unsafe {
|
|
let ret = SetFileTime(
|
|
f.as_raw_handle() as HANDLE,
|
|
ptr::null(),
|
|
atime
|
|
.as_ref()
|
|
.map(|p| p as *const FILETIME)
|
|
.unwrap_or(ptr::null()),
|
|
mtime
|
|
.as_ref()
|
|
.map(|p| p as *const FILETIME)
|
|
.unwrap_or(ptr::null()),
|
|
);
|
|
if ret != 0 {
|
|
Ok(())
|
|
} else {
|
|
Err(io::Error::last_os_error())
|
|
}
|
|
};
|
|
|
|
fn to_filetime(ft: FileTime) -> FILETIME {
|
|
let intervals = ft.seconds() * (1_000_000_000 / 100) + ((ft.nanoseconds() as i64) / 100);
|
|
FILETIME {
|
|
dwLowDateTime: intervals as u32,
|
|
dwHighDateTime: (intervals >> 32) as u32,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> {
|
|
use std::os::windows::fs::OpenOptionsExt;
|
|
|
|
let f = OpenOptions::new()
|
|
.write(true)
|
|
.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)
|
|
.open(p)?;
|
|
set_file_handle_times(&f, Some(atime), Some(mtime))
|
|
}
|
|
|
|
pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
|
|
from_intervals(meta.last_write_time())
|
|
}
|
|
|
|
pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
|
|
from_intervals(meta.last_access_time())
|
|
}
|
|
|
|
pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
|
|
Some(from_intervals(meta.creation_time()))
|
|
}
|
|
|
|
fn from_intervals(ticks: u64) -> FileTime {
|
|
// Windows write times are in 100ns intervals, so do a little math to
|
|
// get it into the right representation.
|
|
FileTime {
|
|
seconds: (ticks / (1_000_000_000 / 100)) as i64,
|
|
nanos: ((ticks % (1_000_000_000 / 100)) * 100) as u32,
|
|
}
|
|
}
|