Skip to main content

std/os/linux/
fs.rs

1//! Linux-specific extensions to primitives in the [`std::fs`] module.
2//!
3//! [`std::fs`]: crate::fs
4
5#![stable(feature = "metadata_ext", since = "1.1.0")]
6
7use crate::fs::Metadata;
8use crate::macros::rustdoc_skip_body;
9#[allow(deprecated)]
10use crate::os::linux::raw;
11use crate::sys::AsInner;
12
13/// OS-specific extensions to [`fs::Metadata`].
14///
15/// [`fs::Metadata`]: crate::fs::Metadata
16#[stable(feature = "metadata_ext", since = "1.1.0")]
17pub trait MetadataExt {
18    /// Gain a reference to the underlying `stat` structure which contains
19    /// the raw information returned by the OS.
20    ///
21    /// The contents of the returned [`stat`] are **not** consistent across
22    /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
23    /// cross-Unix abstractions contained within the raw stat.
24    ///
25    /// [`stat`]: struct@crate::os::linux::raw::stat
26    ///
27    /// # Examples
28    ///
29    #[cfg_attr(target_os = "linux", doc = "```no_run")]
30    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
31    /// use std::fs;
32    /// use std::io;
33    /// use std::os::linux::fs::MetadataExt;
34    ///
35    /// fn main() -> io::Result<()> {
36    ///     let meta = fs::metadata("some_file")?;
37    ///     let stat = meta.as_raw_stat();
38    ///     Ok(())
39    /// }
40    /// ```
41    #[stable(feature = "metadata_ext", since = "1.1.0")]
42    #[deprecated(since = "1.8.0", note = "other methods of this trait are now preferred")]
43    #[allow(deprecated)]
44    fn as_raw_stat(&self) -> &raw::stat;
45
46    /// Returns the device ID on which this file resides.
47    ///
48    /// # Examples
49    ///
50    #[cfg_attr(target_os = "linux", doc = "```no_run")]
51    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
52    /// use std::fs;
53    /// use std::io;
54    /// use std::os::linux::fs::MetadataExt;
55    ///
56    /// fn main() -> io::Result<()> {
57    ///     let meta = fs::metadata("some_file")?;
58    ///     println!("{}", meta.st_dev());
59    ///     Ok(())
60    /// }
61    /// ```
62    #[stable(feature = "metadata_ext2", since = "1.8.0")]
63    fn st_dev(&self) -> u64;
64    /// Returns the inode number.
65    ///
66    /// # Examples
67    ///
68    #[cfg_attr(target_os = "linux", doc = "```no_run")]
69    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
70    /// use std::fs;
71    /// use std::io;
72    /// use std::os::linux::fs::MetadataExt;
73    ///
74    /// fn main() -> io::Result<()> {
75    ///     let meta = fs::metadata("some_file")?;
76    ///     println!("{}", meta.st_ino());
77    ///     Ok(())
78    /// }
79    /// ```
80    #[stable(feature = "metadata_ext2", since = "1.8.0")]
81    fn st_ino(&self) -> u64;
82    /// Returns the file type and mode.
83    ///
84    /// # Examples
85    ///
86    #[cfg_attr(target_os = "linux", doc = "```no_run")]
87    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
88    /// use std::fs;
89    /// use std::io;
90    /// use std::os::linux::fs::MetadataExt;
91    ///
92    /// fn main() -> io::Result<()> {
93    ///     let meta = fs::metadata("some_file")?;
94    ///     println!("{}", meta.st_mode());
95    ///     Ok(())
96    /// }
97    /// ```
98    #[stable(feature = "metadata_ext2", since = "1.8.0")]
99    fn st_mode(&self) -> u32;
100    /// Returns the number of hard links to file.
101    ///
102    /// # Examples
103    ///
104    #[cfg_attr(target_os = "linux", doc = "```no_run")]
105    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
106    /// use std::fs;
107    /// use std::io;
108    /// use std::os::linux::fs::MetadataExt;
109    ///
110    /// fn main() -> io::Result<()> {
111    ///     let meta = fs::metadata("some_file")?;
112    ///     println!("{}", meta.st_nlink());
113    ///     Ok(())
114    /// }
115    /// ```
116    #[stable(feature = "metadata_ext2", since = "1.8.0")]
117    fn st_nlink(&self) -> u64;
118    /// Returns the user ID of the file owner.
119    ///
120    /// # Examples
121    ///
122    #[cfg_attr(target_os = "linux", doc = "```no_run")]
123    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
124    /// use std::fs;
125    /// use std::io;
126    /// use std::os::linux::fs::MetadataExt;
127    ///
128    /// fn main() -> io::Result<()> {
129    ///     let meta = fs::metadata("some_file")?;
130    ///     println!("{}", meta.st_uid());
131    ///     Ok(())
132    /// }
133    /// ```
134    #[stable(feature = "metadata_ext2", since = "1.8.0")]
135    fn st_uid(&self) -> u32;
136    /// Returns the group ID of the file owner.
137    ///
138    /// # Examples
139    ///
140    #[cfg_attr(target_os = "linux", doc = "```no_run")]
141    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
142    /// use std::fs;
143    /// use std::io;
144    /// use std::os::linux::fs::MetadataExt;
145    ///
146    /// fn main() -> io::Result<()> {
147    ///     let meta = fs::metadata("some_file")?;
148    ///     println!("{}", meta.st_gid());
149    ///     Ok(())
150    /// }
151    /// ```
152    #[stable(feature = "metadata_ext2", since = "1.8.0")]
153    fn st_gid(&self) -> u32;
154    /// Returns the device ID that this file represents. Only relevant for special file.
155    ///
156    /// # Examples
157    ///
158    #[cfg_attr(target_os = "linux", doc = "```no_run")]
159    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
160    /// use std::fs;
161    /// use std::io;
162    /// use std::os::linux::fs::MetadataExt;
163    ///
164    /// fn main() -> io::Result<()> {
165    ///     let meta = fs::metadata("some_file")?;
166    ///     println!("{}", meta.st_rdev());
167    ///     Ok(())
168    /// }
169    /// ```
170    #[stable(feature = "metadata_ext2", since = "1.8.0")]
171    fn st_rdev(&self) -> u64;
172    /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
173    ///
174    /// The size of a symbolic link is the length of the pathname it contains,
175    /// without a terminating null byte.
176    ///
177    /// # Examples
178    ///
179    #[cfg_attr(target_os = "linux", doc = "```no_run")]
180    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
181    /// use std::fs;
182    /// use std::io;
183    /// use std::os::linux::fs::MetadataExt;
184    ///
185    /// fn main() -> io::Result<()> {
186    ///     let meta = fs::metadata("some_file")?;
187    ///     println!("{}", meta.st_size());
188    ///     Ok(())
189    /// }
190    /// ```
191    #[stable(feature = "metadata_ext2", since = "1.8.0")]
192    fn st_size(&self) -> u64;
193    /// Returns the last access time of the file, in seconds since Unix Epoch.
194    ///
195    /// # Examples
196    ///
197    #[cfg_attr(target_os = "linux", doc = "```no_run")]
198    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
199    /// use std::fs;
200    /// use std::io;
201    /// use std::os::linux::fs::MetadataExt;
202    ///
203    /// fn main() -> io::Result<()> {
204    ///     let meta = fs::metadata("some_file")?;
205    ///     println!("{}", meta.st_atime());
206    ///     Ok(())
207    /// }
208    /// ```
209    #[stable(feature = "metadata_ext2", since = "1.8.0")]
210    fn st_atime(&self) -> i64;
211    /// Returns the last access time of the file, in nanoseconds since [`st_atime`].
212    ///
213    /// [`st_atime`]: Self::st_atime
214    ///
215    /// # Examples
216    ///
217    #[cfg_attr(target_os = "linux", doc = "```no_run")]
218    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
219    /// use std::fs;
220    /// use std::io;
221    /// use std::os::linux::fs::MetadataExt;
222    ///
223    /// fn main() -> io::Result<()> {
224    ///     let meta = fs::metadata("some_file")?;
225    ///     println!("{}", meta.st_atime_nsec());
226    ///     Ok(())
227    /// }
228    /// ```
229    #[stable(feature = "metadata_ext2", since = "1.8.0")]
230    fn st_atime_nsec(&self) -> i64;
231    /// Returns the last modification time of the file, in seconds since Unix Epoch.
232    ///
233    /// # Examples
234    ///
235    #[cfg_attr(target_os = "linux", doc = "```no_run")]
236    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
237    /// use std::fs;
238    /// use std::io;
239    /// use std::os::linux::fs::MetadataExt;
240    ///
241    /// fn main() -> io::Result<()> {
242    ///     let meta = fs::metadata("some_file")?;
243    ///     println!("{}", meta.st_mtime());
244    ///     Ok(())
245    /// }
246    /// ```
247    #[stable(feature = "metadata_ext2", since = "1.8.0")]
248    fn st_mtime(&self) -> i64;
249    /// Returns the last modification time of the file, in nanoseconds since [`st_mtime`].
250    ///
251    /// [`st_mtime`]: Self::st_mtime
252    ///
253    /// # Examples
254    ///
255    #[cfg_attr(target_os = "linux", doc = "```no_run")]
256    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
257    /// use std::fs;
258    /// use std::io;
259    /// use std::os::linux::fs::MetadataExt;
260    ///
261    /// fn main() -> io::Result<()> {
262    ///     let meta = fs::metadata("some_file")?;
263    ///     println!("{}", meta.st_mtime_nsec());
264    ///     Ok(())
265    /// }
266    /// ```
267    #[stable(feature = "metadata_ext2", since = "1.8.0")]
268    fn st_mtime_nsec(&self) -> i64;
269    /// Returns the last status change time of the file, in seconds since Unix Epoch.
270    ///
271    /// # Examples
272    ///
273    #[cfg_attr(target_os = "linux", doc = "```no_run")]
274    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
275    /// use std::fs;
276    /// use std::io;
277    /// use std::os::linux::fs::MetadataExt;
278    ///
279    /// fn main() -> io::Result<()> {
280    ///     let meta = fs::metadata("some_file")?;
281    ///     println!("{}", meta.st_ctime());
282    ///     Ok(())
283    /// }
284    /// ```
285    #[stable(feature = "metadata_ext2", since = "1.8.0")]
286    fn st_ctime(&self) -> i64;
287    /// Returns the last status change time of the file, in nanoseconds since [`st_ctime`].
288    ///
289    /// [`st_ctime`]: Self::st_ctime
290    ///
291    /// # Examples
292    ///
293    #[cfg_attr(target_os = "linux", doc = "```no_run")]
294    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
295    /// use std::fs;
296    /// use std::io;
297    /// use std::os::linux::fs::MetadataExt;
298    ///
299    /// fn main() -> io::Result<()> {
300    ///     let meta = fs::metadata("some_file")?;
301    ///     println!("{}", meta.st_ctime_nsec());
302    ///     Ok(())
303    /// }
304    /// ```
305    #[stable(feature = "metadata_ext2", since = "1.8.0")]
306    fn st_ctime_nsec(&self) -> i64;
307    /// Returns the "preferred" block size for efficient filesystem I/O.
308    ///
309    /// # Examples
310    ///
311    #[cfg_attr(target_os = "linux", doc = "```no_run")]
312    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
313    /// use std::fs;
314    /// use std::io;
315    /// use std::os::linux::fs::MetadataExt;
316    ///
317    /// fn main() -> io::Result<()> {
318    ///     let meta = fs::metadata("some_file")?;
319    ///     println!("{}", meta.st_blksize());
320    ///     Ok(())
321    /// }
322    /// ```
323    #[stable(feature = "metadata_ext2", since = "1.8.0")]
324    fn st_blksize(&self) -> u64;
325    /// Returns the number of blocks allocated to the file, 512-byte units.
326    ///
327    /// # Examples
328    ///
329    #[cfg_attr(target_os = "linux", doc = "```no_run")]
330    #[cfg_attr(not(target_os = "linux"), doc = "```ignore (needs linux)")]
331    /// use std::fs;
332    /// use std::io;
333    /// use std::os::linux::fs::MetadataExt;
334    ///
335    /// fn main() -> io::Result<()> {
336    ///     let meta = fs::metadata("some_file")?;
337    ///     println!("{}", meta.st_blocks());
338    ///     Ok(())
339    /// }
340    /// ```
341    #[stable(feature = "metadata_ext2", since = "1.8.0")]
342    fn st_blocks(&self) -> u64;
343}
344
345#[stable(feature = "metadata_ext", since = "1.1.0")]
346impl MetadataExt for Metadata {
347    #[allow(deprecated)]
348    #[rustdoc_skip_body]
349    fn as_raw_stat(&self) -> &raw::stat {
350        #[cfg(target_env = "musl")]
351        unsafe {
352            &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat)
353        }
354        #[cfg(not(target_env = "musl"))]
355        unsafe {
356            &*(self.as_inner().as_inner() as *const libc::stat64 as *const raw::stat)
357        }
358    }
359    #[rustdoc_skip_body]
360    fn st_dev(&self) -> u64 {
361        self.as_inner().as_inner().st_dev as u64
362    }
363    #[rustdoc_skip_body]
364    fn st_ino(&self) -> u64 {
365        self.as_inner().as_inner().st_ino as u64
366    }
367    #[rustdoc_skip_body]
368    fn st_mode(&self) -> u32 {
369        self.as_inner().as_inner().st_mode as u32
370    }
371    #[rustdoc_skip_body]
372    fn st_nlink(&self) -> u64 {
373        self.as_inner().as_inner().st_nlink as u64
374    }
375    #[rustdoc_skip_body]
376    fn st_uid(&self) -> u32 {
377        self.as_inner().as_inner().st_uid as u32
378    }
379    #[rustdoc_skip_body]
380    fn st_gid(&self) -> u32 {
381        self.as_inner().as_inner().st_gid as u32
382    }
383    #[rustdoc_skip_body]
384    fn st_rdev(&self) -> u64 {
385        self.as_inner().as_inner().st_rdev as u64
386    }
387    #[rustdoc_skip_body]
388    fn st_size(&self) -> u64 {
389        self.as_inner().as_inner().st_size as u64
390    }
391    #[rustdoc_skip_body]
392    fn st_atime(&self) -> i64 {
393        let file_attr = self.as_inner();
394        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
395        if let Some(atime) = file_attr.stx_atime() {
396            return atime.tv_sec;
397        }
398        file_attr.as_inner().st_atime as i64
399    }
400    #[rustdoc_skip_body]
401    fn st_atime_nsec(&self) -> i64 {
402        self.as_inner().as_inner().st_atime_nsec as i64
403    }
404    #[rustdoc_skip_body]
405    fn st_mtime(&self) -> i64 {
406        let file_attr = self.as_inner();
407        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
408        if let Some(mtime) = file_attr.stx_mtime() {
409            return mtime.tv_sec;
410        }
411        file_attr.as_inner().st_mtime as i64
412    }
413    #[rustdoc_skip_body]
414    fn st_mtime_nsec(&self) -> i64 {
415        self.as_inner().as_inner().st_mtime_nsec as i64
416    }
417    #[rustdoc_skip_body]
418    fn st_ctime(&self) -> i64 {
419        let file_attr = self.as_inner();
420        #[cfg(all(target_env = "gnu", target_pointer_width = "32"))]
421        if let Some(ctime) = file_attr.stx_ctime() {
422            return ctime.tv_sec;
423        }
424        file_attr.as_inner().st_ctime as i64
425    }
426    #[rustdoc_skip_body]
427    fn st_ctime_nsec(&self) -> i64 {
428        self.as_inner().as_inner().st_ctime_nsec as i64
429    }
430    #[rustdoc_skip_body]
431    fn st_blksize(&self) -> u64 {
432        self.as_inner().as_inner().st_blksize as u64
433    }
434    #[rustdoc_skip_body]
435    fn st_blocks(&self) -> u64 {
436        self.as_inner().as_inner().st_blocks as u64
437    }
438}