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
use crate::FileTime; use std::ffi::CString; use std::fs; use std::io; use std::os::unix::prelude::*; use std::path::Path; #[allow(dead_code)] pub fn set_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, Some(atime), Some(mtime), false) } #[allow(dead_code)] pub fn set_file_mtime(p: &Path, mtime: FileTime) -> io::Result<()> { set_times(p, None, Some(mtime), false) } #[allow(dead_code)] pub fn set_file_atime(p: &Path, atime: FileTime) -> io::Result<()> { set_times(p, Some(atime), None, false) } #[allow(dead_code)] pub fn set_file_handle_times( f: &fs::File, atime: Option<FileTime>, mtime: Option<FileTime>, ) -> io::Result<()> { let (atime, mtime) = match get_times(atime, mtime, || f.metadata())? { Some(pair) => pair, None => return Ok(()), }; let times = [to_timeval(&atime), to_timeval(&mtime)]; let rc = unsafe { libc::futimes(f.as_raw_fd(), times.as_ptr()) }; return if rc == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }; } fn get_times( atime: Option<FileTime>, mtime: Option<FileTime>, current: impl FnOnce() -> io::Result<fs::Metadata>, ) -> io::Result<Option<(FileTime, FileTime)>> { let pair = match (atime, mtime) { (Some(a), Some(b)) => (a, b), (None, None) => return Ok(None), (Some(a), None) => { let meta = current()?; (a, FileTime::from_last_modification_time(&meta)) } (None, Some(b)) => { let meta = current()?; (FileTime::from_last_access_time(&meta), b) } }; Ok(Some(pair)) } #[allow(dead_code)] pub fn set_symlink_file_times(p: &Path, atime: FileTime, mtime: FileTime) -> io::Result<()> { set_times(p, Some(atime), Some(mtime), true) } pub fn set_times( p: &Path, atime: Option<FileTime>, mtime: Option<FileTime>, symlink: bool, ) -> io::Result<()> { let (atime, mtime) = match get_times(atime, mtime, || p.metadata())? { Some(pair) => pair, None => return Ok(()), }; let p = CString::new(p.as_os_str().as_bytes())?; let times = [to_timeval(&atime), to_timeval(&mtime)]; let rc = unsafe { if symlink { libc::lutimes(p.as_ptr(), times.as_ptr()) } else { libc::utimes(p.as_ptr(), times.as_ptr()) } }; return if rc == 0 { Ok(()) } else { Err(io::Error::last_os_error()) }; } fn to_timeval(ft: &FileTime) -> libc::timeval { libc::timeval { tv_sec: ft.seconds() as libc::time_t, tv_usec: (ft.nanoseconds() / 1000) as libc::suseconds_t, } }