diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/fs.rs | 11 | ||||
| -rw-r--r-- | library/std/src/os/ios/fs.rs | 22 | ||||
| -rw-r--r-- | library/std/src/os/macos/fs.rs | 22 | ||||
| -rw-r--r-- | library/std/src/os/watchos/fs.rs | 22 | ||||
| -rw-r--r-- | library/std/src/os/windows/fs.rs | 19 | ||||
| -rw-r--r-- | library/std/src/sys/unix/fs.rs | 52 | ||||
| -rw-r--r-- | library/std/src/sys/windows/fs.rs | 22 |
7 files changed, 144 insertions, 26 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 6640c7fb162..5b3f1139a29 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -15,6 +15,7 @@ use crate::ffi::OsString; use crate::fmt; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; +use crate::sealed::Sealed; use crate::sys::fs as fs_imp; use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; @@ -1391,6 +1392,16 @@ impl FileTimes { } } +impl AsInnerMut<fs_imp::FileTimes> for FileTimes { + fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes { + &mut self.0 + } +} + +// For implementing OS extension traits in `std::os` +#[unstable(feature = "file_set_times", issue = "98245")] +impl Sealed for FileTimes {} + impl Permissions { /// Returns `true` if these permissions describe a readonly (unwritable) file. /// diff --git a/library/std/src/os/ios/fs.rs b/library/std/src/os/ios/fs.rs index 4a4637ce072..6d4d54b7c78 100644 --- a/library/std/src/os/ios/fs.rs +++ b/library/std/src/os/ios/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::ios::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/macos/fs.rs b/library/std/src/os/macos/fs.rs index 91915da6a43..fe82d03d869 100644 --- a/library/std/src/os/macos/fs.rs +++ b/library/std/src/os/macos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::macos::raw; @@ -146,3 +148,19 @@ impl MetadataExt for Metadata { [qspare[0] as u64, qspare[1] as u64] } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/watchos/fs.rs b/library/std/src/os/watchos/fs.rs index a14fe35a77c..2ecc4c68a96 100644 --- a/library/std/src/os/watchos/fs.rs +++ b/library/std/src/os/watchos/fs.rs @@ -1,7 +1,9 @@ #![stable(feature = "metadata_ext", since = "1.1.0")] -use crate::fs::Metadata; -use crate::sys_common::AsInner; +use crate::fs::{self, Metadata}; +use crate::sealed::Sealed; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; #[allow(deprecated)] use crate::os::watchos::raw; @@ -140,3 +142,19 @@ impl MetadataExt for Metadata { self.as_inner().as_inner().st_lspare as u32 } } + +/// OS-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index a091f06dd53..94509e54796 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -9,7 +9,8 @@ use crate::io; use crate::path::Path; use crate::sealed::Sealed; use crate::sys; -use crate::sys_common::{AsInner, AsInnerMut}; +use crate::sys_common::{AsInner, AsInnerMut, IntoInner}; +use crate::time::SystemTime; /// Windows-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] @@ -526,6 +527,22 @@ impl FileTypeExt for fs::FileType { } } +/// Windows-specific extensions to [`fs::FileTimes`]. +#[unstable(feature = "file_set_times", issue = "98245")] +pub trait FileTimesExt: Sealed { + /// Set the creation time of a file. + #[unstable(feature = "file_set_times", issue = "98245")] + fn set_created(self, t: SystemTime) -> Self; +} + +#[unstable(feature = "file_set_times", issue = "98245")] +impl FileTimesExt for fs::FileTimes { + fn set_created(mut self, t: SystemTime) -> Self { + self.as_inner_mut().set_created(t.into_inner()); + self + } +} + /// Creates a new symlink to a non-directory file on the filesystem. /// /// The `link` path will be a file symbolic link pointing to the `original` diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index 09db5b11dbf..09e9ae2720f 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -349,6 +349,8 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<SystemTime>, modified: Option<SystemTime>, + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + created: Option<SystemTime>, } #[derive(Copy, Clone, Eq, Debug)] @@ -591,6 +593,11 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t); } + + #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t); + } } impl FileType { @@ -1215,26 +1222,41 @@ impl File { io::ErrorKind::Unsupported, "setting file times not supported", )) - } else if #[cfg(any(target_os = "android", target_os = "macos"))] { + } else if #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))] { + let mut buf = [mem::MaybeUninit::<libc::timespec>::uninit(); 3]; + let mut num_times = 0; + let mut attrlist: libc::attrlist = unsafe { mem::zeroed() }; + attrlist.bitmapcount = libc::ATTR_BIT_MAP_COUNT; + if times.created.is_some() { + buf[num_times].write(to_timespec(times.created)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_CRTIME; + } + if times.modified.is_some() { + buf[num_times].write(to_timespec(times.modified)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_MODTIME; + } + if times.accessed.is_some() { + buf[num_times].write(to_timespec(times.accessed)?); + num_times += 1; + attrlist.commonattr |= libc::ATTR_CMN_ACCTIME; + } + cvt(unsafe { libc::fsetattrlist( + self.as_raw_fd(), + (&attrlist as *const libc::attrlist).cast::<libc::c_void>().cast_mut(), + buf.as_ptr().cast::<libc::c_void>().cast_mut(), + num_times * mem::size_of::<libc::timespec>(), + 0 + ) })?; + Ok(()) + } else if #[cfg(target_os = "android")] { let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?]; - // futimens requires macOS 10.13, and Android API level 19 + // futimens requires Android API level 19 cvt(unsafe { weak!(fn futimens(c_int, *const libc::timespec) -> c_int); match futimens.get() { Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()), - #[cfg(target_os = "macos")] - None => { - fn ts_to_tv(ts: &libc::timespec) -> libc::timeval { - libc::timeval { - tv_sec: ts.tv_sec, - tv_usec: (ts.tv_nsec / 1000) as _ - } - } - let timevals = [ts_to_tv(×[0]), ts_to_tv(×[1])]; - libc::futimes(self.as_raw_fd(), timevals.as_ptr()) - } - // futimes requires even newer Android. - #[cfg(target_os = "android")] None => return Err(io::const_io_error!( io::ErrorKind::Unsupported, "setting file times requires Android API level >= 19", diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index ce427766d17..21a65bc25f3 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -88,8 +88,10 @@ pub struct FilePermissions { pub struct FileTimes { accessed: Option<c::FILETIME>, modified: Option<c::FILETIME>, + created: Option<c::FILETIME>, } -impl core::fmt::Debug for c::FILETIME { + +impl fmt::Debug for c::FILETIME { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let time = ((self.dwHighDateTime as u64) << 32) | self.dwLowDateTime as u64; f.debug_tuple("FILETIME").field(&time).finish() @@ -582,7 +584,10 @@ impl File { pub fn set_times(&self, times: FileTimes) -> io::Result<()> { let is_zero = |t: c::FILETIME| t.dwLowDateTime == 0 && t.dwHighDateTime == 0; - if times.accessed.map_or(false, is_zero) || times.modified.map_or(false, is_zero) { + if times.accessed.map_or(false, is_zero) + || times.modified.map_or(false, is_zero) + || times.created.map_or(false, is_zero) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0", @@ -590,18 +595,23 @@ impl File { } let is_max = |t: c::FILETIME| t.dwLowDateTime == c::DWORD::MAX && t.dwHighDateTime == c::DWORD::MAX; - if times.accessed.map_or(false, is_max) || times.modified.map_or(false, is_max) { + if times.accessed.map_or(false, is_max) + || times.modified.map_or(false, is_max) + || times.created.map_or(false, is_max) + { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, "Cannot set file timestamp to 0xFFFF_FFFF_FFFF_FFFF", )); } cvt(unsafe { + let created = + times.created.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); let accessed = times.accessed.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); let modified = times.modified.as_ref().map(|a| a as *const c::FILETIME).unwrap_or(ptr::null()); - c::SetFileTime(self.as_raw_handle(), ptr::null_mut(), accessed, modified) + c::SetFileTime(self.as_raw_handle(), created, accessed, modified) })?; Ok(()) } @@ -1005,6 +1015,10 @@ impl FileTimes { pub fn set_modified(&mut self, t: SystemTime) { self.modified = Some(t.into_inner()); } + + pub fn set_created(&mut self, t: SystemTime) { + self.created = Some(t.into_inner()); + } } impl FileType { |
