Skip to main content

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