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