diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index b20eafb4d53a5..8bbf76edd6755 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -288,18 +288,22 @@ impl OpenOptionsExt for OpenOptions { /// Windows-specific extensions to [`fs::Metadata`]. /// -/// The data members that this trait exposes correspond to the members -/// of the [`BY_HANDLE_FILE_INFORMATION`] structure. +/// The members of this trait correspond to metadata exposed by calls to either +/// [`GetFileInformationByHandle`] or [`GetFileInformationByHandleEx`]. /// -/// [`BY_HANDLE_FILE_INFORMATION`]: -/// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/ns-fileapi-by_handle_file_information +/// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle +/// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex #[stable(feature = "metadata_ext", since = "1.1.0")] pub trait MetadataExt { - /// Returns the value of the `dwFileAttributes` field of this metadata. + /// Returns the file attributes of a file or directory; + /// corresponds to the `dwFileAttributes` field returned by [`GetFileInformationByHandle`], + /// or the `FileAttributes` field returned by [`GetFileInformationByHandleEx`]. /// - /// This field contains the file system attribute information for a file - /// or directory. For possible values and their descriptions, see - /// [File Attribute Constants] in the Windows Dev Center. + /// For possible values and their descriptions, see [File Attribute Constants] in the Windows Dev Center. + /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + /// [File Attribute Constants]: https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants /// /// # Examples /// @@ -314,13 +318,12 @@ pub trait MetadataExt { /// Ok(()) /// } /// ``` - /// - /// [File Attribute Constants]: - /// https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_attributes(&self) -> u32; - /// Returns the value of the `ftCreationTime` field of this metadata. + /// Returns the creation time of a file or directory; + /// corresponds to the `ftCreationTime` field returned by [`GetFileInformationByHandle`], + /// or the `CreationTime` field returned by [`GetFileInformationByHandleEx`]. /// /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, /// which represents the number of 100-nanosecond intervals since @@ -331,6 +334,10 @@ pub trait MetadataExt { /// If the underlying filesystem does not support creation time, the /// returned value is 0. /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// /// # Examples /// /// ```no_run @@ -344,12 +351,12 @@ pub trait MetadataExt { /// Ok(()) /// } /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn creation_time(&self) -> u64; - /// Returns the value of the `ftLastAccessTime` field of this metadata. + /// Returns the last access time of a file or directory; + /// corresponds to the `ftLastAccessTime` field returned by [`GetFileInformationByHandle`], + /// or the `LastAccessTime` field returned by [`GetFileInformationByHandleEx`]. /// /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, /// which represents the number of 100-nanosecond intervals since @@ -366,6 +373,10 @@ pub trait MetadataExt { /// If the underlying filesystem does not support last access time, the /// returned value is 0. /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// /// # Examples /// /// ```no_run @@ -379,12 +390,12 @@ pub trait MetadataExt { /// Ok(()) /// } /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_access_time(&self) -> u64; - /// Returns the value of the `ftLastWriteTime` field of this metadata. + /// Returns the last write time of a file or directory; + /// corresponds to the `ftLastWriteTime` field returned by [`GetFileInformationByHandle`], + /// or the `LastWriteTime` field returned by [`GetFileInformationByHandleEx`]. /// /// The returned 64-bit value is equivalent to a [`FILETIME`] struct, /// which represents the number of 100-nanosecond intervals since @@ -399,6 +410,10 @@ pub trait MetadataExt { /// If the underlying filesystem does not support the last write time, /// the returned value is 0. /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + /// /// # Examples /// /// ```no_run @@ -412,16 +427,18 @@ pub trait MetadataExt { /// Ok(()) /// } /// ``` - /// - /// [`FILETIME`]: https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime #[stable(feature = "metadata_ext", since = "1.1.0")] fn last_write_time(&self) -> u64; - /// Returns the value of the `nFileSize{High,Low}` fields of this - /// metadata. + /// Returns the size of a file; + /// corresponds to the `nFileSize{High,Low}` fields returned by [`GetFileInformationByHandle`], + /// or the `AllocationSize` field returned by [`GetFileInformationByHandleEx`]. /// /// The returned value does not have meaning for directories. /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + /// /// # Examples /// /// ```no_run @@ -438,32 +455,47 @@ pub trait MetadataExt { #[stable(feature = "metadata_ext", since = "1.1.0")] fn file_size(&self) -> u64; - /// Returns the value of the `dwVolumeSerialNumber` field of this - /// metadata. + /// Returns the volume serial number of a file or directory; + /// corresponds to the `dwVolumeSerialNumber` field returned by [`GetFileInformationByHandle`], + /// or the `VolumeSerialNumber` field returned by [`GetFileInformationByHandleEx`]. /// /// This will return `None` if the `Metadata` instance was created from a /// call to `DirEntry::metadata`. If this `Metadata` was created by using /// `fs::metadata` or `File::metadata`, then this will return `Some`. + /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex #[unstable(feature = "windows_by_handle", issue = "63010")] fn volume_serial_number(&self) -> Option; - /// Returns the value of the `nNumberOfLinks` field of this - /// metadata. + /// Returns the number of links to a file or directory; + /// corresponds to the `nNumberOfLinks` field returned by [`GetFileInformationByHandle`], + /// or the `NumberOfLinks` field returned by [`GetFileInformationByHandleEx`]. /// /// This will return `None` if the `Metadata` instance was created from a /// call to `DirEntry::metadata`. If this `Metadata` was created by using /// `fs::metadata` or `File::metadata`, then this will return `Some`. + /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex #[unstable(feature = "windows_by_handle", issue = "63010")] fn number_of_links(&self) -> Option; - /// Returns the value of the `nFileIndex{Low,High}` fields of this - /// metadata. + /// Returns the file identifier of a file or directory; + /// corresponds to the `nFileIndex{Low,High}` fields returned by [`GetFileInformationByHandle`], + /// or the `FileId` field returned by [`GetFileInformationByHandleEx`]. + /// + /// Note that this is a `u128`, since `GetFileInformationByHandle` returns a 64-bit value, + /// and `GetFileInformationByHandleEx` returns a 128-bit value. /// /// This will return `None` if the `Metadata` instance was created from a /// call to `DirEntry::metadata`. If this `Metadata` was created by using /// `fs::metadata` or `File::metadata`, then this will return `Some`. + /// + /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfileinformationbyhandle + /// [`GetFileInformationByHandleEx`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex #[unstable(feature = "windows_by_handle", issue = "63010")] - fn file_index(&self) -> Option; + fn file_identifier(&self) -> Option; } #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -489,8 +521,8 @@ impl MetadataExt for Metadata { fn number_of_links(&self) -> Option { self.as_inner().number_of_links() } - fn file_index(&self) -> Option { - self.as_inner().file_index() + fn file_identifier(&self) -> Option { + self.as_inner().file_identifier() } } diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs index b7efc884473b4..5b4cb9162a1d4 100644 --- a/library/std/src/sys/windows/c.rs +++ b/library/std/src/sys/windows/c.rs @@ -758,6 +758,9 @@ if #[cfg(not(target_vendor = "uwp"))] { // UWP specific functions & types cfg_if::cfg_if! { if #[cfg(target_vendor = "uwp")] { + use use crate::os::raw::c_ulonglong; + pub type ULONGLONG = c_ulonglong; + pub const BCRYPT_USE_SYSTEM_PREFERRED_RNG: DWORD = 0x00000002; #[repr(C)] @@ -769,6 +772,12 @@ if #[cfg(target_vendor = "uwp")] { pub Directory: BOOLEAN, } + #[repr(C)] + pub struct FILE_ID_INFO { + pub VolumeSerialNumber: ULONGLONG, + pub FileId: u128 + } + #[link(name = "bcrypt")] extern "system" { pub fn BCryptGenRandom( diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs index 2b6143de96056..68a7518beff23 100644 --- a/library/std/src/sys/windows/fs.rs +++ b/library/std/src/sys/windows/fs.rs @@ -29,7 +29,7 @@ pub struct FileAttr { reparse_tag: c::DWORD, volume_serial_number: Option, number_of_links: Option, - file_index: Option, + file_identifier: Option, } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -163,7 +163,7 @@ impl DirEntry { }, volume_serial_number: None, number_of_links: None, - file_index: None, + file_identifier: None, }) } } @@ -343,8 +343,8 @@ impl File { reparse_tag, volume_serial_number: Some(info.dwVolumeSerialNumber), number_of_links: Some(info.nNumberOfLinks), - file_index: Some( - (info.nFileIndexLow as u64) | ((info.nFileIndexHigh as u64) << 32), + file_identifier: Some( + ((info.nFileIndexLow as u64) | ((info.nFileIndexHigh as u64) << 32)) as u128, ), }) } @@ -379,7 +379,7 @@ impl File { reparse_tag: 0, volume_serial_number: None, number_of_links: None, - file_index: None, + file_identifier: None, }; let mut info: c::FILE_STANDARD_INFO = mem::zeroed(); let size = mem::size_of_val(&info); @@ -397,6 +397,16 @@ impl File { attr.reparse_tag = buf.ReparseTag; } } + let mut info: c::FILE_ID_INFO = mem::zeroed(); + let size = mem::size_of_val(&info); + cvt(c::GetFileInformationByHandleEx( + self.handle.raw(), + c::FileIdInfo, + &mut info as *mut _ as *mut libc::c_void, + size as c::DWORD, + ))?; + attr.volume_serial_number = Some(info.VolumeSerialNumber); + attr.file_identifier = Some(info.FileId); Ok(attr) } } @@ -618,8 +628,8 @@ impl FileAttr { self.number_of_links } - pub fn file_index(&self) -> Option { - self.file_index + pub fn file_identifier(&self) -> Option { + self.file_identifier } }