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