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