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