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