From d96eb479243ec43f46e6f513494c57b3b5334974 Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sun, 6 Jun 2021 21:49:45 +0200 Subject: [PATCH 1/3] Document both `GetFileInformationByHandle` and `GetFileInformationByHandleEx` for `os::windows::fs::MetadataExt` --- library/std/src/os/windows/fs.rs | 81 +++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 28 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index b20eafb4d53a5..b3458dcf15ed7 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,30 +455,38 @@ 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`]. /// /// 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 #[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 index of a file or directory; + /// corresponds to the `nFileIndex{Low,High}` fields returned by [`GetFileInformationByHandle`]. /// /// 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 #[unstable(feature = "windows_by_handle", issue = "63010")] fn file_index(&self) -> Option; } From 50c095a57a145391826c8c6dec4cd57359d2f16d Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sun, 6 Jun 2021 22:05:19 +0200 Subject: [PATCH 2/3] Add `GetFileInformationByHandleEx` support to `os::windows::fs::MetadataExt::volume_serial_number` and `file_index` --- library/std/src/os/windows/fs.rs | 15 +++++++++++---- library/std/src/sys/windows/c.rs | 9 +++++++++ library/std/src/sys/windows/fs.rs | 16 +++++++++++++--- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index b3458dcf15ed7..5a85f3a5aa7f8 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -456,13 +456,15 @@ pub trait MetadataExt { fn file_size(&self) -> u64; /// Returns the volume serial number of a file or directory; - /// corresponds to the `dwVolumeSerialNumber` field returned by [`GetFileInformationByHandle`]. + /// 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; @@ -480,15 +482,20 @@ pub trait MetadataExt { fn number_of_links(&self) -> Option; /// Returns the file index of a file or directory; - /// corresponds to the `nFileIndex{Low,High}` fields returned by [`GetFileInformationByHandle`]. + /// 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_index(&self) -> Option; } #[stable(feature = "metadata_ext", since = "1.1.0")] @@ -514,7 +521,7 @@ impl MetadataExt for Metadata { fn number_of_links(&self) -> Option { self.as_inner().number_of_links() } - fn file_index(&self) -> Option { + fn file_index(&self) -> Option { self.as_inner().file_index() } } 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..b56c21b1a0268 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_index: Option, } #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] @@ -344,7 +344,7 @@ impl File { volume_serial_number: Some(info.dwVolumeSerialNumber), number_of_links: Some(info.nNumberOfLinks), file_index: Some( - (info.nFileIndexLow as u64) | ((info.nFileIndexHigh as u64) << 32), + ((info.nFileIndexLow as u64) | ((info.nFileIndexHigh as u64) << 32)) as u128, ), }) } @@ -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_index = Some(info.FileId); Ok(attr) } } @@ -618,7 +628,7 @@ impl FileAttr { self.number_of_links } - pub fn file_index(&self) -> Option { + pub fn file_index(&self) -> Option { self.file_index } } From 326592074c3106b89a5d14df7e42f64e12cb2e6a Mon Sep 17 00:00:00 2001 From: Christiaan Dirkx Date: Sun, 6 Jun 2021 22:10:55 +0200 Subject: [PATCH 3/3] Rename`os::windows::fs::MetadataExt::file_index` to `file_identifier` --- library/std/src/os/windows/fs.rs | 8 ++++---- library/std/src/sys/windows/fs.rs | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 5a85f3a5aa7f8..8bbf76edd6755 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -481,7 +481,7 @@ pub trait MetadataExt { #[unstable(feature = "windows_by_handle", issue = "63010")] fn number_of_links(&self) -> Option; - /// Returns the file index of a file or directory; + /// 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`]. /// @@ -495,7 +495,7 @@ pub trait MetadataExt { /// [`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")] @@ -521,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/fs.rs b/library/std/src/sys/windows/fs.rs index b56c21b1a0268..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,7 +343,7 @@ impl File { reparse_tag, volume_serial_number: Some(info.dwVolumeSerialNumber), number_of_links: Some(info.nNumberOfLinks), - file_index: Some( + 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); @@ -406,7 +406,7 @@ impl File { size as c::DWORD, ))?; attr.volume_serial_number = Some(info.VolumeSerialNumber); - attr.file_index = Some(info.FileId); + attr.file_identifier = Some(info.FileId); Ok(attr) } } @@ -628,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 } }