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