diff options
Diffstat (limited to 'third_party/rust/winapi-util/src/file.rs')
-rw-r--r-- | third_party/rust/winapi-util/src/file.rs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/third_party/rust/winapi-util/src/file.rs b/third_party/rust/winapi-util/src/file.rs new file mode 100644 index 0000000000..56a1e4105f --- /dev/null +++ b/third_party/rust/winapi-util/src/file.rs @@ -0,0 +1,168 @@ +use std::io; +use std::mem; + +use winapi::shared::minwindef::FILETIME; +use winapi::shared::winerror::NO_ERROR; +use winapi::um::errhandlingapi::GetLastError; +use winapi::um::fileapi::{ + GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION, +}; +use winapi::um::winnt; + +use crate::AsHandleRef; + +/// Return various pieces of information about a file. +/// +/// This includes information such as a file's size, unique identifier and +/// time related fields. +/// +/// This corresponds to calling [`GetFileInformationByHandle`]. +/// +/// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle +pub fn information<H: AsHandleRef>(h: H) -> io::Result<Information> { + unsafe { + let mut info: BY_HANDLE_FILE_INFORMATION = mem::zeroed(); + let rc = GetFileInformationByHandle(h.as_raw(), &mut info); + if rc == 0 { + return Err(io::Error::last_os_error()); + }; + Ok(Information(info)) + } +} + +/// Returns the file type of the given handle. +/// +/// If there was a problem querying the file type, then an error is returned. +/// +/// This corresponds to calling [`GetFileType`]. +/// +/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype +pub fn typ<H: AsHandleRef>(h: H) -> io::Result<Type> { + unsafe { + let rc = GetFileType(h.as_raw()); + if rc == 0 && GetLastError() != NO_ERROR { + return Err(io::Error::last_os_error()); + } + Ok(Type(rc)) + } +} + +/// Returns true if and only if the given file attributes contain the +/// `FILE_ATTRIBUTE_HIDDEN` attribute. +pub fn is_hidden(file_attributes: u64) -> bool { + file_attributes & (winnt::FILE_ATTRIBUTE_HIDDEN as u64) > 0 +} + +/// Represents file information such as creation time, file size, etc. +/// +/// This wraps a [`BY_HANDLE_FILE_INFORMATION`]. +/// +/// [`BY_HANDLE_FILE_INFORMATION`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information +#[derive(Clone)] +pub struct Information(BY_HANDLE_FILE_INFORMATION); + +impl Information { + /// Returns file attributes. + /// + /// This corresponds to `dwFileAttributes`. + pub fn file_attributes(&self) -> u64 { + self.0.dwFileAttributes as u64 + } + + /// Returns true if and only if this file information has the + /// `FILE_ATTRIBUTE_HIDDEN` attribute. + pub fn is_hidden(&self) -> bool { + is_hidden(self.file_attributes()) + } + + /// Return the creation time, if one exists. + /// + /// This corresponds to `ftCreationTime`. + pub fn creation_time(&self) -> Option<u64> { + filetime_to_u64(self.0.ftCreationTime) + } + + /// Return the last access time, if one exists. + /// + /// This corresponds to `ftLastAccessTime`. + pub fn last_access_time(&self) -> Option<u64> { + filetime_to_u64(self.0.ftLastAccessTime) + } + + /// Return the last write time, if one exists. + /// + /// This corresponds to `ftLastWriteTime`. + pub fn last_write_time(&self) -> Option<u64> { + filetime_to_u64(self.0.ftLastWriteTime) + } + + /// Return the serial number of the volume that the file is on. + /// + /// This corresponds to `dwVolumeSerialNumber`. + pub fn volume_serial_number(&self) -> u64 { + self.0.dwVolumeSerialNumber as u64 + } + + /// Return the file size, in bytes. + /// + /// This corresponds to `nFileSizeHigh` and `nFileSizeLow`. + pub fn file_size(&self) -> u64 { + ((self.0.nFileSizeHigh as u64) << 32) | (self.0.nFileSizeLow as u64) + } + + /// Return the number of links to this file. + /// + /// This corresponds to `nNumberOfLinks`. + pub fn number_of_links(&self) -> u64 { + self.0.nNumberOfLinks as u64 + } + + /// Return the index of this file. The index of a file is a purpotedly + /// unique identifier for a file within a particular volume. + pub fn file_index(&self) -> u64 { + ((self.0.nFileIndexHigh as u64) << 32) | (self.0.nFileIndexLow as u64) + } +} + +/// Represents a Windows file type. +/// +/// This wraps the result of [`GetFileType`]. +/// +/// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype +#[derive(Clone)] +pub struct Type(u32); + +impl Type { + /// Returns true if this type represents a character file, which is + /// typically an LPT device or a console. + pub fn is_char(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_CHAR + } + + /// Returns true if this type represents a disk file. + pub fn is_disk(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_DISK + } + + /// Returns true if this type represents a sock, named pipe or an + /// anonymous pipe. + pub fn is_pipe(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_PIPE + } + + /// Returns true if this type is not known. + /// + /// Note that this never corresponds to a failure. + pub fn is_unknown(&self) -> bool { + self.0 == ::winapi::um::winbase::FILE_TYPE_UNKNOWN + } +} + +fn filetime_to_u64(t: FILETIME) -> Option<u64> { + let v = ((t.dwHighDateTime as u64) << 32) | (t.dwLowDateTime as u64); + if v == 0 { + None + } else { + Some(v) + } +} |