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