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