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