summaryrefslogtreecommitdiffstats
path: root/third_party/rust/winapi-util/src/file.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/winapi-util/src/file.rs')
-rw-r--r--third_party/rust/winapi-util/src/file.rs168
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)
+ }
+}