diff options
Diffstat (limited to 'vendor/filetime/src/unix/utimes.rs')
-rw-r--r-- | vendor/filetime/src/unix/utimes.rs | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/vendor/filetime/src/unix/utimes.rs b/vendor/filetime/src/unix/utimes.rs new file mode 100644 index 0000000..34bb882 --- /dev/null +++ b/vendor/filetime/src/unix/utimes.rs @@ -0,0 +1,130 @@ +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) +} + +#[cfg(not(target_env = "uclibc"))] +#[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()) + }; +} + +#[cfg(target_env = "uclibc")] +#[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_timespec(&atime), to_timespec(&mtime)]; + let rc = unsafe { libc::futimens(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, + } +} + +#[cfg(target_env = "uclibc")] +fn to_timespec(ft: &FileTime) -> libc::timespec { + libc::timespec { + tv_sec: ft.seconds() as libc::time_t, + #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))] + tv_nsec: (ft.nanoseconds()) as i64, + #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))] + tv_nsec: (ft.nanoseconds()) as libc::c_long, + } +} |