compio_fs\metadata/
mod.rs

1#[cfg(unix)]
2#[path = "unix.rs"]
3mod sys;
4
5#[cfg(windows)]
6#[path = "windows.rs"]
7mod sys;
8
9#[cfg(windows)]
10use std::os::windows::fs::{FileTypeExt, MetadataExt};
11use std::{io, path::Path, time::SystemTime};
12
13#[cfg(unix)]
14use compio_driver::op::Stat;
15
16/// Given a path, query the file system to get information about a file,
17/// directory, etc.
18pub async fn metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
19    sys::metadata(path).await.map(Metadata)
20}
21
22/// Query the metadata about a file without following symlinks.
23pub async fn symlink_metadata(path: impl AsRef<Path>) -> io::Result<Metadata> {
24    sys::symlink_metadata(path).await.map(Metadata)
25}
26
27/// Changes the permissions found on a file or a directory.
28pub async fn set_permissions(path: impl AsRef<Path>, perm: Permissions) -> io::Result<()> {
29    sys::set_permissions(path, perm.0).await
30}
31
32/// Metadata information about a file.
33#[derive(Clone)]
34pub struct Metadata(sys::Metadata);
35
36impl Metadata {
37    /// Returns the file type for this metadata.
38    pub fn file_type(&self) -> FileType {
39        FileType(self.0.file_type())
40    }
41
42    /// Returns `true` if this metadata is for a directory.
43    pub fn is_dir(&self) -> bool {
44        self.0.is_dir()
45    }
46
47    /// Returns `true` if this metadata is for a regular file.
48    pub fn is_file(&self) -> bool {
49        self.0.is_file()
50    }
51
52    /// Returns `true` if this metadata is for a symbolic link.
53    pub fn is_symlink(&self) -> bool {
54        self.0.is_symlink()
55    }
56
57    /// Returns the size of the file, in bytes, this metadata is for.
58    #[allow(clippy::len_without_is_empty)]
59    pub fn len(&self) -> u64 {
60        self.0.len()
61    }
62
63    /// Returns the permissions of the file this metadata is for.
64    pub fn permissions(&self) -> Permissions {
65        Permissions(self.0.permissions())
66    }
67
68    /// Returns the last modification time listed in this metadata.
69    ///
70    /// ## Platform specific
71    /// * Windows: The returned value corresponds to the `ftLastWriteTime`
72    ///   field.
73    /// * Unix: The returned value corresponds to the `mtime` field.
74    pub fn modified(&self) -> io::Result<SystemTime> {
75        self.0.modified()
76    }
77
78    /// Returns the last access time of this metadata.
79    ///
80    /// ## Platform specific
81    /// * Windows: The returned value corresponds to the `ftLastAccessTime`
82    ///   field.
83    /// * Unix: The returned value corresponds to the `atime` field.
84    pub fn accessed(&self) -> io::Result<SystemTime> {
85        self.0.accessed()
86    }
87
88    /// Returns the creation time listed in this metadata.
89    ///
90    /// ## Platform specific
91    /// * Windows: The returned value corresponds to the `ftCreationTime` field.
92    /// * Unix: The returned value corresponds to `st_ctime` or `st_birthtime`
93    ///   of
94    #[cfg_attr(all(unix, not(gnulinux)), doc = "[`libc::stat`](struct@libc::stat).")]
95    #[cfg_attr(gnulinux, doc = "[`libc::stat64`](struct@libc::stat64).")]
96    #[cfg_attr(
97        windows,
98        doc = "[`libc::stat`](https://docs.rs/libc/latest/libc/struct.stat.html)."
99    )]
100    pub fn created(&self) -> io::Result<SystemTime> {
101        self.0.created()
102    }
103}
104
105// The below methods are Windows specific. We cannot impl `MetadataExt` because
106// it is going to be sealed.
107#[cfg(windows)]
108impl Metadata {
109    /// Create [`Metadata`] from [`std::fs::Metadata`].
110    pub fn from_std(m: std::fs::Metadata) -> Self {
111        Self(m)
112    }
113
114    /// Returns the value of the `dwFileAttributes` field of this metadata.
115    pub fn file_attributes(&self) -> u32 {
116        self.0.file_attributes()
117    }
118
119    /// Returns the value of the `ftCreationTime` field of this metadata.
120    pub fn creation_time(&self) -> u64 {
121        self.0.creation_time()
122    }
123
124    /// Returns the value of the `ftLastAccessTime` field of this metadata.
125    pub fn last_access_time(&self) -> u64 {
126        self.0.last_access_time()
127    }
128
129    /// Returns the value of the `ftLastWriteTime` field of this metadata.
130    pub fn last_write_time(&self) -> u64 {
131        self.0.last_write_time()
132    }
133}
134
135#[cfg(all(windows, feature = "windows_by_handle"))]
136impl Metadata {
137    /// Returns the value of the `dwVolumeSerialNumber` field of this
138    /// metadata.
139    pub fn volume_serial_number(&self) -> Option<u32> {
140        self.0.volume_serial_number()
141    }
142
143    /// Returns the value of the `nNumberOfLinks` field of this
144    /// metadata.
145    pub fn number_of_links(&self) -> Option<u32> {
146        self.0.number_of_links()
147    }
148
149    /// Returns the value of the `nFileIndex{Low,High}` fields of this
150    /// metadata.
151    pub fn file_index(&self) -> Option<u64> {
152        self.0.file_index()
153    }
154}
155
156#[cfg(unix)]
157impl Metadata {
158    /// Create from
159    #[cfg_attr(not(gnulinux), doc = "[`libc::stat`](struct@libc::stat).")]
160    #[cfg_attr(gnulinux, doc = "[`libc::stat64`](struct@libc::stat64).")]
161    pub fn from_stat(stat: Stat) -> Self {
162        Self(sys::Metadata::from_stat(stat))
163    }
164}
165
166#[cfg(unix)]
167impl std::os::unix::prelude::MetadataExt for Metadata {
168    fn dev(&self) -> u64 {
169        self.0.dev()
170    }
171
172    fn ino(&self) -> u64 {
173        self.0.ino()
174    }
175
176    fn mode(&self) -> u32 {
177        self.0.mode()
178    }
179
180    fn nlink(&self) -> u64 {
181        self.0.nlink()
182    }
183
184    fn uid(&self) -> u32 {
185        self.0.uid()
186    }
187
188    fn gid(&self) -> u32 {
189        self.0.gid()
190    }
191
192    fn rdev(&self) -> u64 {
193        self.0.rdev()
194    }
195
196    fn size(&self) -> u64 {
197        self.0.size()
198    }
199
200    fn atime(&self) -> i64 {
201        self.0.atime()
202    }
203
204    fn atime_nsec(&self) -> i64 {
205        self.0.atime_nsec()
206    }
207
208    fn mtime(&self) -> i64 {
209        self.0.mtime()
210    }
211
212    fn mtime_nsec(&self) -> i64 {
213        self.0.mtime_nsec()
214    }
215
216    fn ctime(&self) -> i64 {
217        self.0.ctime()
218    }
219
220    fn ctime_nsec(&self) -> i64 {
221        self.0.ctime_nsec()
222    }
223
224    fn blksize(&self) -> u64 {
225        self.0.blksize()
226    }
227
228    fn blocks(&self) -> u64 {
229        self.0.blocks()
230    }
231}
232
233/// A structure representing a type of file with accessors for each file type.
234#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
235pub struct FileType(sys::FileType);
236
237impl FileType {
238    /// Tests whether this file type represents a directory.
239    pub fn is_dir(&self) -> bool {
240        self.0.is_dir()
241    }
242
243    /// Tests whether this file type represents a regular file.
244    pub fn is_file(&self) -> bool {
245        self.0.is_file()
246    }
247
248    /// Tests whether this file type represents a symbolic link.
249    pub fn is_symlink(&self) -> bool {
250        self.0.is_symlink()
251    }
252}
253
254// The below methods are Windows specific. We cannot impl `FileTypeExt` because
255// it is sealed.
256
257#[cfg(windows)]
258impl FileType {
259    /// Returns `true` if this file type is a symbolic link that is also a
260    /// directory.
261    pub fn is_symlink_dir(&self) -> bool {
262        self.0.is_symlink_dir()
263    }
264
265    /// Returns `true` if this file type is a symbolic link that is also a file.
266    pub fn is_symlink_file(&self) -> bool {
267        self.0.is_symlink_file()
268    }
269}
270
271#[cfg(unix)]
272impl std::os::unix::prelude::FileTypeExt for FileType {
273    fn is_block_device(&self) -> bool {
274        self.0.is_block_device()
275    }
276
277    fn is_char_device(&self) -> bool {
278        self.0.is_char_device()
279    }
280
281    fn is_fifo(&self) -> bool {
282        self.0.is_fifo()
283    }
284
285    fn is_socket(&self) -> bool {
286        self.0.is_socket()
287    }
288}
289
290/// Representation of the various permissions on a file.
291#[derive(Clone, PartialEq, Eq, Debug)]
292pub struct Permissions(pub(crate) sys::Permissions);
293
294impl Permissions {
295    /// Returns `true` if these permissions describe a readonly (unwritable)
296    /// file.
297    pub fn readonly(&self) -> bool {
298        self.0.readonly()
299    }
300
301    /// Modifies the readonly flag for this set of permissions.
302    ///
303    /// This operation does **not** modify the files attributes.
304    pub fn set_readonly(&mut self, readonly: bool) {
305        self.0.set_readonly(readonly)
306    }
307}
308
309#[cfg(unix)]
310impl std::os::unix::prelude::PermissionsExt for Permissions {
311    fn mode(&self) -> u32 {
312        self.0.mode()
313    }
314
315    fn set_mode(&mut self, mode: u32) {
316        self.0.set_mode(mode)
317    }
318
319    fn from_mode(mode: u32) -> Self {
320        Self(sys::Permissions::from_mode(mode))
321    }
322}