]> git.lizzy.rs Git - rust.git/blob - library/std/src/fs.rs
Rollup merge of #75837 - GuillaumeGomez:fix-font-color-help-button, r=Cldfire
[rust.git] / library / std / src / fs.rs
1 // ignore-tidy-filelength
2
3 //! Filesystem manipulation operations.
4 //!
5 //! This module contains basic methods to manipulate the contents of the local
6 //! filesystem. All methods in this module represent cross-platform filesystem
7 //! operations. Extra platform-specific functionality can be found in the
8 //! extension traits of `std::os::$platform`.
9
10 #![stable(feature = "rust1", since = "1.0.0")]
11 #![deny(unsafe_op_in_unsafe_fn)]
12
13 use crate::ffi::OsString;
14 use crate::fmt;
15 use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
16 use crate::path::{Path, PathBuf};
17 use crate::sys::fs as fs_imp;
18 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
19 use crate::time::SystemTime;
20
21 /// A reference to an open file on the filesystem.
22 ///
23 /// An instance of a `File` can be read and/or written depending on what options
24 /// it was opened with. Files also implement [`Seek`] to alter the logical cursor
25 /// that the file contains internally.
26 ///
27 /// Files are automatically closed when they go out of scope.  Errors detected
28 /// on closing are ignored by the implementation of `Drop`.  Use the method
29 /// [`sync_all`] if these errors must be manually handled.
30 ///
31 /// # Examples
32 ///
33 /// Creates a new file and write bytes to it (you can also use [`write()`]):
34 ///
35 /// ```no_run
36 /// use std::fs::File;
37 /// use std::io::prelude::*;
38 ///
39 /// fn main() -> std::io::Result<()> {
40 ///     let mut file = File::create("foo.txt")?;
41 ///     file.write_all(b"Hello, world!")?;
42 ///     Ok(())
43 /// }
44 /// ```
45 ///
46 /// Read the contents of a file into a [`String`] (you can also use [`read`]):
47 ///
48 /// ```no_run
49 /// use std::fs::File;
50 /// use std::io::prelude::*;
51 ///
52 /// fn main() -> std::io::Result<()> {
53 ///     let mut file = File::open("foo.txt")?;
54 ///     let mut contents = String::new();
55 ///     file.read_to_string(&mut contents)?;
56 ///     assert_eq!(contents, "Hello, world!");
57 ///     Ok(())
58 /// }
59 /// ```
60 ///
61 /// It can be more efficient to read the contents of a file with a buffered
62 /// [`Read`]er. This can be accomplished with [`BufReader<R>`]:
63 ///
64 /// ```no_run
65 /// use std::fs::File;
66 /// use std::io::BufReader;
67 /// use std::io::prelude::*;
68 ///
69 /// fn main() -> std::io::Result<()> {
70 ///     let file = File::open("foo.txt")?;
71 ///     let mut buf_reader = BufReader::new(file);
72 ///     let mut contents = String::new();
73 ///     buf_reader.read_to_string(&mut contents)?;
74 ///     assert_eq!(contents, "Hello, world!");
75 ///     Ok(())
76 /// }
77 /// ```
78 ///
79 /// Note that, although read and write methods require a `&mut File`, because
80 /// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can
81 /// still modify the file, either through methods that take `&File` or by
82 /// retrieving the underlying OS object and modifying the file that way.
83 /// Additionally, many operating systems allow concurrent modification of files
84 /// by different processes. Avoid assuming that holding a `&File` means that the
85 /// file will not change.
86 ///
87 /// [`BufReader<R>`]: io::BufReader
88 /// [`sync_all`]: File::sync_all
89 #[stable(feature = "rust1", since = "1.0.0")]
90 pub struct File {
91     inner: fs_imp::File,
92 }
93
94 /// Metadata information about a file.
95 ///
96 /// This structure is returned from the [`metadata`] or
97 /// [`symlink_metadata`] function or method and represents known
98 /// metadata about a file such as its permissions, size, modification
99 /// times, etc.
100 #[stable(feature = "rust1", since = "1.0.0")]
101 #[derive(Clone)]
102 pub struct Metadata(fs_imp::FileAttr);
103
104 /// Iterator over the entries in a directory.
105 ///
106 /// This iterator is returned from the [`read_dir`] function of this module and
107 /// will yield instances of [`io::Result`]`<`[`DirEntry`]`>`. Through a [`DirEntry`]
108 /// information like the entry's path and possibly other metadata can be
109 /// learned.
110 ///
111 /// The order in which this iterator returns entries is platform and filesystem
112 /// dependent.
113 ///
114 /// # Errors
115 ///
116 /// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent
117 /// IO error during iteration.
118 #[stable(feature = "rust1", since = "1.0.0")]
119 #[derive(Debug)]
120 pub struct ReadDir(fs_imp::ReadDir);
121
122 /// Entries returned by the [`ReadDir`] iterator.
123 ///
124 /// An instance of `DirEntry` represents an entry inside of a directory on the
125 /// filesystem. Each entry can be inspected via methods to learn about the full
126 /// path or possibly other metadata through per-platform extension traits.
127 #[stable(feature = "rust1", since = "1.0.0")]
128 pub struct DirEntry(fs_imp::DirEntry);
129
130 /// Options and flags which can be used to configure how a file is opened.
131 ///
132 /// This builder exposes the ability to configure how a [`File`] is opened and
133 /// what operations are permitted on the open file. The [`File::open`] and
134 /// [`File::create`] methods are aliases for commonly used options using this
135 /// builder.
136 ///
137 /// Generally speaking, when using `OpenOptions`, you'll first call
138 /// [`OpenOptions::new`], then chain calls to methods to set each option, then
139 /// call [`OpenOptions::open`], passing the path of the file you're trying to
140 /// open. This will give you a [`io::Result`] with a [`File`] inside that you
141 /// can further operate on.
142 ///
143 /// # Examples
144 ///
145 /// Opening a file to read:
146 ///
147 /// ```no_run
148 /// use std::fs::OpenOptions;
149 ///
150 /// let file = OpenOptions::new().read(true).open("foo.txt");
151 /// ```
152 ///
153 /// Opening a file for both reading and writing, as well as creating it if it
154 /// doesn't exist:
155 ///
156 /// ```no_run
157 /// use std::fs::OpenOptions;
158 ///
159 /// let file = OpenOptions::new()
160 ///             .read(true)
161 ///             .write(true)
162 ///             .create(true)
163 ///             .open("foo.txt");
164 /// ```
165 #[derive(Clone, Debug)]
166 #[stable(feature = "rust1", since = "1.0.0")]
167 pub struct OpenOptions(fs_imp::OpenOptions);
168
169 /// Representation of the various permissions on a file.
170 ///
171 /// This module only currently provides one bit of information,
172 /// [`Permissions::readonly`], which is exposed on all currently supported
173 /// platforms. Unix-specific functionality, such as mode bits, is available
174 /// through the [`PermissionsExt`] trait.
175 ///
176 /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
177 #[derive(Clone, PartialEq, Eq, Debug)]
178 #[stable(feature = "rust1", since = "1.0.0")]
179 pub struct Permissions(fs_imp::FilePermissions);
180
181 /// A structure representing a type of file with accessors for each file type.
182 /// It is returned by [`Metadata::file_type`] method.
183 #[stable(feature = "file_type", since = "1.1.0")]
184 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
185 pub struct FileType(fs_imp::FileType);
186
187 /// A builder used to create directories in various manners.
188 ///
189 /// This builder also supports platform-specific options.
190 #[stable(feature = "dir_builder", since = "1.6.0")]
191 #[derive(Debug)]
192 pub struct DirBuilder {
193     inner: fs_imp::DirBuilder,
194     recursive: bool,
195 }
196
197 /// Indicates how large a buffer to pre-allocate before reading the entire file.
198 fn initial_buffer_size(file: &File) -> usize {
199     // Allocate one extra byte so the buffer doesn't need to grow before the
200     // final `read` call at the end of the file.  Don't worry about `usize`
201     // overflow because reading will fail regardless in that case.
202     file.metadata().map(|m| m.len() as usize + 1).unwrap_or(0)
203 }
204
205 /// Read the entire contents of a file into a bytes vector.
206 ///
207 /// This is a convenience function for using [`File::open`] and [`read_to_end`]
208 /// with fewer imports and without an intermediate variable. It pre-allocates a
209 /// buffer based on the file size when available, so it is generally faster than
210 /// reading into a vector created with [`Vec::new()`].
211 ///
212 /// [`read_to_end`]: Read::read_to_end
213 ///
214 /// # Errors
215 ///
216 /// This function will return an error if `path` does not already exist.
217 /// Other errors may also be returned according to [`OpenOptions::open`].
218 ///
219 /// It will also return an error if it encounters while reading an error
220 /// of a kind other than [`io::ErrorKind::Interrupted`].
221 ///
222 /// # Examples
223 ///
224 /// ```no_run
225 /// use std::fs;
226 /// use std::net::SocketAddr;
227 ///
228 /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
229 ///     let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?;
230 ///     Ok(())
231 /// }
232 /// ```
233 #[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
234 pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
235     fn inner(path: &Path) -> io::Result<Vec<u8>> {
236         let mut file = File::open(path)?;
237         let mut bytes = Vec::with_capacity(initial_buffer_size(&file));
238         file.read_to_end(&mut bytes)?;
239         Ok(bytes)
240     }
241     inner(path.as_ref())
242 }
243
244 /// Read the entire contents of a file into a string.
245 ///
246 /// This is a convenience function for using [`File::open`] and [`read_to_string`]
247 /// with fewer imports and without an intermediate variable. It pre-allocates a
248 /// buffer based on the file size when available, so it is generally faster than
249 /// reading into a string created with [`String::new()`].
250 ///
251 /// [`read_to_string`]: Read::read_to_string
252 ///
253 /// # Errors
254 ///
255 /// This function will return an error if `path` does not already exist.
256 /// Other errors may also be returned according to [`OpenOptions::open`].
257 ///
258 /// It will also return an error if it encounters while reading an error
259 /// of a kind other than [`io::ErrorKind::Interrupted`],
260 /// or if the contents of the file are not valid UTF-8.
261 ///
262 /// # Examples
263 ///
264 /// ```no_run
265 /// use std::fs;
266 /// use std::net::SocketAddr;
267 ///
268 /// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
269 ///     let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?;
270 ///     Ok(())
271 /// }
272 /// ```
273 #[stable(feature = "fs_read_write", since = "1.26.0")]
274 pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
275     fn inner(path: &Path) -> io::Result<String> {
276         let mut file = File::open(path)?;
277         let mut string = String::with_capacity(initial_buffer_size(&file));
278         file.read_to_string(&mut string)?;
279         Ok(string)
280     }
281     inner(path.as_ref())
282 }
283
284 /// Write a slice as the entire contents of a file.
285 ///
286 /// This function will create a file if it does not exist,
287 /// and will entirely replace its contents if it does.
288 ///
289 /// This is a convenience function for using [`File::create`] and [`write_all`]
290 /// with fewer imports.
291 ///
292 /// [`write_all`]: Write::write_all
293 ///
294 /// # Examples
295 ///
296 /// ```no_run
297 /// use std::fs;
298 ///
299 /// fn main() -> std::io::Result<()> {
300 ///     fs::write("foo.txt", b"Lorem ipsum")?;
301 ///     fs::write("bar.txt", "dolor sit")?;
302 ///     Ok(())
303 /// }
304 /// ```
305 #[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
306 pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
307     fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
308         File::create(path)?.write_all(contents)
309     }
310     inner(path.as_ref(), contents.as_ref())
311 }
312
313 impl File {
314     /// Attempts to open a file in read-only mode.
315     ///
316     /// See the [`OpenOptions::open`] method for more details.
317     ///
318     /// # Errors
319     ///
320     /// This function will return an error if `path` does not already exist.
321     /// Other errors may also be returned according to [`OpenOptions::open`].
322     ///
323     /// # Examples
324     ///
325     /// ```no_run
326     /// use std::fs::File;
327     ///
328     /// fn main() -> std::io::Result<()> {
329     ///     let mut f = File::open("foo.txt")?;
330     ///     Ok(())
331     /// }
332     /// ```
333     #[stable(feature = "rust1", since = "1.0.0")]
334     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
335         OpenOptions::new().read(true).open(path.as_ref())
336     }
337
338     /// Opens a file in write-only mode.
339     ///
340     /// This function will create a file if it does not exist,
341     /// and will truncate it if it does.
342     ///
343     /// See the [`OpenOptions::open`] function for more details.
344     ///
345     /// # Examples
346     ///
347     /// ```no_run
348     /// use std::fs::File;
349     ///
350     /// fn main() -> std::io::Result<()> {
351     ///     let mut f = File::create("foo.txt")?;
352     ///     Ok(())
353     /// }
354     /// ```
355     #[stable(feature = "rust1", since = "1.0.0")]
356     pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
357         OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
358     }
359
360     /// Returns a new OpenOptions object.
361     ///
362     /// This function returns a new OpenOptions object that you can use to
363     /// open or create a file with specific options if `open()` or `create()`
364     /// are not appropriate.
365     ///
366     /// It is equivalent to `OpenOptions::new()` but allows you to write more
367     /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")`
368     /// you can write `File::with_options().read(true).open("foo.txt")`. This
369     /// also avoids the need to import `OpenOptions`.
370     ///
371     /// See the [`OpenOptions::new`] function for more details.
372     ///
373     /// # Examples
374     ///
375     /// ```no_run
376     /// #![feature(with_options)]
377     /// use std::fs::File;
378     ///
379     /// fn main() -> std::io::Result<()> {
380     ///     let mut f = File::with_options().read(true).open("foo.txt")?;
381     ///     Ok(())
382     /// }
383     /// ```
384     #[unstable(feature = "with_options", issue = "65439")]
385     pub fn with_options() -> OpenOptions {
386         OpenOptions::new()
387     }
388
389     /// Attempts to sync all OS-internal metadata to disk.
390     ///
391     /// This function will attempt to ensure that all in-memory data reaches the
392     /// filesystem before returning.
393     ///
394     /// This can be used to handle errors that would otherwise only be caught
395     /// when the `File` is closed.  Dropping a file will ignore errors in
396     /// synchronizing this in-memory data.
397     ///
398     /// # Examples
399     ///
400     /// ```no_run
401     /// use std::fs::File;
402     /// use std::io::prelude::*;
403     ///
404     /// fn main() -> std::io::Result<()> {
405     ///     let mut f = File::create("foo.txt")?;
406     ///     f.write_all(b"Hello, world!")?;
407     ///
408     ///     f.sync_all()?;
409     ///     Ok(())
410     /// }
411     /// ```
412     #[stable(feature = "rust1", since = "1.0.0")]
413     pub fn sync_all(&self) -> io::Result<()> {
414         self.inner.fsync()
415     }
416
417     /// This function is similar to [`sync_all`], except that it may not
418     /// synchronize file metadata to the filesystem.
419     ///
420     /// This is intended for use cases that must synchronize content, but don't
421     /// need the metadata on disk. The goal of this method is to reduce disk
422     /// operations.
423     ///
424     /// Note that some platforms may simply implement this in terms of
425     /// [`sync_all`].
426     ///
427     /// [`sync_all`]: File::sync_all
428     ///
429     /// # Examples
430     ///
431     /// ```no_run
432     /// use std::fs::File;
433     /// use std::io::prelude::*;
434     ///
435     /// fn main() -> std::io::Result<()> {
436     ///     let mut f = File::create("foo.txt")?;
437     ///     f.write_all(b"Hello, world!")?;
438     ///
439     ///     f.sync_data()?;
440     ///     Ok(())
441     /// }
442     /// ```
443     #[stable(feature = "rust1", since = "1.0.0")]
444     pub fn sync_data(&self) -> io::Result<()> {
445         self.inner.datasync()
446     }
447
448     /// Truncates or extends the underlying file, updating the size of
449     /// this file to become `size`.
450     ///
451     /// If the `size` is less than the current file's size, then the file will
452     /// be shrunk. If it is greater than the current file's size, then the file
453     /// will be extended to `size` and have all of the intermediate data filled
454     /// in with 0s.
455     ///
456     /// The file's cursor isn't changed. In particular, if the cursor was at the
457     /// end and the file is shrunk using this operation, the cursor will now be
458     /// past the end.
459     ///
460     /// # Errors
461     ///
462     /// This function will return an error if the file is not opened for writing.
463     /// Also, std::io::ErrorKind::InvalidInput will be returned if the desired
464     /// length would cause an overflow due to the implementation specifics.
465     ///
466     /// # Examples
467     ///
468     /// ```no_run
469     /// use std::fs::File;
470     ///
471     /// fn main() -> std::io::Result<()> {
472     ///     let mut f = File::create("foo.txt")?;
473     ///     f.set_len(10)?;
474     ///     Ok(())
475     /// }
476     /// ```
477     ///
478     /// Note that this method alters the content of the underlying file, even
479     /// though it takes `&self` rather than `&mut self`.
480     #[stable(feature = "rust1", since = "1.0.0")]
481     pub fn set_len(&self, size: u64) -> io::Result<()> {
482         self.inner.truncate(size)
483     }
484
485     /// Queries metadata about the underlying file.
486     ///
487     /// # Examples
488     ///
489     /// ```no_run
490     /// use std::fs::File;
491     ///
492     /// fn main() -> std::io::Result<()> {
493     ///     let mut f = File::open("foo.txt")?;
494     ///     let metadata = f.metadata()?;
495     ///     Ok(())
496     /// }
497     /// ```
498     #[stable(feature = "rust1", since = "1.0.0")]
499     pub fn metadata(&self) -> io::Result<Metadata> {
500         self.inner.file_attr().map(Metadata)
501     }
502
503     /// Creates a new `File` instance that shares the same underlying file handle
504     /// as the existing `File` instance. Reads, writes, and seeks will affect
505     /// both `File` instances simultaneously.
506     ///
507     /// # Examples
508     ///
509     /// Creates two handles for a file named `foo.txt`:
510     ///
511     /// ```no_run
512     /// use std::fs::File;
513     ///
514     /// fn main() -> std::io::Result<()> {
515     ///     let mut file = File::open("foo.txt")?;
516     ///     let file_copy = file.try_clone()?;
517     ///     Ok(())
518     /// }
519     /// ```
520     ///
521     /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create
522     /// two handles, seek one of them, and read the remaining bytes from the
523     /// other handle:
524     ///
525     /// ```no_run
526     /// use std::fs::File;
527     /// use std::io::SeekFrom;
528     /// use std::io::prelude::*;
529     ///
530     /// fn main() -> std::io::Result<()> {
531     ///     let mut file = File::open("foo.txt")?;
532     ///     let mut file_copy = file.try_clone()?;
533     ///
534     ///     file.seek(SeekFrom::Start(3))?;
535     ///
536     ///     let mut contents = vec![];
537     ///     file_copy.read_to_end(&mut contents)?;
538     ///     assert_eq!(contents, b"def\n");
539     ///     Ok(())
540     /// }
541     /// ```
542     #[stable(feature = "file_try_clone", since = "1.9.0")]
543     pub fn try_clone(&self) -> io::Result<File> {
544         Ok(File { inner: self.inner.duplicate()? })
545     }
546
547     /// Changes the permissions on the underlying file.
548     ///
549     /// # Platform-specific behavior
550     ///
551     /// This function currently corresponds to the `fchmod` function on Unix and
552     /// the `SetFileInformationByHandle` function on Windows. Note that, this
553     /// [may change in the future][changes].
554     ///
555     /// [changes]: ../io/index.html#platform-specific-behavior
556     ///
557     /// # Errors
558     ///
559     /// This function will return an error if the user lacks permission change
560     /// attributes on the underlying file. It may also return an error in other
561     /// os-specific unspecified cases.
562     ///
563     /// # Examples
564     ///
565     /// ```no_run
566     /// fn main() -> std::io::Result<()> {
567     ///     use std::fs::File;
568     ///
569     ///     let file = File::open("foo.txt")?;
570     ///     let mut perms = file.metadata()?.permissions();
571     ///     perms.set_readonly(true);
572     ///     file.set_permissions(perms)?;
573     ///     Ok(())
574     /// }
575     /// ```
576     ///
577     /// Note that this method alters the permissions of the underlying file,
578     /// even though it takes `&self` rather than `&mut self`.
579     #[stable(feature = "set_permissions_atomic", since = "1.16.0")]
580     pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
581         self.inner.set_permissions(perm.0)
582     }
583 }
584
585 impl AsInner<fs_imp::File> for File {
586     fn as_inner(&self) -> &fs_imp::File {
587         &self.inner
588     }
589 }
590 impl FromInner<fs_imp::File> for File {
591     fn from_inner(f: fs_imp::File) -> File {
592         File { inner: f }
593     }
594 }
595 impl IntoInner<fs_imp::File> for File {
596     fn into_inner(self) -> fs_imp::File {
597         self.inner
598     }
599 }
600
601 #[stable(feature = "rust1", since = "1.0.0")]
602 impl fmt::Debug for File {
603     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
604         self.inner.fmt(f)
605     }
606 }
607
608 #[stable(feature = "rust1", since = "1.0.0")]
609 impl Read for File {
610     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
611         self.inner.read(buf)
612     }
613
614     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
615         self.inner.read_vectored(bufs)
616     }
617
618     #[inline]
619     fn is_read_vectored(&self) -> bool {
620         self.inner.is_read_vectored()
621     }
622
623     #[inline]
624     unsafe fn initializer(&self) -> Initializer {
625         // SAFETY: Read is guaranteed to work on uninitialized memory
626         unsafe { Initializer::nop() }
627     }
628 }
629 #[stable(feature = "rust1", since = "1.0.0")]
630 impl Write for File {
631     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
632         self.inner.write(buf)
633     }
634
635     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
636         self.inner.write_vectored(bufs)
637     }
638
639     #[inline]
640     fn is_write_vectored(&self) -> bool {
641         self.inner.is_write_vectored()
642     }
643
644     fn flush(&mut self) -> io::Result<()> {
645         self.inner.flush()
646     }
647 }
648 #[stable(feature = "rust1", since = "1.0.0")]
649 impl Seek for File {
650     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
651         self.inner.seek(pos)
652     }
653 }
654 #[stable(feature = "rust1", since = "1.0.0")]
655 impl Read for &File {
656     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
657         self.inner.read(buf)
658     }
659
660     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
661         self.inner.read_vectored(bufs)
662     }
663
664     #[inline]
665     fn is_read_vectored(&self) -> bool {
666         self.inner.is_read_vectored()
667     }
668
669     #[inline]
670     unsafe fn initializer(&self) -> Initializer {
671         // SAFETY: Read is guaranteed to work on uninitialized memory
672         unsafe { Initializer::nop() }
673     }
674 }
675 #[stable(feature = "rust1", since = "1.0.0")]
676 impl Write for &File {
677     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
678         self.inner.write(buf)
679     }
680
681     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
682         self.inner.write_vectored(bufs)
683     }
684
685     #[inline]
686     fn is_write_vectored(&self) -> bool {
687         self.inner.is_write_vectored()
688     }
689
690     fn flush(&mut self) -> io::Result<()> {
691         self.inner.flush()
692     }
693 }
694 #[stable(feature = "rust1", since = "1.0.0")]
695 impl Seek for &File {
696     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
697         self.inner.seek(pos)
698     }
699 }
700
701 impl OpenOptions {
702     /// Creates a blank new set of options ready for configuration.
703     ///
704     /// All options are initially set to `false`.
705     ///
706     /// # Examples
707     ///
708     /// ```no_run
709     /// use std::fs::OpenOptions;
710     ///
711     /// let mut options = OpenOptions::new();
712     /// let file = options.read(true).open("foo.txt");
713     /// ```
714     #[stable(feature = "rust1", since = "1.0.0")]
715     pub fn new() -> Self {
716         OpenOptions(fs_imp::OpenOptions::new())
717     }
718
719     /// Sets the option for read access.
720     ///
721     /// This option, when true, will indicate that the file should be
722     /// `read`-able if opened.
723     ///
724     /// # Examples
725     ///
726     /// ```no_run
727     /// use std::fs::OpenOptions;
728     ///
729     /// let file = OpenOptions::new().read(true).open("foo.txt");
730     /// ```
731     #[stable(feature = "rust1", since = "1.0.0")]
732     pub fn read(&mut self, read: bool) -> &mut Self {
733         self.0.read(read);
734         self
735     }
736
737     /// Sets the option for write access.
738     ///
739     /// This option, when true, will indicate that the file should be
740     /// `write`-able if opened.
741     ///
742     /// If the file already exists, any write calls on it will overwrite its
743     /// contents, without truncating it.
744     ///
745     /// # Examples
746     ///
747     /// ```no_run
748     /// use std::fs::OpenOptions;
749     ///
750     /// let file = OpenOptions::new().write(true).open("foo.txt");
751     /// ```
752     #[stable(feature = "rust1", since = "1.0.0")]
753     pub fn write(&mut self, write: bool) -> &mut Self {
754         self.0.write(write);
755         self
756     }
757
758     /// Sets the option for the append mode.
759     ///
760     /// This option, when true, means that writes will append to a file instead
761     /// of overwriting previous contents.
762     /// Note that setting `.write(true).append(true)` has the same effect as
763     /// setting only `.append(true)`.
764     ///
765     /// For most filesystems, the operating system guarantees that all writes are
766     /// atomic: no writes get mangled because another process writes at the same
767     /// time.
768     ///
769     /// One maybe obvious note when using append-mode: make sure that all data
770     /// that belongs together is written to the file in one operation. This
771     /// can be done by concatenating strings before passing them to [`write()`],
772     /// or using a buffered writer (with a buffer of adequate size),
773     /// and calling [`flush()`] when the message is complete.
774     ///
775     /// If a file is opened with both read and append access, beware that after
776     /// opening, and after every write, the position for reading may be set at the
777     /// end of the file. So, before writing, save the current position (using
778     /// [`seek`]`(`[`SeekFrom`]`::`[`Current`]`(0))`), and restore it before the next read.
779     ///
780     /// ## Note
781     ///
782     /// This function doesn't create the file if it doesn't exist. Use the
783     /// [`OpenOptions::create`] method to do so.
784     ///
785     /// [`write()`]: Write::write
786     /// [`flush()`]: Write::flush
787     /// [`seek`]: Seek::seek
788     /// [`Current`]: SeekFrom::Current
789     ///
790     /// # Examples
791     ///
792     /// ```no_run
793     /// use std::fs::OpenOptions;
794     ///
795     /// let file = OpenOptions::new().append(true).open("foo.txt");
796     /// ```
797     #[stable(feature = "rust1", since = "1.0.0")]
798     pub fn append(&mut self, append: bool) -> &mut Self {
799         self.0.append(append);
800         self
801     }
802
803     /// Sets the option for truncating a previous file.
804     ///
805     /// If a file is successfully opened with this option set it will truncate
806     /// the file to 0 length if it already exists.
807     ///
808     /// The file must be opened with write access for truncate to work.
809     ///
810     /// # Examples
811     ///
812     /// ```no_run
813     /// use std::fs::OpenOptions;
814     ///
815     /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt");
816     /// ```
817     #[stable(feature = "rust1", since = "1.0.0")]
818     pub fn truncate(&mut self, truncate: bool) -> &mut Self {
819         self.0.truncate(truncate);
820         self
821     }
822
823     /// Sets the option to create a new file, or open it if it already exists.
824     ///
825     /// In order for the file to be created, [`OpenOptions::write`] or
826     /// [`OpenOptions::append`] access must be used.
827     ///
828     /// # Examples
829     ///
830     /// ```no_run
831     /// use std::fs::OpenOptions;
832     ///
833     /// let file = OpenOptions::new().write(true).create(true).open("foo.txt");
834     /// ```
835     #[stable(feature = "rust1", since = "1.0.0")]
836     pub fn create(&mut self, create: bool) -> &mut Self {
837         self.0.create(create);
838         self
839     }
840
841     /// Sets the option to create a new file, failing if it already exists.
842     ///
843     /// No file is allowed to exist at the target location, also no (dangling) symlink. In this
844     /// way, if the call succeeds, the file returned is guaranteed to be new.
845     ///
846     /// This option is useful because it is atomic. Otherwise between checking
847     /// whether a file exists and creating a new one, the file may have been
848     /// created by another process (a TOCTOU race condition / attack).
849     ///
850     /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are
851     /// ignored.
852     ///
853     /// The file must be opened with write or append access in order to create
854     /// a new file.
855     ///
856     /// [`.create()`]: OpenOptions::create
857     /// [`.truncate()`]: OpenOptions::truncate
858     ///
859     /// # Examples
860     ///
861     /// ```no_run
862     /// use std::fs::OpenOptions;
863     ///
864     /// let file = OpenOptions::new().write(true)
865     ///                              .create_new(true)
866     ///                              .open("foo.txt");
867     /// ```
868     #[stable(feature = "expand_open_options2", since = "1.9.0")]
869     pub fn create_new(&mut self, create_new: bool) -> &mut Self {
870         self.0.create_new(create_new);
871         self
872     }
873
874     /// Opens a file at `path` with the options specified by `self`.
875     ///
876     /// # Errors
877     ///
878     /// This function will return an error under a number of different
879     /// circumstances. Some of these error conditions are listed here, together
880     /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not
881     /// part of the compatibility contract of the function, especially the
882     /// [`Other`] kind might change to more specific kinds in the future.
883     ///
884     /// * [`NotFound`]: The specified file does not exist and neither `create`
885     ///   or `create_new` is set.
886     /// * [`NotFound`]: One of the directory components of the file path does
887     ///   not exist.
888     /// * [`PermissionDenied`]: The user lacks permission to get the specified
889     ///   access rights for the file.
890     /// * [`PermissionDenied`]: The user lacks permission to open one of the
891     ///   directory components of the specified path.
892     /// * [`AlreadyExists`]: `create_new` was specified and the file already
893     ///   exists.
894     /// * [`InvalidInput`]: Invalid combinations of open options (truncate
895     ///   without write access, no access mode set, etc.).
896     /// * [`Other`]: One of the directory components of the specified file path
897     ///   was not, in fact, a directory.
898     /// * [`Other`]: Filesystem-level errors: full disk, write permission
899     ///   requested on a read-only file system, exceeded disk quota, too many
900     ///   open files, too long filename, too many symbolic links in the
901     ///   specified path (Unix-like systems only), etc.
902     ///
903     /// # Examples
904     ///
905     /// ```no_run
906     /// use std::fs::OpenOptions;
907     ///
908     /// let file = OpenOptions::new().read(true).open("foo.txt");
909     /// ```
910     ///
911     /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
912     /// [`InvalidInput`]: io::ErrorKind::InvalidInput
913     /// [`NotFound`]: io::ErrorKind::NotFound
914     /// [`Other`]: io::ErrorKind::Other
915     /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
916     #[stable(feature = "rust1", since = "1.0.0")]
917     pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
918         self._open(path.as_ref())
919     }
920
921     fn _open(&self, path: &Path) -> io::Result<File> {
922         fs_imp::File::open(path, &self.0).map(|inner| File { inner })
923     }
924 }
925
926 impl AsInner<fs_imp::OpenOptions> for OpenOptions {
927     fn as_inner(&self) -> &fs_imp::OpenOptions {
928         &self.0
929     }
930 }
931
932 impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
933     fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {
934         &mut self.0
935     }
936 }
937
938 impl Metadata {
939     /// Returns the file type for this metadata.
940     ///
941     /// # Examples
942     ///
943     /// ```no_run
944     /// fn main() -> std::io::Result<()> {
945     ///     use std::fs;
946     ///
947     ///     let metadata = fs::metadata("foo.txt")?;
948     ///
949     ///     println!("{:?}", metadata.file_type());
950     ///     Ok(())
951     /// }
952     /// ```
953     #[stable(feature = "file_type", since = "1.1.0")]
954     pub fn file_type(&self) -> FileType {
955         FileType(self.0.file_type())
956     }
957
958     /// Returns `true` if this metadata is for a directory. The
959     /// result is mutually exclusive to the result of
960     /// [`Metadata::is_file`], and will be false for symlink metadata
961     /// obtained from [`symlink_metadata`].
962     ///
963     /// # Examples
964     ///
965     /// ```no_run
966     /// fn main() -> std::io::Result<()> {
967     ///     use std::fs;
968     ///
969     ///     let metadata = fs::metadata("foo.txt")?;
970     ///
971     ///     assert!(!metadata.is_dir());
972     ///     Ok(())
973     /// }
974     /// ```
975     #[stable(feature = "rust1", since = "1.0.0")]
976     pub fn is_dir(&self) -> bool {
977         self.file_type().is_dir()
978     }
979
980     /// Returns `true` if this metadata is for a regular file. The
981     /// result is mutually exclusive to the result of
982     /// [`Metadata::is_dir`], and will be false for symlink metadata
983     /// obtained from [`symlink_metadata`].
984     ///
985     /// When the goal is simply to read from (or write to) the source, the most
986     /// reliable way to test the source can be read (or written to) is to open
987     /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
988     /// a Unix-like system for example. See [`File::open`] or
989     /// [`OpenOptions::open`] for more information.
990     ///
991     /// # Examples
992     ///
993     /// ```no_run
994     /// use std::fs;
995     ///
996     /// fn main() -> std::io::Result<()> {
997     ///     let metadata = fs::metadata("foo.txt")?;
998     ///
999     ///     assert!(metadata.is_file());
1000     ///     Ok(())
1001     /// }
1002     /// ```
1003     #[stable(feature = "rust1", since = "1.0.0")]
1004     pub fn is_file(&self) -> bool {
1005         self.file_type().is_file()
1006     }
1007
1008     /// Returns the size of the file, in bytes, this metadata is for.
1009     ///
1010     /// # Examples
1011     ///
1012     /// ```no_run
1013     /// use std::fs;
1014     ///
1015     /// fn main() -> std::io::Result<()> {
1016     ///     let metadata = fs::metadata("foo.txt")?;
1017     ///
1018     ///     assert_eq!(0, metadata.len());
1019     ///     Ok(())
1020     /// }
1021     /// ```
1022     #[stable(feature = "rust1", since = "1.0.0")]
1023     pub fn len(&self) -> u64 {
1024         self.0.size()
1025     }
1026
1027     /// Returns the permissions of the file this metadata is for.
1028     ///
1029     /// # Examples
1030     ///
1031     /// ```no_run
1032     /// use std::fs;
1033     ///
1034     /// fn main() -> std::io::Result<()> {
1035     ///     let metadata = fs::metadata("foo.txt")?;
1036     ///
1037     ///     assert!(!metadata.permissions().readonly());
1038     ///     Ok(())
1039     /// }
1040     /// ```
1041     #[stable(feature = "rust1", since = "1.0.0")]
1042     pub fn permissions(&self) -> Permissions {
1043         Permissions(self.0.perm())
1044     }
1045
1046     /// Returns the last modification time listed in this metadata.
1047     ///
1048     /// The returned value corresponds to the `mtime` field of `stat` on Unix
1049     /// platforms and the `ftLastWriteTime` field on Windows platforms.
1050     ///
1051     /// # Errors
1052     ///
1053     /// This field may not be available on all platforms, and will return an
1054     /// `Err` on platforms where it is not available.
1055     ///
1056     /// # Examples
1057     ///
1058     /// ```no_run
1059     /// use std::fs;
1060     ///
1061     /// fn main() -> std::io::Result<()> {
1062     ///     let metadata = fs::metadata("foo.txt")?;
1063     ///
1064     ///     if let Ok(time) = metadata.modified() {
1065     ///         println!("{:?}", time);
1066     ///     } else {
1067     ///         println!("Not supported on this platform");
1068     ///     }
1069     ///     Ok(())
1070     /// }
1071     /// ```
1072     #[stable(feature = "fs_time", since = "1.10.0")]
1073     pub fn modified(&self) -> io::Result<SystemTime> {
1074         self.0.modified().map(FromInner::from_inner)
1075     }
1076
1077     /// Returns the last access time of this metadata.
1078     ///
1079     /// The returned value corresponds to the `atime` field of `stat` on Unix
1080     /// platforms and the `ftLastAccessTime` field on Windows platforms.
1081     ///
1082     /// Note that not all platforms will keep this field update in a file's
1083     /// metadata, for example Windows has an option to disable updating this
1084     /// time when files are accessed and Linux similarly has `noatime`.
1085     ///
1086     /// # Errors
1087     ///
1088     /// This field may not be available on all platforms, and will return an
1089     /// `Err` on platforms where it is not available.
1090     ///
1091     /// # Examples
1092     ///
1093     /// ```no_run
1094     /// use std::fs;
1095     ///
1096     /// fn main() -> std::io::Result<()> {
1097     ///     let metadata = fs::metadata("foo.txt")?;
1098     ///
1099     ///     if let Ok(time) = metadata.accessed() {
1100     ///         println!("{:?}", time);
1101     ///     } else {
1102     ///         println!("Not supported on this platform");
1103     ///     }
1104     ///     Ok(())
1105     /// }
1106     /// ```
1107     #[stable(feature = "fs_time", since = "1.10.0")]
1108     pub fn accessed(&self) -> io::Result<SystemTime> {
1109         self.0.accessed().map(FromInner::from_inner)
1110     }
1111
1112     /// Returns the creation time listed in this metadata.
1113     ///
1114     /// The returned value corresponds to the `btime` field of `statx` on
1115     /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other
1116     /// Unix platforms, and the `ftCreationTime` field on Windows platforms.
1117     ///
1118     /// # Errors
1119     ///
1120     /// This field may not be available on all platforms, and will return an
1121     /// `Err` on platforms or filesystems where it is not available.
1122     ///
1123     /// # Examples
1124     ///
1125     /// ```no_run
1126     /// use std::fs;
1127     ///
1128     /// fn main() -> std::io::Result<()> {
1129     ///     let metadata = fs::metadata("foo.txt")?;
1130     ///
1131     ///     if let Ok(time) = metadata.created() {
1132     ///         println!("{:?}", time);
1133     ///     } else {
1134     ///         println!("Not supported on this platform or filesystem");
1135     ///     }
1136     ///     Ok(())
1137     /// }
1138     /// ```
1139     #[stable(feature = "fs_time", since = "1.10.0")]
1140     pub fn created(&self) -> io::Result<SystemTime> {
1141         self.0.created().map(FromInner::from_inner)
1142     }
1143 }
1144
1145 #[stable(feature = "std_debug", since = "1.16.0")]
1146 impl fmt::Debug for Metadata {
1147     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1148         f.debug_struct("Metadata")
1149             .field("file_type", &self.file_type())
1150             .field("is_dir", &self.is_dir())
1151             .field("is_file", &self.is_file())
1152             .field("permissions", &self.permissions())
1153             .field("modified", &self.modified())
1154             .field("accessed", &self.accessed())
1155             .field("created", &self.created())
1156             .finish()
1157     }
1158 }
1159
1160 impl AsInner<fs_imp::FileAttr> for Metadata {
1161     fn as_inner(&self) -> &fs_imp::FileAttr {
1162         &self.0
1163     }
1164 }
1165
1166 impl FromInner<fs_imp::FileAttr> for Metadata {
1167     fn from_inner(attr: fs_imp::FileAttr) -> Metadata {
1168         Metadata(attr)
1169     }
1170 }
1171
1172 impl Permissions {
1173     /// Returns `true` if these permissions describe a readonly (unwritable) file.
1174     ///
1175     /// # Examples
1176     ///
1177     /// ```no_run
1178     /// use std::fs::File;
1179     ///
1180     /// fn main() -> std::io::Result<()> {
1181     ///     let mut f = File::create("foo.txt")?;
1182     ///     let metadata = f.metadata()?;
1183     ///
1184     ///     assert_eq!(false, metadata.permissions().readonly());
1185     ///     Ok(())
1186     /// }
1187     /// ```
1188     #[stable(feature = "rust1", since = "1.0.0")]
1189     pub fn readonly(&self) -> bool {
1190         self.0.readonly()
1191     }
1192
1193     /// Modifies the readonly flag for this set of permissions. If the
1194     /// `readonly` argument is `true`, using the resulting `Permission` will
1195     /// update file permissions to forbid writing. Conversely, if it's `false`,
1196     /// using the resulting `Permission` will update file permissions to allow
1197     /// writing.
1198     ///
1199     /// This operation does **not** modify the filesystem. To modify the
1200     /// filesystem use the [`set_permissions`] function.
1201     ///
1202     /// # Examples
1203     ///
1204     /// ```no_run
1205     /// use std::fs::File;
1206     ///
1207     /// fn main() -> std::io::Result<()> {
1208     ///     let f = File::create("foo.txt")?;
1209     ///     let metadata = f.metadata()?;
1210     ///     let mut permissions = metadata.permissions();
1211     ///
1212     ///     permissions.set_readonly(true);
1213     ///
1214     ///     // filesystem doesn't change
1215     ///     assert_eq!(false, metadata.permissions().readonly());
1216     ///
1217     ///     // just this particular `permissions`.
1218     ///     assert_eq!(true, permissions.readonly());
1219     ///     Ok(())
1220     /// }
1221     /// ```
1222     #[stable(feature = "rust1", since = "1.0.0")]
1223     pub fn set_readonly(&mut self, readonly: bool) {
1224         self.0.set_readonly(readonly)
1225     }
1226 }
1227
1228 impl FileType {
1229     /// Tests whether this file type represents a directory. The
1230     /// result is mutually exclusive to the results of
1231     /// [`is_file`] and [`is_symlink`]; only zero or one of these
1232     /// tests may pass.
1233     ///
1234     /// [`is_file`]: FileType::is_file
1235     /// [`is_symlink`]: FileType::is_symlink
1236     ///
1237     /// # Examples
1238     ///
1239     /// ```no_run
1240     /// fn main() -> std::io::Result<()> {
1241     ///     use std::fs;
1242     ///
1243     ///     let metadata = fs::metadata("foo.txt")?;
1244     ///     let file_type = metadata.file_type();
1245     ///
1246     ///     assert_eq!(file_type.is_dir(), false);
1247     ///     Ok(())
1248     /// }
1249     /// ```
1250     #[stable(feature = "file_type", since = "1.1.0")]
1251     pub fn is_dir(&self) -> bool {
1252         self.0.is_dir()
1253     }
1254
1255     /// Tests whether this file type represents a regular file.
1256     /// The result is  mutually exclusive to the results of
1257     /// [`is_dir`] and [`is_symlink`]; only zero or one of these
1258     /// tests may pass.
1259     ///
1260     /// When the goal is simply to read from (or write to) the source, the most
1261     /// reliable way to test the source can be read (or written to) is to open
1262     /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
1263     /// a Unix-like system for example. See [`File::open`] or
1264     /// [`OpenOptions::open`] for more information.
1265     ///
1266     /// [`is_dir`]: FileType::is_dir
1267     /// [`is_symlink`]: FileType::is_symlink
1268     ///
1269     /// # Examples
1270     ///
1271     /// ```no_run
1272     /// fn main() -> std::io::Result<()> {
1273     ///     use std::fs;
1274     ///
1275     ///     let metadata = fs::metadata("foo.txt")?;
1276     ///     let file_type = metadata.file_type();
1277     ///
1278     ///     assert_eq!(file_type.is_file(), true);
1279     ///     Ok(())
1280     /// }
1281     /// ```
1282     #[stable(feature = "file_type", since = "1.1.0")]
1283     pub fn is_file(&self) -> bool {
1284         self.0.is_file()
1285     }
1286
1287     /// Tests whether this file type represents a symbolic link.
1288     /// The result is mutually exclusive to the results of
1289     /// [`is_dir`] and [`is_file`]; only zero or one of these
1290     /// tests may pass.
1291     ///
1292     /// The underlying [`Metadata`] struct needs to be retrieved
1293     /// with the [`fs::symlink_metadata`] function and not the
1294     /// [`fs::metadata`] function. The [`fs::metadata`] function
1295     /// follows symbolic links, so [`is_symlink`] would always
1296     /// return `false` for the target file.
1297     ///
1298     /// [`fs::metadata`]: metadata
1299     /// [`fs::symlink_metadata`]: symlink_metadata
1300     /// [`is_dir`]: FileType::is_dir
1301     /// [`is_file`]: FileType::is_file
1302     /// [`is_symlink`]: FileType::is_symlink
1303     ///
1304     /// # Examples
1305     ///
1306     /// ```no_run
1307     /// use std::fs;
1308     ///
1309     /// fn main() -> std::io::Result<()> {
1310     ///     let metadata = fs::symlink_metadata("foo.txt")?;
1311     ///     let file_type = metadata.file_type();
1312     ///
1313     ///     assert_eq!(file_type.is_symlink(), false);
1314     ///     Ok(())
1315     /// }
1316     /// ```
1317     #[stable(feature = "file_type", since = "1.1.0")]
1318     pub fn is_symlink(&self) -> bool {
1319         self.0.is_symlink()
1320     }
1321 }
1322
1323 impl AsInner<fs_imp::FileType> for FileType {
1324     fn as_inner(&self) -> &fs_imp::FileType {
1325         &self.0
1326     }
1327 }
1328
1329 impl FromInner<fs_imp::FilePermissions> for Permissions {
1330     fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
1331         Permissions(f)
1332     }
1333 }
1334
1335 impl AsInner<fs_imp::FilePermissions> for Permissions {
1336     fn as_inner(&self) -> &fs_imp::FilePermissions {
1337         &self.0
1338     }
1339 }
1340
1341 #[stable(feature = "rust1", since = "1.0.0")]
1342 impl Iterator for ReadDir {
1343     type Item = io::Result<DirEntry>;
1344
1345     fn next(&mut self) -> Option<io::Result<DirEntry>> {
1346         self.0.next().map(|entry| entry.map(DirEntry))
1347     }
1348 }
1349
1350 impl DirEntry {
1351     /// Returns the full path to the file that this entry represents.
1352     ///
1353     /// The full path is created by joining the original path to `read_dir`
1354     /// with the filename of this entry.
1355     ///
1356     /// # Examples
1357     ///
1358     /// ```no_run
1359     /// use std::fs;
1360     ///
1361     /// fn main() -> std::io::Result<()> {
1362     ///     for entry in fs::read_dir(".")? {
1363     ///         let dir = entry?;
1364     ///         println!("{:?}", dir.path());
1365     ///     }
1366     ///     Ok(())
1367     /// }
1368     /// ```
1369     ///
1370     /// This prints output like:
1371     ///
1372     /// ```text
1373     /// "./whatever.txt"
1374     /// "./foo.html"
1375     /// "./hello_world.rs"
1376     /// ```
1377     ///
1378     /// The exact text, of course, depends on what files you have in `.`.
1379     #[stable(feature = "rust1", since = "1.0.0")]
1380     pub fn path(&self) -> PathBuf {
1381         self.0.path()
1382     }
1383
1384     /// Returns the metadata for the file that this entry points at.
1385     ///
1386     /// This function will not traverse symlinks if this entry points at a
1387     /// symlink. To traverse symlinks use [`fs::metadata`] or [`fs::File::metadata`].
1388     ///
1389     /// [`fs::metadata`]: metadata
1390     /// [`fs::File::metadata`]: File::metadata
1391     ///
1392     /// # Platform-specific behavior
1393     ///
1394     /// On Windows this function is cheap to call (no extra system calls
1395     /// needed), but on Unix platforms this function is the equivalent of
1396     /// calling `symlink_metadata` on the path.
1397     ///
1398     /// # Examples
1399     ///
1400     /// ```
1401     /// use std::fs;
1402     ///
1403     /// if let Ok(entries) = fs::read_dir(".") {
1404     ///     for entry in entries {
1405     ///         if let Ok(entry) = entry {
1406     ///             // Here, `entry` is a `DirEntry`.
1407     ///             if let Ok(metadata) = entry.metadata() {
1408     ///                 // Now let's show our entry's permissions!
1409     ///                 println!("{:?}: {:?}", entry.path(), metadata.permissions());
1410     ///             } else {
1411     ///                 println!("Couldn't get metadata for {:?}", entry.path());
1412     ///             }
1413     ///         }
1414     ///     }
1415     /// }
1416     /// ```
1417     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1418     pub fn metadata(&self) -> io::Result<Metadata> {
1419         self.0.metadata().map(Metadata)
1420     }
1421
1422     /// Returns the file type for the file that this entry points at.
1423     ///
1424     /// This function will not traverse symlinks if this entry points at a
1425     /// symlink.
1426     ///
1427     /// # Platform-specific behavior
1428     ///
1429     /// On Windows and most Unix platforms this function is free (no extra
1430     /// system calls needed), but some Unix platforms may require the equivalent
1431     /// call to `symlink_metadata` to learn about the target file type.
1432     ///
1433     /// # Examples
1434     ///
1435     /// ```
1436     /// use std::fs;
1437     ///
1438     /// if let Ok(entries) = fs::read_dir(".") {
1439     ///     for entry in entries {
1440     ///         if let Ok(entry) = entry {
1441     ///             // Here, `entry` is a `DirEntry`.
1442     ///             if let Ok(file_type) = entry.file_type() {
1443     ///                 // Now let's show our entry's file type!
1444     ///                 println!("{:?}: {:?}", entry.path(), file_type);
1445     ///             } else {
1446     ///                 println!("Couldn't get file type for {:?}", entry.path());
1447     ///             }
1448     ///         }
1449     ///     }
1450     /// }
1451     /// ```
1452     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1453     pub fn file_type(&self) -> io::Result<FileType> {
1454         self.0.file_type().map(FileType)
1455     }
1456
1457     /// Returns the bare file name of this directory entry without any other
1458     /// leading path component.
1459     ///
1460     /// # Examples
1461     ///
1462     /// ```
1463     /// use std::fs;
1464     ///
1465     /// if let Ok(entries) = fs::read_dir(".") {
1466     ///     for entry in entries {
1467     ///         if let Ok(entry) = entry {
1468     ///             // Here, `entry` is a `DirEntry`.
1469     ///             println!("{:?}", entry.file_name());
1470     ///         }
1471     ///     }
1472     /// }
1473     /// ```
1474     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1475     pub fn file_name(&self) -> OsString {
1476         self.0.file_name()
1477     }
1478 }
1479
1480 #[stable(feature = "dir_entry_debug", since = "1.13.0")]
1481 impl fmt::Debug for DirEntry {
1482     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1483         f.debug_tuple("DirEntry").field(&self.path()).finish()
1484     }
1485 }
1486
1487 impl AsInner<fs_imp::DirEntry> for DirEntry {
1488     fn as_inner(&self) -> &fs_imp::DirEntry {
1489         &self.0
1490     }
1491 }
1492
1493 /// Removes a file from the filesystem.
1494 ///
1495 /// Note that there is no
1496 /// guarantee that the file is immediately deleted (e.g., depending on
1497 /// platform, other open file descriptors may prevent immediate removal).
1498 ///
1499 /// # Platform-specific behavior
1500 ///
1501 /// This function currently corresponds to the `unlink` function on Unix
1502 /// and the `DeleteFile` function on Windows.
1503 /// Note that, this [may change in the future][changes].
1504 ///
1505 /// [changes]: ../io/index.html#platform-specific-behavior
1506 ///
1507 /// # Errors
1508 ///
1509 /// This function will return an error in the following situations, but is not
1510 /// limited to just these cases:
1511 ///
1512 /// * `path` points to a directory.
1513 /// * The file doesn't exist.
1514 /// * The user lacks permissions to remove the file.
1515 ///
1516 /// # Examples
1517 ///
1518 /// ```no_run
1519 /// use std::fs;
1520 ///
1521 /// fn main() -> std::io::Result<()> {
1522 ///     fs::remove_file("a.txt")?;
1523 ///     Ok(())
1524 /// }
1525 /// ```
1526 #[stable(feature = "rust1", since = "1.0.0")]
1527 pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
1528     fs_imp::unlink(path.as_ref())
1529 }
1530
1531 /// Given a path, query the file system to get information about a file,
1532 /// directory, etc.
1533 ///
1534 /// This function will traverse symbolic links to query information about the
1535 /// destination file.
1536 ///
1537 /// # Platform-specific behavior
1538 ///
1539 /// This function currently corresponds to the `stat` function on Unix
1540 /// and the `GetFileAttributesEx` function on Windows.
1541 /// Note that, this [may change in the future][changes].
1542 ///
1543 /// [changes]: ../io/index.html#platform-specific-behavior
1544 ///
1545 /// # Errors
1546 ///
1547 /// This function will return an error in the following situations, but is not
1548 /// limited to just these cases:
1549 ///
1550 /// * The user lacks permissions to perform `metadata` call on `path`.
1551 /// * `path` does not exist.
1552 ///
1553 /// # Examples
1554 ///
1555 /// ```rust,no_run
1556 /// use std::fs;
1557 ///
1558 /// fn main() -> std::io::Result<()> {
1559 ///     let attr = fs::metadata("/some/file/path.txt")?;
1560 ///     // inspect attr ...
1561 ///     Ok(())
1562 /// }
1563 /// ```
1564 #[stable(feature = "rust1", since = "1.0.0")]
1565 pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
1566     fs_imp::stat(path.as_ref()).map(Metadata)
1567 }
1568
1569 /// Query the metadata about a file without following symlinks.
1570 ///
1571 /// # Platform-specific behavior
1572 ///
1573 /// This function currently corresponds to the `lstat` function on Unix
1574 /// and the `GetFileAttributesEx` function on Windows.
1575 /// Note that, this [may change in the future][changes].
1576 ///
1577 /// [changes]: ../io/index.html#platform-specific-behavior
1578 ///
1579 /// # Errors
1580 ///
1581 /// This function will return an error in the following situations, but is not
1582 /// limited to just these cases:
1583 ///
1584 /// * The user lacks permissions to perform `metadata` call on `path`.
1585 /// * `path` does not exist.
1586 ///
1587 /// # Examples
1588 ///
1589 /// ```rust,no_run
1590 /// use std::fs;
1591 ///
1592 /// fn main() -> std::io::Result<()> {
1593 ///     let attr = fs::symlink_metadata("/some/file/path.txt")?;
1594 ///     // inspect attr ...
1595 ///     Ok(())
1596 /// }
1597 /// ```
1598 #[stable(feature = "symlink_metadata", since = "1.1.0")]
1599 pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
1600     fs_imp::lstat(path.as_ref()).map(Metadata)
1601 }
1602
1603 /// Rename a file or directory to a new name, replacing the original file if
1604 /// `to` already exists.
1605 ///
1606 /// This will not work if the new name is on a different mount point.
1607 ///
1608 /// # Platform-specific behavior
1609 ///
1610 /// This function currently corresponds to the `rename` function on Unix
1611 /// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows.
1612 ///
1613 /// Because of this, the behavior when both `from` and `to` exist differs. On
1614 /// Unix, if `from` is a directory, `to` must also be an (empty) directory. If
1615 /// `from` is not a directory, `to` must also be not a directory. In contrast,
1616 /// on Windows, `from` can be anything, but `to` must *not* be a directory.
1617 ///
1618 /// Note that, this [may change in the future][changes].
1619 ///
1620 /// [changes]: ../io/index.html#platform-specific-behavior
1621 ///
1622 /// # Errors
1623 ///
1624 /// This function will return an error in the following situations, but is not
1625 /// limited to just these cases:
1626 ///
1627 /// * `from` does not exist.
1628 /// * The user lacks permissions to view contents.
1629 /// * `from` and `to` are on separate filesystems.
1630 ///
1631 /// # Examples
1632 ///
1633 /// ```no_run
1634 /// use std::fs;
1635 ///
1636 /// fn main() -> std::io::Result<()> {
1637 ///     fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
1638 ///     Ok(())
1639 /// }
1640 /// ```
1641 #[stable(feature = "rust1", since = "1.0.0")]
1642 pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
1643     fs_imp::rename(from.as_ref(), to.as_ref())
1644 }
1645
1646 /// Copies the contents of one file to another. This function will also
1647 /// copy the permission bits of the original file to the destination file.
1648 ///
1649 /// This function will **overwrite** the contents of `to`.
1650 ///
1651 /// Note that if `from` and `to` both point to the same file, then the file
1652 /// will likely get truncated by this operation.
1653 ///
1654 /// On success, the total number of bytes copied is returned and it is equal to
1655 /// the length of the `to` file as reported by `metadata`.
1656 ///
1657 /// If you’re wanting to copy the contents of one file to another and you’re
1658 /// working with [`File`]s, see the [`io::copy`] function.
1659 ///
1660 /// # Platform-specific behavior
1661 ///
1662 /// This function currently corresponds to the `open` function in Unix
1663 /// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
1664 /// `O_CLOEXEC` is set for returned file descriptors.
1665 /// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
1666 /// NTFS streams are copied but only the size of the main stream is returned by
1667 /// this function. On MacOS, this function corresponds to `fclonefileat` and
1668 /// `fcopyfile`.
1669 /// Note that, this [may change in the future][changes].
1670 ///
1671 /// [changes]: ../io/index.html#platform-specific-behavior
1672 ///
1673 /// # Errors
1674 ///
1675 /// This function will return an error in the following situations, but is not
1676 /// limited to just these cases:
1677 ///
1678 /// * The `from` path is not a file.
1679 /// * The `from` file does not exist.
1680 /// * The current process does not have the permission rights to access
1681 ///   `from` or write `to`.
1682 ///
1683 /// # Examples
1684 ///
1685 /// ```no_run
1686 /// use std::fs;
1687 ///
1688 /// fn main() -> std::io::Result<()> {
1689 ///     fs::copy("foo.txt", "bar.txt")?;  // Copy foo.txt to bar.txt
1690 ///     Ok(())
1691 /// }
1692 /// ```
1693 #[stable(feature = "rust1", since = "1.0.0")]
1694 pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
1695     fs_imp::copy(from.as_ref(), to.as_ref())
1696 }
1697
1698 /// Creates a new hard link on the filesystem.
1699 ///
1700 /// The `dst` path will be a link pointing to the `src` path. Note that systems
1701 /// often require these two paths to both be located on the same filesystem.
1702 ///
1703 /// # Platform-specific behavior
1704 ///
1705 /// This function currently corresponds to the `link` function on Unix
1706 /// and the `CreateHardLink` function on Windows.
1707 /// Note that, this [may change in the future][changes].
1708 ///
1709 /// [changes]: ../io/index.html#platform-specific-behavior
1710 ///
1711 /// # Errors
1712 ///
1713 /// This function will return an error in the following situations, but is not
1714 /// limited to just these cases:
1715 ///
1716 /// * The `src` path is not a file or doesn't exist.
1717 ///
1718 /// # Examples
1719 ///
1720 /// ```no_run
1721 /// use std::fs;
1722 ///
1723 /// fn main() -> std::io::Result<()> {
1724 ///     fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
1725 ///     Ok(())
1726 /// }
1727 /// ```
1728 #[stable(feature = "rust1", since = "1.0.0")]
1729 pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
1730     fs_imp::link(src.as_ref(), dst.as_ref())
1731 }
1732
1733 /// Creates a new symbolic link on the filesystem.
1734 ///
1735 /// The `dst` path will be a symbolic link pointing to the `src` path.
1736 /// On Windows, this will be a file symlink, not a directory symlink;
1737 /// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
1738 /// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
1739 /// used instead to make the intent explicit.
1740 ///
1741 /// [`std::os::unix::fs::symlink`]: crate::os::unix::fs::symlink
1742 /// [`std::os::windows::fs::symlink_file`]: crate::os::windows::fs::symlink_file
1743 /// [`symlink_dir`]: crate::os::windows::fs::symlink_dir
1744 ///
1745 /// # Examples
1746 ///
1747 /// ```no_run
1748 /// use std::fs;
1749 ///
1750 /// fn main() -> std::io::Result<()> {
1751 ///     fs::soft_link("a.txt", "b.txt")?;
1752 ///     Ok(())
1753 /// }
1754 /// ```
1755 #[stable(feature = "rust1", since = "1.0.0")]
1756 #[rustc_deprecated(
1757     since = "1.1.0",
1758     reason = "replaced with std::os::unix::fs::symlink and \
1759               std::os::windows::fs::{symlink_file, symlink_dir}"
1760 )]
1761 pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()> {
1762     fs_imp::symlink(src.as_ref(), dst.as_ref())
1763 }
1764
1765 /// Reads a symbolic link, returning the file that the link points to.
1766 ///
1767 /// # Platform-specific behavior
1768 ///
1769 /// This function currently corresponds to the `readlink` function on Unix
1770 /// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and
1771 /// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows.
1772 /// Note that, this [may change in the future][changes].
1773 ///
1774 /// [changes]: ../io/index.html#platform-specific-behavior
1775 ///
1776 /// # Errors
1777 ///
1778 /// This function will return an error in the following situations, but is not
1779 /// limited to just these cases:
1780 ///
1781 /// * `path` is not a symbolic link.
1782 /// * `path` does not exist.
1783 ///
1784 /// # Examples
1785 ///
1786 /// ```no_run
1787 /// use std::fs;
1788 ///
1789 /// fn main() -> std::io::Result<()> {
1790 ///     let path = fs::read_link("a.txt")?;
1791 ///     Ok(())
1792 /// }
1793 /// ```
1794 #[stable(feature = "rust1", since = "1.0.0")]
1795 pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
1796     fs_imp::readlink(path.as_ref())
1797 }
1798
1799 /// Returns the canonical, absolute form of a path with all intermediate
1800 /// components normalized and symbolic links resolved.
1801 ///
1802 /// # Platform-specific behavior
1803 ///
1804 /// This function currently corresponds to the `realpath` function on Unix
1805 /// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
1806 /// Note that, this [may change in the future][changes].
1807 ///
1808 /// On Windows, this converts the path to use [extended length path][path]
1809 /// syntax, which allows your program to use longer path names, but means you
1810 /// can only join backslash-delimited paths to it, and it may be incompatible
1811 /// with other applications (if passed to the application on the command-line,
1812 /// or written to a file another application may read).
1813 ///
1814 /// [changes]: ../io/index.html#platform-specific-behavior
1815 /// [path]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
1816 ///
1817 /// # Errors
1818 ///
1819 /// This function will return an error in the following situations, but is not
1820 /// limited to just these cases:
1821 ///
1822 /// * `path` does not exist.
1823 /// * A non-final component in path is not a directory.
1824 ///
1825 /// # Examples
1826 ///
1827 /// ```no_run
1828 /// use std::fs;
1829 ///
1830 /// fn main() -> std::io::Result<()> {
1831 ///     let path = fs::canonicalize("../a/../foo.txt")?;
1832 ///     Ok(())
1833 /// }
1834 /// ```
1835 #[stable(feature = "fs_canonicalize", since = "1.5.0")]
1836 pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
1837     fs_imp::canonicalize(path.as_ref())
1838 }
1839
1840 /// Creates a new, empty directory at the provided path
1841 ///
1842 /// # Platform-specific behavior
1843 ///
1844 /// This function currently corresponds to the `mkdir` function on Unix
1845 /// and the `CreateDirectory` function on Windows.
1846 /// Note that, this [may change in the future][changes].
1847 ///
1848 /// [changes]: ../io/index.html#platform-specific-behavior
1849 ///
1850 /// **NOTE**: If a parent of the given path doesn't exist, this function will
1851 /// return an error. To create a directory and all its missing parents at the
1852 /// same time, use the [`create_dir_all`] function.
1853 ///
1854 /// # Errors
1855 ///
1856 /// This function will return an error in the following situations, but is not
1857 /// limited to just these cases:
1858 ///
1859 /// * User lacks permissions to create directory at `path`.
1860 /// * A parent of the given path doesn't exist. (To create a directory and all
1861 ///   its missing parents at the same time, use the [`create_dir_all`]
1862 ///   function.)
1863 /// * `path` already exists.
1864 ///
1865 /// # Examples
1866 ///
1867 /// ```no_run
1868 /// use std::fs;
1869 ///
1870 /// fn main() -> std::io::Result<()> {
1871 ///     fs::create_dir("/some/dir")?;
1872 ///     Ok(())
1873 /// }
1874 /// ```
1875 #[stable(feature = "rust1", since = "1.0.0")]
1876 pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
1877     DirBuilder::new().create(path.as_ref())
1878 }
1879
1880 /// Recursively create a directory and all of its parent components if they
1881 /// are missing.
1882 ///
1883 /// # Platform-specific behavior
1884 ///
1885 /// This function currently corresponds to the `mkdir` function on Unix
1886 /// and the `CreateDirectory` function on Windows.
1887 /// Note that, this [may change in the future][changes].
1888 ///
1889 /// [changes]: ../io/index.html#platform-specific-behavior
1890 ///
1891 /// # Errors
1892 ///
1893 /// This function will return an error in the following situations, but is not
1894 /// limited to just these cases:
1895 ///
1896 /// * If any directory in the path specified by `path`
1897 /// does not already exist and it could not be created otherwise. The specific
1898 /// error conditions for when a directory is being created (after it is
1899 /// determined to not exist) are outlined by [`fs::create_dir`].
1900 ///
1901 /// Notable exception is made for situations where any of the directories
1902 /// specified in the `path` could not be created as it was being created concurrently.
1903 /// Such cases are considered to be successful. That is, calling `create_dir_all`
1904 /// concurrently from multiple threads or processes is guaranteed not to fail
1905 /// due to a race condition with itself.
1906 ///
1907 /// [`fs::create_dir`]: create_dir
1908 ///
1909 /// # Examples
1910 ///
1911 /// ```no_run
1912 /// use std::fs;
1913 ///
1914 /// fn main() -> std::io::Result<()> {
1915 ///     fs::create_dir_all("/some/dir")?;
1916 ///     Ok(())
1917 /// }
1918 /// ```
1919 #[stable(feature = "rust1", since = "1.0.0")]
1920 pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
1921     DirBuilder::new().recursive(true).create(path.as_ref())
1922 }
1923
1924 /// Removes an empty directory.
1925 ///
1926 /// # Platform-specific behavior
1927 ///
1928 /// This function currently corresponds to the `rmdir` function on Unix
1929 /// and the `RemoveDirectory` function on Windows.
1930 /// Note that, this [may change in the future][changes].
1931 ///
1932 /// [changes]: ../io/index.html#platform-specific-behavior
1933 ///
1934 /// # Errors
1935 ///
1936 /// This function will return an error in the following situations, but is not
1937 /// limited to just these cases:
1938 ///
1939 /// * `path` doesn't exist.
1940 /// * `path` isn't a directory.
1941 /// * The user lacks permissions to remove the directory at the provided `path`.
1942 /// * The directory isn't empty.
1943 ///
1944 /// # Examples
1945 ///
1946 /// ```no_run
1947 /// use std::fs;
1948 ///
1949 /// fn main() -> std::io::Result<()> {
1950 ///     fs::remove_dir("/some/dir")?;
1951 ///     Ok(())
1952 /// }
1953 /// ```
1954 #[stable(feature = "rust1", since = "1.0.0")]
1955 pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
1956     fs_imp::rmdir(path.as_ref())
1957 }
1958
1959 /// Removes a directory at this path, after removing all its contents. Use
1960 /// carefully!
1961 ///
1962 /// This function does **not** follow symbolic links and it will simply remove the
1963 /// symbolic link itself.
1964 ///
1965 /// # Platform-specific behavior
1966 ///
1967 /// This function currently corresponds to `opendir`, `lstat`, `rm` and `rmdir` functions on Unix
1968 /// and the `FindFirstFile`, `GetFileAttributesEx`, `DeleteFile`, and `RemoveDirectory` functions
1969 /// on Windows.
1970 /// Note that, this [may change in the future][changes].
1971 ///
1972 /// [changes]: ../io/index.html#platform-specific-behavior
1973 ///
1974 /// # Errors
1975 ///
1976 /// See [`fs::remove_file`] and [`fs::remove_dir`].
1977 ///
1978 /// [`fs::remove_file`]: remove_file
1979 /// [`fs::remove_dir`]: remove_dir
1980 ///
1981 /// # Examples
1982 ///
1983 /// ```no_run
1984 /// use std::fs;
1985 ///
1986 /// fn main() -> std::io::Result<()> {
1987 ///     fs::remove_dir_all("/some/dir")?;
1988 ///     Ok(())
1989 /// }
1990 /// ```
1991 #[stable(feature = "rust1", since = "1.0.0")]
1992 pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
1993     fs_imp::remove_dir_all(path.as_ref())
1994 }
1995
1996 /// Returns an iterator over the entries within a directory.
1997 ///
1998 /// The iterator will yield instances of [`io::Result`]`<`[`DirEntry`]`>`.
1999 /// New errors may be encountered after an iterator is initially constructed.
2000 ///
2001 /// # Platform-specific behavior
2002 ///
2003 /// This function currently corresponds to the `opendir` function on Unix
2004 /// and the `FindFirstFile` function on Windows. Advancing the iterator
2005 /// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows.
2006 /// Note that, this [may change in the future][changes].
2007 ///
2008 /// [changes]: ../io/index.html#platform-specific-behavior
2009 ///
2010 /// The order in which this iterator returns entries is platform and filesystem
2011 /// dependent.
2012 ///
2013 /// # Errors
2014 ///
2015 /// This function will return an error in the following situations, but is not
2016 /// limited to just these cases:
2017 ///
2018 /// * The provided `path` doesn't exist.
2019 /// * The process lacks permissions to view the contents.
2020 /// * The `path` points at a non-directory file.
2021 ///
2022 /// # Examples
2023 ///
2024 /// ```
2025 /// use std::io;
2026 /// use std::fs::{self, DirEntry};
2027 /// use std::path::Path;
2028 ///
2029 /// // one possible implementation of walking a directory only visiting files
2030 /// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> {
2031 ///     if dir.is_dir() {
2032 ///         for entry in fs::read_dir(dir)? {
2033 ///             let entry = entry?;
2034 ///             let path = entry.path();
2035 ///             if path.is_dir() {
2036 ///                 visit_dirs(&path, cb)?;
2037 ///             } else {
2038 ///                 cb(&entry);
2039 ///             }
2040 ///         }
2041 ///     }
2042 ///     Ok(())
2043 /// }
2044 /// ```
2045 ///
2046 /// ```rust,no_run
2047 /// use std::{fs, io};
2048 ///
2049 /// fn main() -> io::Result<()> {
2050 ///     let mut entries = fs::read_dir(".")?
2051 ///         .map(|res| res.map(|e| e.path()))
2052 ///         .collect::<Result<Vec<_>, io::Error>>()?;
2053 ///
2054 ///     // The order in which `read_dir` returns entries is not guaranteed. If reproducible
2055 ///     // ordering is required the entries should be explicitly sorted.
2056 ///
2057 ///     entries.sort();
2058 ///
2059 ///     // The entries have now been sorted by their path.
2060 ///
2061 ///     Ok(())
2062 /// }
2063 /// ```
2064 #[stable(feature = "rust1", since = "1.0.0")]
2065 pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
2066     fs_imp::readdir(path.as_ref()).map(ReadDir)
2067 }
2068
2069 /// Changes the permissions found on a file or a directory.
2070 ///
2071 /// # Platform-specific behavior
2072 ///
2073 /// This function currently corresponds to the `chmod` function on Unix
2074 /// and the `SetFileAttributes` function on Windows.
2075 /// Note that, this [may change in the future][changes].
2076 ///
2077 /// [changes]: ../io/index.html#platform-specific-behavior
2078 ///
2079 /// # Errors
2080 ///
2081 /// This function will return an error in the following situations, but is not
2082 /// limited to just these cases:
2083 ///
2084 /// * `path` does not exist.
2085 /// * The user lacks the permission to change attributes of the file.
2086 ///
2087 /// # Examples
2088 ///
2089 /// ```no_run
2090 /// use std::fs;
2091 ///
2092 /// fn main() -> std::io::Result<()> {
2093 ///     let mut perms = fs::metadata("foo.txt")?.permissions();
2094 ///     perms.set_readonly(true);
2095 ///     fs::set_permissions("foo.txt", perms)?;
2096 ///     Ok(())
2097 /// }
2098 /// ```
2099 #[stable(feature = "set_permissions", since = "1.1.0")]
2100 pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
2101     fs_imp::set_perm(path.as_ref(), perm.0)
2102 }
2103
2104 impl DirBuilder {
2105     /// Creates a new set of options with default mode/security settings for all
2106     /// platforms and also non-recursive.
2107     ///
2108     /// # Examples
2109     ///
2110     /// ```
2111     /// use std::fs::DirBuilder;
2112     ///
2113     /// let builder = DirBuilder::new();
2114     /// ```
2115     #[stable(feature = "dir_builder", since = "1.6.0")]
2116     pub fn new() -> DirBuilder {
2117         DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false }
2118     }
2119
2120     /// Indicates that directories should be created recursively, creating all
2121     /// parent directories. Parents that do not exist are created with the same
2122     /// security and permissions settings.
2123     ///
2124     /// This option defaults to `false`.
2125     ///
2126     /// # Examples
2127     ///
2128     /// ```
2129     /// use std::fs::DirBuilder;
2130     ///
2131     /// let mut builder = DirBuilder::new();
2132     /// builder.recursive(true);
2133     /// ```
2134     #[stable(feature = "dir_builder", since = "1.6.0")]
2135     pub fn recursive(&mut self, recursive: bool) -> &mut Self {
2136         self.recursive = recursive;
2137         self
2138     }
2139
2140     /// Creates the specified directory with the options configured in this
2141     /// builder.
2142     ///
2143     /// It is considered an error if the directory already exists unless
2144     /// recursive mode is enabled.
2145     ///
2146     /// # Examples
2147     ///
2148     /// ```no_run
2149     /// use std::fs::{self, DirBuilder};
2150     ///
2151     /// let path = "/tmp/foo/bar/baz";
2152     /// DirBuilder::new()
2153     ///     .recursive(true)
2154     ///     .create(path).unwrap();
2155     ///
2156     /// assert!(fs::metadata(path).unwrap().is_dir());
2157     /// ```
2158     #[stable(feature = "dir_builder", since = "1.6.0")]
2159     pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
2160         self._create(path.as_ref())
2161     }
2162
2163     fn _create(&self, path: &Path) -> io::Result<()> {
2164         if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) }
2165     }
2166
2167     fn create_dir_all(&self, path: &Path) -> io::Result<()> {
2168         if path == Path::new("") {
2169             return Ok(());
2170         }
2171
2172         match self.inner.mkdir(path) {
2173             Ok(()) => return Ok(()),
2174             Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
2175             Err(_) if path.is_dir() => return Ok(()),
2176             Err(e) => return Err(e),
2177         }
2178         match path.parent() {
2179             Some(p) => self.create_dir_all(p)?,
2180             None => {
2181                 return Err(io::Error::new(io::ErrorKind::Other, "failed to create whole tree"));
2182             }
2183         }
2184         match self.inner.mkdir(path) {
2185             Ok(()) => Ok(()),
2186             Err(_) if path.is_dir() => Ok(()),
2187             Err(e) => Err(e),
2188         }
2189     }
2190 }
2191
2192 impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
2193     fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
2194         &mut self.inner
2195     }
2196 }
2197
2198 #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))]
2199 mod tests {
2200     use crate::io::prelude::*;
2201
2202     use crate::fs::{self, File, OpenOptions};
2203     use crate::io::{ErrorKind, SeekFrom};
2204     use crate::path::Path;
2205     use crate::str;
2206     use crate::sys_common::io::test::{tmpdir, TempDir};
2207     use crate::thread;
2208
2209     use rand::{rngs::StdRng, RngCore, SeedableRng};
2210
2211     #[cfg(unix)]
2212     use crate::os::unix::fs::symlink as symlink_dir;
2213     #[cfg(unix)]
2214     use crate::os::unix::fs::symlink as symlink_file;
2215     #[cfg(unix)]
2216     use crate::os::unix::fs::symlink as symlink_junction;
2217     #[cfg(windows)]
2218     use crate::os::windows::fs::{symlink_dir, symlink_file};
2219     #[cfg(windows)]
2220     use crate::sys::fs::symlink_junction;
2221
2222     macro_rules! check {
2223         ($e:expr) => {
2224             match $e {
2225                 Ok(t) => t,
2226                 Err(e) => panic!("{} failed with: {}", stringify!($e), e),
2227             }
2228         };
2229     }
2230
2231     #[cfg(windows)]
2232     macro_rules! error {
2233         ($e:expr, $s:expr) => {
2234             match $e {
2235                 Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
2236                 Err(ref err) => assert!(
2237                     err.raw_os_error() == Some($s),
2238                     format!("`{}` did not have a code of `{}`", err, $s)
2239                 ),
2240             }
2241         };
2242     }
2243
2244     #[cfg(unix)]
2245     macro_rules! error {
2246         ($e:expr, $s:expr) => {
2247             error_contains!($e, $s)
2248         };
2249     }
2250
2251     macro_rules! error_contains {
2252         ($e:expr, $s:expr) => {
2253             match $e {
2254                 Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
2255                 Err(ref err) => assert!(
2256                     err.to_string().contains($s),
2257                     format!("`{}` did not contain `{}`", err, $s)
2258                 ),
2259             }
2260         };
2261     }
2262
2263     // Several test fail on windows if the user does not have permission to
2264     // create symlinks (the `SeCreateSymbolicLinkPrivilege`). Instead of
2265     // disabling these test on Windows, use this function to test whether we
2266     // have permission, and return otherwise. This way, we still don't run these
2267     // tests most of the time, but at least we do if the user has the right
2268     // permissions.
2269     pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
2270         if cfg!(unix) {
2271             return true;
2272         }
2273         let link = tmpdir.join("some_hopefully_unique_link_name");
2274
2275         match symlink_file(r"nonexisting_target", link) {
2276             Ok(_) => true,
2277             // ERROR_PRIVILEGE_NOT_HELD = 1314
2278             Err(ref err) if err.raw_os_error() == Some(1314) => false,
2279             Err(_) => true,
2280         }
2281     }
2282
2283     #[test]
2284     fn file_test_io_smoke_test() {
2285         let message = "it's alright. have a good time";
2286         let tmpdir = tmpdir();
2287         let filename = &tmpdir.join("file_rt_io_file_test.txt");
2288         {
2289             let mut write_stream = check!(File::create(filename));
2290             check!(write_stream.write(message.as_bytes()));
2291         }
2292         {
2293             let mut read_stream = check!(File::open(filename));
2294             let mut read_buf = [0; 1028];
2295             let read_str = match check!(read_stream.read(&mut read_buf)) {
2296                 0 => panic!("shouldn't happen"),
2297                 n => str::from_utf8(&read_buf[..n]).unwrap().to_string(),
2298             };
2299             assert_eq!(read_str, message);
2300         }
2301         check!(fs::remove_file(filename));
2302     }
2303
2304     #[test]
2305     fn invalid_path_raises() {
2306         let tmpdir = tmpdir();
2307         let filename = &tmpdir.join("file_that_does_not_exist.txt");
2308         let result = File::open(filename);
2309
2310         #[cfg(all(unix, not(target_os = "vxworks")))]
2311         error!(result, "No such file or directory");
2312         #[cfg(target_os = "vxworks")]
2313         error!(result, "no such file or directory");
2314         #[cfg(windows)]
2315         error!(result, 2); // ERROR_FILE_NOT_FOUND
2316     }
2317
2318     #[test]
2319     fn file_test_iounlinking_invalid_path_should_raise_condition() {
2320         let tmpdir = tmpdir();
2321         let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
2322
2323         let result = fs::remove_file(filename);
2324
2325         #[cfg(all(unix, not(target_os = "vxworks")))]
2326         error!(result, "No such file or directory");
2327         #[cfg(target_os = "vxworks")]
2328         error!(result, "no such file or directory");
2329         #[cfg(windows)]
2330         error!(result, 2); // ERROR_FILE_NOT_FOUND
2331     }
2332
2333     #[test]
2334     fn file_test_io_non_positional_read() {
2335         let message: &str = "ten-four";
2336         let mut read_mem = [0; 8];
2337         let tmpdir = tmpdir();
2338         let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
2339         {
2340             let mut rw_stream = check!(File::create(filename));
2341             check!(rw_stream.write(message.as_bytes()));
2342         }
2343         {
2344             let mut read_stream = check!(File::open(filename));
2345             {
2346                 let read_buf = &mut read_mem[0..4];
2347                 check!(read_stream.read(read_buf));
2348             }
2349             {
2350                 let read_buf = &mut read_mem[4..8];
2351                 check!(read_stream.read(read_buf));
2352             }
2353         }
2354         check!(fs::remove_file(filename));
2355         let read_str = str::from_utf8(&read_mem).unwrap();
2356         assert_eq!(read_str, message);
2357     }
2358
2359     #[test]
2360     fn file_test_io_seek_and_tell_smoke_test() {
2361         let message = "ten-four";
2362         let mut read_mem = [0; 4];
2363         let set_cursor = 4 as u64;
2364         let tell_pos_pre_read;
2365         let tell_pos_post_read;
2366         let tmpdir = tmpdir();
2367         let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
2368         {
2369             let mut rw_stream = check!(File::create(filename));
2370             check!(rw_stream.write(message.as_bytes()));
2371         }
2372         {
2373             let mut read_stream = check!(File::open(filename));
2374             check!(read_stream.seek(SeekFrom::Start(set_cursor)));
2375             tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0)));
2376             check!(read_stream.read(&mut read_mem));
2377             tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0)));
2378         }
2379         check!(fs::remove_file(filename));
2380         let read_str = str::from_utf8(&read_mem).unwrap();
2381         assert_eq!(read_str, &message[4..8]);
2382         assert_eq!(tell_pos_pre_read, set_cursor);
2383         assert_eq!(tell_pos_post_read, message.len() as u64);
2384     }
2385
2386     #[test]
2387     fn file_test_io_seek_and_write() {
2388         let initial_msg = "food-is-yummy";
2389         let overwrite_msg = "-the-bar!!";
2390         let final_msg = "foo-the-bar!!";
2391         let seek_idx = 3;
2392         let mut read_mem = [0; 13];
2393         let tmpdir = tmpdir();
2394         let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
2395         {
2396             let mut rw_stream = check!(File::create(filename));
2397             check!(rw_stream.write(initial_msg.as_bytes()));
2398             check!(rw_stream.seek(SeekFrom::Start(seek_idx)));
2399             check!(rw_stream.write(overwrite_msg.as_bytes()));
2400         }
2401         {
2402             let mut read_stream = check!(File::open(filename));
2403             check!(read_stream.read(&mut read_mem));
2404         }
2405         check!(fs::remove_file(filename));
2406         let read_str = str::from_utf8(&read_mem).unwrap();
2407         assert!(read_str == final_msg);
2408     }
2409
2410     #[test]
2411     fn file_test_io_seek_shakedown() {
2412         //                   01234567890123
2413         let initial_msg = "qwer-asdf-zxcv";
2414         let chunk_one: &str = "qwer";
2415         let chunk_two: &str = "asdf";
2416         let chunk_three: &str = "zxcv";
2417         let mut read_mem = [0; 4];
2418         let tmpdir = tmpdir();
2419         let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
2420         {
2421             let mut rw_stream = check!(File::create(filename));
2422             check!(rw_stream.write(initial_msg.as_bytes()));
2423         }
2424         {
2425             let mut read_stream = check!(File::open(filename));
2426
2427             check!(read_stream.seek(SeekFrom::End(-4)));
2428             check!(read_stream.read(&mut read_mem));
2429             assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three);
2430
2431             check!(read_stream.seek(SeekFrom::Current(-9)));
2432             check!(read_stream.read(&mut read_mem));
2433             assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two);
2434
2435             check!(read_stream.seek(SeekFrom::Start(0)));
2436             check!(read_stream.read(&mut read_mem));
2437             assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one);
2438         }
2439         check!(fs::remove_file(filename));
2440     }
2441
2442     #[test]
2443     fn file_test_io_eof() {
2444         let tmpdir = tmpdir();
2445         let filename = tmpdir.join("file_rt_io_file_test_eof.txt");
2446         let mut buf = [0; 256];
2447         {
2448             let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
2449             let mut rw = check!(oo.open(&filename));
2450             assert_eq!(check!(rw.read(&mut buf)), 0);
2451             assert_eq!(check!(rw.read(&mut buf)), 0);
2452         }
2453         check!(fs::remove_file(&filename));
2454     }
2455
2456     #[test]
2457     #[cfg(unix)]
2458     fn file_test_io_read_write_at() {
2459         use crate::os::unix::fs::FileExt;
2460
2461         let tmpdir = tmpdir();
2462         let filename = tmpdir.join("file_rt_io_file_test_read_write_at.txt");
2463         let mut buf = [0; 256];
2464         let write1 = "asdf";
2465         let write2 = "qwer-";
2466         let write3 = "-zxcv";
2467         let content = "qwer-asdf-zxcv";
2468         {
2469             let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
2470             let mut rw = check!(oo.open(&filename));
2471             assert_eq!(check!(rw.write_at(write1.as_bytes(), 5)), write1.len());
2472             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
2473             assert_eq!(check!(rw.read_at(&mut buf, 5)), write1.len());
2474             assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
2475             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
2476             assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
2477             assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok("\0\0\0\0\0"));
2478             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 0);
2479             assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
2480             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
2481             assert_eq!(check!(rw.read(&mut buf)), write1.len());
2482             assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
2483             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2484             assert_eq!(check!(rw.read_at(&mut buf[..write2.len()], 0)), write2.len());
2485             assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
2486             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2487             assert_eq!(check!(rw.write_at(write3.as_bytes(), 9)), write3.len());
2488             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2489         }
2490         {
2491             let mut read = check!(File::open(&filename));
2492             assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
2493             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2494             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 0);
2495             assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
2496             assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
2497             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2498             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 9);
2499             assert_eq!(check!(read.read(&mut buf)), write3.len());
2500             assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
2501             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2502             assert_eq!(check!(read.read_at(&mut buf, 0)), content.len());
2503             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2504             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2505             assert_eq!(check!(read.read_at(&mut buf, 14)), 0);
2506             assert_eq!(check!(read.read_at(&mut buf, 15)), 0);
2507             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2508         }
2509         check!(fs::remove_file(&filename));
2510     }
2511
2512     #[test]
2513     #[cfg(unix)]
2514     fn set_get_unix_permissions() {
2515         use crate::os::unix::fs::PermissionsExt;
2516
2517         let tmpdir = tmpdir();
2518         let filename = &tmpdir.join("set_get_unix_permissions");
2519         check!(fs::create_dir(filename));
2520         let mask = 0o7777;
2521
2522         check!(fs::set_permissions(filename, fs::Permissions::from_mode(0)));
2523         let metadata0 = check!(fs::metadata(filename));
2524         assert_eq!(mask & metadata0.permissions().mode(), 0);
2525
2526         check!(fs::set_permissions(filename, fs::Permissions::from_mode(0o1777)));
2527         let metadata1 = check!(fs::metadata(filename));
2528         #[cfg(all(unix, not(target_os = "vxworks")))]
2529         assert_eq!(mask & metadata1.permissions().mode(), 0o1777);
2530         #[cfg(target_os = "vxworks")]
2531         assert_eq!(mask & metadata1.permissions().mode(), 0o0777);
2532     }
2533
2534     #[test]
2535     #[cfg(windows)]
2536     fn file_test_io_seek_read_write() {
2537         use crate::os::windows::fs::FileExt;
2538
2539         let tmpdir = tmpdir();
2540         let filename = tmpdir.join("file_rt_io_file_test_seek_read_write.txt");
2541         let mut buf = [0; 256];
2542         let write1 = "asdf";
2543         let write2 = "qwer-";
2544         let write3 = "-zxcv";
2545         let content = "qwer-asdf-zxcv";
2546         {
2547             let oo = OpenOptions::new().create_new(true).write(true).read(true).clone();
2548             let mut rw = check!(oo.open(&filename));
2549             assert_eq!(check!(rw.seek_write(write1.as_bytes(), 5)), write1.len());
2550             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2551             assert_eq!(check!(rw.seek_read(&mut buf, 5)), write1.len());
2552             assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
2553             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2554             assert_eq!(check!(rw.seek(SeekFrom::Start(0))), 0);
2555             assert_eq!(check!(rw.write(write2.as_bytes())), write2.len());
2556             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
2557             assert_eq!(check!(rw.read(&mut buf)), write1.len());
2558             assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1));
2559             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 9);
2560             assert_eq!(check!(rw.seek_read(&mut buf[..write2.len()], 0)), write2.len());
2561             assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2));
2562             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 5);
2563             assert_eq!(check!(rw.seek_write(write3.as_bytes(), 9)), write3.len());
2564             assert_eq!(check!(rw.seek(SeekFrom::Current(0))), 14);
2565         }
2566         {
2567             let mut read = check!(File::open(&filename));
2568             assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
2569             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2570             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2571             assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
2572             assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
2573             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2574             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2575             assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9);
2576             assert_eq!(check!(read.read(&mut buf)), write3.len());
2577             assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3));
2578             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2579             assert_eq!(check!(read.seek_read(&mut buf, 0)), content.len());
2580             assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content));
2581             assert_eq!(check!(read.seek(SeekFrom::Current(0))), 14);
2582             assert_eq!(check!(read.seek_read(&mut buf, 14)), 0);
2583             assert_eq!(check!(read.seek_read(&mut buf, 15)), 0);
2584         }
2585         check!(fs::remove_file(&filename));
2586     }
2587
2588     #[test]
2589     fn file_test_stat_is_correct_on_is_file() {
2590         let tmpdir = tmpdir();
2591         let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
2592         {
2593             let mut opts = OpenOptions::new();
2594             let mut fs = check!(opts.read(true).write(true).create(true).open(filename));
2595             let msg = "hw";
2596             fs.write(msg.as_bytes()).unwrap();
2597
2598             let fstat_res = check!(fs.metadata());
2599             assert!(fstat_res.is_file());
2600         }
2601         let stat_res_fn = check!(fs::metadata(filename));
2602         assert!(stat_res_fn.is_file());
2603         let stat_res_meth = check!(filename.metadata());
2604         assert!(stat_res_meth.is_file());
2605         check!(fs::remove_file(filename));
2606     }
2607
2608     #[test]
2609     fn file_test_stat_is_correct_on_is_dir() {
2610         let tmpdir = tmpdir();
2611         let filename = &tmpdir.join("file_stat_correct_on_is_dir");
2612         check!(fs::create_dir(filename));
2613         let stat_res_fn = check!(fs::metadata(filename));
2614         assert!(stat_res_fn.is_dir());
2615         let stat_res_meth = check!(filename.metadata());
2616         assert!(stat_res_meth.is_dir());
2617         check!(fs::remove_dir(filename));
2618     }
2619
2620     #[test]
2621     fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
2622         let tmpdir = tmpdir();
2623         let dir = &tmpdir.join("fileinfo_false_on_dir");
2624         check!(fs::create_dir(dir));
2625         assert!(!dir.is_file());
2626         check!(fs::remove_dir(dir));
2627     }
2628
2629     #[test]
2630     fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
2631         let tmpdir = tmpdir();
2632         let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
2633         check!(check!(File::create(file)).write(b"foo"));
2634         assert!(file.exists());
2635         check!(fs::remove_file(file));
2636         assert!(!file.exists());
2637     }
2638
2639     #[test]
2640     fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
2641         let tmpdir = tmpdir();
2642         let dir = &tmpdir.join("before_and_after_dir");
2643         assert!(!dir.exists());
2644         check!(fs::create_dir(dir));
2645         assert!(dir.exists());
2646         assert!(dir.is_dir());
2647         check!(fs::remove_dir(dir));
2648         assert!(!dir.exists());
2649     }
2650
2651     #[test]
2652     fn file_test_directoryinfo_readdir() {
2653         let tmpdir = tmpdir();
2654         let dir = &tmpdir.join("di_readdir");
2655         check!(fs::create_dir(dir));
2656         let prefix = "foo";
2657         for n in 0..3 {
2658             let f = dir.join(&format!("{}.txt", n));
2659             let mut w = check!(File::create(&f));
2660             let msg_str = format!("{}{}", prefix, n.to_string());
2661             let msg = msg_str.as_bytes();
2662             check!(w.write(msg));
2663         }
2664         let files = check!(fs::read_dir(dir));
2665         let mut mem = [0; 4];
2666         for f in files {
2667             let f = f.unwrap().path();
2668             {
2669                 let n = f.file_stem().unwrap();
2670                 check!(check!(File::open(&f)).read(&mut mem));
2671                 let read_str = str::from_utf8(&mem).unwrap();
2672                 let expected = format!("{}{}", prefix, n.to_str().unwrap());
2673                 assert_eq!(expected, read_str);
2674             }
2675             check!(fs::remove_file(&f));
2676         }
2677         check!(fs::remove_dir(dir));
2678     }
2679
2680     #[test]
2681     fn file_create_new_already_exists_error() {
2682         let tmpdir = tmpdir();
2683         let file = &tmpdir.join("file_create_new_error_exists");
2684         check!(fs::File::create(file));
2685         let e = fs::OpenOptions::new().write(true).create_new(true).open(file).unwrap_err();
2686         assert_eq!(e.kind(), ErrorKind::AlreadyExists);
2687     }
2688
2689     #[test]
2690     fn mkdir_path_already_exists_error() {
2691         let tmpdir = tmpdir();
2692         let dir = &tmpdir.join("mkdir_error_twice");
2693         check!(fs::create_dir(dir));
2694         let e = fs::create_dir(dir).unwrap_err();
2695         assert_eq!(e.kind(), ErrorKind::AlreadyExists);
2696     }
2697
2698     #[test]
2699     fn recursive_mkdir() {
2700         let tmpdir = tmpdir();
2701         let dir = tmpdir.join("d1/d2");
2702         check!(fs::create_dir_all(&dir));
2703         assert!(dir.is_dir())
2704     }
2705
2706     #[test]
2707     fn recursive_mkdir_failure() {
2708         let tmpdir = tmpdir();
2709         let dir = tmpdir.join("d1");
2710         let file = dir.join("f1");
2711
2712         check!(fs::create_dir_all(&dir));
2713         check!(File::create(&file));
2714
2715         let result = fs::create_dir_all(&file);
2716
2717         assert!(result.is_err());
2718     }
2719
2720     #[test]
2721     fn concurrent_recursive_mkdir() {
2722         for _ in 0..100 {
2723             let dir = tmpdir();
2724             let mut dir = dir.join("a");
2725             for _ in 0..40 {
2726                 dir = dir.join("a");
2727             }
2728             let mut join = vec![];
2729             for _ in 0..8 {
2730                 let dir = dir.clone();
2731                 join.push(thread::spawn(move || {
2732                     check!(fs::create_dir_all(&dir));
2733                 }))
2734             }
2735
2736             // No `Display` on result of `join()`
2737             join.drain(..).map(|join| join.join().unwrap()).count();
2738         }
2739     }
2740
2741     #[test]
2742     fn recursive_mkdir_slash() {
2743         check!(fs::create_dir_all(Path::new("/")));
2744     }
2745
2746     #[test]
2747     fn recursive_mkdir_dot() {
2748         check!(fs::create_dir_all(Path::new(".")));
2749     }
2750
2751     #[test]
2752     fn recursive_mkdir_empty() {
2753         check!(fs::create_dir_all(Path::new("")));
2754     }
2755
2756     #[test]
2757     fn recursive_rmdir() {
2758         let tmpdir = tmpdir();
2759         let d1 = tmpdir.join("d1");
2760         let dt = d1.join("t");
2761         let dtt = dt.join("t");
2762         let d2 = tmpdir.join("d2");
2763         let canary = d2.join("do_not_delete");
2764         check!(fs::create_dir_all(&dtt));
2765         check!(fs::create_dir_all(&d2));
2766         check!(check!(File::create(&canary)).write(b"foo"));
2767         check!(symlink_junction(&d2, &dt.join("d2")));
2768         let _ = symlink_file(&canary, &d1.join("canary"));
2769         check!(fs::remove_dir_all(&d1));
2770
2771         assert!(!d1.is_dir());
2772         assert!(canary.exists());
2773     }
2774
2775     #[test]
2776     fn recursive_rmdir_of_symlink() {
2777         // test we do not recursively delete a symlink but only dirs.
2778         let tmpdir = tmpdir();
2779         let link = tmpdir.join("d1");
2780         let dir = tmpdir.join("d2");
2781         let canary = dir.join("do_not_delete");
2782         check!(fs::create_dir_all(&dir));
2783         check!(check!(File::create(&canary)).write(b"foo"));
2784         check!(symlink_junction(&dir, &link));
2785         check!(fs::remove_dir_all(&link));
2786
2787         assert!(!link.is_dir());
2788         assert!(canary.exists());
2789     }
2790
2791     #[test]
2792     // only Windows makes a distinction between file and directory symlinks.
2793     #[cfg(windows)]
2794     fn recursive_rmdir_of_file_symlink() {
2795         let tmpdir = tmpdir();
2796         if !got_symlink_permission(&tmpdir) {
2797             return;
2798         };
2799
2800         let f1 = tmpdir.join("f1");
2801         let f2 = tmpdir.join("f2");
2802         check!(check!(File::create(&f1)).write(b"foo"));
2803         check!(symlink_file(&f1, &f2));
2804         match fs::remove_dir_all(&f2) {
2805             Ok(..) => panic!("wanted a failure"),
2806             Err(..) => {}
2807         }
2808     }
2809
2810     #[test]
2811     fn unicode_path_is_dir() {
2812         assert!(Path::new(".").is_dir());
2813         assert!(!Path::new("test/stdtest/fs.rs").is_dir());
2814
2815         let tmpdir = tmpdir();
2816
2817         let mut dirpath = tmpdir.path().to_path_buf();
2818         dirpath.push("test-가一ー你好");
2819         check!(fs::create_dir(&dirpath));
2820         assert!(dirpath.is_dir());
2821
2822         let mut filepath = dirpath;
2823         filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
2824         check!(File::create(&filepath)); // ignore return; touch only
2825         assert!(!filepath.is_dir());
2826         assert!(filepath.exists());
2827     }
2828
2829     #[test]
2830     fn unicode_path_exists() {
2831         assert!(Path::new(".").exists());
2832         assert!(!Path::new("test/nonexistent-bogus-path").exists());
2833
2834         let tmpdir = tmpdir();
2835         let unicode = tmpdir.path();
2836         let unicode = unicode.join("test-각丁ー再见");
2837         check!(fs::create_dir(&unicode));
2838         assert!(unicode.exists());
2839         assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists());
2840     }
2841
2842     #[test]
2843     fn copy_file_does_not_exist() {
2844         let from = Path::new("test/nonexistent-bogus-path");
2845         let to = Path::new("test/other-bogus-path");
2846
2847         match fs::copy(&from, &to) {
2848             Ok(..) => panic!(),
2849             Err(..) => {
2850                 assert!(!from.exists());
2851                 assert!(!to.exists());
2852             }
2853         }
2854     }
2855
2856     #[test]
2857     fn copy_src_does_not_exist() {
2858         let tmpdir = tmpdir();
2859         let from = Path::new("test/nonexistent-bogus-path");
2860         let to = tmpdir.join("out.txt");
2861         check!(check!(File::create(&to)).write(b"hello"));
2862         assert!(fs::copy(&from, &to).is_err());
2863         assert!(!from.exists());
2864         let mut v = Vec::new();
2865         check!(check!(File::open(&to)).read_to_end(&mut v));
2866         assert_eq!(v, b"hello");
2867     }
2868
2869     #[test]
2870     fn copy_file_ok() {
2871         let tmpdir = tmpdir();
2872         let input = tmpdir.join("in.txt");
2873         let out = tmpdir.join("out.txt");
2874
2875         check!(check!(File::create(&input)).write(b"hello"));
2876         check!(fs::copy(&input, &out));
2877         let mut v = Vec::new();
2878         check!(check!(File::open(&out)).read_to_end(&mut v));
2879         assert_eq!(v, b"hello");
2880
2881         assert_eq!(check!(input.metadata()).permissions(), check!(out.metadata()).permissions());
2882     }
2883
2884     #[test]
2885     fn copy_file_dst_dir() {
2886         let tmpdir = tmpdir();
2887         let out = tmpdir.join("out");
2888
2889         check!(File::create(&out));
2890         match fs::copy(&*out, tmpdir.path()) {
2891             Ok(..) => panic!(),
2892             Err(..) => {}
2893         }
2894     }
2895
2896     #[test]
2897     fn copy_file_dst_exists() {
2898         let tmpdir = tmpdir();
2899         let input = tmpdir.join("in");
2900         let output = tmpdir.join("out");
2901
2902         check!(check!(File::create(&input)).write("foo".as_bytes()));
2903         check!(check!(File::create(&output)).write("bar".as_bytes()));
2904         check!(fs::copy(&input, &output));
2905
2906         let mut v = Vec::new();
2907         check!(check!(File::open(&output)).read_to_end(&mut v));
2908         assert_eq!(v, b"foo".to_vec());
2909     }
2910
2911     #[test]
2912     fn copy_file_src_dir() {
2913         let tmpdir = tmpdir();
2914         let out = tmpdir.join("out");
2915
2916         match fs::copy(tmpdir.path(), &out) {
2917             Ok(..) => panic!(),
2918             Err(..) => {}
2919         }
2920         assert!(!out.exists());
2921     }
2922
2923     #[test]
2924     fn copy_file_preserves_perm_bits() {
2925         let tmpdir = tmpdir();
2926         let input = tmpdir.join("in.txt");
2927         let out = tmpdir.join("out.txt");
2928
2929         let attr = check!(check!(File::create(&input)).metadata());
2930         let mut p = attr.permissions();
2931         p.set_readonly(true);
2932         check!(fs::set_permissions(&input, p));
2933         check!(fs::copy(&input, &out));
2934         assert!(check!(out.metadata()).permissions().readonly());
2935         check!(fs::set_permissions(&input, attr.permissions()));
2936         check!(fs::set_permissions(&out, attr.permissions()));
2937     }
2938
2939     #[test]
2940     #[cfg(windows)]
2941     fn copy_file_preserves_streams() {
2942         let tmp = tmpdir();
2943         check!(check!(File::create(tmp.join("in.txt:bunny"))).write("carrot".as_bytes()));
2944         assert_eq!(check!(fs::copy(tmp.join("in.txt"), tmp.join("out.txt"))), 0);
2945         assert_eq!(check!(tmp.join("out.txt").metadata()).len(), 0);
2946         let mut v = Vec::new();
2947         check!(check!(File::open(tmp.join("out.txt:bunny"))).read_to_end(&mut v));
2948         assert_eq!(v, b"carrot".to_vec());
2949     }
2950
2951     #[test]
2952     fn copy_file_returns_metadata_len() {
2953         let tmp = tmpdir();
2954         let in_path = tmp.join("in.txt");
2955         let out_path = tmp.join("out.txt");
2956         check!(check!(File::create(&in_path)).write(b"lettuce"));
2957         #[cfg(windows)]
2958         check!(check!(File::create(tmp.join("in.txt:bunny"))).write(b"carrot"));
2959         let copied_len = check!(fs::copy(&in_path, &out_path));
2960         assert_eq!(check!(out_path.metadata()).len(), copied_len);
2961     }
2962
2963     #[test]
2964     fn copy_file_follows_dst_symlink() {
2965         let tmp = tmpdir();
2966         if !got_symlink_permission(&tmp) {
2967             return;
2968         };
2969
2970         let in_path = tmp.join("in.txt");
2971         let out_path = tmp.join("out.txt");
2972         let out_path_symlink = tmp.join("out_symlink.txt");
2973
2974         check!(fs::write(&in_path, "foo"));
2975         check!(fs::write(&out_path, "bar"));
2976         check!(symlink_file(&out_path, &out_path_symlink));
2977
2978         check!(fs::copy(&in_path, &out_path_symlink));
2979
2980         assert!(check!(out_path_symlink.symlink_metadata()).file_type().is_symlink());
2981         assert_eq!(check!(fs::read(&out_path_symlink)), b"foo".to_vec());
2982         assert_eq!(check!(fs::read(&out_path)), b"foo".to_vec());
2983     }
2984
2985     #[test]
2986     fn symlinks_work() {
2987         let tmpdir = tmpdir();
2988         if !got_symlink_permission(&tmpdir) {
2989             return;
2990         };
2991
2992         let input = tmpdir.join("in.txt");
2993         let out = tmpdir.join("out.txt");
2994
2995         check!(check!(File::create(&input)).write("foobar".as_bytes()));
2996         check!(symlink_file(&input, &out));
2997         assert!(check!(out.symlink_metadata()).file_type().is_symlink());
2998         assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len());
2999         let mut v = Vec::new();
3000         check!(check!(File::open(&out)).read_to_end(&mut v));
3001         assert_eq!(v, b"foobar".to_vec());
3002     }
3003
3004     #[test]
3005     fn symlink_noexist() {
3006         // Symlinks can point to things that don't exist
3007         let tmpdir = tmpdir();
3008         if !got_symlink_permission(&tmpdir) {
3009             return;
3010         };
3011
3012         // Use a relative path for testing. Symlinks get normalized by Windows,
3013         // so we may not get the same path back for absolute paths
3014         check!(symlink_file(&"foo", &tmpdir.join("bar")));
3015         assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))).to_str().unwrap(), "foo");
3016     }
3017
3018     #[test]
3019     fn read_link() {
3020         if cfg!(windows) {
3021             // directory symlink
3022             assert_eq!(
3023                 check!(fs::read_link(r"C:\Users\All Users")).to_str().unwrap(),
3024                 r"C:\ProgramData"
3025             );
3026             // junction
3027             assert_eq!(
3028                 check!(fs::read_link(r"C:\Users\Default User")).to_str().unwrap(),
3029                 r"C:\Users\Default"
3030             );
3031             // junction with special permissions
3032             assert_eq!(
3033                 check!(fs::read_link(r"C:\Documents and Settings\")).to_str().unwrap(),
3034                 r"C:\Users"
3035             );
3036         }
3037         let tmpdir = tmpdir();
3038         let link = tmpdir.join("link");
3039         if !got_symlink_permission(&tmpdir) {
3040             return;
3041         };
3042         check!(symlink_file(&"foo", &link));
3043         assert_eq!(check!(fs::read_link(&link)).to_str().unwrap(), "foo");
3044     }
3045
3046     #[test]
3047     fn readlink_not_symlink() {
3048         let tmpdir = tmpdir();
3049         match fs::read_link(tmpdir.path()) {
3050             Ok(..) => panic!("wanted a failure"),
3051             Err(..) => {}
3052         }
3053     }
3054
3055     #[test]
3056     fn links_work() {
3057         let tmpdir = tmpdir();
3058         let input = tmpdir.join("in.txt");
3059         let out = tmpdir.join("out.txt");
3060
3061         check!(check!(File::create(&input)).write("foobar".as_bytes()));
3062         check!(fs::hard_link(&input, &out));
3063         assert_eq!(check!(fs::metadata(&out)).len(), check!(fs::metadata(&input)).len());
3064         assert_eq!(check!(fs::metadata(&out)).len(), check!(input.metadata()).len());
3065         let mut v = Vec::new();
3066         check!(check!(File::open(&out)).read_to_end(&mut v));
3067         assert_eq!(v, b"foobar".to_vec());
3068
3069         // can't link to yourself
3070         match fs::hard_link(&input, &input) {
3071             Ok(..) => panic!("wanted a failure"),
3072             Err(..) => {}
3073         }
3074         // can't link to something that doesn't exist
3075         match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
3076             Ok(..) => panic!("wanted a failure"),
3077             Err(..) => {}
3078         }
3079     }
3080
3081     #[test]
3082     fn chmod_works() {
3083         let tmpdir = tmpdir();
3084         let file = tmpdir.join("in.txt");
3085
3086         check!(File::create(&file));
3087         let attr = check!(fs::metadata(&file));
3088         assert!(!attr.permissions().readonly());
3089         let mut p = attr.permissions();
3090         p.set_readonly(true);
3091         check!(fs::set_permissions(&file, p.clone()));
3092         let attr = check!(fs::metadata(&file));
3093         assert!(attr.permissions().readonly());
3094
3095         match fs::set_permissions(&tmpdir.join("foo"), p.clone()) {
3096             Ok(..) => panic!("wanted an error"),
3097             Err(..) => {}
3098         }
3099
3100         p.set_readonly(false);
3101         check!(fs::set_permissions(&file, p));
3102     }
3103
3104     #[test]
3105     fn fchmod_works() {
3106         let tmpdir = tmpdir();
3107         let path = tmpdir.join("in.txt");
3108
3109         let file = check!(File::create(&path));
3110         let attr = check!(fs::metadata(&path));
3111         assert!(!attr.permissions().readonly());
3112         let mut p = attr.permissions();
3113         p.set_readonly(true);
3114         check!(file.set_permissions(p.clone()));
3115         let attr = check!(fs::metadata(&path));
3116         assert!(attr.permissions().readonly());
3117
3118         p.set_readonly(false);
3119         check!(file.set_permissions(p));
3120     }
3121
3122     #[test]
3123     fn sync_doesnt_kill_anything() {
3124         let tmpdir = tmpdir();
3125         let path = tmpdir.join("in.txt");
3126
3127         let mut file = check!(File::create(&path));
3128         check!(file.sync_all());
3129         check!(file.sync_data());
3130         check!(file.write(b"foo"));
3131         check!(file.sync_all());
3132         check!(file.sync_data());
3133     }
3134
3135     #[test]
3136     fn truncate_works() {
3137         let tmpdir = tmpdir();
3138         let path = tmpdir.join("in.txt");
3139
3140         let mut file = check!(File::create(&path));
3141         check!(file.write(b"foo"));
3142         check!(file.sync_all());
3143
3144         // Do some simple things with truncation
3145         assert_eq!(check!(file.metadata()).len(), 3);
3146         check!(file.set_len(10));
3147         assert_eq!(check!(file.metadata()).len(), 10);
3148         check!(file.write(b"bar"));
3149         check!(file.sync_all());
3150         assert_eq!(check!(file.metadata()).len(), 10);
3151
3152         let mut v = Vec::new();
3153         check!(check!(File::open(&path)).read_to_end(&mut v));
3154         assert_eq!(v, b"foobar\0\0\0\0".to_vec());
3155
3156         // Truncate to a smaller length, don't seek, and then write something.
3157         // Ensure that the intermediate zeroes are all filled in (we have `seek`ed
3158         // past the end of the file).
3159         check!(file.set_len(2));
3160         assert_eq!(check!(file.metadata()).len(), 2);
3161         check!(file.write(b"wut"));
3162         check!(file.sync_all());
3163         assert_eq!(check!(file.metadata()).len(), 9);
3164         let mut v = Vec::new();
3165         check!(check!(File::open(&path)).read_to_end(&mut v));
3166         assert_eq!(v, b"fo\0\0\0\0wut".to_vec());
3167     }
3168
3169     #[test]
3170     fn open_flavors() {
3171         use crate::fs::OpenOptions as OO;
3172         fn c<T: Clone>(t: &T) -> T {
3173             t.clone()
3174         }
3175
3176         let tmpdir = tmpdir();
3177
3178         let mut r = OO::new();
3179         r.read(true);
3180         let mut w = OO::new();
3181         w.write(true);
3182         let mut rw = OO::new();
3183         rw.read(true).write(true);
3184         let mut a = OO::new();
3185         a.append(true);
3186         let mut ra = OO::new();
3187         ra.read(true).append(true);
3188
3189         #[cfg(windows)]
3190         let invalid_options = 87; // ERROR_INVALID_PARAMETER
3191         #[cfg(all(unix, not(target_os = "vxworks")))]
3192         let invalid_options = "Invalid argument";
3193         #[cfg(target_os = "vxworks")]
3194         let invalid_options = "invalid argument";
3195
3196         // Test various combinations of creation modes and access modes.
3197         //
3198         // Allowed:
3199         // creation mode           | read  | write | read-write | append | read-append |
3200         // :-----------------------|:-----:|:-----:|:----------:|:------:|:-----------:|
3201         // not set (open existing) |   X   |   X   |     X      |   X    |      X      |
3202         // create                  |       |   X   |     X      |   X    |      X      |
3203         // truncate                |       |   X   |     X      |        |             |
3204         // create and truncate     |       |   X   |     X      |        |             |
3205         // create_new              |       |   X   |     X      |   X    |      X      |
3206         //
3207         // tested in reverse order, so 'create_new' creates the file, and 'open existing' opens it.
3208
3209         // write-only
3210         check!(c(&w).create_new(true).open(&tmpdir.join("a")));
3211         check!(c(&w).create(true).truncate(true).open(&tmpdir.join("a")));
3212         check!(c(&w).truncate(true).open(&tmpdir.join("a")));
3213         check!(c(&w).create(true).open(&tmpdir.join("a")));
3214         check!(c(&w).open(&tmpdir.join("a")));
3215
3216         // read-only
3217         error!(c(&r).create_new(true).open(&tmpdir.join("b")), invalid_options);
3218         error!(c(&r).create(true).truncate(true).open(&tmpdir.join("b")), invalid_options);
3219         error!(c(&r).truncate(true).open(&tmpdir.join("b")), invalid_options);
3220         error!(c(&r).create(true).open(&tmpdir.join("b")), invalid_options);
3221         check!(c(&r).open(&tmpdir.join("a"))); // try opening the file created with write_only
3222
3223         // read-write
3224         check!(c(&rw).create_new(true).open(&tmpdir.join("c")));
3225         check!(c(&rw).create(true).truncate(true).open(&tmpdir.join("c")));
3226         check!(c(&rw).truncate(true).open(&tmpdir.join("c")));
3227         check!(c(&rw).create(true).open(&tmpdir.join("c")));
3228         check!(c(&rw).open(&tmpdir.join("c")));
3229
3230         // append
3231         check!(c(&a).create_new(true).open(&tmpdir.join("d")));
3232         error!(c(&a).create(true).truncate(true).open(&tmpdir.join("d")), invalid_options);
3233         error!(c(&a).truncate(true).open(&tmpdir.join("d")), invalid_options);
3234         check!(c(&a).create(true).open(&tmpdir.join("d")));
3235         check!(c(&a).open(&tmpdir.join("d")));
3236
3237         // read-append
3238         check!(c(&ra).create_new(true).open(&tmpdir.join("e")));
3239         error!(c(&ra).create(true).truncate(true).open(&tmpdir.join("e")), invalid_options);
3240         error!(c(&ra).truncate(true).open(&tmpdir.join("e")), invalid_options);
3241         check!(c(&ra).create(true).open(&tmpdir.join("e")));
3242         check!(c(&ra).open(&tmpdir.join("e")));
3243
3244         // Test opening a file without setting an access mode
3245         let mut blank = OO::new();
3246         error!(blank.create(true).open(&tmpdir.join("f")), invalid_options);
3247
3248         // Test write works
3249         check!(check!(File::create(&tmpdir.join("h"))).write("foobar".as_bytes()));
3250
3251         // Test write fails for read-only
3252         check!(r.open(&tmpdir.join("h")));
3253         {
3254             let mut f = check!(r.open(&tmpdir.join("h")));
3255             assert!(f.write("wut".as_bytes()).is_err());
3256         }
3257
3258         // Test write overwrites
3259         {
3260             let mut f = check!(c(&w).open(&tmpdir.join("h")));
3261             check!(f.write("baz".as_bytes()));
3262         }
3263         {
3264             let mut f = check!(c(&r).open(&tmpdir.join("h")));
3265             let mut b = vec![0; 6];
3266             check!(f.read(&mut b));
3267             assert_eq!(b, "bazbar".as_bytes());
3268         }
3269
3270         // Test truncate works
3271         {
3272             let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
3273             check!(f.write("foo".as_bytes()));
3274         }
3275         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
3276
3277         // Test append works
3278         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
3279         {
3280             let mut f = check!(c(&a).open(&tmpdir.join("h")));
3281             check!(f.write("bar".as_bytes()));
3282         }
3283         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
3284
3285         // Test .append(true) equals .write(true).append(true)
3286         {
3287             let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
3288             check!(f.write("baz".as_bytes()));
3289         }
3290         assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 9);
3291     }
3292
3293     #[test]
3294     fn _assert_send_sync() {
3295         fn _assert_send_sync<T: Send + Sync>() {}
3296         _assert_send_sync::<OpenOptions>();
3297     }
3298
3299     #[test]
3300     fn binary_file() {
3301         let mut bytes = [0; 1024];
3302         StdRng::from_entropy().fill_bytes(&mut bytes);
3303
3304         let tmpdir = tmpdir();
3305
3306         check!(check!(File::create(&tmpdir.join("test"))).write(&bytes));
3307         let mut v = Vec::new();
3308         check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v));
3309         assert!(v == &bytes[..]);
3310     }
3311
3312     #[test]
3313     fn write_then_read() {
3314         let mut bytes = [0; 1024];
3315         StdRng::from_entropy().fill_bytes(&mut bytes);
3316
3317         let tmpdir = tmpdir();
3318
3319         check!(fs::write(&tmpdir.join("test"), &bytes[..]));
3320         let v = check!(fs::read(&tmpdir.join("test")));
3321         assert!(v == &bytes[..]);
3322
3323         check!(fs::write(&tmpdir.join("not-utf8"), &[0xFF]));
3324         error_contains!(
3325             fs::read_to_string(&tmpdir.join("not-utf8")),
3326             "stream did not contain valid UTF-8"
3327         );
3328
3329         let s = "𐁁𐀓𐀠𐀴𐀍";
3330         check!(fs::write(&tmpdir.join("utf8"), s.as_bytes()));
3331         let string = check!(fs::read_to_string(&tmpdir.join("utf8")));
3332         assert_eq!(string, s);
3333     }
3334
3335     #[test]
3336     fn file_try_clone() {
3337         let tmpdir = tmpdir();
3338
3339         let mut f1 = check!(
3340             OpenOptions::new().read(true).write(true).create(true).open(&tmpdir.join("test"))
3341         );
3342         let mut f2 = check!(f1.try_clone());
3343
3344         check!(f1.write_all(b"hello world"));
3345         check!(f1.seek(SeekFrom::Start(2)));
3346
3347         let mut buf = vec![];
3348         check!(f2.read_to_end(&mut buf));
3349         assert_eq!(buf, b"llo world");
3350         drop(f2);
3351
3352         check!(f1.write_all(b"!"));
3353     }
3354
3355     #[test]
3356     #[cfg(not(windows))]
3357     fn unlink_readonly() {
3358         let tmpdir = tmpdir();
3359         let path = tmpdir.join("file");
3360         check!(File::create(&path));
3361         let mut perm = check!(fs::metadata(&path)).permissions();
3362         perm.set_readonly(true);
3363         check!(fs::set_permissions(&path, perm));
3364         check!(fs::remove_file(&path));
3365     }
3366
3367     #[test]
3368     fn mkdir_trailing_slash() {
3369         let tmpdir = tmpdir();
3370         let path = tmpdir.join("file");
3371         check!(fs::create_dir_all(&path.join("a/")));
3372     }
3373
3374     #[test]
3375     fn canonicalize_works_simple() {
3376         let tmpdir = tmpdir();
3377         let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
3378         let file = tmpdir.join("test");
3379         File::create(&file).unwrap();
3380         assert_eq!(fs::canonicalize(&file).unwrap(), file);
3381     }
3382
3383     #[test]
3384     fn realpath_works() {
3385         let tmpdir = tmpdir();
3386         if !got_symlink_permission(&tmpdir) {
3387             return;
3388         };
3389
3390         let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
3391         let file = tmpdir.join("test");
3392         let dir = tmpdir.join("test2");
3393         let link = dir.join("link");
3394         let linkdir = tmpdir.join("test3");
3395
3396         File::create(&file).unwrap();
3397         fs::create_dir(&dir).unwrap();
3398         symlink_file(&file, &link).unwrap();
3399         symlink_dir(&dir, &linkdir).unwrap();
3400
3401         assert!(link.symlink_metadata().unwrap().file_type().is_symlink());
3402
3403         assert_eq!(fs::canonicalize(&tmpdir).unwrap(), tmpdir);
3404         assert_eq!(fs::canonicalize(&file).unwrap(), file);
3405         assert_eq!(fs::canonicalize(&link).unwrap(), file);
3406         assert_eq!(fs::canonicalize(&linkdir).unwrap(), dir);
3407         assert_eq!(fs::canonicalize(&linkdir.join("link")).unwrap(), file);
3408     }
3409
3410     #[test]
3411     fn realpath_works_tricky() {
3412         let tmpdir = tmpdir();
3413         if !got_symlink_permission(&tmpdir) {
3414             return;
3415         };
3416
3417         let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
3418         let a = tmpdir.join("a");
3419         let b = a.join("b");
3420         let c = b.join("c");
3421         let d = a.join("d");
3422         let e = d.join("e");
3423         let f = a.join("f");
3424
3425         fs::create_dir_all(&b).unwrap();
3426         fs::create_dir_all(&d).unwrap();
3427         File::create(&f).unwrap();
3428         if cfg!(not(windows)) {
3429             symlink_file("../d/e", &c).unwrap();
3430             symlink_file("../f", &e).unwrap();
3431         }
3432         if cfg!(windows) {
3433             symlink_file(r"..\d\e", &c).unwrap();
3434             symlink_file(r"..\f", &e).unwrap();
3435         }
3436
3437         assert_eq!(fs::canonicalize(&c).unwrap(), f);
3438         assert_eq!(fs::canonicalize(&e).unwrap(), f);
3439     }
3440
3441     #[test]
3442     fn dir_entry_methods() {
3443         let tmpdir = tmpdir();
3444
3445         fs::create_dir_all(&tmpdir.join("a")).unwrap();
3446         File::create(&tmpdir.join("b")).unwrap();
3447
3448         for file in tmpdir.path().read_dir().unwrap().map(|f| f.unwrap()) {
3449             let fname = file.file_name();
3450             match fname.to_str() {
3451                 Some("a") => {
3452                     assert!(file.file_type().unwrap().is_dir());
3453                     assert!(file.metadata().unwrap().is_dir());
3454                 }
3455                 Some("b") => {
3456                     assert!(file.file_type().unwrap().is_file());
3457                     assert!(file.metadata().unwrap().is_file());
3458                 }
3459                 f => panic!("unknown file name: {:?}", f),
3460             }
3461         }
3462     }
3463
3464     #[test]
3465     fn dir_entry_debug() {
3466         let tmpdir = tmpdir();
3467         File::create(&tmpdir.join("b")).unwrap();
3468         let mut read_dir = tmpdir.path().read_dir().unwrap();
3469         let dir_entry = read_dir.next().unwrap().unwrap();
3470         let actual = format!("{:?}", dir_entry);
3471         let expected = format!("DirEntry({:?})", dir_entry.0.path());
3472         assert_eq!(actual, expected);
3473     }
3474
3475     #[test]
3476     fn read_dir_not_found() {
3477         let res = fs::read_dir("/path/that/does/not/exist");
3478         assert_eq!(res.err().unwrap().kind(), ErrorKind::NotFound);
3479     }
3480
3481     #[test]
3482     fn create_dir_all_with_junctions() {
3483         let tmpdir = tmpdir();
3484         let target = tmpdir.join("target");
3485
3486         let junction = tmpdir.join("junction");
3487         let b = junction.join("a/b");
3488
3489         let link = tmpdir.join("link");
3490         let d = link.join("c/d");
3491
3492         fs::create_dir(&target).unwrap();
3493
3494         check!(symlink_junction(&target, &junction));
3495         check!(fs::create_dir_all(&b));
3496         // the junction itself is not a directory, but `is_dir()` on a Path
3497         // follows links
3498         assert!(junction.is_dir());
3499         assert!(b.exists());
3500
3501         if !got_symlink_permission(&tmpdir) {
3502             return;
3503         };
3504         check!(symlink_dir(&target, &link));
3505         check!(fs::create_dir_all(&d));
3506         assert!(link.is_dir());
3507         assert!(d.exists());
3508     }
3509
3510     #[test]
3511     fn metadata_access_times() {
3512         let tmpdir = tmpdir();
3513
3514         let b = tmpdir.join("b");
3515         File::create(&b).unwrap();
3516
3517         let a = check!(fs::metadata(&tmpdir.path()));
3518         let b = check!(fs::metadata(&b));
3519
3520         assert_eq!(check!(a.accessed()), check!(a.accessed()));
3521         assert_eq!(check!(a.modified()), check!(a.modified()));
3522         assert_eq!(check!(b.accessed()), check!(b.modified()));
3523
3524         if cfg!(target_os = "macos") || cfg!(target_os = "windows") {
3525             check!(a.created());
3526             check!(b.created());
3527         }
3528
3529         if cfg!(target_os = "linux") {
3530             // Not always available
3531             match (a.created(), b.created()) {
3532                 (Ok(t1), Ok(t2)) => assert!(t1 <= t2),
3533                 (Err(e1), Err(e2))
3534                     if e1.kind() == ErrorKind::Other && e2.kind() == ErrorKind::Other => {}
3535                 (a, b) => panic!(
3536                     "creation time must be always supported or not supported: {:?} {:?}",
3537                     a, b,
3538                 ),
3539             }
3540         }
3541     }
3542 }