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