]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/unix/ext/fs.rs
732cd677a18594f495f651c13f6b5ec7688ab476
[rust.git] / src / libstd / sys / unix / ext / fs.rs
1 //! Unix-specific extensions to primitives in the `std::fs` module.
2
3 #![stable(feature = "rust1", since = "1.0.0")]
4
5 use crate::fs::{self, OpenOptions, Permissions};
6 use crate::io;
7 use crate::path::Path;
8 use crate::sys;
9 use crate::sys::platform::fs::MetadataExt as UnixMetadataExt;
10 use crate::sys_common::{AsInner, AsInnerMut, FromInner};
11
12 /// Unix-specific extensions to [`File`].
13 ///
14 /// [`File`]: ../../../../std/fs/struct.File.html
15 #[stable(feature = "file_offset", since = "1.15.0")]
16 pub trait FileExt {
17     /// Reads a number of bytes starting from a given offset.
18     ///
19     /// Returns the number of bytes read.
20     ///
21     /// The offset is relative to the start of the file and thus independent
22     /// from the current cursor.
23     ///
24     /// The current file cursor is not affected by this function.
25     ///
26     /// Note that similar to [`File::read`], it is not an error to return with a
27     /// short read.
28     ///
29     /// [`File::read`]: ../../../../std/fs/struct.File.html#method.read
30     ///
31     /// # Examples
32     ///
33     /// ```no_run
34     /// use std::io;
35     /// use std::fs::File;
36     /// use std::os::unix::prelude::FileExt;
37     ///
38     /// fn main() -> io::Result<()> {
39     ///     let mut buf = [0u8; 8];
40     ///     let file = File::open("foo.txt")?;
41     ///
42     ///     // We now read 8 bytes from the offset 10.
43     ///     let num_bytes_read = file.read_at(&mut buf, 10)?;
44     ///     println!("read {} bytes: {:?}", num_bytes_read, buf);
45     ///     Ok(())
46     /// }
47     /// ```
48     #[stable(feature = "file_offset", since = "1.15.0")]
49     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize>;
50
51     /// Reads the exact number of byte required to fill `buf` from the given offset.
52     ///
53     /// The offset is relative to the start of the file and thus independent
54     /// from the current cursor.
55     ///
56     /// The current file cursor is not affected by this function.
57     ///
58     /// Similar to [`Read::read_exact`] but uses [`read_at`] instead of `read`.
59     ///
60     /// [`Read::read_exact`]: ../../../../std/io/trait.Read.html#method.read_exact
61     /// [`read_at`]: #tymethod.read_at
62     ///
63     /// # Errors
64     ///
65     /// If this function encounters an error of the kind
66     /// [`ErrorKind::Interrupted`] then the error is ignored and the operation
67     /// will continue.
68     ///
69     /// If this function encounters an "end of file" before completely filling
70     /// the buffer, it returns an error of the kind [`ErrorKind::UnexpectedEof`].
71     /// The contents of `buf` are unspecified in this case.
72     ///
73     /// If any other read error is encountered then this function immediately
74     /// returns. The contents of `buf` are unspecified in this case.
75     ///
76     /// If this function returns an error, it is unspecified how many bytes it
77     /// has read, but it will never read more than would be necessary to
78     /// completely fill the buffer.
79     ///
80     /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
81     /// [`ErrorKind::UnexpectedEof`]: ../../../../std/io/enum.ErrorKind.html#variant.UnexpectedEof
82     ///
83     /// # Examples
84     ///
85     /// ```no_run
86     /// use std::io;
87     /// use std::fs::File;
88     /// use std::os::unix::prelude::FileExt;
89     ///
90     /// fn main() -> io::Result<()> {
91     ///     let mut buf = [0u8; 8];
92     ///     let file = File::open("foo.txt")?;
93     ///
94     ///     // We now read exactly 8 bytes from the offset 10.
95     ///     file.read_exact_at(&mut buf, 10)?;
96     ///     println!("read {} bytes: {:?}", buf.len(), buf);
97     ///     Ok(())
98     /// }
99     /// ```
100     #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
101     fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> {
102         while !buf.is_empty() {
103             match self.read_at(buf, offset) {
104                 Ok(0) => break,
105                 Ok(n) => {
106                     let tmp = buf;
107                     buf = &mut tmp[n..];
108                     offset += n as u64;
109                 }
110                 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
111                 Err(e) => return Err(e),
112             }
113         }
114         if !buf.is_empty() {
115             Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
116         } else {
117             Ok(())
118         }
119     }
120
121     /// Writes a number of bytes starting from a given offset.
122     ///
123     /// Returns the number of bytes written.
124     ///
125     /// The offset is relative to the start of the file and thus independent
126     /// from the current cursor.
127     ///
128     /// The current file cursor is not affected by this function.
129     ///
130     /// When writing beyond the end of the file, the file is appropriately
131     /// extended and the intermediate bytes are initialized with the value 0.
132     ///
133     /// Note that similar to [`File::write`], it is not an error to return a
134     /// short write.
135     ///
136     /// [`File::write`]: ../../../../std/fs/struct.File.html#write.v
137     ///
138     /// # Examples
139     ///
140     /// ```no_run
141     /// use std::fs::File;
142     /// use std::io;
143     /// use std::os::unix::prelude::FileExt;
144     ///
145     /// fn main() -> io::Result<()> {
146     ///     let file = File::open("foo.txt")?;
147     ///
148     ///     // We now write at the offset 10.
149     ///     file.write_at(b"sushi", 10)?;
150     ///     Ok(())
151     /// }
152     /// ```
153     #[stable(feature = "file_offset", since = "1.15.0")]
154     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize>;
155
156     /// Attempts to write an entire buffer starting from a given offset.
157     ///
158     /// The offset is relative to the start of the file and thus independent
159     /// from the current cursor.
160     ///
161     /// The current file cursor is not affected by this function.
162     ///
163     /// This method will continuously call [`write_at`] until there is no more data
164     /// to be written or an error of non-[`ErrorKind::Interrupted`] kind is
165     /// returned. This method will not return until the entire buffer has been
166     /// successfully written or such an error occurs. The first error that is
167     /// not of [`ErrorKind::Interrupted`] kind generated from this method will be
168     /// returned.
169     ///
170     /// # Errors
171     ///
172     /// This function will return the first error of
173     /// non-[`ErrorKind::Interrupted`] kind that [`write_at`] returns.
174     ///
175     /// [`ErrorKind::Interrupted`]: ../../../../std/io/enum.ErrorKind.html#variant.Interrupted
176     /// [`write_at`]: #tymethod.write_at
177     ///
178     /// # Examples
179     ///
180     /// ```no_run
181     /// use std::fs::File;
182     /// use std::io;
183     /// use std::os::unix::prelude::FileExt;
184     ///
185     /// fn main() -> io::Result<()> {
186     ///     let file = File::open("foo.txt")?;
187     ///
188     ///     // We now write at the offset 10.
189     ///     file.write_all_at(b"sushi", 10)?;
190     ///     Ok(())
191     /// }
192     /// ```
193     #[stable(feature = "rw_exact_all_at", since = "1.33.0")]
194     fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> {
195         while !buf.is_empty() {
196             match self.write_at(buf, offset) {
197                 Ok(0) => {
198                     return Err(io::Error::new(
199                         io::ErrorKind::WriteZero,
200                         "failed to write whole buffer",
201                     ));
202                 }
203                 Ok(n) => {
204                     buf = &buf[n..];
205                     offset += n as u64
206                 }
207                 Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
208                 Err(e) => return Err(e),
209             }
210         }
211         Ok(())
212     }
213 }
214
215 #[stable(feature = "file_offset", since = "1.15.0")]
216 impl FileExt for fs::File {
217     fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
218         self.as_inner().read_at(buf, offset)
219     }
220     fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
221         self.as_inner().write_at(buf, offset)
222     }
223 }
224
225 /// Unix-specific extensions to [`fs::Permissions`].
226 ///
227 /// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html
228 #[stable(feature = "fs_ext", since = "1.1.0")]
229 pub trait PermissionsExt {
230     /// Returns the underlying raw `st_mode` bits that contain the standard
231     /// Unix permissions for this file.
232     ///
233     /// # Examples
234     ///
235     /// ```no_run
236     /// use std::fs::File;
237     /// use std::os::unix::fs::PermissionsExt;
238     ///
239     /// fn main() -> std::io::Result<()> {
240     ///     let f = File::create("foo.txt")?;
241     ///     let metadata = f.metadata()?;
242     ///     let permissions = metadata.permissions();
243     ///
244     ///     println!("permissions: {:o}", permissions.mode());
245     ///     Ok(()) }
246     /// ```
247     #[stable(feature = "fs_ext", since = "1.1.0")]
248     fn mode(&self) -> u32;
249
250     /// Sets the underlying raw bits for this set of permissions.
251     ///
252     /// # Examples
253     ///
254     /// ```no_run
255     /// use std::fs::File;
256     /// use std::os::unix::fs::PermissionsExt;
257     ///
258     /// fn main() -> std::io::Result<()> {
259     ///     let f = File::create("foo.txt")?;
260     ///     let metadata = f.metadata()?;
261     ///     let mut permissions = metadata.permissions();
262     ///
263     ///     permissions.set_mode(0o644); // Read/write for owner and read for others.
264     ///     assert_eq!(permissions.mode(), 0o644);
265     ///     Ok(()) }
266     /// ```
267     #[stable(feature = "fs_ext", since = "1.1.0")]
268     fn set_mode(&mut self, mode: u32);
269
270     /// Creates a new instance of `Permissions` from the given set of Unix
271     /// permission bits.
272     ///
273     /// # Examples
274     ///
275     /// ```
276     /// use std::fs::Permissions;
277     /// use std::os::unix::fs::PermissionsExt;
278     ///
279     /// // Read/write for owner and read for others.
280     /// let permissions = Permissions::from_mode(0o644);
281     /// assert_eq!(permissions.mode(), 0o644);
282     /// ```
283     #[stable(feature = "fs_ext", since = "1.1.0")]
284     fn from_mode(mode: u32) -> Self;
285 }
286
287 #[stable(feature = "fs_ext", since = "1.1.0")]
288 impl PermissionsExt for Permissions {
289     fn mode(&self) -> u32 {
290         self.as_inner().mode()
291     }
292
293     fn set_mode(&mut self, mode: u32) {
294         *self = Permissions::from_inner(FromInner::from_inner(mode));
295     }
296
297     fn from_mode(mode: u32) -> Permissions {
298         Permissions::from_inner(FromInner::from_inner(mode))
299     }
300 }
301
302 /// Unix-specific extensions to [`fs::OpenOptions`].
303 ///
304 /// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
305 #[stable(feature = "fs_ext", since = "1.1.0")]
306 pub trait OpenOptionsExt {
307     /// Sets the mode bits that a new file will be created with.
308     ///
309     /// If a new file is created as part of an `OpenOptions::open` call then this
310     /// specified `mode` will be used as the permission bits for the new file.
311     /// If no `mode` is set, the default of `0o666` will be used.
312     /// The operating system masks out bits with the system's `umask`, to produce
313     /// the final permissions.
314     ///
315     /// # Examples
316     ///
317     /// ```no_run
318     /// use std::fs::OpenOptions;
319     /// use std::os::unix::fs::OpenOptionsExt;
320     ///
321     /// # fn main() {
322     /// let mut options = OpenOptions::new();
323     /// options.mode(0o644); // Give read/write for owner and read for others.
324     /// let file = options.open("foo.txt");
325     /// # }
326     /// ```
327     #[stable(feature = "fs_ext", since = "1.1.0")]
328     fn mode(&mut self, mode: u32) -> &mut Self;
329
330     /// Pass custom flags to the `flags` argument of `open`.
331     ///
332     /// The bits that define the access mode are masked out with `O_ACCMODE`, to
333     /// ensure they do not interfere with the access mode set by Rusts options.
334     ///
335     /// Custom flags can only set flags, not remove flags set by Rusts options.
336     /// This options overwrites any previously set custom flags.
337     ///
338     /// # Examples
339     ///
340     /// ```no_run
341     /// # #![feature(rustc_private)]
342     /// extern crate libc;
343     /// use std::fs::OpenOptions;
344     /// use std::os::unix::fs::OpenOptionsExt;
345     ///
346     /// # fn main() {
347     /// let mut options = OpenOptions::new();
348     /// options.write(true);
349     /// if cfg!(unix) {
350     ///     options.custom_flags(libc::O_NOFOLLOW);
351     /// }
352     /// let file = options.open("foo.txt");
353     /// # }
354     /// ```
355     #[stable(feature = "open_options_ext", since = "1.10.0")]
356     fn custom_flags(&mut self, flags: i32) -> &mut Self;
357 }
358
359 #[stable(feature = "fs_ext", since = "1.1.0")]
360 impl OpenOptionsExt for OpenOptions {
361     fn mode(&mut self, mode: u32) -> &mut OpenOptions {
362         self.as_inner_mut().mode(mode);
363         self
364     }
365
366     fn custom_flags(&mut self, flags: i32) -> &mut OpenOptions {
367         self.as_inner_mut().custom_flags(flags);
368         self
369     }
370 }
371
372 /// Unix-specific extensions to [`fs::Metadata`].
373 ///
374 /// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
375 #[stable(feature = "metadata_ext", since = "1.1.0")]
376 pub trait MetadataExt {
377     /// Returns the ID of the device containing the file.
378     ///
379     /// # Examples
380     ///
381     /// ```no_run
382     /// use std::io;
383     /// use std::fs;
384     /// use std::os::unix::fs::MetadataExt;
385     ///
386     /// fn main() -> io::Result<()> {
387     ///     let meta = fs::metadata("some_file")?;
388     ///     let dev_id = meta.dev();
389     ///     Ok(())
390     /// }
391     /// ```
392     #[stable(feature = "metadata_ext", since = "1.1.0")]
393     fn dev(&self) -> u64;
394     /// Returns the inode number.
395     ///
396     /// # Examples
397     ///
398     /// ```no_run
399     /// use std::fs;
400     /// use std::os::unix::fs::MetadataExt;
401     /// use std::io;
402     ///
403     /// fn main() -> io::Result<()> {
404     ///     let meta = fs::metadata("some_file")?;
405     ///     let inode = meta.ino();
406     ///     Ok(())
407     /// }
408     /// ```
409     #[stable(feature = "metadata_ext", since = "1.1.0")]
410     fn ino(&self) -> u64;
411     /// Returns the rights applied to this file.
412     ///
413     /// # Examples
414     ///
415     /// ```no_run
416     /// use std::fs;
417     /// use std::os::unix::fs::MetadataExt;
418     /// use std::io;
419     ///
420     /// fn main() -> io::Result<()> {
421     ///     let meta = fs::metadata("some_file")?;
422     ///     let mode = meta.mode();
423     ///     let user_has_write_access      = mode & 0o200;
424     ///     let user_has_read_write_access = mode & 0o600;
425     ///     let group_has_read_access      = mode & 0o040;
426     ///     let others_have_exec_access    = mode & 0o001;
427     ///     Ok(())
428     /// }
429     /// ```
430     #[stable(feature = "metadata_ext", since = "1.1.0")]
431     fn mode(&self) -> u32;
432     /// Returns the number of hard links pointing to this file.
433     ///
434     /// # Examples
435     ///
436     /// ```no_run
437     /// use std::fs;
438     /// use std::os::unix::fs::MetadataExt;
439     ///  use std::io;
440     ///
441     /// fn main() -> io::Result<()> {
442     ///     let meta = fs::metadata("some_file")?;
443     ///     let nb_hard_links = meta.nlink();
444     ///     Ok(())
445     /// }
446     /// ```
447     #[stable(feature = "metadata_ext", since = "1.1.0")]
448     fn nlink(&self) -> u64;
449     /// Returns the user ID of the owner of this file.
450     ///
451     /// # Examples
452     ///
453     /// ```no_run
454     /// use std::fs;
455     /// use std::os::unix::fs::MetadataExt;
456     /// use std::io;
457     ///
458     /// fn main() -> io::Result<()> {
459     ///     let meta = fs::metadata("some_file")?;
460     ///     let user_id = meta.uid();
461     ///     Ok(())
462     /// }
463     /// ```
464     #[stable(feature = "metadata_ext", since = "1.1.0")]
465     fn uid(&self) -> u32;
466     /// Returns the group ID of the owner of this file.
467     ///
468     /// # Examples
469     ///
470     /// ```no_run
471     /// use std::fs;
472     /// use std::os::unix::fs::MetadataExt;
473     /// use std::io;
474     ///
475     /// fn main() -> io::Result<()> {
476     ///     let meta = fs::metadata("some_file")?;
477     ///     let group_id = meta.gid();
478     ///     Ok(())
479     /// }
480     /// ```
481     #[stable(feature = "metadata_ext", since = "1.1.0")]
482     fn gid(&self) -> u32;
483     /// Returns the device ID of this file (if it is a special one).
484     ///
485     /// # Examples
486     ///
487     /// ```no_run
488     /// use std::fs;
489     /// use std::os::unix::fs::MetadataExt;
490     /// use std::io;
491     ///
492     /// fn main() -> io::Result<()> {
493     ///     let meta = fs::metadata("some_file")?;
494     ///     let device_id = meta.rdev();
495     ///     Ok(())
496     /// }
497     /// ```
498     #[stable(feature = "metadata_ext", since = "1.1.0")]
499     fn rdev(&self) -> u64;
500     /// Returns the total size of this file in bytes.
501     ///
502     /// # Examples
503     ///
504     /// ```no_run
505     /// use std::fs;
506     /// use std::os::unix::fs::MetadataExt;
507     /// use std::io;
508     ///
509     /// fn main() -> io::Result<()> {
510     ///     let meta = fs::metadata("some_file")?;
511     ///     let file_size = meta.size();
512     ///     Ok(())
513     /// }
514     /// ```
515     #[stable(feature = "metadata_ext", since = "1.1.0")]
516     fn size(&self) -> u64;
517     /// Returns the last access time of the file, in seconds since Unix Epoch.
518     ///
519     /// # Examples
520     ///
521     /// ```no_run
522     /// use std::fs;
523     /// use std::os::unix::fs::MetadataExt;
524     /// use std::io;
525     ///
526     /// fn main() -> io::Result<()> {
527     ///     let meta = fs::metadata("some_file")?;
528     ///     let last_access_time = meta.atime();
529     ///     Ok(())
530     /// }
531     /// ```
532     #[stable(feature = "metadata_ext", since = "1.1.0")]
533     fn atime(&self) -> i64;
534     /// Returns the last access time of the file, in nanoseconds since [`atime`].
535     ///
536     /// [`atime`]: #tymethod.atime
537     ///
538     /// # Examples
539     ///
540     /// ```no_run
541     /// use std::fs;
542     /// use std::os::unix::fs::MetadataExt;
543     /// use std::io;
544     ///
545     /// fn main() -> io::Result<()> {
546     ///     let meta = fs::metadata("some_file")?;
547     ///     let nano_last_access_time = meta.atime_nsec();
548     ///     Ok(())
549     /// }
550     /// ```
551     #[stable(feature = "metadata_ext", since = "1.1.0")]
552     fn atime_nsec(&self) -> i64;
553     /// Returns the last modification time of the file, in seconds since Unix Epoch.
554     ///
555     /// # Examples
556     ///
557     /// ```no_run
558     /// use std::fs;
559     /// use std::os::unix::fs::MetadataExt;
560     /// use std::io;
561     ///
562     /// fn main() -> io::Result<()> {
563     ///     let meta = fs::metadata("some_file")?;
564     ///     let last_modification_time = meta.mtime();
565     ///     Ok(())
566     /// }
567     /// ```
568     #[stable(feature = "metadata_ext", since = "1.1.0")]
569     fn mtime(&self) -> i64;
570     /// Returns the last modification time of the file, in nanoseconds since [`mtime`].
571     ///
572     /// [`mtime`]: #tymethod.mtime
573     ///
574     /// # Examples
575     ///
576     /// ```no_run
577     /// use std::fs;
578     /// use std::os::unix::fs::MetadataExt;
579     /// use std::io;
580     ///
581     /// fn main() -> io::Result<()> {
582     ///     let meta = fs::metadata("some_file")?;
583     ///     let nano_last_modification_time = meta.mtime_nsec();
584     ///     Ok(())
585     /// }
586     /// ```
587     #[stable(feature = "metadata_ext", since = "1.1.0")]
588     fn mtime_nsec(&self) -> i64;
589     /// Returns the last status change time of the file, in seconds since Unix Epoch.
590     ///
591     /// # Examples
592     ///
593     /// ```no_run
594     /// use std::fs;
595     /// use std::os::unix::fs::MetadataExt;
596     /// use std::io;
597     ///
598     /// fn main() -> io::Result<()> {
599     ///     let meta = fs::metadata("some_file")?;
600     ///     let last_status_change_time = meta.ctime();
601     ///     Ok(())
602     /// }
603     /// ```
604     #[stable(feature = "metadata_ext", since = "1.1.0")]
605     fn ctime(&self) -> i64;
606     /// Returns the last status change time of the file, in nanoseconds since [`ctime`].
607     ///
608     /// [`ctime`]: #tymethod.ctime
609     ///
610     /// # Examples
611     ///
612     /// ```no_run
613     /// use std::fs;
614     /// use std::os::unix::fs::MetadataExt;
615     /// use std::io;
616     ///
617     /// fn main() -> io::Result<()> {
618     ///     let meta = fs::metadata("some_file")?;
619     ///     let nano_last_status_change_time = meta.ctime_nsec();
620     ///     Ok(())
621     /// }
622     /// ```
623     #[stable(feature = "metadata_ext", since = "1.1.0")]
624     fn ctime_nsec(&self) -> i64;
625     /// Returns the blocksize for filesystem I/O.
626     ///
627     /// # Examples
628     ///
629     /// ```no_run
630     /// use std::fs;
631     /// use std::os::unix::fs::MetadataExt;
632     /// use std::io;
633     ///
634     /// fn main() -> io::Result<()> {
635     ///     let meta = fs::metadata("some_file")?;
636     ///     let blocksize = meta.blksize();
637     ///     Ok(())
638     /// }
639     /// ```
640     #[stable(feature = "metadata_ext", since = "1.1.0")]
641     fn blksize(&self) -> u64;
642     /// Returns the number of blocks allocated to the file, in 512-byte units.
643     ///
644     /// Please note that this may be smaller than `st_size / 512` when the file has holes.
645     ///
646     /// # Examples
647     ///
648     /// ```no_run
649     /// use std::fs;
650     /// use std::os::unix::fs::MetadataExt;
651     /// use std::io;
652     ///
653     /// fn main() -> io::Result<()> {
654     ///     let meta = fs::metadata("some_file")?;
655     ///     let blocks = meta.blocks();
656     ///     Ok(())
657     /// }
658     /// ```
659     #[stable(feature = "metadata_ext", since = "1.1.0")]
660     fn blocks(&self) -> u64;
661 }
662
663 #[stable(feature = "metadata_ext", since = "1.1.0")]
664 impl MetadataExt for fs::Metadata {
665     fn dev(&self) -> u64 {
666         self.st_dev()
667     }
668     fn ino(&self) -> u64 {
669         self.st_ino()
670     }
671     fn mode(&self) -> u32 {
672         self.st_mode()
673     }
674     fn nlink(&self) -> u64 {
675         self.st_nlink()
676     }
677     fn uid(&self) -> u32 {
678         self.st_uid()
679     }
680     fn gid(&self) -> u32 {
681         self.st_gid()
682     }
683     fn rdev(&self) -> u64 {
684         self.st_rdev()
685     }
686     fn size(&self) -> u64 {
687         self.st_size()
688     }
689     fn atime(&self) -> i64 {
690         self.st_atime()
691     }
692     fn atime_nsec(&self) -> i64 {
693         self.st_atime_nsec()
694     }
695     fn mtime(&self) -> i64 {
696         self.st_mtime()
697     }
698     fn mtime_nsec(&self) -> i64 {
699         self.st_mtime_nsec()
700     }
701     fn ctime(&self) -> i64 {
702         self.st_ctime()
703     }
704     fn ctime_nsec(&self) -> i64 {
705         self.st_ctime_nsec()
706     }
707     fn blksize(&self) -> u64 {
708         self.st_blksize()
709     }
710     fn blocks(&self) -> u64 {
711         self.st_blocks()
712     }
713 }
714
715 /// Unix-specific extensions for [`FileType`].
716 ///
717 /// Adds support for special Unix file types such as block/character devices,
718 /// pipes, and sockets.
719 ///
720 /// [`FileType`]: ../../../../std/fs/struct.FileType.html
721 #[stable(feature = "file_type_ext", since = "1.5.0")]
722 pub trait FileTypeExt {
723     /// Returns `true` if this file type is a block device.
724     ///
725     /// # Examples
726     ///
727     /// ```no_run
728     /// use std::fs;
729     /// use std::os::unix::fs::FileTypeExt;
730     /// use std::io;
731     ///
732     /// fn main() -> io::Result<()> {
733     ///     let meta = fs::metadata("block_device_file")?;
734     ///     let file_type = meta.file_type();
735     ///     assert!(file_type.is_block_device());
736     ///     Ok(())
737     /// }
738     /// ```
739     #[stable(feature = "file_type_ext", since = "1.5.0")]
740     fn is_block_device(&self) -> bool;
741     /// Returns `true` if this file type is a char device.
742     ///
743     /// # Examples
744     ///
745     /// ```no_run
746     /// use std::fs;
747     /// use std::os::unix::fs::FileTypeExt;
748     /// use std::io;
749     ///
750     /// fn main() -> io::Result<()> {
751     ///     let meta = fs::metadata("char_device_file")?;
752     ///     let file_type = meta.file_type();
753     ///     assert!(file_type.is_char_device());
754     ///     Ok(())
755     /// }
756     /// ```
757     #[stable(feature = "file_type_ext", since = "1.5.0")]
758     fn is_char_device(&self) -> bool;
759     /// Returns `true` if this file type is a fifo.
760     ///
761     /// # Examples
762     ///
763     /// ```no_run
764     /// use std::fs;
765     /// use std::os::unix::fs::FileTypeExt;
766     /// use std::io;
767     ///
768     /// fn main() -> io::Result<()> {
769     ///     let meta = fs::metadata("fifo_file")?;
770     ///     let file_type = meta.file_type();
771     ///     assert!(file_type.is_fifo());
772     ///     Ok(())
773     /// }
774     /// ```
775     #[stable(feature = "file_type_ext", since = "1.5.0")]
776     fn is_fifo(&self) -> bool;
777     /// Returns `true` if this file type is a socket.
778     ///
779     /// # Examples
780     ///
781     /// ```no_run
782     /// use std::fs;
783     /// use std::os::unix::fs::FileTypeExt;
784     /// use std::io;
785     ///
786     /// fn main() -> io::Result<()> {
787     ///     let meta = fs::metadata("unix.socket")?;
788     ///     let file_type = meta.file_type();
789     ///     assert!(file_type.is_socket());
790     ///     Ok(())
791     /// }
792     /// ```
793     #[stable(feature = "file_type_ext", since = "1.5.0")]
794     fn is_socket(&self) -> bool;
795 }
796
797 #[stable(feature = "file_type_ext", since = "1.5.0")]
798 impl FileTypeExt for fs::FileType {
799     fn is_block_device(&self) -> bool {
800         self.as_inner().is(libc::S_IFBLK)
801     }
802     fn is_char_device(&self) -> bool {
803         self.as_inner().is(libc::S_IFCHR)
804     }
805     fn is_fifo(&self) -> bool {
806         self.as_inner().is(libc::S_IFIFO)
807     }
808     fn is_socket(&self) -> bool {
809         self.as_inner().is(libc::S_IFSOCK)
810     }
811 }
812
813 /// Unix-specific extension methods for [`fs::DirEntry`].
814 ///
815 /// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
816 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
817 pub trait DirEntryExt {
818     /// Returns the underlying `d_ino` field in the contained `dirent`
819     /// structure.
820     ///
821     /// # Examples
822     ///
823     /// ```
824     /// use std::fs;
825     /// use std::os::unix::fs::DirEntryExt;
826     ///
827     /// if let Ok(entries) = fs::read_dir(".") {
828     ///     for entry in entries {
829     ///         if let Ok(entry) = entry {
830     ///             // Here, `entry` is a `DirEntry`.
831     ///             println!("{:?}: {}", entry.file_name(), entry.ino());
832     ///         }
833     ///     }
834     /// }
835     /// ```
836     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
837     fn ino(&self) -> u64;
838 }
839
840 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
841 impl DirEntryExt for fs::DirEntry {
842     fn ino(&self) -> u64 {
843         self.as_inner().ino()
844     }
845 }
846
847 /// Creates a new symbolic link on the filesystem.
848 ///
849 /// The `dst` path will be a symbolic link pointing to the `src` path.
850 ///
851 /// # Note
852 ///
853 /// On Windows, you must specify whether a symbolic link points to a file
854 /// or directory. Use `os::windows::fs::symlink_file` to create a
855 /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
856 /// symbolic link to a directory. Additionally, the process must have
857 /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
858 /// symbolic link.
859 ///
860 /// # Examples
861 ///
862 /// ```no_run
863 /// use std::os::unix::fs;
864 ///
865 /// fn main() -> std::io::Result<()> {
866 ///     fs::symlink("a.txt", "b.txt")?;
867 ///     Ok(())
868 /// }
869 /// ```
870 #[stable(feature = "symlink", since = "1.1.0")]
871 pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
872     sys::fs::symlink(src.as_ref(), dst.as_ref())
873 }
874
875 /// Unix-specific extensions to [`fs::DirBuilder`].
876 ///
877 /// [`fs::DirBuilder`]: ../../../../std/fs/struct.DirBuilder.html
878 #[stable(feature = "dir_builder", since = "1.6.0")]
879 pub trait DirBuilderExt {
880     /// Sets the mode to create new directories with. This option defaults to
881     /// 0o777.
882     ///
883     /// # Examples
884     ///
885     /// ```no_run
886     /// use std::fs::DirBuilder;
887     /// use std::os::unix::fs::DirBuilderExt;
888     ///
889     /// let mut builder = DirBuilder::new();
890     /// builder.mode(0o755);
891     /// ```
892     #[stable(feature = "dir_builder", since = "1.6.0")]
893     fn mode(&mut self, mode: u32) -> &mut Self;
894 }
895
896 #[stable(feature = "dir_builder", since = "1.6.0")]
897 impl DirBuilderExt for fs::DirBuilder {
898     fn mode(&mut self, mode: u32) -> &mut fs::DirBuilder {
899         self.as_inner_mut().set_mode(mode);
900         self
901     }
902 }