diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 27947d91c99..7cac8c39ea8 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -471,6 +471,13 @@ pub trait MetadataExt { /// `fs::metadata` or `File::metadata`, then this will return `Some`. #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; + + /// Returns the change time, which is the last time file metadata was changed, such as + /// renames, attributes, etc + /// + /// This will return `None` if the `Metadata` instance was not created using the `FILE_BASIC_INFO` type. + #[unstable(feature = "windows_change_time", issue = "121478")] + fn change_time(&self) -> Option; } #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -499,6 +506,9 @@ impl MetadataExt for Metadata { fn file_index(&self) -> Option { self.as_inner().file_index() } + fn change_time(&self) -> Option { + self.as_inner().changed_u64() + } } /// Windows-specific extensions to [`fs::FileType`]. diff --git a/library/std/src/sys/pal/windows/fs.rs b/library/std/src/sys/pal/windows/fs.rs index 48c39392047..15d446786ad 100644 --- a/library/std/src/sys/pal/windows/fs.rs +++ b/library/std/src/sys/pal/windows/fs.rs @@ -32,6 +32,7 @@ pub struct FileAttr { creation_time: c::FILETIME, last_access_time: c::FILETIME, last_write_time: c::FILETIME, + change_time: Option, file_size: u64, reparse_tag: u32, volume_serial_number: Option, @@ -377,6 +378,7 @@ impl File { creation_time: info.ftCreationTime, last_access_time: info.ftLastAccessTime, last_write_time: info.ftLastWriteTime, + change_time: None, // Only available in FILE_BASIC_INFO file_size: (info.nFileSizeLow as u64) | ((info.nFileSizeHigh as u64) << 32), reparse_tag, volume_serial_number: Some(info.dwVolumeSerialNumber), @@ -413,6 +415,10 @@ impl File { dwLowDateTime: info.LastWriteTime as u32, dwHighDateTime: (info.LastWriteTime >> 32) as u32, }, + change_time: Some(c::FILETIME { + dhLowDateTime: info.ChangeTime as c::DWORD, + dhHighDateTime: (info.ChangeTime >> 32) as c::DWORD, + }), file_size: 0, reparse_tag: 0, volume_serial_number: None, @@ -957,6 +963,10 @@ impl FileAttr { to_u64(&self.creation_time) } + pub fn changed_u64(&self) -> Option { + self.change_time.as_ref().map(|c| to_u64(c)) + } + pub fn volume_serial_number(&self) -> Option { self.volume_serial_number } @@ -976,6 +986,7 @@ impl From for FileAttr { creation_time: wfd.ftCreationTime, last_access_time: wfd.ftLastAccessTime, last_write_time: wfd.ftLastWriteTime, + change_time: None, file_size: ((wfd.nFileSizeHigh as u64) << 32) | (wfd.nFileSizeLow as u64), reparse_tag: if wfd.dwFileAttributes & c::FILE_ATTRIBUTE_REPARSE_POINT != 0 { // reserved unless this is a reparse point