1//! Filesystem manipulation operations.2//!3//! This module contains basic methods to manipulate the contents of the local4//! filesystem. All methods in this module represent cross-platform filesystem5//! operations. Extra platform-specific functionality can be found in the6//! 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 changed13//! 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 to16//! 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 replaces19//! the directory with a symbolic link between the check and the removal operation, the removal20//! might affect the wrong location. This is why operations like [`remove_dir_all`] need to use21//! 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 by25//! 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.2829#![stable(feature = "rust1", since = "1.0.0")]30#![deny(unsafe_op_in_unsafe_fn)]3132#[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;4344use crate::ffi::OsString;45use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};46use crate::path::{Path, PathBuf};47use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, fs as fs_imp};48use crate::time::SystemTime;49use crate::{error, fmt};5051/// An object providing access to an open file on the filesystem.52///53/// An instance of a `File` can be read and/or written depending on what options54/// it was opened with. Files also implement [`Seek`] to alter the logical cursor55/// that the file contains internally.56///57/// Files are automatically closed when they go out of scope. Errors detected58/// on closing are ignored by the implementation of `Drop`. Use the method59/// [`sync_all`] if these errors must be manually handled.60///61/// `File` does not buffer reads and writes. For efficiency, consider wrapping the62/// file in a [`BufReader`] or [`BufWriter`] when performing many small [`read`]63/// or [`write`] calls, unless unbuffered reads and writes are required.64///65/// # Examples66///67/// Creates a new file and write bytes to it (you can also use [`write`]):68///69/// ```no_run70/// use std::fs::File;71/// use std::io::prelude::*;72///73/// fn main() -> std::io::Result<()> {74/// let mut file = File::create("foo.txt")?;75/// file.write_all(b"Hello, world!")?;76/// Ok(())77/// }78/// ```79///80/// Reads the contents of a file into a [`String`] (you can also use [`read`]):81///82/// ```no_run83/// use std::fs::File;84/// use std::io::prelude::*;85///86/// fn main() -> std::io::Result<()> {87/// let mut file = File::open("foo.txt")?;88/// let mut contents = String::new();89/// file.read_to_string(&mut contents)?;90/// assert_eq!(contents, "Hello, world!");91/// Ok(())92/// }93/// ```94///95/// Using a buffered [`Read`]er:96///97/// ```no_run98/// use std::fs::File;99/// use std::io::BufReader;100/// use std::io::prelude::*;101///102/// fn main() -> std::io::Result<()> {103/// let file = File::open("foo.txt")?;104/// let mut buf_reader = BufReader::new(file);105/// let mut contents = String::new();106/// buf_reader.read_to_string(&mut contents)?;107/// assert_eq!(contents, "Hello, world!");108/// Ok(())109/// }110/// ```111///112/// Note that, although read and write methods require a `&mut File`, because113/// of the interfaces for [`Read`] and [`Write`], the holder of a `&File` can114/// still modify the file, either through methods that take `&File` or by115/// retrieving the underlying OS object and modifying the file that way.116/// Additionally, many operating systems allow concurrent modification of files117/// by different processes. Avoid assuming that holding a `&File` means that the118/// file will not change.119///120/// # Platform-specific behavior121///122/// On Windows, the implementation of [`Read`] and [`Write`] traits for `File`123/// perform synchronous I/O operations. Therefore the underlying file must not124/// have been opened for asynchronous I/O (e.g. by using `FILE_FLAG_OVERLAPPED`).125///126/// [`BufReader`]: io::BufReader127/// [`BufWriter`]: io::BufWriter128/// [`sync_all`]: File::sync_all129/// [`write`]: File::write130/// [`read`]: File::read131#[stable(feature = "rust1", since = "1.0.0")]132#[cfg_attr(not(test), rustc_diagnostic_item = "File")]133#[diagnostic::on_move(note = "you can use `File::try_clone` to duplicate a `File` instance")]134pub struct File {135 inner: fs_imp::File,136}137138/// An enumeration of possible errors which can occur while trying to acquire a lock139/// from the [`try_lock`] method and [`try_lock_shared`] method on a [`File`].140///141/// [`try_lock`]: File::try_lock142/// [`try_lock_shared`]: File::try_lock_shared143#[stable(feature = "file_lock", since = "1.89.0")]144pub enum TryLockError {145 /// The lock could not be acquired due to an I/O error on the file. The standard library will146 /// not return an [`ErrorKind::WouldBlock`] error inside [`TryLockError::Error`]147 ///148 /// [`ErrorKind::WouldBlock`]: io::ErrorKind::WouldBlock149 Error(io::Error),150 /// The lock could not be acquired at this time because it is held by another handle/process.151 WouldBlock,152}153154/// An object providing access to a directory on the filesystem.155///156/// Directories are automatically closed when they go out of scope. Errors detected157/// on closing are ignored by the implementation of `Drop`.158///159/// # Platform-specific behavior160///161/// On supported systems (including Windows and some UNIX-based OSes), this function acquires a162/// handle/file descriptor for the directory. This allows functions like [`Dir::open_file`] to163/// avoid [TOCTOU] errors when the directory itself is being moved.164///165/// On other systems, it stores an absolute path (see [`canonicalize()`]). In the latter case, no166/// [TOCTOU] guarantees are made.167///168/// # Examples169///170/// Opens a directory and then a file inside it.171///172/// ```no_run173/// #![feature(dirfd)]174/// use std::{fs::Dir, io};175///176/// fn main() -> std::io::Result<()> {177/// let dir = Dir::open("foo")?;178/// let mut file = dir.open_file("bar.txt")?;179/// let contents = io::read_to_string(file)?;180/// assert_eq!(contents, "Hello, world!");181/// Ok(())182/// }183/// ```184///185/// [TOCTOU]: self#time-of-check-to-time-of-use-toctou186#[unstable(feature = "dirfd", issue = "120426")]187pub struct Dir {188 inner: fs_imp::Dir,189}190191/// Metadata information about a file.192///193/// This structure is returned from the [`metadata`] or194/// [`symlink_metadata`] function or method and represents known195/// metadata about a file such as its permissions, size, modification196/// times, etc.197#[stable(feature = "rust1", since = "1.0.0")]198#[derive(Clone)]199pub struct Metadata(fs_imp::FileAttr);200201/// Iterator over the entries in a directory.202///203/// This iterator is returned from the [`read_dir`] function of this module and204/// will yield instances of <code>[io::Result]<[DirEntry]></code>. Through a [`DirEntry`]205/// information like the entry's path and possibly other metadata can be206/// learned.207///208/// The order in which this iterator returns entries is platform and filesystem209/// dependent.210///211/// # Errors212/// This [`io::Result`] will be an [`Err`] if an error occurred while fetching213/// the next entry from the OS.214#[stable(feature = "rust1", since = "1.0.0")]215#[derive(Debug)]216pub struct ReadDir(fs_imp::ReadDir);217218/// Entries returned by the [`ReadDir`] iterator.219///220/// An instance of `DirEntry` represents an entry inside of a directory on the221/// filesystem. Each entry can be inspected via methods to learn about the full222/// path or possibly other metadata through per-platform extension traits.223///224/// # Platform-specific behavior225///226/// On Unix, the `DirEntry` struct contains an internal reference to the open227/// directory. Holding `DirEntry` objects will consume a file handle even228/// after the `ReadDir` iterator is dropped.229///230/// Note that this [may change in the future][changes].231///232/// [changes]: io#platform-specific-behavior233#[stable(feature = "rust1", since = "1.0.0")]234pub struct DirEntry(fs_imp::DirEntry);235236/// Options and flags which can be used to configure how a file is opened.237///238/// This builder exposes the ability to configure how a [`File`] is opened and239/// what operations are permitted on the open file. The [`File::open`] and240/// [`File::create`] methods are aliases for commonly used options using this241/// builder.242///243/// Generally speaking, when using `OpenOptions`, you'll first call244/// [`OpenOptions::new`], then chain calls to methods to set each option, then245/// call [`OpenOptions::open`], passing the path of the file you're trying to246/// open. This will give you a [`io::Result`] with a [`File`] inside that you247/// can further operate on.248///249/// # Examples250///251/// Opening a file to read:252///253/// ```no_run254/// use std::fs::OpenOptions;255///256/// let file = OpenOptions::new().read(true).open("foo.txt");257/// ```258///259/// Opening a file for both reading and writing, as well as creating it if it260/// doesn't exist:261///262/// ```no_run263/// use std::fs::OpenOptions;264///265/// let file = OpenOptions::new()266/// .read(true)267/// .write(true)268/// .create(true)269/// .open("foo.txt");270/// ```271#[derive(Clone, Debug)]272#[stable(feature = "rust1", since = "1.0.0")]273#[cfg_attr(not(test), rustc_diagnostic_item = "FsOpenOptions")]274pub struct OpenOptions(fs_imp::OpenOptions);275276/// Representation of the various timestamps on a file.277#[derive(Copy, Clone, Debug, Default)]278#[stable(feature = "file_set_times", since = "1.75.0")]279#[must_use = "must be applied to a file via `File::set_times` to have any effect"]280pub struct FileTimes(fs_imp::FileTimes);281282/// Representation of the various permissions on a file.283///284/// This module only currently provides one bit of information,285/// [`Permissions::readonly`], which is exposed on all currently supported286/// platforms. Unix-specific functionality, such as mode bits, is available287/// through the [`PermissionsExt`] trait.288///289/// [`PermissionsExt`]: crate::os::unix::fs::PermissionsExt290#[derive(Clone, PartialEq, Eq, Debug)]291#[stable(feature = "rust1", since = "1.0.0")]292#[cfg_attr(not(test), rustc_diagnostic_item = "FsPermissions")]293pub struct Permissions(fs_imp::FilePermissions);294295/// A structure representing a type of file with accessors for each file type.296/// It is returned by [`Metadata::file_type`] method.297#[stable(feature = "file_type", since = "1.1.0")]298#[derive(Copy, Clone, PartialEq, Eq, Hash)]299#[cfg_attr(not(test), rustc_diagnostic_item = "FileType")]300pub struct FileType(fs_imp::FileType);301302/// A builder used to create directories in various manners.303///304/// This builder also supports platform-specific options.305#[stable(feature = "dir_builder", since = "1.6.0")]306#[cfg_attr(not(test), rustc_diagnostic_item = "DirBuilder")]307#[derive(Debug)]308pub struct DirBuilder {309 inner: fs_imp::DirBuilder,310 recursive: bool,311}312313/// Reads the entire contents of a file into a bytes vector.314///315/// This is a convenience function for using [`File::open`] and [`read_to_end`]316/// with fewer imports and without an intermediate variable.317///318/// [`read_to_end`]: Read::read_to_end319///320/// # Errors321///322/// This function will return an error if `path` does not already exist.323/// Other errors may also be returned according to [`OpenOptions::open`].324///325/// While reading from the file, this function handles [`io::ErrorKind::Interrupted`]326/// with automatic retries. See [io::Read] documentation for details.327///328/// # Examples329///330/// ```no_run331/// use std::fs;332///333/// fn main() -> Result<(), Box<dyn std::error::Error + 'static>> {334/// let data: Vec<u8> = fs::read("image.jpg")?;335/// assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]);336/// Ok(())337/// }338/// ```339#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]340pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {341 fn inner(path: &Path) -> io::Result<Vec<u8>> {342 let mut file = File::open(path)?;343 let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();344 let mut bytes = Vec::try_with_capacity(size.unwrap_or(0))?;345 io::default_read_to_end(&mut file, &mut bytes, size)?;346 Ok(bytes)347 }348 inner(path.as_ref())349}350351/// Reads the entire contents of a file into a string.352///353/// This is a convenience function for using [`File::open`] and [`read_to_string`]354/// with fewer imports and without an intermediate variable.355///356/// [`read_to_string`]: Read::read_to_string357///358/// # Errors359///360/// This function will return an error if `path` does not already exist.361/// Other errors may also be returned according to [`OpenOptions::open`].362///363/// If the contents of the file are not valid UTF-8, then an error will also be364/// returned.365///366/// While reading from the file, this function handles [`io::ErrorKind::Interrupted`]367/// with automatic retries. See [io::Read] documentation for details.368///369/// # Examples370///371/// ```no_run372/// use std::fs;373/// use std::error::Error;374///375/// fn main() -> Result<(), Box<dyn Error>> {376/// let message: String = fs::read_to_string("message.txt")?;377/// println!("{}", message);378/// Ok(())379/// }380/// ```381#[stable(feature = "fs_read_write", since = "1.26.0")]382pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {383 fn inner(path: &Path) -> io::Result<String> {384 let mut file = File::open(path)?;385 let size = file.metadata().map(|m| usize::try_from(m.len()).unwrap_or(usize::MAX)).ok();386 let mut string = String::new();387 string.try_reserve_exact(size.unwrap_or(0))?;388 io::default_read_to_string(&mut file, &mut string, size)?;389 Ok(string)390 }391 inner(path.as_ref())392}393394/// Writes a slice as the entire contents of a file.395///396/// This function will create a file if it does not exist,397/// and will entirely replace its contents if it does.398///399/// Depending on the platform, this function may fail if the400/// full directory path does not exist.401///402/// This is a convenience function for using [`File::create`] and [`write_all`]403/// with fewer imports.404///405/// [`write_all`]: Write::write_all406///407/// # Examples408///409/// ```no_run410/// use std::fs;411///412/// fn main() -> std::io::Result<()> {413/// fs::write("foo.txt", b"Lorem ipsum")?;414/// fs::write("bar.txt", "dolor sit")?;415/// Ok(())416/// }417/// ```418#[stable(feature = "fs_read_write_bytes", since = "1.26.0")]419pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {420 fn inner(path: &Path, contents: &[u8]) -> io::Result<()> {421 File::create(path)?.write_all(contents)422 }423 inner(path.as_ref(), contents.as_ref())424}425426/// Changes the timestamps of the file or directory at the specified path.427///428/// This function will attempt to set the access and modification times429/// to the times specified. If the path refers to a symbolic link, this function430/// will follow the link and change the timestamps of the target file.431///432/// # Platform-specific behavior433///434/// This function currently corresponds to the `utimensat` function on Unix platforms, the435/// `setattrlist` function on Apple platforms, and the `SetFileTime` function on Windows.436///437/// # Errors438///439/// This function will return an error if the user lacks permission to change timestamps on the440/// target file or symlink. It may also return an error if the OS does not support it.441///442/// # Examples443///444/// ```no_run445/// #![feature(fs_set_times)]446/// use std::fs::{self, FileTimes};447/// use std::time::SystemTime;448///449/// fn main() -> std::io::Result<()> {450/// let now = SystemTime::now();451/// let times = FileTimes::new()452/// .set_accessed(now)453/// .set_modified(now);454/// fs::set_times("foo.txt", times)?;455/// Ok(())456/// }457/// ```458#[unstable(feature = "fs_set_times", issue = "147455")]459#[doc(alias = "utimens")]460#[doc(alias = "utimes")]461#[doc(alias = "utime")]462pub fn set_times<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {463 fs_imp::set_times(path.as_ref(), times.0)464}465466/// Changes the timestamps of the file or symlink at the specified path.467///468/// This function will attempt to set the access and modification times469/// to the times specified. Differ from `set_times`, if the path refers to a symbolic link,470/// this function will change the timestamps of the symlink itself, not the target file.471///472/// # Platform-specific behavior473///474/// This function currently corresponds to the `utimensat` function with `AT_SYMLINK_NOFOLLOW` on475/// Unix platforms, the `setattrlist` function with `FSOPT_NOFOLLOW` on Apple platforms, and the476/// `SetFileTime` function on Windows.477///478/// # Errors479///480/// This function will return an error if the user lacks permission to change timestamps on the481/// target file or symlink. It may also return an error if the OS does not support it.482///483/// # Examples484///485/// ```no_run486/// #![feature(fs_set_times)]487/// use std::fs::{self, FileTimes};488/// use std::time::SystemTime;489///490/// fn main() -> std::io::Result<()> {491/// let now = SystemTime::now();492/// let times = FileTimes::new()493/// .set_accessed(now)494/// .set_modified(now);495/// fs::set_times_nofollow("symlink.txt", times)?;496/// Ok(())497/// }498/// ```499#[unstable(feature = "fs_set_times", issue = "147455")]500#[doc(alias = "utimensat")]501#[doc(alias = "lutimens")]502#[doc(alias = "lutimes")]503pub fn set_times_nofollow<P: AsRef<Path>>(path: P, times: FileTimes) -> io::Result<()> {504 fs_imp::set_times_nofollow(path.as_ref(), times.0)505}506507#[stable(feature = "file_lock", since = "1.89.0")]508impl error::Error for TryLockError {}509510#[stable(feature = "file_lock", since = "1.89.0")]511impl fmt::Debug for TryLockError {512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {513 match self {514 TryLockError::Error(err) => err.fmt(f),515 TryLockError::WouldBlock => "WouldBlock".fmt(f),516 }517 }518}519520#[stable(feature = "file_lock", since = "1.89.0")]521impl fmt::Display for TryLockError {522 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {523 match self {524 TryLockError::Error(_) => "lock acquisition failed due to I/O error",525 TryLockError::WouldBlock => "lock acquisition failed because the operation would block",526 }527 .fmt(f)528 }529}530531#[stable(feature = "file_lock", since = "1.89.0")]532impl From<TryLockError> for io::Error {533 fn from(err: TryLockError) -> io::Error {534 match err {535 TryLockError::Error(err) => err,536 TryLockError::WouldBlock => io::ErrorKind::WouldBlock.into(),537 }538 }539}540541impl File {542 /// Attempts to open a file in read-only mode.543 ///544 /// See the [`OpenOptions::open`] method for more details.545 ///546 /// If you only need to read the entire file contents,547 /// consider [`std::fs::read()`][self::read] or548 /// [`std::fs::read_to_string()`][self::read_to_string] instead.549 ///550 /// # Errors551 ///552 /// This function will return an error if `path` does not already exist.553 /// Other errors may also be returned according to [`OpenOptions::open`].554 ///555 /// # Examples556 ///557 /// ```no_run558 /// use std::fs::File;559 /// use std::io::Read;560 ///561 /// fn main() -> std::io::Result<()> {562 /// let mut f = File::open("foo.txt")?;563 /// let mut data = vec![];564 /// f.read_to_end(&mut data)?;565 /// Ok(())566 /// }567 /// ```568 #[stable(feature = "rust1", since = "1.0.0")]569 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {570 OpenOptions::new().read(true).open(path.as_ref())571 }572573 /// Attempts to open a file in read-only mode with buffering.574 ///575 /// See the [`OpenOptions::open`] method, the [`BufReader`][io::BufReader] type,576 /// and the [`BufRead`][io::BufRead] trait for more details.577 ///578 /// If you only need to read the entire file contents,579 /// consider [`std::fs::read()`][self::read] or580 /// [`std::fs::read_to_string()`][self::read_to_string] instead.581 ///582 /// # Errors583 ///584 /// This function will return an error if `path` does not already exist,585 /// or if memory allocation fails for the new buffer.586 /// Other errors may also be returned according to [`OpenOptions::open`].587 ///588 /// # Examples589 ///590 /// ```no_run591 /// #![feature(file_buffered)]592 /// use std::fs::File;593 /// use std::io::BufRead;594 ///595 /// fn main() -> std::io::Result<()> {596 /// let mut f = File::open_buffered("foo.txt")?;597 /// assert!(f.capacity() > 0);598 /// for (line, i) in f.lines().zip(1..) {599 /// println!("{i:6}: {}", line?);600 /// }601 /// Ok(())602 /// }603 /// ```604 #[unstable(feature = "file_buffered", issue = "130804")]605 pub fn open_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufReader<File>> {606 // Allocate the buffer *first* so we don't affect the filesystem otherwise.607 let buffer = io::BufReader::<Self>::try_new_buffer()?;608 let file = File::open(path)?;609 Ok(io::BufReader::with_buffer(file, buffer))610 }611612 /// Opens a file in write-only mode.613 ///614 /// This function will create a file if it does not exist,615 /// and will truncate it if it does.616 ///617 /// Depending on the platform, this function may fail if the618 /// full directory path does not exist.619 /// See the [`OpenOptions::open`] function for more details.620 ///621 /// See also [`std::fs::write()`][self::write] for a simple function to622 /// create a file with some given data.623 ///624 /// # Examples625 ///626 /// ```no_run627 /// use std::fs::File;628 /// use std::io::Write;629 ///630 /// fn main() -> std::io::Result<()> {631 /// let mut f = File::create("foo.txt")?;632 /// f.write_all(&1234_u32.to_be_bytes())?;633 /// Ok(())634 /// }635 /// ```636 #[stable(feature = "rust1", since = "1.0.0")]637 pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {638 OpenOptions::new().write(true).create(true).truncate(true).open(path.as_ref())639 }640641 /// Opens a file in write-only mode with buffering.642 ///643 /// This function will create a file if it does not exist,644 /// and will truncate it if it does.645 ///646 /// Depending on the platform, this function may fail if the647 /// full directory path does not exist.648 ///649 /// See the [`OpenOptions::open`] method and the650 /// [`BufWriter`][io::BufWriter] type for more details.651 ///652 /// See also [`std::fs::write()`][self::write] for a simple function to653 /// create a file with some given data.654 ///655 /// # Examples656 ///657 /// ```no_run658 /// #![feature(file_buffered)]659 /// use std::fs::File;660 /// use std::io::Write;661 ///662 /// fn main() -> std::io::Result<()> {663 /// let mut f = File::create_buffered("foo.txt")?;664 /// assert!(f.capacity() > 0);665 /// for i in 0..100 {666 /// writeln!(&mut f, "{i}")?;667 /// }668 /// f.flush()?;669 /// Ok(())670 /// }671 /// ```672 #[unstable(feature = "file_buffered", issue = "130804")]673 pub fn create_buffered<P: AsRef<Path>>(path: P) -> io::Result<io::BufWriter<File>> {674 // Allocate the buffer *first* so we don't affect the filesystem otherwise.675 let buffer = io::BufWriter::<Self>::try_new_buffer()?;676 let file = File::create(path)?;677 Ok(io::BufWriter::with_buffer(file, buffer))678 }679680 /// Creates a new file in read-write mode; error if the file exists.681 ///682 /// This function will create a file if it does not exist, or return an error if it does. This683 /// way, if the call succeeds, the file returned is guaranteed to be new.684 /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`]685 /// or another error based on the situation. See [`OpenOptions::open`] for a686 /// non-exhaustive list of likely errors.687 ///688 /// This option is useful because it is atomic. Otherwise between checking whether a file689 /// exists and creating a new one, the file may have been created by another process (a [TOCTOU]690 /// race condition / attack).691 ///692 /// This can also be written using693 /// `File::options().read(true).write(true).create_new(true).open(...)`.694 ///695 /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists696 /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou697 ///698 /// # Examples699 ///700 /// ```no_run701 /// use std::fs::File;702 /// use std::io::Write;703 ///704 /// fn main() -> std::io::Result<()> {705 /// let mut f = File::create_new("foo.txt")?;706 /// f.write_all("Hello, world!".as_bytes())?;707 /// Ok(())708 /// }709 /// ```710 #[stable(feature = "file_create_new", since = "1.77.0")]711 pub fn create_new<P: AsRef<Path>>(path: P) -> io::Result<File> {712 OpenOptions::new().read(true).write(true).create_new(true).open(path.as_ref())713 }714715 /// Returns a new OpenOptions object.716 ///717 /// This function returns a new OpenOptions object that you can use to718 /// open or create a file with specific options if `open()` or `create()`719 /// are not appropriate.720 ///721 /// It is equivalent to `OpenOptions::new()`, but allows you to write more722 /// readable code. Instead of723 /// `OpenOptions::new().append(true).open("example.log")`,724 /// you can write `File::options().append(true).open("example.log")`. This725 /// also avoids the need to import `OpenOptions`.726 ///727 /// See the [`OpenOptions::new`] function for more details.728 ///729 /// # Examples730 ///731 /// ```no_run732 /// use std::fs::File;733 /// use std::io::Write;734 ///735 /// fn main() -> std::io::Result<()> {736 /// let mut f = File::options().append(true).open("example.log")?;737 /// writeln!(&mut f, "new line")?;738 /// Ok(())739 /// }740 /// ```741 #[must_use]742 #[stable(feature = "with_options", since = "1.58.0")]743 #[cfg_attr(not(test), rustc_diagnostic_item = "file_options")]744 pub fn options() -> OpenOptions {745 OpenOptions::new()746 }747748 /// Attempts to sync all OS-internal file content and metadata to disk.749 ///750 /// This function will attempt to ensure that all in-memory data reaches the751 /// filesystem before returning.752 ///753 /// This can be used to handle errors that would otherwise only be caught754 /// when the `File` is closed, as dropping a `File` will ignore all errors.755 /// Note, however, that `sync_all` is generally more expensive than closing756 /// a file by dropping it, because the latter is not required to block until757 /// the data has been written to the filesystem.758 ///759 /// If synchronizing the metadata is not required, use [`sync_data`] instead.760 ///761 /// [`sync_data`]: File::sync_data762 ///763 /// # Examples764 ///765 /// ```no_run766 /// use std::fs::File;767 /// use std::io::prelude::*;768 ///769 /// fn main() -> std::io::Result<()> {770 /// let mut f = File::create("foo.txt")?;771 /// f.write_all(b"Hello, world!")?;772 ///773 /// f.sync_all()?;774 /// Ok(())775 /// }776 /// ```777 #[stable(feature = "rust1", since = "1.0.0")]778 #[doc(alias = "fsync")]779 pub fn sync_all(&self) -> io::Result<()> {780 self.inner.fsync()781 }782783 /// This function is similar to [`sync_all`], except that it might not784 /// synchronize file metadata to the filesystem.785 ///786 /// This is intended for use cases that must synchronize content, but don't787 /// need the metadata on disk. The goal of this method is to reduce disk788 /// operations.789 ///790 /// Note that some platforms may simply implement this in terms of791 /// [`sync_all`].792 ///793 /// [`sync_all`]: File::sync_all794 ///795 /// # Examples796 ///797 /// ```no_run798 /// use std::fs::File;799 /// use std::io::prelude::*;800 ///801 /// fn main() -> std::io::Result<()> {802 /// let mut f = File::create("foo.txt")?;803 /// f.write_all(b"Hello, world!")?;804 ///805 /// f.sync_data()?;806 /// Ok(())807 /// }808 /// ```809 #[stable(feature = "rust1", since = "1.0.0")]810 #[doc(alias = "fdatasync")]811 pub fn sync_data(&self) -> io::Result<()> {812 self.inner.datasync()813 }814815 /// Acquire an exclusive lock on the file. Blocks until the lock can be acquired.816 ///817 /// This acquires an exclusive lock. No *other* file handle to this file, in this or any other818 /// process, may acquire another lock.819 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior820 /// is unspecified and platform dependent, including the possibility that it will deadlock.821 /// However, if this method returns, then an exclusive lock is held.822 ///823 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],824 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with825 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not826 /// cause non-lockholders to block.827 ///828 /// If the file is not open for writing, it is unspecified whether this function returns an error.829 ///830 /// The lock will be released when this file (along with any other file descriptors/handles831 /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.832 ///833 /// # Platform-specific behavior834 ///835 /// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` flag,836 /// and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK` flag. Note that,837 /// this [may change in the future][changes].838 ///839 /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,840 /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.841 ///842 /// [changes]: io#platform-specific-behavior843 ///844 /// [`lock`]: File::lock845 /// [`lock_shared`]: File::lock_shared846 /// [`try_lock`]: File::try_lock847 /// [`try_lock_shared`]: File::try_lock_shared848 /// [`unlock`]: File::unlock849 /// [`read`]: Read::read850 /// [`write`]: Write::write851 ///852 /// # Examples853 ///854 /// ```no_run855 /// use std::fs::File;856 ///857 /// fn main() -> std::io::Result<()> {858 /// let f = File::create("foo.txt")?;859 /// f.lock()?;860 /// Ok(())861 /// }862 /// ```863 #[stable(feature = "file_lock", since = "1.89.0")]864 pub fn lock(&self) -> io::Result<()> {865 self.inner.lock()866 }867868 /// Acquire a shared (non-exclusive) lock on the file. Blocks until the lock can be acquired.869 ///870 /// This acquires a shared lock. More than one file handle to this file, in this or any other871 /// process, may hold a shared lock, but no *other* file handle may hold an exclusive lock at872 /// the same time.873 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact874 /// behavior is unspecified and platform dependent, including the possibility that it will875 /// deadlock. However, if this method returns, then a shared lock is held.876 ///877 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],878 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with879 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not880 /// cause non-lockholders to block.881 ///882 /// The lock will be released when this file (along with any other file descriptors/handles883 /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.884 ///885 /// # Platform-specific behavior886 ///887 /// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` flag,888 /// and the `LockFileEx` function on Windows. Note that, this889 /// [may change in the future][changes].890 ///891 /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,892 /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.893 ///894 /// [changes]: io#platform-specific-behavior895 ///896 /// [`lock`]: File::lock897 /// [`lock_shared`]: File::lock_shared898 /// [`try_lock`]: File::try_lock899 /// [`try_lock_shared`]: File::try_lock_shared900 /// [`unlock`]: File::unlock901 /// [`read`]: Read::read902 /// [`write`]: Write::write903 ///904 /// # Examples905 ///906 /// ```no_run907 /// use std::fs::File;908 ///909 /// fn main() -> std::io::Result<()> {910 /// let f = File::open("foo.txt")?;911 /// f.lock_shared()?;912 /// Ok(())913 /// }914 /// ```915 #[stable(feature = "file_lock", since = "1.89.0")]916 pub fn lock_shared(&self) -> io::Result<()> {917 self.inner.lock_shared()918 }919920 /// Try to acquire an exclusive lock on the file.921 ///922 /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file923 /// (via another handle/descriptor).924 ///925 /// This acquires an exclusive lock; no other file handle to this file, in this or any other926 /// process, may acquire another lock.927 ///928 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],929 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with930 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not931 /// cause non-lockholders to block.932 ///933 /// If this file handle/descriptor, or a clone of it, already holds a lock, the exact behavior934 /// is unspecified and platform dependent, including the possibility that it will deadlock.935 /// However, if this method returns `Ok(())`, then it has acquired an exclusive lock.936 ///937 /// If the file is not open for writing, it is unspecified whether this function returns an error.938 ///939 /// The lock will be released when this file (along with any other file descriptors/handles940 /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.941 ///942 /// # Platform-specific behavior943 ///944 /// This function currently corresponds to the `flock` function on Unix with the `LOCK_EX` and945 /// `LOCK_NB` flags, and the `LockFileEx` function on Windows with the `LOCKFILE_EXCLUSIVE_LOCK`946 /// and `LOCKFILE_FAIL_IMMEDIATELY` flags. Note that, this947 /// [may change in the future][changes].948 ///949 /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,950 /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.951 ///952 /// [changes]: io#platform-specific-behavior953 ///954 /// [`lock`]: File::lock955 /// [`lock_shared`]: File::lock_shared956 /// [`try_lock`]: File::try_lock957 /// [`try_lock_shared`]: File::try_lock_shared958 /// [`unlock`]: File::unlock959 /// [`read`]: Read::read960 /// [`write`]: Write::write961 ///962 /// # Examples963 ///964 /// ```no_run965 /// use std::fs::{File, TryLockError};966 ///967 /// fn main() -> std::io::Result<()> {968 /// let f = File::create("foo.txt")?;969 /// // Explicit handling of the WouldBlock error970 /// match f.try_lock() {971 /// Ok(_) => (),972 /// Err(TryLockError::WouldBlock) => (), // Lock not acquired973 /// Err(TryLockError::Error(err)) => return Err(err),974 /// }975 /// // Alternately, propagate the error as an io::Error976 /// f.try_lock()?;977 /// Ok(())978 /// }979 /// ```980 #[stable(feature = "file_lock", since = "1.89.0")]981 pub fn try_lock(&self) -> Result<(), TryLockError> {982 self.inner.try_lock()983 }984985 /// Try to acquire a shared (non-exclusive) lock on the file.986 ///987 /// Returns `Err(TryLockError::WouldBlock)` if a different lock is already held on this file988 /// (via another handle/descriptor).989 ///990 /// This acquires a shared lock; more than one file handle, in this or any other process, may991 /// hold a shared lock, but none may hold an exclusive lock at the same time.992 ///993 /// This lock may be advisory or mandatory. This lock is meant to interact with [`lock`],994 /// [`try_lock`], [`lock_shared`], [`try_lock_shared`], and [`unlock`]. Its interactions with995 /// other methods, such as [`read`] and [`write`] are platform specific, and it may or may not996 /// cause non-lockholders to block.997 ///998 /// If this file handle, or a clone of it, already holds a lock, the exact behavior is999 /// unspecified and platform dependent, including the possibility that it will deadlock.1000 /// However, if this method returns `Ok(())`, then it has acquired a shared lock.1001 ///1002 /// The lock will be released when this file (along with any other file descriptors/handles1003 /// duplicated or inherited from it) is closed, or if the [`unlock`] method is called.1004 ///1005 /// # Platform-specific behavior1006 ///1007 /// This function currently corresponds to the `flock` function on Unix with the `LOCK_SH` and1008 /// `LOCK_NB` flags, and the `LockFileEx` function on Windows with the1009 /// `LOCKFILE_FAIL_IMMEDIATELY` flag. Note that, this1010 /// [may change in the future][changes].1011 ///1012 /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,1013 /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.1014 ///1015 /// [changes]: io#platform-specific-behavior1016 ///1017 /// [`lock`]: File::lock1018 /// [`lock_shared`]: File::lock_shared1019 /// [`try_lock`]: File::try_lock1020 /// [`try_lock_shared`]: File::try_lock_shared1021 /// [`unlock`]: File::unlock1022 /// [`read`]: Read::read1023 /// [`write`]: Write::write1024 ///1025 /// # Examples1026 ///1027 /// ```no_run1028 /// use std::fs::{File, TryLockError};1029 ///1030 /// fn main() -> std::io::Result<()> {1031 /// let f = File::open("foo.txt")?;1032 /// // Explicit handling of the WouldBlock error1033 /// match f.try_lock_shared() {1034 /// Ok(_) => (),1035 /// Err(TryLockError::WouldBlock) => (), // Lock not acquired1036 /// Err(TryLockError::Error(err)) => return Err(err),1037 /// }1038 /// // Alternately, propagate the error as an io::Error1039 /// f.try_lock_shared()?;1040 ///1041 /// Ok(())1042 /// }1043 /// ```1044 #[stable(feature = "file_lock", since = "1.89.0")]1045 pub fn try_lock_shared(&self) -> Result<(), TryLockError> {1046 self.inner.try_lock_shared()1047 }10481049 /// Release all locks on the file.1050 ///1051 /// All locks are released when the file (along with any other file descriptors/handles1052 /// duplicated or inherited from it) is closed. This method allows releasing locks without1053 /// closing the file.1054 ///1055 /// If no lock is currently held via this file descriptor/handle, this method may return an1056 /// error, or may return successfully without taking any action.1057 ///1058 /// # Platform-specific behavior1059 ///1060 /// This function currently corresponds to the `flock` function on Unix with the `LOCK_UN` flag,1061 /// and the `UnlockFile` function on Windows. Note that, this1062 /// [may change in the future][changes].1063 ///1064 /// On Windows, locking a file will fail if the file is opened only for append. To lock a file,1065 /// open it with one of `.read(true)`, `.read(true).append(true)`, or `.write(true)`.1066 ///1067 /// [changes]: io#platform-specific-behavior1068 ///1069 /// # Examples1070 ///1071 /// ```no_run1072 /// use std::fs::File;1073 ///1074 /// fn main() -> std::io::Result<()> {1075 /// let f = File::open("foo.txt")?;1076 /// f.lock()?;1077 /// f.unlock()?;1078 /// Ok(())1079 /// }1080 /// ```1081 #[stable(feature = "file_lock", since = "1.89.0")]1082 pub fn unlock(&self) -> io::Result<()> {1083 self.inner.unlock()1084 }10851086 /// Truncates or extends the underlying file, updating the size of1087 /// this file to become `size`.1088 ///1089 /// If the `size` is less than the current file's size, then the file will1090 /// be shrunk. If it is greater than the current file's size, then the file1091 /// will be extended to `size` and have all of the intermediate data filled1092 /// in with 0s.1093 ///1094 /// The file's cursor isn't changed. In particular, if the cursor was at the1095 /// end and the file is shrunk using this operation, the cursor will now be1096 /// past the end.1097 ///1098 /// # Errors1099 ///1100 /// This function will return an error if the file is not opened for writing.1101 /// Also, [`std::io::ErrorKind::InvalidInput`](crate::io::ErrorKind::InvalidInput)1102 /// will be returned if the desired length would cause an overflow due to1103 /// the implementation specifics.1104 ///1105 /// # Examples1106 ///1107 /// ```no_run1108 /// use std::fs::File;1109 ///1110 /// fn main() -> std::io::Result<()> {1111 /// let mut f = File::create("foo.txt")?;1112 /// f.set_len(10)?;1113 /// Ok(())1114 /// }1115 /// ```1116 ///1117 /// Note that this method alters the content of the underlying file, even1118 /// though it takes `&self` rather than `&mut self`.1119 #[stable(feature = "rust1", since = "1.0.0")]1120 pub fn set_len(&self, size: u64) -> io::Result<()> {1121 self.inner.truncate(size)1122 }11231124 /// Queries metadata about the underlying file.1125 ///1126 /// # Examples1127 ///1128 /// ```no_run1129 /// use std::fs::File;1130 ///1131 /// fn main() -> std::io::Result<()> {1132 /// let mut f = File::open("foo.txt")?;1133 /// let metadata = f.metadata()?;1134 /// Ok(())1135 /// }1136 /// ```1137 #[stable(feature = "rust1", since = "1.0.0")]1138 pub fn metadata(&self) -> io::Result<Metadata> {1139 self.inner.file_attr().map(Metadata)1140 }11411142 /// Creates a new `File` instance that shares the same underlying file handle1143 /// as the existing `File` instance. Reads, writes, and seeks will affect1144 /// both `File` instances simultaneously.1145 ///1146 /// # Examples1147 ///1148 /// Creates two handles for a file named `foo.txt`:1149 ///1150 /// ```no_run1151 /// use std::fs::File;1152 ///1153 /// fn main() -> std::io::Result<()> {1154 /// let mut file = File::open("foo.txt")?;1155 /// let file_copy = file.try_clone()?;1156 /// Ok(())1157 /// }1158 /// ```1159 ///1160 /// Assuming there’s a file named `foo.txt` with contents `abcdef\n`, create1161 /// two handles, seek one of them, and read the remaining bytes from the1162 /// other handle:1163 ///1164 /// ```no_run1165 /// use std::fs::File;1166 /// use std::io::SeekFrom;1167 /// use std::io::prelude::*;1168 ///1169 /// fn main() -> std::io::Result<()> {1170 /// let mut file = File::open("foo.txt")?;1171 /// let mut file_copy = file.try_clone()?;1172 ///1173 /// file.seek(SeekFrom::Start(3))?;1174 ///1175 /// let mut contents = vec![];1176 /// file_copy.read_to_end(&mut contents)?;1177 /// assert_eq!(contents, b"def\n");1178 /// Ok(())1179 /// }1180 /// ```1181 #[stable(feature = "file_try_clone", since = "1.9.0")]1182 pub fn try_clone(&self) -> io::Result<File> {1183 Ok(File { inner: self.inner.duplicate()? })1184 }11851186 /// Changes the permissions on the underlying file.1187 ///1188 /// # Platform-specific behavior1189 ///1190 /// This function currently corresponds to the `fchmod` function on Unix and1191 /// the `SetFileInformationByHandle` function on Windows. Note that, this1192 /// [may change in the future][changes].1193 ///1194 /// [changes]: io#platform-specific-behavior1195 ///1196 /// # Errors1197 ///1198 /// This function will return an error if the user lacks permission change1199 /// attributes on the underlying file. It may also return an error in other1200 /// os-specific unspecified cases.1201 ///1202 /// # Examples1203 ///1204 /// ```no_run1205 /// fn main() -> std::io::Result<()> {1206 /// use std::fs::File;1207 ///1208 /// let file = File::open("foo.txt")?;1209 /// let mut perms = file.metadata()?.permissions();1210 /// perms.set_readonly(true);1211 /// file.set_permissions(perms)?;1212 /// Ok(())1213 /// }1214 /// ```1215 ///1216 /// Note that this method alters the permissions of the underlying file,1217 /// even though it takes `&self` rather than `&mut self`.1218 #[doc(alias = "fchmod", alias = "SetFileInformationByHandle")]1219 #[stable(feature = "set_permissions_atomic", since = "1.16.0")]1220 pub fn set_permissions(&self, perm: Permissions) -> io::Result<()> {1221 self.inner.set_permissions(perm.0)1222 }12231224 /// Changes the timestamps of the underlying file.1225 ///1226 /// # Platform-specific behavior1227 ///1228 /// This function currently corresponds to the `futimens` function on Unix (falling back to1229 /// `futimes` on macOS before 10.13) and the `SetFileTime` function on Windows. Note that this1230 /// [may change in the future][changes].1231 ///1232 /// On most platforms, including UNIX and Windows platforms, this function can also change the1233 /// timestamps of a directory. To get a `File` representing a directory in order to call1234 /// `set_times`, open the directory with `File::open` without attempting to obtain write1235 /// permission.1236 ///1237 /// [changes]: io#platform-specific-behavior1238 ///1239 /// # Errors1240 ///1241 /// This function will return an error if the user lacks permission to change timestamps on the1242 /// underlying file. It may also return an error in other os-specific unspecified cases.1243 ///1244 /// This function may return an error if the operating system lacks support to change one or1245 /// more of the timestamps set in the `FileTimes` structure.1246 ///1247 /// # Examples1248 ///1249 /// ```no_run1250 /// fn main() -> std::io::Result<()> {1251 /// use std::fs::{self, File, FileTimes};1252 ///1253 /// let src = fs::metadata("src")?;1254 /// let dest = File::open("dest")?;1255 /// let times = FileTimes::new()1256 /// .set_accessed(src.accessed()?)1257 /// .set_modified(src.modified()?);1258 /// dest.set_times(times)?;1259 /// Ok(())1260 /// }1261 /// ```1262 #[stable(feature = "file_set_times", since = "1.75.0")]1263 #[doc(alias = "futimens")]1264 #[doc(alias = "futimes")]1265 #[doc(alias = "SetFileTime")]1266 #[doc(alias = "filetime")]1267 pub fn set_times(&self, times: FileTimes) -> io::Result<()> {1268 self.inner.set_times(times.0)1269 }12701271 /// Changes the modification time of the underlying file.1272 ///1273 /// This is an alias for `set_times(FileTimes::new().set_modified(time))`.1274 #[stable(feature = "file_set_times", since = "1.75.0")]1275 #[inline]1276 pub fn set_modified(&self, time: SystemTime) -> io::Result<()> {1277 self.set_times(FileTimes::new().set_modified(time))1278 }1279}12801281// In addition to the `impl`s here, `File` also has `impl`s for1282// `AsFd`/`From<OwnedFd>`/`Into<OwnedFd>` and1283// `AsRawFd`/`IntoRawFd`/`FromRawFd`, on Unix and WASI, and1284// `AsHandle`/`From<OwnedHandle>`/`Into<OwnedHandle>` and1285// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.12861287impl AsInner<fs_imp::File> for File {1288 #[inline]1289 fn as_inner(&self) -> &fs_imp::File {1290 &self.inner1291 }1292}1293impl FromInner<fs_imp::File> for File {1294 fn from_inner(f: fs_imp::File) -> File {1295 File { inner: f }1296 }1297}1298impl IntoInner<fs_imp::File> for File {1299 fn into_inner(self) -> fs_imp::File {1300 self.inner1301 }1302}13031304#[stable(feature = "rust1", since = "1.0.0")]1305impl fmt::Debug for File {1306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {1307 self.inner.fmt(f)1308 }1309}13101311/// Indicates how much extra capacity is needed to read the rest of the file.1312fn buffer_capacity_required(mut file: &File) -> Option<usize> {1313 let size = file.metadata().map(|m| m.len()).ok()?;1314 let pos = file.stream_position().ok()?;1315 // Don't worry about `usize` overflow because reading will fail regardless1316 // in that case.1317 Some(size.saturating_sub(pos) as usize)1318}13191320#[stable(feature = "rust1", since = "1.0.0")]1321impl Read for &File {1322 /// Reads some bytes from the file.1323 ///1324 /// See [`Read::read`] docs for more info.1325 ///1326 /// # Platform-specific behavior1327 ///1328 /// This function currently corresponds to the `read` function on Unix and1329 /// the `NtReadFile` function on Windows. Note that this [may change in1330 /// the future][changes].1331 ///1332 /// [changes]: io#platform-specific-behavior1333 #[inline]1334 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {1335 self.inner.read(buf)1336 }13371338 /// Like `read`, except that it reads into a slice of buffers.1339 ///1340 /// See [`Read::read_vectored`] docs for more info.1341 ///1342 /// # Platform-specific behavior1343 ///1344 /// This function currently corresponds to the `readv` function on Unix and1345 /// falls back to the `read` implementation on Windows. Note that this1346 /// [may change in the future][changes].1347 ///1348 /// [changes]: io#platform-specific-behavior1349 #[inline]1350 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {1351 self.inner.read_vectored(bufs)1352 }13531354 #[inline]1355 fn read_buf(&mut self, cursor: BorrowedCursor<'_, u8>) -> io::Result<()> {1356 self.inner.read_buf(cursor)1357 }13581359 /// Determines if `File` has an efficient `read_vectored` implementation.1360 ///1361 /// See [`Read::is_read_vectored`] docs for more info.1362 ///1363 /// # Platform-specific behavior1364 ///1365 /// This function currently returns `true` on Unix and `false` on Windows.1366 /// Note that this [may change in the future][changes].1367 ///1368 /// [changes]: io#platform-specific-behavior1369 #[inline]1370 fn is_read_vectored(&self) -> bool {1371 self.inner.is_read_vectored()1372 }13731374 // Reserves space in the buffer based on the file size when available.1375 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {1376 let size = buffer_capacity_required(self);1377 buf.try_reserve(size.unwrap_or(0))?;1378 io::default_read_to_end(self, buf, size)1379 }13801381 // Reserves space in the buffer based on the file size when available.1382 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {1383 let size = buffer_capacity_required(self);1384 buf.try_reserve(size.unwrap_or(0))?;1385 io::default_read_to_string(self, buf, size)1386 }1387}1388#[stable(feature = "rust1", since = "1.0.0")]1389impl Write for &File {1390 /// Writes some bytes to the file.1391 ///1392 /// See [`Write::write`] docs for more info.1393 ///1394 /// # Platform-specific behavior1395 ///1396 /// This function currently corresponds to the `write` function on Unix and1397 /// the `NtWriteFile` function on Windows. Note that this [may change in1398 /// the future][changes].1399 ///1400 /// [changes]: io#platform-specific-behavior1401 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {1402 self.inner.write(buf)1403 }14041405 /// Like `write`, except that it writes into a slice of buffers.1406 ///1407 /// See [`Write::write_vectored`] docs for more info.1408 ///1409 /// # Platform-specific behavior1410 ///1411 /// This function currently corresponds to the `writev` function on Unix1412 /// and falls back to the `write` implementation on Windows. Note that this1413 /// [may change in the future][changes].1414 ///1415 /// [changes]: io#platform-specific-behavior1416 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {1417 self.inner.write_vectored(bufs)1418 }14191420 /// Determines if `File` has an efficient `write_vectored` implementation.1421 ///1422 /// See [`Write::is_write_vectored`] docs for more info.1423 ///1424 /// # Platform-specific behavior1425 ///1426 /// This function currently returns `true` on Unix and `false` on Windows.1427 /// Note that this [may change in the future][changes].1428 ///1429 /// [changes]: io#platform-specific-behavior1430 #[inline]1431 fn is_write_vectored(&self) -> bool {1432 self.inner.is_write_vectored()1433 }14341435 /// Flushes the file, ensuring that all intermediately buffered contents1436 /// reach their destination.1437 ///1438 /// See [`Write::flush`] docs for more info.1439 ///1440 /// # Platform-specific behavior1441 ///1442 /// Since a `File` structure doesn't contain any buffers, this function is1443 /// currently a no-op on Unix and Windows. Note that this [may change in1444 /// the future][changes].1445 ///1446 /// [changes]: io#platform-specific-behavior1447 #[inline]1448 fn flush(&mut self) -> io::Result<()> {1449 self.inner.flush()1450 }1451}1452#[stable(feature = "rust1", since = "1.0.0")]1453impl Seek for &File {1454 /// Seek to an offset, in bytes in a file.1455 ///1456 /// See [`Seek::seek`] docs for more info.1457 ///1458 /// # Platform-specific behavior1459 ///1460 /// This function currently corresponds to the `lseek64` function on Unix1461 /// and the `SetFilePointerEx` function on Windows. Note that this [may1462 /// change in the future][changes].1463 ///1464 /// [changes]: io#platform-specific-behavior1465 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {1466 self.inner.seek(pos)1467 }14681469 /// Returns the length of this file (in bytes).1470 ///1471 /// See [`Seek::stream_len`] docs for more info.1472 ///1473 /// # Platform-specific behavior1474 ///1475 /// This function currently corresponds to the `statx` function on Linux1476 /// (with fallbacks) and the `GetFileSizeEx` function on Windows. Note that1477 /// this [may change in the future][changes].1478 ///1479 /// [changes]: io#platform-specific-behavior1480 fn stream_len(&mut self) -> io::Result<u64> {1481 if let Some(result) = self.inner.size() {1482 return result;1483 }1484 io::stream_len_default(self)1485 }14861487 fn stream_position(&mut self) -> io::Result<u64> {1488 self.inner.tell()1489 }1490}14911492#[stable(feature = "rust1", since = "1.0.0")]1493impl Read for File {1494 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {1495 (&*self).read(buf)1496 }1497 fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {1498 (&*self).read_vectored(bufs)1499 }1500 fn read_buf(&mut self, cursor: BorrowedCursor<'_, u8>) -> io::Result<()> {1501 (&*self).read_buf(cursor)1502 }1503 #[inline]1504 fn is_read_vectored(&self) -> bool {1505 (&&*self).is_read_vectored()1506 }1507 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {1508 (&*self).read_to_end(buf)1509 }1510 fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {1511 (&*self).read_to_string(buf)1512 }1513}1514#[stable(feature = "rust1", since = "1.0.0")]1515impl Write for File {1516 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {1517 (&*self).write(buf)1518 }1519 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {1520 (&*self).write_vectored(bufs)1521 }1522 #[inline]1523 fn is_write_vectored(&self) -> bool {1524 (&&*self).is_write_vectored()1525 }1526 #[inline]1527 fn flush(&mut self) -> io::Result<()> {1528 (&*self).flush()1529 }1530}1531#[stable(feature = "rust1", since = "1.0.0")]1532impl Seek for File {1533 fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {1534 (&*self).seek(pos)1535 }1536 fn stream_len(&mut self) -> io::Result<u64> {1537 (&*self).stream_len()1538 }1539 fn stream_position(&mut self) -> io::Result<u64> {1540 (&*self).stream_position()1541 }1542}1543impl crate::io::IoHandle for File {}15441545impl Dir {1546 /// Attempts to open a directory at `path` in read-only mode.1547 ///1548 /// # Errors1549 ///1550 /// This function will return an error if `path` does not point to an existing directory.1551 /// Other errors may also be returned according to [`OpenOptions::open`].1552 ///1553 /// # Examples1554 ///1555 /// ```no_run1556 /// #![feature(dirfd)]1557 /// use std::{fs::Dir, io};1558 ///1559 /// fn main() -> std::io::Result<()> {1560 /// let dir = Dir::open("foo")?;1561 /// let mut f = dir.open_file("bar.txt")?;1562 /// let contents = io::read_to_string(f)?;1563 /// assert_eq!(contents, "Hello, world!");1564 /// Ok(())1565 /// }1566 /// ```1567 #[unstable(feature = "dirfd", issue = "120426")]1568 pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {1569 fs_imp::Dir::open(path.as_ref(), &OpenOptions::new().read(true).0)1570 .map(|inner| Self { inner })1571 }15721573 /// Attempts to open a file in read-only mode relative to this directory.1574 ///1575 /// # Errors1576 ///1577 /// This function will return an error if `path` does not point to an existing file.1578 /// Other errors may also be returned according to [`OpenOptions::open`].1579 ///1580 /// # Examples1581 ///1582 /// ```no_run1583 /// #![feature(dirfd)]1584 /// use std::{fs::Dir, io};1585 ///1586 /// fn main() -> std::io::Result<()> {1587 /// let dir = Dir::open("foo")?;1588 /// let mut f = dir.open_file("bar.txt")?;1589 /// let contents = io::read_to_string(f)?;1590 /// assert_eq!(contents, "Hello, world!");1591 /// Ok(())1592 /// }1593 /// ```1594 #[unstable(feature = "dirfd", issue = "120426")]1595 pub fn open_file<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {1596 self.inner1597 .open_file(path.as_ref(), &OpenOptions::new().read(true).0)1598 .map(|f| File { inner: f })1599 }16001601 /// Queries metadata about the underlying directory.1602 ///1603 /// # Examples1604 ///1605 /// ```no_run1606 /// #![feature(dirfd)]1607 /// use std::fs::Dir;1608 ///1609 /// fn main() -> std::io::Result<()> {1610 /// let dir = Dir::open("foo")?;1611 /// let metadata = dir.metadata()?;1612 /// Ok(())1613 /// }1614 /// ```1615 #[unstable(feature = "dirfd", issue = "120426")]1616 pub fn metadata(&self) -> io::Result<Metadata> {1617 self.inner.metadata().map(Metadata)1618 }1619}16201621impl AsInner<fs_imp::Dir> for Dir {1622 #[inline]1623 fn as_inner(&self) -> &fs_imp::Dir {1624 &self.inner1625 }1626}1627impl FromInner<fs_imp::Dir> for Dir {1628 fn from_inner(f: fs_imp::Dir) -> Dir {1629 Dir { inner: f }1630 }1631}1632impl IntoInner<fs_imp::Dir> for Dir {1633 fn into_inner(self) -> fs_imp::Dir {1634 self.inner1635 }1636}16371638#[unstable(feature = "dirfd", issue = "120426")]1639impl fmt::Debug for Dir {1640 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {1641 self.inner.fmt(f)1642 }1643}16441645impl OpenOptions {1646 /// Creates a blank new set of options ready for configuration.1647 ///1648 /// All options are initially set to `false`.1649 ///1650 /// # Examples1651 ///1652 /// ```no_run1653 /// use std::fs::OpenOptions;1654 ///1655 /// let mut options = OpenOptions::new();1656 /// let file = options.read(true).open("foo.txt");1657 /// ```1658 #[cfg_attr(not(test), rustc_diagnostic_item = "open_options_new")]1659 #[stable(feature = "rust1", since = "1.0.0")]1660 #[must_use]1661 pub fn new() -> Self {1662 OpenOptions(fs_imp::OpenOptions::new())1663 }16641665 /// Sets the option for read access.1666 ///1667 /// This option, when true, will indicate that the file should be1668 /// `read`-able if opened.1669 ///1670 /// # Examples1671 ///1672 /// ```no_run1673 /// use std::fs::OpenOptions;1674 ///1675 /// let file = OpenOptions::new().read(true).open("foo.txt");1676 /// ```1677 #[stable(feature = "rust1", since = "1.0.0")]1678 pub fn read(&mut self, read: bool) -> &mut Self {1679 self.0.read(read);1680 self1681 }16821683 /// Sets the option for write access.1684 ///1685 /// This option, when true, will indicate that the file should be1686 /// `write`-able if opened.1687 ///1688 /// If the file already exists, any write calls on it will overwrite its1689 /// contents, without truncating it.1690 ///1691 /// # Examples1692 ///1693 /// ```no_run1694 /// use std::fs::OpenOptions;1695 ///1696 /// let file = OpenOptions::new().write(true).open("foo.txt");1697 /// ```1698 #[stable(feature = "rust1", since = "1.0.0")]1699 pub fn write(&mut self, write: bool) -> &mut Self {1700 self.0.write(write);1701 self1702 }17031704 /// Sets the option for the append mode.1705 ///1706 /// This option, when true, means that writes will append to a file instead1707 /// of overwriting previous contents.1708 /// Note that setting `.write(true).append(true)` has the same effect as1709 /// setting only `.append(true)`.1710 ///1711 /// Append mode guarantees that writes will be positioned at the current end of file,1712 /// even when there are other processes or threads appending to the same file. This is1713 /// unlike <code>[seek]\([SeekFrom]::[End]\(0))</code> followed by `write()`, which1714 /// has a race between seeking and writing during which another writer can write, with1715 /// our `write()` overwriting their data.1716 ///1717 /// Keep in mind that this does not necessarily guarantee that data appended by1718 /// different processes or threads does not interleave. The amount of data accepted a1719 /// single `write()` call depends on the operating system and file system. A1720 /// successful `write()` is allowed to write only part of the given data, so even if1721 /// you're careful to provide the whole message in a single call to `write()`, there1722 /// is no guarantee that it will be written out in full. If you rely on the filesystem1723 /// accepting the message in a single write, make sure that all data that belongs1724 /// together is written in one operation. This can be done by concatenating strings1725 /// before passing them to [`write()`].1726 ///1727 /// If a file is opened with both read and append access, beware that after1728 /// opening, and after every write, the position for reading may be set at the1729 /// end of the file. So, before writing, save the current position (using1730 /// <code>[Seek]::[stream_position]</code>), and restore it before the next read.1731 ///1732 /// ## Note1733 ///1734 /// This function doesn't create the file if it doesn't exist. Use the1735 /// [`OpenOptions::create`] method to do so.1736 ///1737 /// [`write()`]: Write::write "io::Write::write"1738 /// [`flush()`]: Write::flush "io::Write::flush"1739 /// [stream_position]: Seek::stream_position "io::Seek::stream_position"1740 /// [seek]: Seek::seek "io::Seek::seek"1741 /// [Current]: SeekFrom::Current "io::SeekFrom::Current"1742 /// [End]: SeekFrom::End "io::SeekFrom::End"1743 ///1744 /// # Examples1745 ///1746 /// ```no_run1747 /// use std::fs::OpenOptions;1748 ///1749 /// let file = OpenOptions::new().append(true).open("foo.txt");1750 /// ```1751 #[stable(feature = "rust1", since = "1.0.0")]1752 pub fn append(&mut self, append: bool) -> &mut Self {1753 self.0.append(append);1754 self1755 }17561757 /// Sets the option for truncating a previous file.1758 ///1759 /// If a file is successfully opened with this option set to true, it will truncate1760 /// the file to 0 length if it already exists.1761 ///1762 /// The file must be opened with write access for truncate to work.1763 ///1764 /// # Examples1765 ///1766 /// ```no_run1767 /// use std::fs::OpenOptions;1768 ///1769 /// let file = OpenOptions::new().write(true).truncate(true).open("foo.txt");1770 /// ```1771 #[stable(feature = "rust1", since = "1.0.0")]1772 pub fn truncate(&mut self, truncate: bool) -> &mut Self {1773 self.0.truncate(truncate);1774 self1775 }17761777 /// Sets the option to create a new file, or open it if it already exists.1778 ///1779 /// In order for the file to be created, [`OpenOptions::write`] or1780 /// [`OpenOptions::append`] access must be used.1781 ///1782 /// See also [`std::fs::write()`][self::write] for a simple function to1783 /// create a file with some given data.1784 ///1785 /// # Errors1786 ///1787 /// If `.create(true)` is set without `.write(true)` or `.append(true)`,1788 /// calling [`open`](Self::open) will fail with [`InvalidInput`](io::ErrorKind::InvalidInput) error.1789 /// # Examples1790 ///1791 /// ```no_run1792 /// use std::fs::OpenOptions;1793 ///1794 /// let file = OpenOptions::new().write(true).create(true).open("foo.txt");1795 /// ```1796 #[stable(feature = "rust1", since = "1.0.0")]1797 pub fn create(&mut self, create: bool) -> &mut Self {1798 self.0.create(create);1799 self1800 }18011802 /// Sets the option to create a new file, failing if it already exists.1803 ///1804 /// No file is allowed to exist at the target location, also no (dangling) symlink. In this1805 /// way, if the call succeeds, the file returned is guaranteed to be new.1806 /// If a file exists at the target location, creating a new file will fail with [`AlreadyExists`]1807 /// or another error based on the situation. See [`OpenOptions::open`] for a1808 /// non-exhaustive list of likely errors.1809 ///1810 /// This option is useful because it is atomic. Otherwise between checking1811 /// whether a file exists and creating a new one, the file may have been1812 /// created by another process (a [TOCTOU] race condition / attack).1813 ///1814 /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are1815 /// ignored.1816 ///1817 /// The file must be opened with write or append access in order to create1818 /// a new file.1819 ///1820 /// [`.create()`]: OpenOptions::create1821 /// [`.truncate()`]: OpenOptions::truncate1822 /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists1823 /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou1824 ///1825 /// # Examples1826 ///1827 /// ```no_run1828 /// use std::fs::OpenOptions;1829 ///1830 /// let file = OpenOptions::new().write(true)1831 /// .create_new(true)1832 /// .open("foo.txt");1833 /// ```1834 #[stable(feature = "expand_open_options2", since = "1.9.0")]1835 pub fn create_new(&mut self, create_new: bool) -> &mut Self {1836 self.0.create_new(create_new);1837 self1838 }18391840 /// Opens a file at `path` with the options specified by `self`.1841 ///1842 /// # Errors1843 ///1844 /// This function will return an error under a number of different1845 /// circumstances. Some of these error conditions are listed here, together1846 /// with their [`io::ErrorKind`]. The mapping to [`io::ErrorKind`]s is not1847 /// part of the compatibility contract of the function.1848 ///1849 /// * [`NotFound`]: The specified file does not exist and neither `create`1850 /// or `create_new` is set.1851 /// * [`NotFound`]: One of the directory components of the file path does1852 /// not exist.1853 /// * [`PermissionDenied`]: The user lacks permission to get the specified1854 /// access rights for the file.1855 /// * [`PermissionDenied`]: The user lacks permission to open one of the1856 /// directory components of the specified path.1857 /// * [`AlreadyExists`]: `create_new` was specified and the file already1858 /// exists.1859 /// * [`InvalidInput`]: Invalid combinations of open options (truncate1860 /// without write access, create without write or append access,1861 /// no access mode set, etc.).1862 ///1863 /// The following errors don't match any existing [`io::ErrorKind`] at the moment:1864 /// * One of the directory components of the specified file path1865 /// was not, in fact, a directory.1866 /// * Filesystem-level errors: full disk, write permission1867 /// requested on a read-only file system, exceeded disk quota, too many1868 /// open files, too long filename, too many symbolic links in the1869 /// specified path (Unix-like systems only), etc.1870 ///1871 /// # Examples1872 ///1873 /// ```no_run1874 /// use std::fs::OpenOptions;1875 ///1876 /// let file = OpenOptions::new().read(true).open("foo.txt");1877 /// ```1878 ///1879 /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists1880 /// [`InvalidInput`]: io::ErrorKind::InvalidInput1881 /// [`NotFound`]: io::ErrorKind::NotFound1882 /// [`PermissionDenied`]: io::ErrorKind::PermissionDenied1883 #[stable(feature = "rust1", since = "1.0.0")]1884 pub fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {1885 self._open(path.as_ref())1886 }18871888 fn _open(&self, path: &Path) -> io::Result<File> {1889 fs_imp::File::open(path, &self.0).map(|inner| File { inner })1890 }1891}18921893impl AsInner<fs_imp::OpenOptions> for OpenOptions {1894 #[inline]1895 fn as_inner(&self) -> &fs_imp::OpenOptions {1896 &self.01897 }1898}18991900impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {1901 #[inline]1902 fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {1903 &mut self.01904 }1905}19061907impl Metadata {1908 /// Returns the file type for this metadata.1909 ///1910 /// # Examples1911 ///1912 /// ```no_run1913 /// fn main() -> std::io::Result<()> {1914 /// use std::fs;1915 ///1916 /// let metadata = fs::metadata("foo.txt")?;1917 ///1918 /// println!("{:?}", metadata.file_type());1919 /// Ok(())1920 /// }1921 /// ```1922 #[must_use]1923 #[stable(feature = "file_type", since = "1.1.0")]1924 pub fn file_type(&self) -> FileType {1925 FileType(self.0.file_type())1926 }19271928 /// Returns `true` if this metadata is for a directory. The1929 /// result is mutually exclusive to the result of1930 /// [`Metadata::is_file`], and will be false for symlink metadata1931 /// obtained from [`symlink_metadata`].1932 ///1933 /// # Examples1934 ///1935 /// ```no_run1936 /// fn main() -> std::io::Result<()> {1937 /// use std::fs;1938 ///1939 /// let metadata = fs::metadata("foo.txt")?;1940 ///1941 /// assert!(!metadata.is_dir());1942 /// Ok(())1943 /// }1944 /// ```1945 #[must_use]1946 #[stable(feature = "rust1", since = "1.0.0")]1947 pub fn is_dir(&self) -> bool {1948 self.file_type().is_dir()1949 }19501951 /// Returns `true` if this metadata is for a regular file. The1952 /// result is mutually exclusive to the result of1953 /// [`Metadata::is_dir`], and will be false for symlink metadata1954 /// obtained from [`symlink_metadata`].1955 ///1956 /// When the goal is simply to read from (or write to) the source, the most1957 /// reliable way to test the source can be read (or written to) is to open1958 /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on1959 /// a Unix-like system for example. See [`File::open`] or1960 /// [`OpenOptions::open`] for more information.1961 ///1962 /// # Examples1963 ///1964 /// ```no_run1965 /// use std::fs;1966 ///1967 /// fn main() -> std::io::Result<()> {1968 /// let metadata = fs::metadata("foo.txt")?;1969 ///1970 /// assert!(metadata.is_file());1971 /// Ok(())1972 /// }1973 /// ```1974 #[must_use]1975 #[stable(feature = "rust1", since = "1.0.0")]1976 pub fn is_file(&self) -> bool {1977 self.file_type().is_file()1978 }19791980 /// Returns `true` if this metadata is for a symbolic link.1981 ///1982 /// # Examples1983 ///1984 #[cfg_attr(unix, doc = "```no_run")]1985 #[cfg_attr(not(unix), doc = "```ignore")]1986 /// use std::fs;1987 /// use std::path::Path;1988 /// use std::os::unix::fs::symlink;1989 ///1990 /// fn main() -> std::io::Result<()> {1991 /// let link_path = Path::new("link");1992 /// symlink("/origin_does_not_exist/", link_path)?;1993 ///1994 /// let metadata = fs::symlink_metadata(link_path)?;1995 ///1996 /// assert!(metadata.is_symlink());1997 /// Ok(())1998 /// }1999 /// ```2000 #[must_use]
Findings
✓ No findings reported for this file.