1 use std::io;
2 use std::mem;
3
4 use winapi::shared::minwindef::FILETIME;
5 use winapi::shared::winerror::NO_ERROR;
6 use winapi::um::errhandlingapi::GetLastError;
7 use winapi::um::fileapi::{
8 GetFileInformationByHandle, GetFileType, BY_HANDLE_FILE_INFORMATION,
9 };
10 use winapi::um::winnt;
11
12 use crate::AsHandleRef;
13
14 /// Return various pieces of information about a file.
15 ///
16 /// This includes information such as a file's size, unique identifier and
17 /// time related fields.
18 ///
19 /// This corresponds to calling [`GetFileInformationByHandle`].
20 ///
21 /// [`GetFileInformationByHandle`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileinformationbyhandle
information<H: AsHandleRef>(h: H) -> io::Result<Information>22 pub fn information<H: AsHandleRef>(h: H) -> io::Result<Information> {
23 unsafe {
24 let mut info: BY_HANDLE_FILE_INFORMATION = mem::zeroed();
25 let rc = GetFileInformationByHandle(h.as_raw(), &mut info);
26 if rc == 0 {
27 return Err(io::Error::last_os_error());
28 };
29 Ok(Information(info))
30 }
31 }
32
33 /// Returns the file type of the given handle.
34 ///
35 /// If there was a problem querying the file type, then an error is returned.
36 ///
37 /// This corresponds to calling [`GetFileType`].
38 ///
39 /// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype
typ<H: AsHandleRef>(h: H) -> io::Result<Type>40 pub fn typ<H: AsHandleRef>(h: H) -> io::Result<Type> {
41 unsafe {
42 let rc = GetFileType(h.as_raw());
43 if rc == 0 && GetLastError() != NO_ERROR {
44 return Err(io::Error::last_os_error());
45 }
46 Ok(Type(rc))
47 }
48 }
49
50 /// Returns true if and only if the given file attributes contain the
51 /// `FILE_ATTRIBUTE_HIDDEN` attribute.
is_hidden(file_attributes: u64) -> bool52 pub fn is_hidden(file_attributes: u64) -> bool {
53 file_attributes & (winnt::FILE_ATTRIBUTE_HIDDEN as u64) > 0
54 }
55
56 /// Represents file information such as creation time, file size, etc.
57 ///
58 /// This wraps a [`BY_HANDLE_FILE_INFORMATION`].
59 ///
60 /// [`BY_HANDLE_FILE_INFORMATION`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/ns-fileapi-_by_handle_file_information
61 #[derive(Clone)]
62 pub struct Information(BY_HANDLE_FILE_INFORMATION);
63
64 impl Information {
65 /// Returns file attributes.
66 ///
67 /// This corresponds to `dwFileAttributes`.
file_attributes(&self) -> u6468 pub fn file_attributes(&self) -> u64 {
69 self.0.dwFileAttributes as u64
70 }
71
72 /// Returns true if and only if this file information has the
73 /// `FILE_ATTRIBUTE_HIDDEN` attribute.
is_hidden(&self) -> bool74 pub fn is_hidden(&self) -> bool {
75 is_hidden(self.file_attributes())
76 }
77
78 /// Return the creation time, if one exists.
79 ///
80 /// This corresponds to `ftCreationTime`.
creation_time(&self) -> Option<u64>81 pub fn creation_time(&self) -> Option<u64> {
82 filetime_to_u64(self.0.ftCreationTime)
83 }
84
85 /// Return the last access time, if one exists.
86 ///
87 /// This corresponds to `ftLastAccessTime`.
last_access_time(&self) -> Option<u64>88 pub fn last_access_time(&self) -> Option<u64> {
89 filetime_to_u64(self.0.ftLastAccessTime)
90 }
91
92 /// Return the last write time, if one exists.
93 ///
94 /// This corresponds to `ftLastWriteTime`.
last_write_time(&self) -> Option<u64>95 pub fn last_write_time(&self) -> Option<u64> {
96 filetime_to_u64(self.0.ftLastWriteTime)
97 }
98
99 /// Return the serial number of the volume that the file is on.
100 ///
101 /// This corresponds to `dwVolumeSerialNumber`.
volume_serial_number(&self) -> u64102 pub fn volume_serial_number(&self) -> u64 {
103 self.0.dwVolumeSerialNumber as u64
104 }
105
106 /// Return the file size, in bytes.
107 ///
108 /// This corresponds to `nFileSizeHigh` and `nFileSizeLow`.
file_size(&self) -> u64109 pub fn file_size(&self) -> u64 {
110 ((self.0.nFileSizeHigh as u64) << 32) | (self.0.nFileSizeLow as u64)
111 }
112
113 /// Return the number of links to this file.
114 ///
115 /// This corresponds to `nNumberOfLinks`.
number_of_links(&self) -> u64116 pub fn number_of_links(&self) -> u64 {
117 self.0.nNumberOfLinks as u64
118 }
119
120 /// Return the index of this file. The index of a file is a purpotedly
121 /// unique identifier for a file within a particular volume.
file_index(&self) -> u64122 pub fn file_index(&self) -> u64 {
123 ((self.0.nFileIndexHigh as u64) << 32) | (self.0.nFileIndexLow as u64)
124 }
125 }
126
127 /// Represents a Windows file type.
128 ///
129 /// This wraps the result of [`GetFileType`].
130 ///
131 /// [`GetFileType`]: https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfiletype
132 #[derive(Clone)]
133 pub struct Type(u32);
134
135 impl Type {
136 /// Returns true if this type represents a character file, which is
137 /// typically an LPT device or a console.
is_char(&self) -> bool138 pub fn is_char(&self) -> bool {
139 self.0 == ::winapi::um::winbase::FILE_TYPE_CHAR
140 }
141
142 /// Returns true if this type represents a disk file.
is_disk(&self) -> bool143 pub fn is_disk(&self) -> bool {
144 self.0 == ::winapi::um::winbase::FILE_TYPE_DISK
145 }
146
147 /// Returns true if this type represents a sock, named pipe or an
148 /// anonymous pipe.
is_pipe(&self) -> bool149 pub fn is_pipe(&self) -> bool {
150 self.0 == ::winapi::um::winbase::FILE_TYPE_PIPE
151 }
152
153 /// Returns true if this type is not known.
154 ///
155 /// Note that this never corresponds to a failure.
is_unknown(&self) -> bool156 pub fn is_unknown(&self) -> bool {
157 self.0 == ::winapi::um::winbase::FILE_TYPE_UNKNOWN
158 }
159 }
160
filetime_to_u64(t: FILETIME) -> Option<u64>161 fn filetime_to_u64(t: FILETIME) -> Option<u64> {
162 let v = ((t.dwHighDateTime as u64) << 32) | (t.dwLowDateTime as u64);
163 if v == 0 {
164 None
165 } else {
166 Some(v)
167 }
168 }
169