1//! Filesystem manipulation operations.
2//!
3//! This module contains basic methods to manipulate the contents of the local
4//! filesystem. All methods in this module represent cross-platform filesystem
5//! operations. Extra platform-specific functionality can be found in the
6//! extension traits of `std::os::$platform`.
7
8#![stable(feature = "rust1", since = "1.0.0")]
9#![deny(unsafe_op_in_unsafe_fn)]
10
11#[cfg(all(test, not(any(target_os = "emscripten", target_env = "sgx", target_os = "xous"))))]
12mod tests;
13
14use crate::ffi::OsString;
15use crate::fmt;
16use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
17use crate::path::{Path, PathBuf};
18use crate::sealed::Sealed;
19use crate::sync::Arc;
20use crate::sys::fs as fs_imp;
21use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
22use crate::time::SystemTime;
23
24/// An object providing access to an open file on the filesystem.
25///
26/// An instance of a `File` can be read and/or written depending on what options
27/// it was opened with. Files also implement [`Seek`] to alter the logical cursor
28/// that the file contains internally.
29///
30/// Files are automatically closed when they go out of scope. Errors detected
31/// on closing are ignored by the implementation of `Drop`. Use the method
32/// [`sync_all`] if these errors must be manually handled.
33///
34/// `File` does not buffer reads and writes. For efficiency, consider wrapping the
35/// file in a [`BufReader`] or [`BufWriter`] when performing many small [`read`]
36/// or [`write`] calls, unless unbuffered reads and writes are required.
37///
38/// # Examples
39///
40/// Creates a new file and write bytes to it (you can also use [`write`]):
41///
42/// ```no_run
43/// use std::fs::File;
44/// use std::io::prelude::*;
45///
46/// fn main() -> std::io::Result<()> {
47/// let mut file = File::create("foo.txt")?;
48/// file.write_all(b"Hello, world!")?;
49/// Ok(())
50/// }
51/// ```
52///
53/// Read the contents of a file into a [`String`] (you can also use [`read`]):
54///
55/// ```no_run
56/// use std::fs::File;
57/// use std::io::prelude::*;
58///
59/// fn main() -> std::io::Result<()> {
60/// let mut file = File::open("foo.txt")?;
61/// let mut contents = String::new();
62/// file.read_to_string(&mut contents)?;
63/// assert_eq!(contents, "Hello, world!");
64/// Ok(())
65/// }
66/// ```
67///
68/// Using a buffered [`Read`]er:
69///
70/// ```no_run
71/// use std::fs::File;
72/// use std::io::BufReader;
73/// use std::io::prelude::*;
74///
75/// fn main() -> std::io::Result<()> {
76/// let file = File::open("foo.txt")?;
77/// let mut buf_reader = BufReader::new(file);
78/// let mut contents = String::new();
79/// buf_reader.read_to_string(&mut contents)?;
80/// assert_eq!(contents, "Hello, world!");
81/// Ok(())
82/// }
83/// ```
84///
85/// Note that, although read and write methods require a `&mut File`, because
86/// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can
87/// still modify the file, either through methods that take `&File` or by
88/// retrieving the underlying OS object and modifying the file that way.
89/// Additionally, many operating systems allow concurrent modification of files
90/// by different processes. Avoid assuming that holding a `&File` means that the
91/// file will not change.
92///
93/// # Platform-specific behavior
94///
95/// On Windows, the implementation of [`Read`] and [`Write`] traits for `File`
96/// perform synchronous I/O operations. Therefore the underlying file must not
97/// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).
98///
99/// [`BufReader`]: io::BufReader
100/// [`BufWriter`]: io::BufWriter
101/// [`sync_all`]: File::sync_all
102/// [`write`]: File::write
103/// [`read`]: File::read
104#[stable(feature = "rust1", since = "1.0.0")]
105#[cfg_attr(not(test), rustc_diagnostic_item = "File")]
106pub struct File {
107 inner: fs_imp::File,
108}
109
110/// Metadata information about a file.
111///
112/// This structure is returned from the [`metadata`] or
113/// [`symlink_metadata`] function or method and represents known
114/// metadata about a file such as its permissions, size, modification
115/// times, etc.
116#[stable(feature = "rust1", since = "1.0.0")]
117#[derive(Clone)]
118pub struct Metadata(fs_imp::FileAttr);
119
120/// Iterator over the entries in a directory.
121///
122/// This iterator is returned from the [`read_dir`] function of this module and
123/// will yield instances of <code>[io::Result]<[DirEntry]></code>. Through a [`DirEntry`]
124/// information like the entry's path and possibly other metadata can be
125/// learned.
126///
127/// The order in which this iterator returns entries is platform and filesystem
128/// dependent.
129///
130/// # Errors
131///
132/// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent
133/// IO error during iteration.
134#[stable(feature = "rust1", since = "1.0.0")]
135#[derive(Debug)]
136pub struct ReadDir(fs_imp::ReadDir);
137
138/// Entries returned by the [`ReadDir`] iterator.
139///
140/// An instance of `DirEntry` represents an entry inside of a directory on the
141/// filesystem. Each entry can be inspected via methods to learn about the full
142/// path or possibly other metadata through per-platform extension traits.
143///
144/// # Platform-specific behavior
145///
146/// On Unix, the `DirEntry` struct contains an internal reference to the open
147/// directory. Holding `DirEntry` objects will consume a file handle even
148/// after the `ReadDir` iterator is dropped.
149///
150/// Note that this [may change in the future][changes].
151///
152/// [changes]: io#platform-specific-behavior
153#[stable(feature = "rust1", since = "1.0.0")]
154pub struct DirEntry(fs_imp::DirEntry);
155
156/// Options and flags which can be used to configure how a file is opened.
157///
158/// This builder exposes the ability to configure how a [`File`] is opened and
159/// what operations are permitted on the open file. The [`File::open`] and
160/// [`File::create`] methods are aliases for commonly used options using this
161/// builder.
162///
163/// Generally speaking, when using `OpenOptions`, you'll first call
164/// [`OpenOptions::new`], then chain calls to methods to set each option, then
165/// call [`OpenOptions::open`], passing the path of the file you're trying to
166/// open. This will give you a [`io::Result`] with a [`File`] inside that you
167/// can further operate on.
168///
169/// # Examples
170///
171/// Opening a file to read:
172///
173/// ```no_run
174/// use std::fs::OpenOptions;
175///
176/// let file = OpenOptions::new().read(true).open("foo.txt");
177/// ```
178///
179/// Opening a file for both reading and writing, as well as creating it if it
180/// doesn't exist:
181///
182/// ```no_run
183/// use std::fs::OpenOptions;
184///
185/// let file = OpenOptions::new()
186/// .read(true)
187/// .write(true)
188/// .create(true)
189/// .open("foo.txt");
190/// ```
191#[derive(Clone, Debug)]
192#[stable(feature = "rust1", since = "1.0.0")]
193#[cfg_attr(not(test), rustc_diagnostic_item = "FsOpenOptions")]
194pub struct OpenOptions(fs_imp::OpenOptions);
195
196/// Representation of the various timestamps on a file.
197#[derive(Copy, Clone, Debug, Default)]
198#[stable(feature = "file_set_times", since = "1.75.0")]
199pub struct FileTimes(fs_imp::FileTimes);
200
201/// Representation of the various permissions on a file.
202///
203/// This module only currently provides one bit of information,
204/// [`Permissions::readonly`], which is exposed on all currently supported
205/// platforms. Unix-specific functionality, such as mode bits, is available
206/// through the [`PermissionsExt`] trait.
207///
208/// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
209#[derive(Clone, PartialEq, Eq, Debug)]
210#[stable(feature = "rust1", since = "1.0.0")]
211#[cfg_attr(not(test), rustc_diagnostic_item = "FsPermissions")]
212pub struct Permissions(fs_imp::FilePermissions);
213
214/// A structure representing a type of file with accessors for each file type.
215/// It is returned by [`Metadata::file_type`] method.
216#[stable(feature = "file_type", since = "1.1.0")]
217#[derive(Copy, Clone, PartialEq, Eq, Hash)]
218#[cfg_attr(not(test), rustc_diagnostic_item = "FileType")]
219pub struct FileType(fs_imp::FileType);
220
221/// A builder used to create directories in various manners.
222///
223/// This builder also supports platform-specific options.
224#[stable(feature = "dir_builder", since = "1.6.0")]
225#[cfg_attr(not(test), rustc_diagnostic_item = "DirBuilder")]
226#[derive(Debug)]
227pub struct DirBuilder {
228 inner: fs_imp::DirBuilder,
229 recursive: bool,
230}
231
232/// Read the entire contents of a file into a bytes vector.
233///
234/// This is a convenience function for using [`File::open`] and [`read_to_end`]
235/// with fewer imports and without an intermediate variable.
236///
237/// [`read_to_end`]: Read::read_to_end
238///
239/// # Errors
240///
241/// This function will return an error if `path` does not already exist.
242/// Other errors may also be returned according to [`OpenOptions::open`].
243///
244/// While reading from the file, this function handles [`io::ErrorKind::Interrupted`]
245/// with automatic retries. See [io::Read] documentation for details.
246///
247/// # Examples
248///
249/// ```no_run
250/// use std::fs;
251///
252/// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {
253/// let data: Vec<u8> = fs::read("image.jpg")?;
254/// assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]);
255/// Ok(())
256/// }
257/// ```
258#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
259pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
260 fn inner(path: &Path) -> io::Result<Vec<u8>> {
261 let mut file: File = File::open(path)?;
262 let size: Option = file.metadata().map(|m: Metadata| m.len() as usize).ok();
263 let mut bytes: Vec = Vec::new();
264 bytes.try_reserve_exact(additional:size.unwrap_or(default:0))?;
265 io::default_read_to_end(&mut file, &mut bytes, size_hint:size)?;
266 Ok(bytes)
267 }
268 inner(path.as_ref())
269}
270
271/// Read the entire contents of a file into a string.
272///
273/// This is a convenience function for using [`File::open`] and [`read_to_string`]
274/// with fewer imports and without an intermediate variable.
275///
276/// [`read_to_string`]: Read::read_to_string
277///
278/// # Errors
279///
280/// This function will return an error if `path` does not already exist.
281/// Other errors may also be returned according to [`OpenOptions::open`].
282///
283/// If the contents of the file are not valid UTF-8, then an error will also be
284/// returned.
285///
286/// While reading from the file, this function handles [`io::ErrorKind::Interrupted`]
287/// with automatic retries. See [io::Read] documentation for details.
288///
289/// # Examples
290///
291/// ```no_run
292/// use std::fs;
293/// use std::error::Error;
294///
295/// fn main() -> Result<(), Box<dyn Error>> {
296/// let message: String = fs::read_to_string("message.txt")?;
297/// println!("{}", message);
298/// Ok(())
299/// }
300/// ```
301#[stable(feature = "fs_read_write", since = "1.26.0")]
302pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
303 fn inner(path: &Path) -> io::Result<String> {
304 let mut file: File = File::open(path)?;
305 let size: Option = file.metadata().map(|m: Metadata| m.len() as usize).ok();
306 let mut string: String = String::new();
307 string.try_reserve_exact(additional:size.unwrap_or(default:0))?;
308 io::default_read_to_string(&mut file, &mut string, size_hint:size)?;
309 Ok(string)
310 }
311 inner(path.as_ref())
312}
313
314/// Write a slice as the entire contents of a file.
315///
316/// This function will create a file if it does not exist,
317/// and will entirely replace its contents if it does.
318///
319/// Depending on the platform, this function may fail if the
320/// full directory path does not exist.
321///
322/// This is a convenience function for using [`File::create`] and [`write_all`]
323/// with fewer imports.
324///
325/// [`write_all`]: Write::write_all
326///
327/// # Examples
328///
329/// ```no_run
330/// use std::fs;
331///
332/// fn main() -> std::io::Result<()> {
333/// fs::write("foo.txt", b"Lorem ipsum")?;
334/// fs::write("bar.txt", "dolor sit")?;
335/// Ok(())
336/// }
337/// ```
338#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]
339pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
340 fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {
341 File::create(path)?.write_all(buf:contents)
342 }
343 inner(path.as_ref(), contents.as_ref())
344}
345
346impl File {
347 /// Attempts to open a file in read-only mode.
348 ///
349 /// See the [`OpenOptions::open`] method for more details.
350 ///
351 /// If you only need to read the entire file contents,
352 /// consider [`std::fs::read()`][self::read] or
353 /// [`std::fs::read_to_string()`][self::read_to_string] instead.
354 ///
355 /// # Errors
356 ///
357 /// This function will return an error if `path` does not already exist.
358 /// Other errors may also be returned according to [`OpenOptions::open`].
359 ///
360 /// # Examples
361 ///
362 /// ```no_run
363 /// use std::fs::File;
364 /// use std::io::Read;
365 ///
366 /// fn main() -> std::io::Result<()> {
367 /// let mut f = File::open("foo.txt")?;
368 /// let mut data = vec![];
369 /// f.read_to_end(&mut data)?;
370 /// Ok(())
371 /// }
372 /// ```
373 #[stable(feature = "rust1", since = "1.0.0")]
374 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
375 OpenOptions::new().read(true).open(path.as_ref())
376 }
377
378 /// Opens a file in write-only mode.
379 ///
380 /// This function will create a file if it does not exist,
381 /// and will truncate it if it does.
382 ///
383 /// Depending on the platform, this function may fail if the
384 /// full directory path does not exist.
385 /// See the [`OpenOptions::open`] function for more details.
386 ///
387 /// See also [`std::fs::write()`][self::write] for a simple function to
388 /// create a file with some given data.
389 ///
390 /// # Examples
391 ///
392 /// ```no_run
393 /// use std::fs::File;
394 /// use std::io::Write;
395 ///
396 /// fn main() -> std::io::Result<()> {
397 /// let mut f = File::create("foo.txt")?;
398 /// f.write_all(&1234_u32.to_be_bytes())?;
399 /// Ok(())
400 /// }
401 /// ```
402 #[stable(feature = "rust1", since = "1.0.0")]
403 pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
404 OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())
405 }
406
407 /// Creates a new file in read-write mode; error if the file exists.
408 ///
409 /// This function will create a file if it does not exist, or return an error if it does. This
410 /// way, if the call succeeds, the file returned is guaranteed to be new.
411 ///
412 /// This option is useful because it is atomic. Otherwise between checking whether a file
413 /// exists and creating a new one, the file may have been created by another process (a TOCTOU
414 /// race condition / attack).
415 ///
416 /// This can also be written using
417 /// `File::options().read(true).write(true).create_new(true).open(...)`.
418 ///
419 /// # Examples
420 ///
421 /// ```no_run
422 /// use std::fs::File;
423 /// use std::io::Write;
424 ///
425 /// fn main() -> std::io::Result<()> {
426 /// let mut f = File::create_new("foo.txt")?;
427 /// f.write_all("Hello, world!".as_bytes())?;
428 /// Ok(())
429 /// }
430 /// ```
431 #[stable(feature = "file_create_new", since = "1.77.0")]
432 pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {
433 OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref())
434 }
435
436 /// Returns a new OpenOptions object.
437 ///
438 /// This function returns a new OpenOptions object that you can use to
439 /// open or create a file with specific options if `open()` or `create()`
440 /// are not appropriate.
441 ///
442 /// It is equivalent to `OpenOptions::new()`, but allows you to write more
443 /// readable code. Instead of
444 /// `OpenOptions::new().append(true).open("example.log")`,
445 /// you can write `File::options().append(true).open("example.log")`. This
446 /// also avoids the need to import `OpenOptions`.
447 ///
448 /// See the [`OpenOptions::new`] function for more details.
449 ///
450 /// # Examples
451 ///
452 /// ```no_run
453 /// use std::fs::File;
454 /// use std::io::Write;
455 ///
456 /// fn main() -> std::io::Result<()> {
457 /// let mut f = File::options().append(true).open("example.log")?;
458 /// writeln!(&mut f, "new line")?;
459 /// Ok(())
460 /// }
461 /// ```
462 #[must_use]
463 #[stable(feature = "with_options", since = "1.58.0")]
464 pub fn options() -> OpenOptions {
465 OpenOptions::new()
466 }
467
468 /// Attempts to sync all OS-internal file content and metadata to disk.
469 ///
470 /// This function will attempt to ensure that all in-memory data reaches the
471 /// filesystem before returning.
472 ///
473 /// This can be used to handle errors that would otherwise only be caught
474 /// when the `File` is closed, as dropping a `File` will ignore all errors.
475 /// Note, however, that `sync_all` is generally more expensive than closing
476 /// a file by dropping it, because the latter is not required to block until
477 /// the data has been written to the filesystem.
478 ///
479 /// If synchronizing the metadata is not required, use [`sync_data`] instead.
480 ///
481 /// [`sync_data`]: File::sync_data
482 ///
483 /// # Examples
484 ///
485 /// ```no_run
486 /// use std::fs::File;
487 /// use std::io::prelude::*;
488 ///
489 /// fn main() -> std::io::Result<()> {
490 /// let mut f = File::create("foo.txt")?;
491 /// f.write_all(b"Hello, world!")?;
492 ///
493 /// f.sync_all()?;
494 /// Ok(())
495 /// }
496 /// ```
497 #[stable(feature = "rust1", since = "1.0.0")]
498 #[doc(alias = "fsync")]
499 pub fn sync_all(&self) -> io::Result<()> {
500 self.inner.fsync()
501 }
502
503 /// This function is similar to [`sync_all`], except that it might not
504 /// synchronize file metadata to the filesystem.
505 ///
506 /// This is intended for use cases that must synchronize content, but don't
507 /// need the metadata on disk. The goal of this method is to reduce disk
508 /// operations.
509 ///
510 /// Note that some platforms may simply implement this in terms of
511 /// [`sync_all`].
512 ///
513 /// [`sync_all`]: File::sync_all
514 ///
515 /// # Examples
516 ///
517 /// ```no_run
518 /// use std::fs::File;
519 /// use std::io::prelude::*;
520 ///
521 /// fn main() -> std::io::Result<()> {
522 /// let mut f = File::create("foo.txt")?;
523 /// f.write_all(b"Hello, world!")?;
524 ///
525 /// f.sync_data()?;
526 /// Ok(())
527 /// }
528 /// ```
529 #[stable(feature = "rust1", since = "1.0.0")]
530 #[doc(alias = "fdatasync")]
531 pub fn sync_data(&self) -> io::Result<()> {
532 self.inner.datasync()
533 }
534
535 /// Truncates or extends the underlying file, updating the size of
536 /// this file to become `size`.
537 ///
538 /// If the `size` is less than the current file's size, then the file will
539 /// be shrunk. If it is greater than the current file's size, then the file
540 /// will be extended to `size` and have all of the intermediate data filled
541 /// in with 0s.
542 ///
543 /// The file's cursor isn't changed. In particular, if the cursor was at the
544 /// end and the file is shrunk using this operation, the cursor will now be
545 /// past the end.
546 ///
547 /// # Errors
548 ///
549 /// This function will return an error if the file is not opened for writing.
550 /// Also, [`std::io::ErrorKind::InvalidInput`](crate::io::ErrorKind::InvalidInput)
551 /// will be returned if the desired length would cause an overflow due to
552 /// the implementation specifics.
553 ///
554 /// # Examples
555 ///
556 /// ```no_run
557 /// use std::fs::File;
558 ///
559 /// fn main() -> std::io::Result<()> {
560 /// let mut f = File::create("foo.txt")?;
561 /// f.set_len(10)?;
562 /// Ok(())
563 /// }
564 /// ```
565 ///
566 /// Note that this method alters the content of the underlying file, even
567 /// though it takes `&self` rather than `&mut self`.
568 #[stable(feature = "rust1", since = "1.0.0")]
569 pub fn set_len(&self, size: u64) -> io::Result<()> {
570 self.inner.truncate(size)
571 }
572
573 /// Queries metadata about the underlying file.
574 ///
575 /// # Examples
576 ///
577 /// ```no_run
578 /// use std::fs::File;
579 ///
580 /// fn main() -> std::io::Result<()> {
581 /// let mut f = File::open("foo.txt")?;
582 /// let metadata = f.metadata()?;
583 /// Ok(())
584 /// }
585 /// ```
586 #[stable(feature = "rust1", since = "1.0.0")]
587 pub fn metadata(&self) -> io::Result<Metadata> {
588 self.inner.file_attr().map(Metadata)
589 }
590
591 /// Creates a new `File` instance that shares the same underlying file handle
592 /// as the existing `File` instance. Reads, writes, and seeks will affect
593 /// both `File` instances simultaneously.
594 ///
595 /// # Examples
596 ///
597 /// Creates two handles for a file named `foo.txt`:
598 ///
599 /// ```no_run
600 /// use std::fs::File;
601 ///
602 /// fn main() -> std::io::Result<()> {
603 /// let mut file = File::open("foo.txt")?;
604 /// let file_copy = file.try_clone()?;
605 /// Ok(())
606 /// }
607 /// ```
608 ///
609 /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create
610 /// two handles, seek one of them, and read the remaining bytes from the
611 /// other handle:
612 ///
613 /// ```no_run
614 /// use std::fs::File;
615 /// use std::io::SeekFrom;
616 /// use std::io::prelude::*;
617 ///
618 /// fn main() -> std::io::Result<()> {
619 /// let mut file = File::open("foo.txt")?;
620 /// let mut file_copy = file.try_clone()?;
621 ///
622 /// file.seek(SeekFrom::Start(3))?;
623 ///
624 /// let mut contents = vec![];
625 /// file_copy.read_to_end(&mut contents)?;
626 /// assert_eq!(contents, b"def\n");
627 /// Ok(())
628 /// }
629 /// ```
630 #[stable(feature = "file_try_clone", since = "1.9.0")]
631 pub fn try_clone(&self) -> io::Result<File> {
632 Ok(File { inner: self.inner.duplicate()? })
633 }
634
635 /// Changes the permissions on the underlying file.
636 ///
637 /// # Platform-specific behavior
638 ///
639 /// This function currently corresponds to the `fchmod` function on Unix and
640 /// the `SetFileInformationByHandle` function on Windows. Note that, this
641 /// [may change in the future][changes].
642 ///
643 /// [changes]: io#platform-specific-behavior
644 ///
645 /// # Errors
646 ///
647 /// This function will return an error if the user lacks permission change
648 /// attributes on the underlying file. It may also return an error in other
649 /// os-specific unspecified cases.
650 ///
651 /// # Examples
652 ///
653 /// ```no_run
654 /// fn main() -> std::io::Result<()> {
655 /// use std::fs::File;
656 ///
657 /// let file = File::open("foo.txt")?;
658 /// let mut perms = file.metadata()?.permissions();
659 /// perms.set_readonly(true);
660 /// file.set_permissions(perms)?;
661 /// Ok(())
662 /// }
663 /// ```
664 ///
665 /// Note that this method alters the permissions of the underlying file,
666 /// even though it takes `&self` rather than `&mut self`.
667 #[doc(alias = "fchmod", alias = "SetFileInformationByHandle")]
668 #[stable(feature = "set_permissions_atomic", since = "1.16.0")]
669 pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
670 self.inner.set_permissions(perm.0)
671 }
672
673 /// Changes the timestamps of the underlying file.
674 ///
675 /// # Platform-specific behavior
676 ///
677 /// This function currently corresponds to the `futimens` function on Unix (falling back to
678 /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this
679 /// [may change in the future][changes].
680 ///
681 /// [changes]: io#platform-specific-behavior
682 ///
683 /// # Errors
684 ///
685 /// This function will return an error if the user lacks permission to change timestamps on the
686 /// underlying file. It may also return an error in other os-specific unspecified cases.
687 ///
688 /// This function may return an error if the operating system lacks support to change one or
689 /// more of the timestamps set in the `FileTimes` structure.
690 ///
691 /// # Examples
692 ///
693 /// ```no_run
694 /// fn main() -> std::io::Result<()> {
695 /// use std::fs::{self, File, FileTimes};
696 ///
697 /// let src = fs::metadata("src")?;
698 /// let dest = File::options().write(true).open("dest")?;
699 /// let times = FileTimes::new()
700 /// .set_accessed(src.accessed()?)
701 /// .set_modified(src.modified()?);
702 /// dest.set_times(times)?;
703 /// Ok(())
704 /// }
705 /// ```
706 #[stable(feature = "file_set_times", since = "1.75.0")]
707 #[doc(alias = "futimens")]
708 #[doc(alias = "futimes")]
709 #[doc(alias = "SetFileTime")]
710 pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
711 self.inner.set_times(times.0)
712 }
713
714 /// Changes the modification time of the underlying file.
715 ///
716 /// This is an alias for `set_times(FileTimes::new().set_modified(time))`.
717 #[stable(feature = "file_set_times", since = "1.75.0")]
718 #[inline]
719 pub fn set_modified(&self, time: SystemTime) -> io::Result<()> {
720 self.set_times(FileTimes::new().set_modified(time))
721 }
722}
723
724// In addition to the `impl`s here, `File` also has `impl`s for
725// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and
726// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and
727// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and
728// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
729
730impl AsInner<fs_imp::File> for File {
731 #[inline]
732 fn as_inner(&self) -> &fs_imp::File {
733 &self.inner
734 }
735}
736impl FromInner<fs_imp::File> for File {
737 fn from_inner(f: fs_imp::File) -> File {
738 File { inner: f }
739 }
740}
741impl IntoInner<fs_imp::File> for File {
742 fn into_inner(self) -> fs_imp::File {
743 self.inner
744 }
745}
746
747#[stable(feature = "rust1", since = "1.0.0")]
748impl fmt::Debug for File {
749 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
750 self.inner.fmt(f)
751 }
752}
753
754/// Indicates how much extra capacity is needed to read the rest of the file.
755fn buffer_capacity_required(mut file: &File) -> Option<usize> {
756 let size: u64 = file.metadata().map(|m: Metadata| m.len()).ok()?;
757 let pos: u64 = file.stream_position().ok()?;
758 // Don't worry about `usize` overflow because reading will fail regardless
759 // in that case.
760 Some(size.saturating_sub(pos) as usize)
761}
762
763#[stable(feature = "rust1", since = "1.0.0")]
764impl Read for &File {
765 #[inline]
766 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
767 self.inner.read(buf)
768 }
769
770 #[inline]
771 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
772 self.inner.read_vectored(bufs)
773 }
774
775 #[inline]
776 fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
777 self.inner.read_buf(cursor)
778 }
779
780 #[inline]
781 fn is_read_vectored(&self) -> bool {
782 self.inner.is_read_vectored()
783 }
784
785 // Reserves space in the buffer based on the file size when available.
786 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
787 let size = buffer_capacity_required(self);
788 buf.try_reserve(size.unwrap_or(0))?;
789 io::default_read_to_end(self, buf, size)
790 }
791
792 // Reserves space in the buffer based on the file size when available.
793 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
794 let size = buffer_capacity_required(self);
795 buf.try_reserve(size.unwrap_or(0))?;
796 io::default_read_to_string(self, buf, size)
797 }
798}
799#[stable(feature = "rust1", since = "1.0.0")]
800impl Write for &File {
801 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
802 self.inner.write(buf)
803 }
804
805 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
806 self.inner.write_vectored(bufs)
807 }
808
809 #[inline]
810 fn is_write_vectored(&self) -> bool {
811 self.inner.is_write_vectored()
812 }
813
814 #[inline]
815 fn flush(&mut self) -> io::Result<()> {
816 self.inner.flush()
817 }
818}
819#[stable(feature = "rust1", since = "1.0.0")]
820impl Seek for &File {
821 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
822 self.inner.seek(pos)
823 }
824}
825
826#[stable(feature = "rust1", since = "1.0.0")]
827impl Read for File {
828 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
829 (&*self).read(buf)
830 }
831 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
832 (&*self).read_vectored(bufs)
833 }
834 fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
835 (&*self).read_buf(cursor)
836 }
837 #[inline]
838 fn is_read_vectored(&self) -> bool {
839 (&&*self).is_read_vectored()
840 }
841 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
842 (&*self).read_to_end(buf)
843 }
844 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
845 (&*self).read_to_string(buf)
846 }
847}
848#[stable(feature = "rust1", since = "1.0.0")]
849impl Write for File {
850 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
851 (&*self).write(buf)
852 }
853 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
854 (&*self).write_vectored(bufs)
855 }
856 #[inline]
857 fn is_write_vectored(&self) -> bool {
858 (&&*self).is_write_vectored()
859 }
860 #[inline]
861 fn flush(&mut self) -> io::Result<()> {
862 (&*self).flush()
863 }
864}
865#[stable(feature = "rust1", since = "1.0.0")]
866impl Seek for File {
867 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
868 (&*self).seek(pos)
869 }
870}
871
872#[stable(feature = "io_traits_arc", since = "1.73.0")]
873impl Read for Arc<File> {
874 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
875 (&**self).read(buf)
876 }
877 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
878 (&**self).read_vectored(bufs)
879 }
880 fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
881 (&**self).read_buf(cursor)
882 }
883 #[inline]
884 fn is_read_vectored(&self) -> bool {
885 (&**self).is_read_vectored()
886 }
887 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
888 (&**self).read_to_end(buf)
889 }
890 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
891 (&**self).read_to_string(buf)
892 }
893}
894#[stable(feature = "io_traits_arc", since = "1.73.0")]
895impl Write for Arc<File> {
896 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
897 (&**self).write(buf)
898 }
899 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
900 (&**self).write_vectored(bufs)
901 }
902 #[inline]
903 fn is_write_vectored(&self) -> bool {
904 (&**self).is_write_vectored()
905 }
906 #[inline]
907 fn flush(&mut self) -> io::Result<()> {
908 (&**self).flush()
909 }
910}
911#[stable(feature = "io_traits_arc", since = "1.73.0")]
912impl Seek for Arc<File> {
913 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
914 (&**self).seek(pos)
915 }
916}
917
918impl OpenOptions {
919 /// Creates a blank new set of options ready for configuration.
920 ///
921 /// All options are initially set to `false`.
922 ///
923 /// # Examples
924 ///
925 /// ```no_run
926 /// use std::fs::OpenOptions;
927 ///
928 /// let mut options = OpenOptions::new();
929 /// let file = options.read(true).open("foo.txt");
930 /// ```
931 #[stable(feature = "rust1", since = "1.0.0")]
932 #[must_use]
933 pub fn new() -> Self {
934 OpenOptions(fs_imp::OpenOptions::new())
935 }
936
937 /// Sets the option for read access.
938 ///
939 /// This option, when true, will indicate that the file should be
940 /// `read`-able if opened.
941 ///
942 /// # Examples
943 ///
944 /// ```no_run
945 /// use std::fs::OpenOptions;
946 ///
947 /// let file = OpenOptions::new().read(true).open("foo.txt");
948 /// ```
949 #[stable(feature = "rust1", since = "1.0.0")]
950 pub fn read(&mut self, read: bool) -> &mut Self {
951 self.0.read(read);
952 self
953 }
954
955 /// Sets the option for write access.
956 ///
957 /// This option, when true, will indicate that the file should be
958 /// `write`-able if opened.
959 ///
960 /// If the file already exists, any write calls on it will overwrite its
961 /// contents, without truncating it.
962 ///
963 /// # Examples
964 ///
965 /// ```no_run
966 /// use std::fs::OpenOptions;
967 ///
968 /// let file = OpenOptions::new().write(true).open("foo.txt");
969 /// ```
970 #[stable(feature = "rust1", since = "1.0.0")]
971 pub fn write(&mut self, write: bool) -> &mut Self {
972 self.0.write(write);
973 self
974 }
975
976 /// Sets the option for the append mode.
977 ///
978 /// This option, when true, means that writes will append to a file instead
979 /// of overwriting previous contents.
980 /// Note that setting `.write(true).append(true)` has the same effect as
981 /// setting only `.append(true)`.
982 ///
983 /// Append mode guarantees that writes will be positioned at the current end of file,
984 /// even when there are other processes or threads appending to the same file. This is
985 /// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which
986 /// has a race between seeking and writing during which another writer can write, with
987 /// our `write()` overwriting their data.
988 ///
989 /// Keep in mind that this does not necessarily guarantee that data appended by
990 /// different processes or threads does not interleave. The amount of data accepted a
991 /// single `write()` call depends on the operating system and file system. A
992 /// successful `write()` is allowed to write only part of the given data, so even if
993 /// you're careful to provide the whole message in a single call to `write()`, there
994 /// is no guarantee that it will be written out in full. If you rely on the filesystem
995 /// accepting the message in a single write, make sure that all data that belongs
996 /// together is written in one operation. This can be done by concatenating strings
997 /// before passing them to [`write()`].
998 ///
999 /// If a file is opened with both read and append access, beware that after
1000 /// opening, and after every write, the position for reading may be set at the
1001 /// end of the file. So, before writing, save the current position (using
1002 /// <code>[Seek]::[stream_position]</code>), and restore it before the next read.
1003 ///
1004 /// ## Note
1005 ///
1006 /// This function doesn't create the file if it doesn't exist. Use the
1007 /// [`OpenOptions::create`] method to do so.
1008 ///
1009 /// [`write()`]: Write::write "io::Write::write"
1010 /// [`flush()`]: Write::flush "io::Write::flush"
1011 /// [stream_position]: Seek::stream_position "io::Seek::stream_position"
1012 /// [seek]: Seek::seek "io::Seek::seek"
1013 /// [Current]: SeekFrom::Current "io::SeekFrom::Current"
1014 /// [End]: SeekFrom::End "io::SeekFrom::End"
1015 ///
1016 /// # Examples
1017 ///
1018 /// ```no_run
1019 /// use std::fs::OpenOptions;
1020 ///
1021 /// let file = OpenOptions::new().append(true).open("foo.txt");
1022 /// ```
1023 #[stable(feature = "rust1", since = "1.0.0")]
1024 pub fn append(&mut self, append: bool) -> &mut Self {
1025 self.0.append(append);
1026 self
1027 }
1028
1029 /// Sets the option for truncating a previous file.
1030 ///
1031 /// If a file is successfully opened with this option set it will truncate
1032 /// the file to 0 length if it already exists.
1033 ///
1034 /// The file must be opened with write access for truncate to work.
1035 ///
1036 /// # Examples
1037 ///
1038 /// ```no_run
1039 /// use std::fs::OpenOptions;
1040 ///
1041 /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt");
1042 /// ```
1043 #[stable(feature = "rust1", since = "1.0.0")]
1044 pub fn truncate(&mut self, truncate: bool) -> &mut Self {
1045 self.0.truncate(truncate);
1046 self
1047 }
1048
1049 /// Sets the option to create a new file, or open it if it already exists.
1050 ///
1051 /// In order for the file to be created, [`OpenOptions::write`] or
1052 /// [`OpenOptions::append`] access must be used.
1053 ///
1054 /// See also [`std::fs::write()`][self::write] for a simple function to
1055 /// create a file with some given data.
1056 ///
1057 /// # Examples
1058 ///
1059 /// ```no_run
1060 /// use std::fs::OpenOptions;
1061 ///
1062 /// let file = OpenOptions::new().write(true).create(true).open("foo.txt");
1063 /// ```
1064 #[stable(feature = "rust1", since = "1.0.0")]
1065 pub fn create(&mut self, create: bool) -> &mut Self {
1066 self.0.create(create);
1067 self
1068 }
1069
1070 /// Sets the option to create a new file, failing if it already exists.
1071 ///
1072 /// No file is allowed to exist at the target location, also no (dangling) symlink. In this
1073 /// way, if the call succeeds, the file returned is guaranteed to be new.
1074 ///
1075 /// This option is useful because it is atomic. Otherwise between checking
1076 /// whether a file exists and creating a new one, the file may have been
1077 /// created by another process (a TOCTOU race condition / attack).
1078 ///
1079 /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are
1080 /// ignored.
1081 ///
1082 /// The file must be opened with write or append access in order to create
1083 /// a new file.
1084 ///
1085 /// [`.create()`]: OpenOptions::create
1086 /// [`.truncate()`]: OpenOptions::truncate
1087 ///
1088 /// # Examples
1089 ///
1090 /// ```no_run
1091 /// use std::fs::OpenOptions;
1092 ///
1093 /// let file = OpenOptions::new().write(true)
1094 /// .create_new(true)
1095 /// .open("foo.txt");
1096 /// ```
1097 #[stable(feature = "expand_open_options2", since = "1.9.0")]
1098 pub fn create_new(&mut self, create_new: bool) -> &mut Self {
1099 self.0.create_new(create_new);
1100 self
1101 }
1102
1103 /// Opens a file at `path` with the options specified by `self`.
1104 ///
1105 /// # Errors
1106 ///
1107 /// This function will return an error under a number of different
1108 /// circumstances. Some of these error conditions are listed here, together
1109 /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not
1110 /// part of the compatibility contract of the function.
1111 ///
1112 /// * [`NotFound`]: The specified file does not exist and neither `create`
1113 /// or `create_new` is set.
1114 /// * [`NotFound`]: One of the directory components of the file path does
1115 /// not exist.
1116 /// * [`PermissionDenied`]: The user lacks permission to get the specified
1117 /// access rights for the file.
1118 /// * [`PermissionDenied`]: The user lacks permission to open one of the
1119 /// directory components of the specified path.
1120 /// * [`AlreadyExists`]: `create_new` was specified and the file already
1121 /// exists.
1122 /// * [`InvalidInput`]: Invalid combinations of open options (truncate
1123 /// without write access, no access mode set, etc.).
1124 ///
1125 /// The following errors don't match any existing [`io::ErrorKind`] at the moment:
1126 /// * One of the directory components of the specified file path
1127 /// was not, in fact, a directory.
1128 /// * Filesystem-level errors: full disk, write permission
1129 /// requested on a read-only file system, exceeded disk quota, too many
1130 /// open files, too long filename, too many symbolic links in the
1131 /// specified path (Unix-like systems only), etc.
1132 ///
1133 /// # Examples
1134 ///
1135 /// ```no_run
1136 /// use std::fs::OpenOptions;
1137 ///
1138 /// let file = OpenOptions::new().read(true).open("foo.txt");
1139 /// ```
1140 ///
1141 /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
1142 /// [`InvalidInput`]: io::ErrorKind::InvalidInput
1143 /// [`NotFound`]: io::ErrorKind::NotFound
1144 /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied
1145 #[stable(feature = "rust1", since = "1.0.0")]
1146 pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
1147 self._open(path.as_ref())
1148 }
1149
1150 fn _open(&self, path: &Path) -> io::Result<File> {
1151 fs_imp::File::open(path, &self.0).map(|inner| File { inner })
1152 }
1153}
1154
1155impl AsInner<fs_imp::OpenOptions> for OpenOptions {
1156 #[inline]
1157 fn as_inner(&self) -> &fs_imp::OpenOptions {
1158 &self.0
1159 }
1160}
1161
1162impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
1163 #[inline]
1164 fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {
1165 &mut self.0
1166 }
1167}
1168
1169impl Metadata {
1170 /// Returns the file type for this metadata.
1171 ///
1172 /// # Examples
1173 ///
1174 /// ```no_run
1175 /// fn main() -> std::io::Result<()> {
1176 /// use std::fs;
1177 ///
1178 /// let metadata = fs::metadata("foo.txt")?;
1179 ///
1180 /// println!("{:?}", metadata.file_type());
1181 /// Ok(())
1182 /// }
1183 /// ```
1184 #[must_use]
1185 #[stable(feature = "file_type", since = "1.1.0")]
1186 pub fn file_type(&self) -> FileType {
1187 FileType(self.0.file_type())
1188 }
1189
1190 /// Returns `true` if this metadata is for a directory. The
1191 /// result is mutually exclusive to the result of
1192 /// [`Metadata::is_file`], and will be false for symlink metadata
1193 /// obtained from [`symlink_metadata`].
1194 ///
1195 /// # Examples
1196 ///
1197 /// ```no_run
1198 /// fn main() -> std::io::Result<()> {
1199 /// use std::fs;
1200 ///
1201 /// let metadata = fs::metadata("foo.txt")?;
1202 ///
1203 /// assert!(!metadata.is_dir());
1204 /// Ok(())
1205 /// }
1206 /// ```
1207 #[must_use]
1208 #[stable(feature = "rust1", since = "1.0.0")]
1209 pub fn is_dir(&self) -> bool {
1210 self.file_type().is_dir()
1211 }
1212
1213 /// Returns `true` if this metadata is for a regular file. The
1214 /// result is mutually exclusive to the result of
1215 /// [`Metadata::is_dir`], and will be false for symlink metadata
1216 /// obtained from [`symlink_metadata`].
1217 ///
1218 /// When the goal is simply to read from (or write to) the source, the most
1219 /// reliable way to test the source can be read (or written to) is to open
1220 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
1221 /// a Unix-like system for example. See [`File::open`] or
1222 /// [`OpenOptions::open`] for more information.
1223 ///
1224 /// # Examples
1225 ///
1226 /// ```no_run
1227 /// use std::fs;
1228 ///
1229 /// fn main() -> std::io::Result<()> {
1230 /// let metadata = fs::metadata("foo.txt")?;
1231 ///
1232 /// assert!(metadata.is_file());
1233 /// Ok(())
1234 /// }
1235 /// ```
1236 #[must_use]
1237 #[stable(feature = "rust1", since = "1.0.0")]
1238 pub fn is_file(&self) -> bool {
1239 self.file_type().is_file()
1240 }
1241
1242 /// Returns `true` if this metadata is for a symbolic link.
1243 ///
1244 /// # Examples
1245 ///
1246 #[cfg_attr(unix, doc = "```no_run")]
1247 #[cfg_attr(not(unix), doc = "```ignore")]
1248 /// use std::fs;
1249 /// use std::path::Path;
1250 /// use std::os::unix::fs::symlink;
1251 ///
1252 /// fn main() -> std::io::Result<()> {
1253 /// let link_path = Path::new("link");
1254 /// symlink("/origin_does_not_exist/", link_path)?;
1255 ///
1256 /// let metadata = fs::symlink_metadata(link_path)?;
1257 ///
1258 /// assert!(metadata.is_symlink());
1259 /// Ok(())
1260 /// }
1261 /// ```
1262 #[must_use]
1263 #[stable(feature = "is_symlink", since = "1.58.0")]
1264 pub fn is_symlink(&self) -> bool {
1265 self.file_type().is_symlink()
1266 }
1267
1268 /// Returns the size of the file, in bytes, this metadata is for.
1269 ///
1270 /// # Examples
1271 ///
1272 /// ```no_run
1273 /// use std::fs;
1274 ///
1275 /// fn main() -> std::io::Result<()> {
1276 /// let metadata = fs::metadata("foo.txt")?;
1277 ///
1278 /// assert_eq!(0, metadata.len());
1279 /// Ok(())
1280 /// }
1281 /// ```
1282 #[must_use]
1283 #[stable(feature = "rust1", since = "1.0.0")]
1284 pub fn len(&self) -> u64 {
1285 self.0.size()
1286 }
1287
1288 /// Returns the permissions of the file this metadata is for.
1289 ///
1290 /// # Examples
1291 ///
1292 /// ```no_run
1293 /// use std::fs;
1294 ///
1295 /// fn main() -> std::io::Result<()> {
1296 /// let metadata = fs::metadata("foo.txt")?;
1297 ///
1298 /// assert!(!metadata.permissions().readonly());
1299 /// Ok(())
1300 /// }
1301 /// ```
1302 #[must_use]
1303 #[stable(feature = "rust1", since = "1.0.0")]
1304 pub fn permissions(&self) -> Permissions {
1305 Permissions(self.0.perm())
1306 }
1307
1308 /// Returns the last modification time listed in this metadata.
1309 ///
1310 /// The returned value corresponds to the `mtime` field of `stat` on Unix
1311 /// platforms and the `ftLastWriteTime` field on Windows platforms.
1312 ///
1313 /// # Errors
1314 ///
1315 /// This field might not be available on all platforms, and will return an
1316 /// `Err` on platforms where it is not available.
1317 ///
1318 /// # Examples
1319 ///
1320 /// ```no_run
1321 /// use std::fs;
1322 ///
1323 /// fn main() -> std::io::Result<()> {
1324 /// let metadata = fs::metadata("foo.txt")?;
1325 ///
1326 /// if let Ok(time) = metadata.modified() {
1327 /// println!("{time:?}");
1328 /// } else {
1329 /// println!("Not supported on this platform");
1330 /// }
1331 /// Ok(())
1332 /// }
1333 /// ```
1334 #[doc(alias = "mtime", alias = "ftLastWriteTime")]
1335 #[stable(feature = "fs_time", since = "1.10.0")]
1336 pub fn modified(&self) -> io::Result<SystemTime> {
1337 self.0.modified().map(FromInner::from_inner)
1338 }
1339
1340 /// Returns the last access time of this metadata.
1341 ///
1342 /// The returned value corresponds to the `atime` field of `stat` on Unix
1343 /// platforms and the `ftLastAccessTime` field on Windows platforms.
1344 ///
1345 /// Note that not all platforms will keep this field update in a file's
1346 /// metadata, for example Windows has an option to disable updating this
1347 /// time when files are accessed and Linux similarly has `noatime`.
1348 ///
1349 /// # Errors
1350 ///
1351 /// This field might not be available on all platforms, and will return an
1352 /// `Err` on platforms where it is not available.
1353 ///
1354 /// # Examples
1355 ///
1356 /// ```no_run
1357 /// use std::fs;
1358 ///
1359 /// fn main() -> std::io::Result<()> {
1360 /// let metadata = fs::metadata("foo.txt")?;
1361 ///
1362 /// if let Ok(time) = metadata.accessed() {
1363 /// println!("{time:?}");
1364 /// } else {
1365 /// println!("Not supported on this platform");
1366 /// }
1367 /// Ok(())
1368 /// }
1369 /// ```
1370 #[doc(alias = "atime", alias = "ftLastAccessTime")]
1371 #[stable(feature = "fs_time", since = "1.10.0")]
1372 pub fn accessed(&self) -> io::Result<SystemTime> {
1373 self.0.accessed().map(FromInner::from_inner)
1374 }
1375
1376 /// Returns the creation time listed in this metadata.
1377 ///
1378 /// The returned value corresponds to the `btime` field of `statx` on
1379 /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other
1380 /// Unix platforms, and the `ftCreationTime` field on Windows platforms.
1381 ///
1382 /// # Errors
1383 ///
1384 /// This field might not be available on all platforms, and will return an
1385 /// `Err` on platforms or filesystems where it is not available.
1386 ///
1387 /// # Examples
1388 ///
1389 /// ```no_run
1390 /// use std::fs;
1391 ///
1392 /// fn main() -> std::io::Result<()> {
1393 /// let metadata = fs::metadata("foo.txt")?;
1394 ///
1395 /// if let Ok(time) = metadata.created() {
1396 /// println!("{time:?}");
1397 /// } else {
1398 /// println!("Not supported on this platform or filesystem");
1399 /// }
1400 /// Ok(())
1401 /// }
1402 /// ```
1403 #[doc(alias = "btime", alias = "birthtime", alias = "ftCreationTime")]
1404 #[stable(feature = "fs_time", since = "1.10.0")]
1405 pub fn created(&self) -> io::Result<SystemTime> {
1406 self.0.created().map(FromInner::from_inner)
1407 }
1408}
1409
1410#[stable(feature = "std_debug", since = "1.16.0")]
1411impl fmt::Debug for Metadata {
1412 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1413 let mut debug: DebugStruct<'_, '_> = f.debug_struct(name:"Metadata");
1414 debug.field(name:"file_type", &self.file_type());
1415 debug.field(name:"permissions", &self.permissions());
1416 debug.field(name:"len", &self.len());
1417 if let Ok(modified: SystemTime) = self.modified() {
1418 debug.field(name:"modified", &modified);
1419 }
1420 if let Ok(accessed: SystemTime) = self.accessed() {
1421 debug.field(name:"accessed", &accessed);
1422 }
1423 if let Ok(created: SystemTime) = self.created() {
1424 debug.field(name:"created", &created);
1425 }
1426 debug.finish_non_exhaustive()
1427 }
1428}
1429
1430impl AsInner<fs_imp::FileAttr> for Metadata {
1431 #[inline]
1432 fn as_inner(&self) -> &fs_imp::FileAttr {
1433 &self.0
1434 }
1435}
1436
1437impl FromInner<fs_imp::FileAttr> for Metadata {
1438 fn from_inner(attr: fs_imp::FileAttr) -> Metadata {
1439 Metadata(attr)
1440 }
1441}
1442
1443impl FileTimes {
1444 /// Create a new `FileTimes` with no times set.
1445 ///
1446 /// Using the resulting `FileTimes` in [`File::set_times`] will not modify any timestamps.
1447 #[stable(feature = "file_set_times", since = "1.75.0")]
1448 pub fn new() -> Self {
1449 Self::default()
1450 }
1451
1452 /// Set the last access time of a file.
1453 #[stable(feature = "file_set_times", since = "1.75.0")]
1454 pub fn set_accessed(mut self, t: SystemTime) -> Self {
1455 self.0.set_accessed(t.into_inner());
1456 self
1457 }
1458
1459 /// Set the last modified time of a file.
1460 #[stable(feature = "file_set_times", since = "1.75.0")]
1461 pub fn set_modified(mut self, t: SystemTime) -> Self {
1462 self.0.set_modified(t.into_inner());
1463 self
1464 }
1465}
1466
1467impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
1468 fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes {
1469 &mut self.0
1470 }
1471}
1472
1473// For implementing OS extension traits in `std::os`
1474#[stable(feature = "file_set_times", since = "1.75.0")]
1475impl Sealed for FileTimes {}
1476
1477impl Permissions {
1478 /// Returns `true` if these permissions describe a readonly (unwritable) file.
1479 ///
1480 /// # Note
1481 ///
1482 /// This function does not take Access Control Lists (ACLs) or Unix group
1483 /// membership into account.
1484 ///
1485 /// # Windows
1486 ///
1487 /// On Windows this returns [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
1488 /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
1489 /// but the user may still have permission to change this flag. If
1490 /// `FILE_ATTRIBUTE_READONLY` is *not* set then writes may still fail due
1491 /// to lack of write permission.
1492 /// The behavior of this attribute for directories depends on the Windows
1493 /// version.
1494 ///
1495 /// # Unix (including macOS)
1496 ///
1497 /// On Unix-based platforms this checks if *any* of the owner, group or others
1498 /// write permission bits are set. It does not check if the current
1499 /// user is in the file's assigned group. It also does not check ACLs.
1500 /// Therefore the return value of this function cannot be relied upon
1501 /// to predict whether attempts to read or write the file will actually succeed.
1502 /// The [`PermissionsExt`] trait gives direct access to the permission bits but
1503 /// also does not read ACLs.
1504 ///
1505 /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
1506 ///
1507 /// # Examples
1508 ///
1509 /// ```no_run
1510 /// use std::fs::File;
1511 ///
1512 /// fn main() -> std::io::Result<()> {
1513 /// let mut f = File::create("foo.txt")?;
1514 /// let metadata = f.metadata()?;
1515 ///
1516 /// assert_eq!(false, metadata.permissions().readonly());
1517 /// Ok(())
1518 /// }
1519 /// ```
1520 #[must_use = "call `set_readonly` to modify the readonly flag"]
1521 #[stable(feature = "rust1", since = "1.0.0")]
1522 pub fn readonly(&self) -> bool {
1523 self.0.readonly()
1524 }
1525
1526 /// Modifies the readonly flag for this set of permissions. If the
1527 /// `readonly` argument is `true`, using the resulting `Permission` will
1528 /// update file permissions to forbid writing. Conversely, if it's `false`,
1529 /// using the resulting `Permission` will update file permissions to allow
1530 /// writing.
1531 ///
1532 /// This operation does **not** modify the files attributes. This only
1533 /// changes the in-memory value of these attributes for this `Permissions`
1534 /// instance. To modify the files attributes use the [`set_permissions`]
1535 /// function which commits these attribute changes to the file.
1536 ///
1537 /// # Note
1538 ///
1539 /// `set_readonly(false)` makes the file *world-writable* on Unix.
1540 /// You can use the [`PermissionsExt`] trait on Unix to avoid this issue.
1541 ///
1542 /// It also does not take Access Control Lists (ACLs) or Unix group
1543 /// membership into account.
1544 ///
1545 /// # Windows
1546 ///
1547 /// On Windows this sets or clears [`FILE_ATTRIBUTE_READONLY`](https://docs.microsoft.com/en-us/windows/win32/fileio/file-attribute-constants).
1548 /// If `FILE_ATTRIBUTE_READONLY` is set then writes to the file will fail
1549 /// but the user may still have permission to change this flag. If
1550 /// `FILE_ATTRIBUTE_READONLY` is *not* set then the write may still fail if
1551 /// the user does not have permission to write to the file.
1552 ///
1553 /// In Windows 7 and earlier this attribute prevents deleting empty
1554 /// directories. It does not prevent modifying the directory contents.
1555 /// On later versions of Windows this attribute is ignored for directories.
1556 ///
1557 /// # Unix (including macOS)
1558 ///
1559 /// On Unix-based platforms this sets or clears the write access bit for
1560 /// the owner, group *and* others, equivalent to `chmod a+w <file>`
1561 /// or `chmod a-w <file>` respectively. The latter will grant write access
1562 /// to all users! You can use the [`PermissionsExt`] trait on Unix
1563 /// to avoid this issue.
1564 ///
1565 /// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt
1566 ///
1567 /// # Examples
1568 ///
1569 /// ```no_run
1570 /// use std::fs::File;
1571 ///
1572 /// fn main() -> std::io::Result<()> {
1573 /// let f = File::create("foo.txt")?;
1574 /// let metadata = f.metadata()?;
1575 /// let mut permissions = metadata.permissions();
1576 ///
1577 /// permissions.set_readonly(true);
1578 ///
1579 /// // filesystem doesn't change, only the in memory state of the
1580 /// // readonly permission
1581 /// assert_eq!(false, metadata.permissions().readonly());
1582 ///
1583 /// // just this particular `permissions`.
1584 /// assert_eq!(true, permissions.readonly());
1585 /// Ok(())
1586 /// }
1587 /// ```
1588 #[stable(feature = "rust1", since = "1.0.0")]
1589 pub fn set_readonly(&mut self, readonly: bool) {
1590 self.0.set_readonly(readonly)
1591 }
1592}
1593
1594impl FileType {
1595 /// Tests whether this file type represents a directory. The
1596 /// result is mutually exclusive to the results of
1597 /// [`is_file`] and [`is_symlink`]; only zero or one of these
1598 /// tests may pass.
1599 ///
1600 /// [`is_file`]: FileType::is_file
1601 /// [`is_symlink`]: FileType::is_symlink
1602 ///
1603 /// # Examples
1604 ///
1605 /// ```no_run
1606 /// fn main() -> std::io::Result<()> {
1607 /// use std::fs;
1608 ///
1609 /// let metadata = fs::metadata("foo.txt")?;
1610 /// let file_type = metadata.file_type();
1611 ///
1612 /// assert_eq!(file_type.is_dir(), false);
1613 /// Ok(())
1614 /// }
1615 /// ```
1616 #[must_use]
1617 #[stable(feature = "file_type", since = "1.1.0")]
1618 pub fn is_dir(&self) -> bool {
1619 self.0.is_dir()
1620 }
1621
1622 /// Tests whether this file type represents a regular file.
1623 /// The result is mutually exclusive to the results of
1624 /// [`is_dir`] and [`is_symlink`]; only zero or one of these
1625 /// tests may pass.
1626 ///
1627 /// When the goal is simply to read from (or write to) the source, the most
1628 /// reliable way to test the source can be read (or written to) is to open
1629 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
1630 /// a Unix-like system for example. See [`File::open`] or
1631 /// [`OpenOptions::open`] for more information.
1632 ///
1633 /// [`is_dir`]: FileType::is_dir
1634 /// [`is_symlink`]: FileType::is_symlink
1635 ///
1636 /// # Examples
1637 ///
1638 /// ```no_run
1639 /// fn main() -> std::io::Result<()> {
1640 /// use std::fs;
1641 ///
1642 /// let metadata = fs::metadata("foo.txt")?;
1643 /// let file_type = metadata.file_type();
1644 ///
1645 /// assert_eq!(file_type.is_file(), true);
1646 /// Ok(())
1647 /// }
1648 /// ```
1649 #[must_use]
1650 #[stable(feature = "file_type", since = "1.1.0")]
1651 pub fn is_file(&self) -> bool {
1652 self.0.is_file()
1653 }
1654
1655 /// Tests whether this file type represents a symbolic link.
1656 /// The result is mutually exclusive to the results of
1657 /// [`is_dir`] and [`is_file`]; only zero or one of these
1658 /// tests may pass.
1659 ///
1660 /// The underlying [`Metadata`] struct needs to be retrieved
1661 /// with the [`fs::symlink_metadata`] function and not the
1662 /// [`fs::metadata`] function. The [`fs::metadata`] function
1663 /// follows symbolic links, so [`is_symlink`] would always
1664 /// return `false` for the target file.
1665 ///
1666 /// [`fs::metadata`]: metadata
1667 /// [`fs::symlink_metadata`]: symlink_metadata
1668 /// [`is_dir`]: FileType::is_dir
1669 /// [`is_file`]: FileType::is_file
1670 /// [`is_symlink`]: FileType::is_symlink
1671 ///
1672 /// # Examples
1673 ///
1674 /// ```no_run
1675 /// use std::fs;
1676 ///
1677 /// fn main() -> std::io::Result<()> {
1678 /// let metadata = fs::symlink_metadata("foo.txt")?;
1679 /// let file_type = metadata.file_type();
1680 ///
1681 /// assert_eq!(file_type.is_symlink(), false);
1682 /// Ok(())
1683 /// }
1684 /// ```
1685 #[must_use]
1686 #[stable(feature = "file_type", since = "1.1.0")]
1687 pub fn is_symlink(&self) -> bool {
1688 self.0.is_symlink()
1689 }
1690}
1691
1692#[stable(feature = "std_debug", since = "1.16.0")]
1693impl fmt::Debug for FileType {
1694 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1695 f&mut DebugStruct<'_, '_>.debug_struct("FileType")
1696 .field("is_file", &self.is_file())
1697 .field("is_dir", &self.is_dir())
1698 .field(name:"is_symlink", &self.is_symlink())
1699 .finish_non_exhaustive()
1700 }
1701}
1702
1703impl AsInner<fs_imp::FileType> for FileType {
1704 #[inline]
1705 fn as_inner(&self) -> &fs_imp::FileType {
1706 &self.0
1707 }
1708}
1709
1710impl FromInner<fs_imp::FilePermissions> for Permissions {
1711 fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
1712 Permissions(f)
1713 }
1714}
1715
1716impl AsInner<fs_imp::FilePermissions> for Permissions {
1717 #[inline]
1718 fn as_inner(&self) -> &fs_imp::FilePermissions {
1719 &self.0
1720 }
1721}
1722
1723#[stable(feature = "rust1", since = "1.0.0")]
1724impl Iterator for ReadDir {
1725 type Item = io::Result<DirEntry>;
1726
1727 fn next(&mut self) -> Option<io::Result<DirEntry>> {
1728 self.0.next().map(|entry: Result| entry.map(op:DirEntry))
1729 }
1730}
1731
1732impl DirEntry {
1733 /// Returns the full path to the file that this entry represents.
1734 ///
1735 /// The full path is created by joining the original path to `read_dir`
1736 /// with the filename of this entry.
1737 ///
1738 /// # Examples
1739 ///
1740 /// ```no_run
1741 /// use std::fs;
1742 ///
1743 /// fn main() -> std::io::Result<()> {
1744 /// for entry in fs::read_dir(".")? {
1745 /// let dir = entry?;
1746 /// println!("{:?}", dir.path());
1747 /// }
1748 /// Ok(())
1749 /// }
1750 /// ```
1751 ///
1752 /// This prints output like:
1753 ///
1754 /// ```text
1755 /// "./whatever.txt"
1756 /// "./foo.html"
1757 /// "./hello_world.rs"
1758 /// ```
1759 ///
1760 /// The exact text, of course, depends on what files you have in `.`.
1761 #[must_use]
1762 #[stable(feature = "rust1", since = "1.0.0")]
1763 pub fn path(&self) -> PathBuf {
1764 self.0.path()
1765 }
1766
1767 /// Returns the metadata for the file that this entry points at.
1768 ///
1769 /// This function will not traverse symlinks if this entry points at a
1770 /// symlink. To traverse symlinks use [`fs::metadata`] or [`fs::File::metadata`].
1771 ///
1772 /// [`fs::metadata`]: metadata
1773 /// [`fs::File::metadata`]: File::metadata
1774 ///
1775 /// # Platform-specific behavior
1776 ///
1777 /// On Windows this function is cheap to call (no extra system calls
1778 /// needed), but on Unix platforms this function is the equivalent of
1779 /// calling `symlink_metadata` on the path.
1780 ///
1781 /// # Examples
1782 ///
1783 /// ```
1784 /// use std::fs;
1785 ///
1786 /// if let Ok(entries) = fs::read_dir(".") {
1787 /// for entry in entries {
1788 /// if let Ok(entry) = entry {
1789 /// // Here, `entry` is a `DirEntry`.
1790 /// if let Ok(metadata) = entry.metadata() {
1791 /// // Now let's show our entry's permissions!
1792 /// println!("{:?}: {:?}", entry.path(), metadata.permissions());
1793 /// } else {
1794 /// println!("Couldn't get metadata for {:?}", entry.path());
1795 /// }
1796 /// }
1797 /// }
1798 /// }
1799 /// ```
1800 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1801 pub fn metadata(&self) -> io::Result<Metadata> {
1802 self.0.metadata().map(Metadata)
1803 }
1804
1805 /// Returns the file type for the file that this entry points at.
1806 ///
1807 /// This function will not traverse symlinks if this entry points at a
1808 /// symlink.
1809 ///
1810 /// # Platform-specific behavior
1811 ///
1812 /// On Windows and most Unix platforms this function is free (no extra
1813 /// system calls needed), but some Unix platforms may require the equivalent
1814 /// call to `symlink_metadata` to learn about the target file type.
1815 ///
1816 /// # Examples
1817 ///
1818 /// ```
1819 /// use std::fs;
1820 ///
1821 /// if let Ok(entries) = fs::read_dir(".") {
1822 /// for entry in entries {
1823 /// if let Ok(entry) = entry {
1824 /// // Here, `entry` is a `DirEntry`.
1825 /// if let Ok(file_type) = entry.file_type() {
1826 /// // Now let's show our entry's file type!
1827 /// println!("{:?}: {:?}", entry.path(), file_type);
1828 /// } else {
1829 /// println!("Couldn't get file type for {:?}", entry.path());
1830 /// }
1831 /// }
1832 /// }
1833 /// }
1834 /// ```
1835 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1836 pub fn file_type(&self) -> io::Result<FileType> {
1837 self.0.file_type().map(FileType)
1838 }
1839
1840 /// Returns the file name of this directory entry without any
1841 /// leading path component(s).
1842 ///
1843 /// As an example,
1844 /// the output of the function will result in "foo" for all the following paths:
1845 /// - "./foo"
1846 /// - "/the/foo"
1847 /// - "../../foo"
1848 ///
1849 /// # Examples
1850 ///
1851 /// ```
1852 /// use std::fs;
1853 ///
1854 /// if let Ok(entries) = fs::read_dir(".") {
1855 /// for entry in entries {
1856 /// if let Ok(entry) = entry {
1857 /// // Here, `entry` is a `DirEntry`.
1858 /// println!("{:?}", entry.file_name());
1859 /// }
1860 /// }
1861 /// }
1862 /// ```
1863 #[must_use]
1864 #[stable(feature = "dir_entry_ext", since = "1.1.0")]
1865 pub fn file_name(&self) -> OsString {
1866 self.0.file_name()
1867 }
1868}
1869
1870#[stable(feature = "dir_entry_debug", since = "1.13.0")]
1871impl fmt::Debug for DirEntry {
1872 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1873 f.debug_tuple(name:"DirEntry").field(&self.path()).finish()
1874 }
1875}
1876
1877impl AsInner<fs_imp::DirEntry> for DirEntry {
1878 #[inline]
1879 fn as_inner(&self) -> &fs_imp::DirEntry {
1880 &self.0
1881 }
1882}
1883
1884/// Removes a file from the filesystem.
1885///
1886/// Note that there is no
1887/// guarantee that the file is immediately deleted (e.g., depending on
1888/// platform, other open file descriptors may prevent immediate removal).
1889///
1890/// # Platform-specific behavior
1891///
1892/// This function currently corresponds to the `unlink` function on Unix
1893/// and the `DeleteFile` function on Windows.
1894/// Note that, this [may change in the future][changes].
1895///
1896/// [changes]: io#platform-specific-behavior
1897///
1898/// # Errors
1899///
1900/// This function will return an error in the following situations, but is not
1901/// limited to just these cases:
1902///
1903/// * `path` points to a directory.
1904/// * The file doesn't exist.
1905/// * The user lacks permissions to remove the file.
1906///
1907/// # Examples
1908///
1909/// ```no_run
1910/// use std::fs;
1911///
1912/// fn main() -> std::io::Result<()> {
1913/// fs::remove_file("a.txt")?;
1914/// Ok(())
1915/// }
1916/// ```
1917#[doc(alias = "rm", alias = "unlink", alias = "DeleteFile")]
1918#[stable(feature = "rust1", since = "1.0.0")]
1919pub fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
1920 fs_imp::unlink(path.as_ref())
1921}
1922
1923/// Given a path, query the file system to get information about a file,
1924/// directory, etc.
1925///
1926/// This function will traverse symbolic links to query information about the
1927/// destination file.
1928///
1929/// # Platform-specific behavior
1930///
1931/// This function currently corresponds to the `stat` function on Unix
1932/// and the `GetFileInformationByHandle` function on Windows.
1933/// Note that, this [may change in the future][changes].
1934///
1935/// [changes]: io#platform-specific-behavior
1936///
1937/// # Errors
1938///
1939/// This function will return an error in the following situations, but is not
1940/// limited to just these cases:
1941///
1942/// * The user lacks permissions to perform `metadata` call on `path`.
1943/// * `path` does not exist.
1944///
1945/// # Examples
1946///
1947/// ```rust,no_run
1948/// use std::fs;
1949///
1950/// fn main() -> std::io::Result<()> {
1951/// let attr = fs::metadata("/some/file/path.txt")?;
1952/// // inspect attr ...
1953/// Ok(())
1954/// }
1955/// ```
1956#[doc(alias = "stat")]
1957#[stable(feature = "rust1", since = "1.0.0")]
1958pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
1959 fs_imp::stat(path.as_ref()).map(op:Metadata)
1960}
1961
1962/// Query the metadata about a file without following symlinks.
1963///
1964/// # Platform-specific behavior
1965///
1966/// This function currently corresponds to the `lstat` function on Unix
1967/// and the `GetFileInformationByHandle` function on Windows.
1968/// Note that, this [may change in the future][changes].
1969///
1970/// [changes]: io#platform-specific-behavior
1971///
1972/// # Errors
1973///
1974/// This function will return an error in the following situations, but is not
1975/// limited to just these cases:
1976///
1977/// * The user lacks permissions to perform `metadata` call on `path`.
1978/// * `path` does not exist.
1979///
1980/// # Examples
1981///
1982/// ```rust,no_run
1983/// use std::fs;
1984///
1985/// fn main() -> std::io::Result<()> {
1986/// let attr = fs::symlink_metadata("/some/file/path.txt")?;
1987/// // inspect attr ...
1988/// Ok(())
1989/// }
1990/// ```
1991#[doc(alias = "lstat")]
1992#[stable(feature = "symlink_metadata", since = "1.1.0")]
1993pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
1994 fs_imp::lstat(path.as_ref()).map(op:Metadata)
1995}
1996
1997/// Rename a file or directory to a new name, replacing the original file if
1998/// `to` already exists.
1999///
2000/// This will not work if the new name is on a different mount point.
2001///
2002/// # Platform-specific behavior
2003///
2004/// This function currently corresponds to the `rename` function on Unix
2005/// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows.
2006///
2007/// Because of this, the behavior when both `from` and `to` exist differs. On
2008/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If
2009/// `from` is not a directory, `to` must also be not a directory. In contrast,
2010/// on Windows, `from` can be anything, but `to` must *not* be a directory.
2011///
2012/// Note that, this [may change in the future][changes].
2013///
2014/// [changes]: io#platform-specific-behavior
2015///
2016/// # Errors
2017///
2018/// This function will return an error in the following situations, but is not
2019/// limited to just these cases:
2020///
2021/// * `from` does not exist.
2022/// * The user lacks permissions to view contents.
2023/// * `from` and `to` are on separate filesystems.
2024///
2025/// # Examples
2026///
2027/// ```no_run
2028/// use std::fs;
2029///
2030/// fn main() -> std::io::Result<()> {
2031/// fs::rename("a.txt", "b.txt")?; // Rename a.txt to b.txt
2032/// Ok(())
2033/// }
2034/// ```
2035#[doc(alias = "mv", alias = "MoveFile", alias = "MoveFileEx")]
2036#[stable(feature = "rust1", since = "1.0.0")]
2037pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
2038 fs_imp::rename(old:from.as_ref(), new:to.as_ref())
2039}
2040
2041/// Copies the contents of one file to another. This function will also
2042/// copy the permission bits of the original file to the destination file.
2043///
2044/// This function will **overwrite** the contents of `to`.
2045///
2046/// Note that if `from` and `to` both point to the same file, then the file
2047/// will likely get truncated by this operation.
2048///
2049/// On success, the total number of bytes copied is returned and it is equal to
2050/// the length of the `to` file as reported by `metadata`.
2051///
2052/// If you want to copy the contents of one file to another and you’re
2053/// working with [`File`]s, see the [`io::copy`](io::copy()) function.
2054///
2055/// # Platform-specific behavior
2056///
2057/// This function currently corresponds to the `open` function in Unix
2058/// with `O_RDONLY` for `from` and `O_WRONLY`, `O_CREAT`, and `O_TRUNC` for `to`.
2059/// `O_CLOEXEC` is set for returned file descriptors.
2060///
2061/// On Linux (including Android), this function attempts to use `copy_file_range(2)`,
2062/// and falls back to reading and writing if that is not possible.
2063///
2064/// On Windows, this function currently corresponds to `CopyFileEx`. Alternate
2065/// NTFS streams are copied but only the size of the main stream is returned by
2066/// this function.
2067///
2068/// On MacOS, this function corresponds to `fclonefileat` and `fcopyfile`.
2069///
2070/// Note that platform-specific behavior [may change in the future][changes].
2071///
2072/// [changes]: io#platform-specific-behavior
2073///
2074/// # Errors
2075///
2076/// This function will return an error in the following situations, but is not
2077/// limited to just these cases:
2078///
2079/// * `from` is neither a regular file nor a symlink to a regular file.
2080/// * `from` does not exist.
2081/// * The current process does not have the permission rights to read
2082/// `from` or write `to`.
2083///
2084/// # Examples
2085///
2086/// ```no_run
2087/// use std::fs;
2088///
2089/// fn main() -> std::io::Result<()> {
2090/// fs::copy("foo.txt", "bar.txt")?; // Copy foo.txt to bar.txt
2091/// Ok(())
2092/// }
2093/// ```
2094#[doc(alias = "cp")]
2095#[doc(alias = "CopyFile", alias = "CopyFileEx")]
2096#[doc(alias = "fclonefileat", alias = "fcopyfile")]
2097#[stable(feature = "rust1", since = "1.0.0")]
2098pub fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
2099 fs_imp::copy(from.as_ref(), to.as_ref())
2100}
2101
2102/// Creates a new hard link on the filesystem.
2103///
2104/// The `link` path will be a link pointing to the `original` path. Note that
2105/// systems often require these two paths to both be located on the same
2106/// filesystem.
2107///
2108/// If `original` names a symbolic link, it is platform-specific whether the
2109/// symbolic link is followed. On platforms where it's possible to not follow
2110/// it, it is not followed, and the created hard link points to the symbolic
2111/// link itself.
2112///
2113/// # Platform-specific behavior
2114///
2115/// This function currently corresponds the `CreateHardLink` function on Windows.
2116/// On most Unix systems, it corresponds to the `linkat` function with no flags.
2117/// On Android, VxWorks, and Redox, it instead corresponds to the `link` function.
2118/// On MacOS, it uses the `linkat` function if it is available, but on very old
2119/// systems where `linkat` is not available, `link` is selected at runtime instead.
2120/// Note that, this [may change in the future][changes].
2121///
2122/// [changes]: io#platform-specific-behavior
2123///
2124/// # Errors
2125///
2126/// This function will return an error in the following situations, but is not
2127/// limited to just these cases:
2128///
2129/// * The `original` path is not a file or doesn't exist.
2130///
2131/// # Examples
2132///
2133/// ```no_run
2134/// use std::fs;
2135///
2136/// fn main() -> std::io::Result<()> {
2137/// fs::hard_link("a.txt", "b.txt")?; // Hard link a.txt to b.txt
2138/// Ok(())
2139/// }
2140/// ```
2141#[doc(alias = "CreateHardLink", alias = "linkat")]
2142#[stable(feature = "rust1", since = "1.0.0")]
2143pub fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
2144 fs_imp::link(original.as_ref(), link.as_ref())
2145}
2146
2147/// Creates a new symbolic link on the filesystem.
2148///
2149/// The `link` path will be a symbolic link pointing to the `original` path.
2150/// On Windows, this will be a file symlink, not a directory symlink;
2151/// for this reason, the platform-specific [`std::os::unix::fs::symlink`]
2152/// and [`std::os::windows::fs::symlink_file`] or [`symlink_dir`] should be
2153/// used instead to make the intent explicit.
2154///
2155/// [`std::os::unix::fs::symlink`]: crate::os::unix::fs::symlink
2156/// [`std::os::windows::fs::symlink_file`]: crate::os::windows::fs::symlink_file
2157/// [`symlink_dir`]: crate::os::windows::fs::symlink_dir
2158///
2159/// # Examples
2160///
2161/// ```no_run
2162/// use std::fs;
2163///
2164/// fn main() -> std::io::Result<()> {
2165/// fs::soft_link("a.txt", "b.txt")?;
2166/// Ok(())
2167/// }
2168/// ```
2169#[stable(feature = "rust1", since = "1.0.0")]
2170#[deprecated(
2171 since = "1.1.0",
2172 note = "replaced with std::os::unix::fs::symlink and \
2173 std::os::windows::fs::{symlink_file, symlink_dir}"
2174)]
2175pub fn soft_link<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> io::Result<()> {
2176 fs_imp::symlink(original.as_ref(), link.as_ref())
2177}
2178
2179/// Reads a symbolic link, returning the file that the link points to.
2180///
2181/// # Platform-specific behavior
2182///
2183/// This function currently corresponds to the `readlink` function on Unix
2184/// and the `CreateFile` function with `FILE_FLAG_OPEN_REPARSE_POINT` and
2185/// `FILE_FLAG_BACKUP_SEMANTICS` flags on Windows.
2186/// Note that, this [may change in the future][changes].
2187///
2188/// [changes]: io#platform-specific-behavior
2189///
2190/// # Errors
2191///
2192/// This function will return an error in the following situations, but is not
2193/// limited to just these cases:
2194///
2195/// * `path` is not a symbolic link.
2196/// * `path` does not exist.
2197///
2198/// # Examples
2199///
2200/// ```no_run
2201/// use std::fs;
2202///
2203/// fn main() -> std::io::Result<()> {
2204/// let path = fs::read_link("a.txt")?;
2205/// Ok(())
2206/// }
2207/// ```
2208#[stable(feature = "rust1", since = "1.0.0")]
2209pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
2210 fs_imp::readlink(path.as_ref())
2211}
2212
2213/// Returns the canonical, absolute form of a path with all intermediate
2214/// components normalized and symbolic links resolved.
2215///
2216/// # Platform-specific behavior
2217///
2218/// This function currently corresponds to the `realpath` function on Unix
2219/// and the `CreateFile` and `GetFinalPathNameByHandle` functions on Windows.
2220/// Note that, this [may change in the future][changes].
2221///
2222/// On Windows, this converts the path to use [extended length path][path]
2223/// syntax, which allows your program to use longer path names, but means you
2224/// can only join backslash-delimited paths to it, and it may be incompatible
2225/// with other applications (if passed to the application on the command-line,
2226/// or written to a file another application may read).
2227///
2228/// [changes]: io#platform-specific-behavior
2229/// [path]: https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
2230///
2231/// # Errors
2232///
2233/// This function will return an error in the following situations, but is not
2234/// limited to just these cases:
2235///
2236/// * `path` does not exist.
2237/// * A non-final component in path is not a directory.
2238///
2239/// # Examples
2240///
2241/// ```no_run
2242/// use std::fs;
2243///
2244/// fn main() -> std::io::Result<()> {
2245/// let path = fs::canonicalize("../a/../foo.txt")?;
2246/// Ok(())
2247/// }
2248/// ```
2249#[doc(alias = "realpath")]
2250#[doc(alias = "GetFinalPathNameByHandle")]
2251#[stable(feature = "fs_canonicalize", since = "1.5.0")]
2252pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
2253 fs_imp::canonicalize(path.as_ref())
2254}
2255
2256/// Creates a new, empty directory at the provided path
2257///
2258/// # Platform-specific behavior
2259///
2260/// This function currently corresponds to the `mkdir` function on Unix
2261/// and the `CreateDirectory` function on Windows.
2262/// Note that, this [may change in the future][changes].
2263///
2264/// [changes]: io#platform-specific-behavior
2265///
2266/// **NOTE**: If a parent of the given path doesn't exist, this function will
2267/// return an error. To create a directory and all its missing parents at the
2268/// same time, use the [`create_dir_all`] function.
2269///
2270/// # Errors
2271///
2272/// This function will return an error in the following situations, but is not
2273/// limited to just these cases:
2274///
2275/// * User lacks permissions to create directory at `path`.
2276/// * A parent of the given path doesn't exist. (To create a directory and all
2277/// its missing parents at the same time, use the [`create_dir_all`]
2278/// function.)
2279/// * `path` already exists.
2280///
2281/// # Examples
2282///
2283/// ```no_run
2284/// use std::fs;
2285///
2286/// fn main() -> std::io::Result<()> {
2287/// fs::create_dir("/some/dir")?;
2288/// Ok(())
2289/// }
2290/// ```
2291#[doc(alias = "mkdir", alias = "CreateDirectory")]
2292#[stable(feature = "rust1", since = "1.0.0")]
2293#[cfg_attr(not(test), rustc_diagnostic_item = "fs_create_dir")]
2294pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
2295 DirBuilder::new().create(path.as_ref())
2296}
2297
2298/// Recursively create a directory and all of its parent components if they
2299/// are missing.
2300///
2301/// # Platform-specific behavior
2302///
2303/// This function currently corresponds to the `mkdir` function on Unix
2304/// and the `CreateDirectory` function on Windows.
2305/// Note that, this [may change in the future][changes].
2306///
2307/// [changes]: io#platform-specific-behavior
2308///
2309/// # Errors
2310///
2311/// This function will return an error in the following situations, but is not
2312/// limited to just these cases:
2313///
2314/// * If any directory in the path specified by `path`
2315/// does not already exist and it could not be created otherwise. The specific
2316/// error conditions for when a directory is being created (after it is
2317/// determined to not exist) are outlined by [`fs::create_dir`].
2318///
2319/// Notable exception is made for situations where any of the directories
2320/// specified in the `path` could not be created as it was being created concurrently.
2321/// Such cases are considered to be successful. That is, calling `create_dir_all`
2322/// concurrently from multiple threads or processes is guaranteed not to fail
2323/// due to a race condition with itself.
2324///
2325/// [`fs::create_dir`]: create_dir
2326///
2327/// # Examples
2328///
2329/// ```no_run
2330/// use std::fs;
2331///
2332/// fn main() -> std::io::Result<()> {
2333/// fs::create_dir_all("/some/dir")?;
2334/// Ok(())
2335/// }
2336/// ```
2337#[stable(feature = "rust1", since = "1.0.0")]
2338pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
2339 DirBuilder::new().recursive(true).create(path.as_ref())
2340}
2341
2342/// Removes an empty directory.
2343///
2344/// # Platform-specific behavior
2345///
2346/// This function currently corresponds to the `rmdir` function on Unix
2347/// and the `RemoveDirectory` function on Windows.
2348/// Note that, this [may change in the future][changes].
2349///
2350/// [changes]: io#platform-specific-behavior
2351///
2352/// # Errors
2353///
2354/// This function will return an error in the following situations, but is not
2355/// limited to just these cases:
2356///
2357/// * `path` doesn't exist.
2358/// * `path` isn't a directory.
2359/// * The user lacks permissions to remove the directory at the provided `path`.
2360/// * The directory isn't empty.
2361///
2362/// # Examples
2363///
2364/// ```no_run
2365/// use std::fs;
2366///
2367/// fn main() -> std::io::Result<()> {
2368/// fs::remove_dir("/some/dir")?;
2369/// Ok(())
2370/// }
2371/// ```
2372#[doc(alias = "rmdir", alias = "RemoveDirectory")]
2373#[stable(feature = "rust1", since = "1.0.0")]
2374pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
2375 fs_imp::rmdir(path.as_ref())
2376}
2377
2378/// Removes a directory at this path, after removing all its contents. Use
2379/// carefully!
2380///
2381/// This function does **not** follow symbolic links and it will simply remove the
2382/// symbolic link itself.
2383///
2384/// # Platform-specific behavior
2385///
2386/// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions
2387/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`,
2388/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile` functions on
2389/// Windows. Note that, this [may change in the future][changes].
2390///
2391/// [changes]: io#platform-specific-behavior
2392///
2393/// On macOS before version 10.10 and REDOX, as well as when running in Miri for any target, this
2394/// function is not protected against time-of-check to time-of-use (TOCTOU) race conditions, and
2395/// should not be used in security-sensitive code on those platforms. All other platforms are
2396/// protected.
2397///
2398/// # Errors
2399///
2400/// See [`fs::remove_file`] and [`fs::remove_dir`].
2401///
2402/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path.
2403/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent.
2404///
2405/// Consider ignoring the error if validating the removal is not required for your use case.
2406///
2407/// [`fs::remove_file`]: remove_file
2408/// [`fs::remove_dir`]: remove_dir
2409///
2410/// # Examples
2411///
2412/// ```no_run
2413/// use std::fs;
2414///
2415/// fn main() -> std::io::Result<()> {
2416/// fs::remove_dir_all("/some/dir")?;
2417/// Ok(())
2418/// }
2419/// ```
2420#[stable(feature = "rust1", since = "1.0.0")]
2421pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
2422 fs_imp::remove_dir_all(path.as_ref())
2423}
2424
2425/// Returns an iterator over the entries within a directory.
2426///
2427/// The iterator will yield instances of <code>[io::Result]<[DirEntry]></code>.
2428/// New errors may be encountered after an iterator is initially constructed.
2429/// Entries for the current and parent directories (typically `.` and `..`) are
2430/// skipped.
2431///
2432/// # Platform-specific behavior
2433///
2434/// This function currently corresponds to the `opendir` function on Unix
2435/// and the `FindFirstFile` function on Windows. Advancing the iterator
2436/// currently corresponds to `readdir` on Unix and `FindNextFile` on Windows.
2437/// Note that, this [may change in the future][changes].
2438///
2439/// [changes]: io#platform-specific-behavior
2440///
2441/// The order in which this iterator returns entries is platform and filesystem
2442/// dependent.
2443///
2444/// # Errors
2445///
2446/// This function will return an error in the following situations, but is not
2447/// limited to just these cases:
2448///
2449/// * The provided `path` doesn't exist.
2450/// * The process lacks permissions to view the contents.
2451/// * The `path` points at a non-directory file.
2452///
2453/// # Examples
2454///
2455/// ```
2456/// use std::io;
2457/// use std::fs::{self, DirEntry};
2458/// use std::path::Path;
2459///
2460/// // one possible implementation of walking a directory only visiting files
2461/// fn visit_dirs(dir: &Path, cb: &dyn Fn(&DirEntry)) -> io::Result<()> {
2462/// if dir.is_dir() {
2463/// for entry in fs::read_dir(dir)? {
2464/// let entry = entry?;
2465/// let path = entry.path();
2466/// if path.is_dir() {
2467/// visit_dirs(&path, cb)?;
2468/// } else {
2469/// cb(&entry);
2470/// }
2471/// }
2472/// }
2473/// Ok(())
2474/// }
2475/// ```
2476///
2477/// ```rust,no_run
2478/// use std::{fs, io};
2479///
2480/// fn main() -> io::Result<()> {
2481/// let mut entries = fs::read_dir(".")?
2482/// .map(|res| res.map(|e| e.path()))
2483/// .collect::<Result<Vec<_>, io::Error>>()?;
2484///
2485/// // The order in which `read_dir` returns entries is not guaranteed. If reproducible
2486/// // ordering is required the entries should be explicitly sorted.
2487///
2488/// entries.sort();
2489///
2490/// // The entries have now been sorted by their path.
2491///
2492/// Ok(())
2493/// }
2494/// ```
2495#[doc(alias = "ls", alias = "opendir", alias = "FindFirstFile", alias = "FindNextFile")]
2496#[stable(feature = "rust1", since = "1.0.0")]
2497pub fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
2498 fs_imp::readdir(path.as_ref()).map(op:ReadDir)
2499}
2500
2501/// Changes the permissions found on a file or a directory.
2502///
2503/// # Platform-specific behavior
2504///
2505/// This function currently corresponds to the `chmod` function on Unix
2506/// and the `SetFileAttributes` function on Windows.
2507/// Note that, this [may change in the future][changes].
2508///
2509/// [changes]: io#platform-specific-behavior
2510///
2511/// # Errors
2512///
2513/// This function will return an error in the following situations, but is not
2514/// limited to just these cases:
2515///
2516/// * `path` does not exist.
2517/// * The user lacks the permission to change attributes of the file.
2518///
2519/// # Examples
2520///
2521/// ```no_run
2522/// use std::fs;
2523///
2524/// fn main() -> std::io::Result<()> {
2525/// let mut perms = fs::metadata("foo.txt")?.permissions();
2526/// perms.set_readonly(true);
2527/// fs::set_permissions("foo.txt", perms)?;
2528/// Ok(())
2529/// }
2530/// ```
2531#[doc(alias = "chmod", alias = "SetFileAttributes")]
2532#[stable(feature = "set_permissions", since = "1.1.0")]
2533pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
2534 fs_imp::set_perm(p:path.as_ref(), perm:perm.0)
2535}
2536
2537impl DirBuilder {
2538 /// Creates a new set of options with default mode/security settings for all
2539 /// platforms and also non-recursive.
2540 ///
2541 /// # Examples
2542 ///
2543 /// ```
2544 /// use std::fs::DirBuilder;
2545 ///
2546 /// let builder = DirBuilder::new();
2547 /// ```
2548 #[stable(feature = "dir_builder", since = "1.6.0")]
2549 #[must_use]
2550 pub fn new() -> DirBuilder {
2551 DirBuilder { inner: fs_imp::DirBuilder::new(), recursive: false }
2552 }
2553
2554 /// Indicates that directories should be created recursively, creating all
2555 /// parent directories. Parents that do not exist are created with the same
2556 /// security and permissions settings.
2557 ///
2558 /// This option defaults to `false`.
2559 ///
2560 /// # Examples
2561 ///
2562 /// ```
2563 /// use std::fs::DirBuilder;
2564 ///
2565 /// let mut builder = DirBuilder::new();
2566 /// builder.recursive(true);
2567 /// ```
2568 #[stable(feature = "dir_builder", since = "1.6.0")]
2569 pub fn recursive(&mut self, recursive: bool) -> &mut Self {
2570 self.recursive = recursive;
2571 self
2572 }
2573
2574 /// Creates the specified directory with the options configured in this
2575 /// builder.
2576 ///
2577 /// It is considered an error if the directory already exists unless
2578 /// recursive mode is enabled.
2579 ///
2580 /// # Examples
2581 ///
2582 /// ```no_run
2583 /// use std::fs::{self, DirBuilder};
2584 ///
2585 /// let path = "/tmp/foo/bar/baz";
2586 /// DirBuilder::new()
2587 /// .recursive(true)
2588 /// .create(path).unwrap();
2589 ///
2590 /// assert!(fs::metadata(path).unwrap().is_dir());
2591 /// ```
2592 #[stable(feature = "dir_builder", since = "1.6.0")]
2593 pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
2594 self._create(path.as_ref())
2595 }
2596
2597 fn _create(&self, path: &Path) -> io::Result<()> {
2598 if self.recursive { self.create_dir_all(path) } else { self.inner.mkdir(path) }
2599 }
2600
2601 fn create_dir_all(&self, path: &Path) -> io::Result<()> {
2602 if path == Path::new("") {
2603 return Ok(());
2604 }
2605
2606 match self.inner.mkdir(path) {
2607 Ok(()) => return Ok(()),
2608 Err(ref e) if e.kind() == io::ErrorKind::NotFound => {}
2609 Err(_) if path.is_dir() => return Ok(()),
2610 Err(e) => return Err(e),
2611 }
2612 match path.parent() {
2613 Some(p) => self.create_dir_all(p)?,
2614 None => {
2615 return Err(io::const_io_error!(
2616 io::ErrorKind::Uncategorized,
2617 "failed to create whole tree",
2618 ));
2619 }
2620 }
2621 match self.inner.mkdir(path) {
2622 Ok(()) => Ok(()),
2623 Err(_) if path.is_dir() => Ok(()),
2624 Err(e) => Err(e),
2625 }
2626 }
2627}
2628
2629impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
2630 #[inline]
2631 fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
2632 &mut self.inner
2633 }
2634}
2635
2636/// Returns `Ok(true)` if the path points at an existing entity.
2637///
2638/// This function will traverse symbolic links to query information about the
2639/// destination file. In case of broken symbolic links this will return `Ok(false)`.
2640///
2641/// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)`
2642/// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed
2643/// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing
2644/// permission is denied on one of the parent directories.
2645///
2646/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
2647/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios
2648/// where those bugs are not an issue.
2649///
2650/// # Examples
2651///
2652/// ```no_run
2653/// #![feature(fs_try_exists)]
2654/// use std::fs;
2655///
2656/// assert!(!fs::try_exists("does_not_exist.txt").expect("Can't check existence of file does_not_exist.txt"));
2657/// assert!(fs::try_exists("/root/secret_file.txt").is_err());
2658/// ```
2659///
2660/// [`Path::exists`]: crate::path::Path::exists
2661// FIXME: stabilization should modify documentation of `exists()` to recommend this method
2662// instead.
2663#[unstable(feature = "fs_try_exists", issue = "83186")]
2664#[inline]
2665pub fn try_exists<P: AsRef<Path>>(path: P) -> io::Result<bool> {
2666 fs_imp::try_exists(path.as_ref())
2667}
2668