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