summaryrefslogtreecommitdiffstats
path: root/library/std/src/fs.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/fs.rs')
-rw-r--r--library/std/src/fs.rs73
1 files changed, 51 insertions, 22 deletions
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index c550378e7..89dfdfafd 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -15,6 +15,7 @@ use crate::ffi::OsString;
use crate::fmt;
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use crate::path::{Path, PathBuf};
+use crate::sealed::Sealed;
use crate::sys::fs as fs_imp;
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
use crate::time::SystemTime;
@@ -249,9 +250,9 @@ pub struct DirBuilder {
pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
fn inner(path: &Path) -> io::Result<Vec<u8>> {
let mut file = File::open(path)?;
- let size = file.metadata().map(|m| m.len()).unwrap_or(0);
- let mut bytes = Vec::with_capacity(size as usize);
- io::default_read_to_end(&mut file, &mut bytes)?;
+ let size = file.metadata().map(|m| m.len() as usize).ok();
+ let mut bytes = Vec::with_capacity(size.unwrap_or(0));
+ io::default_read_to_end(&mut file, &mut bytes, size)?;
Ok(bytes)
}
inner(path.as_ref())
@@ -289,9 +290,9 @@ pub fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
pub fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
fn inner(path: &Path) -> io::Result<String> {
let mut file = File::open(path)?;
- let size = file.metadata().map(|m| m.len()).unwrap_or(0);
- let mut string = String::with_capacity(size as usize);
- io::default_read_to_string(&mut file, &mut string)?;
+ let size = file.metadata().map(|m| m.len() as usize).ok();
+ let mut string = String::with_capacity(size.unwrap_or(0));
+ io::default_read_to_string(&mut file, &mut string, size)?;
Ok(string)
}
inner(path.as_ref())
@@ -709,6 +710,7 @@ impl File {
// `AsRawHandle`/`IntoRawHandle`/`FromRawHandle` on Windows.
impl AsInner<fs_imp::File> for File {
+ #[inline]
fn as_inner(&self) -> &fs_imp::File {
&self.inner
}
@@ -732,12 +734,12 @@ impl fmt::Debug for File {
}
/// Indicates how much extra capacity is needed to read the rest of the file.
-fn buffer_capacity_required(mut file: &File) -> usize {
- let size = file.metadata().map(|m| m.len()).unwrap_or(0);
- let pos = file.stream_position().unwrap_or(0);
+fn buffer_capacity_required(mut file: &File) -> Option<usize> {
+ let size = file.metadata().map(|m| m.len()).ok()?;
+ let pos = file.stream_position().ok()?;
// Don't worry about `usize` overflow because reading will fail regardless
// in that case.
- size.saturating_sub(pos) as usize
+ Some(size.saturating_sub(pos) as usize)
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -761,14 +763,16 @@ impl Read for File {
// Reserves space in the buffer based on the file size when available.
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
- buf.reserve(buffer_capacity_required(self));
- io::default_read_to_end(self, buf)
+ let size = buffer_capacity_required(self);
+ buf.reserve(size.unwrap_or(0));
+ io::default_read_to_end(self, buf, size)
}
// Reserves space in the buffer based on the file size when available.
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
- buf.reserve(buffer_capacity_required(self));
- io::default_read_to_string(self, buf)
+ let size = buffer_capacity_required(self);
+ buf.reserve(size.unwrap_or(0));
+ io::default_read_to_string(self, buf, size)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -817,14 +821,16 @@ impl Read for &File {
// Reserves space in the buffer based on the file size when available.
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
- buf.reserve(buffer_capacity_required(self));
- io::default_read_to_end(self, buf)
+ let size = buffer_capacity_required(self);
+ buf.reserve(size.unwrap_or(0));
+ io::default_read_to_end(self, buf, size)
}
// Reserves space in the buffer based on the file size when available.
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
- buf.reserve(buffer_capacity_required(self));
- io::default_read_to_string(self, buf)
+ let size = buffer_capacity_required(self);
+ buf.reserve(size.unwrap_or(0));
+ io::default_read_to_string(self, buf, size)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -1083,12 +1089,14 @@ impl OpenOptions {
}
impl AsInner<fs_imp::OpenOptions> for OpenOptions {
+ #[inline]
fn as_inner(&self) -> &fs_imp::OpenOptions {
&self.0
}
}
impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
+ #[inline]
fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {
&mut self.0
}
@@ -1348,6 +1356,7 @@ impl fmt::Debug for Metadata {
}
impl AsInner<fs_imp::FileAttr> for Metadata {
+ #[inline]
fn as_inner(&self) -> &fs_imp::FileAttr {
&self.0
}
@@ -1383,6 +1392,16 @@ impl FileTimes {
}
}
+impl AsInnerMut<fs_imp::FileTimes> for FileTimes {
+ fn as_inner_mut(&mut self) -> &mut fs_imp::FileTimes {
+ &mut self.0
+ }
+}
+
+// For implementing OS extension traits in `std::os`
+#[unstable(feature = "file_set_times", issue = "98245")]
+impl Sealed for FileTimes {}
+
impl Permissions {
/// Returns `true` if these permissions describe a readonly (unwritable) file.
///
@@ -1600,6 +1619,7 @@ impl FileType {
}
impl AsInner<fs_imp::FileType> for FileType {
+ #[inline]
fn as_inner(&self) -> &fs_imp::FileType {
&self.0
}
@@ -1612,6 +1632,7 @@ impl FromInner<fs_imp::FilePermissions> for Permissions {
}
impl AsInner<fs_imp::FilePermissions> for Permissions {
+ #[inline]
fn as_inner(&self) -> &fs_imp::FilePermissions {
&self.0
}
@@ -1766,6 +1787,7 @@ impl fmt::Debug for DirEntry {
}
impl AsInner<fs_imp::DirEntry> for DirEntry {
+ #[inline]
fn as_inner(&self) -> &fs_imp::DirEntry {
&self.0
}
@@ -1935,7 +1957,7 @@ pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()>
/// On success, the total number of bytes copied is returned and it is equal to
/// the length of the `to` file as reported by `metadata`.
///
-/// If you’re wanting to copy the contents of one file to another and you’re
+/// If you want to copy the contents of one file to another and you’re
/// working with [`File`]s, see the [`io::copy()`] function.
///
/// # Platform-specific behavior
@@ -2280,6 +2302,11 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
///
/// See [`fs::remove_file`] and [`fs::remove_dir`].
///
+/// `remove_dir_all` will fail if `remove_dir` or `remove_file` fail on any constituent paths, including the root path.
+/// As a result, the directory you are deleting must exist, meaning that this function is not idempotent.
+///
+/// Consider ignoring the error if validating the removal is not required for your use case.
+///
/// [`fs::remove_file`]: remove_file
/// [`fs::remove_dir`]: remove_dir
///
@@ -2501,6 +2528,7 @@ impl DirBuilder {
}
impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
+ #[inline]
fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
&mut self.inner
}
@@ -2511,9 +2539,10 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
/// This function will traverse symbolic links to query information about the
/// destination file. In case of broken symbolic links this will return `Ok(false)`.
///
-/// As opposed to the [`Path::exists`] method, this one doesn't silently ignore errors
-/// unrelated to the path not existing. (E.g. it will return `Err(_)` in case of permission
-/// denied on some of the parent directories.)
+/// As opposed to the [`Path::exists`] method, this will only return `Ok(true)` or `Ok(false)`
+/// if the path was _verified_ to exist or not exist. If its existence can neither be confirmed
+/// nor denied, an `Err(_)` will be propagated instead. This can be the case if e.g. listing
+/// permission is denied on one of the parent directories.
///
/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
/// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios