From 6b46de7f13d584b86191e2255c8333487b6934c0 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 2 Nov 2020 20:57:07 +0000 Subject: [PATCH 1/2] io::error: Provide NoStorageSpace The lack of this is surprising. Also I am about to want it for an example. This has to be insta-stable because we can't sensibly have a different set of ErrorKinds depending on a std feature flag. Signed-off-by: Ian Jackson --- library/std/src/io/error.rs | 6 ++++++ library/std/src/sys/unix/mod.rs | 1 + 2 files changed, 7 insertions(+) diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs index ba0f0a0cd714a..c83407a426597 100644 --- a/library/std/src/io/error.rs +++ b/library/std/src/io/error.rs @@ -156,6 +156,11 @@ pub enum ErrorKind { /// [`Ok(0)`]: Ok #[stable(feature = "rust1", since = "1.0.0")] WriteZero, + /// The underlying storage (typically, a filesystem) is full. + /// + /// This does not include out of quota errors. + #[stable(feature = "io_error_no_storage_space", since = "1.51.0")] + NoStorageSpace, /// This operation was interrupted. /// /// Interrupted operations can typically be retried. @@ -199,6 +204,7 @@ impl ErrorKind { ErrorKind::TimedOut => "timed out", ErrorKind::WriteZero => "write zero", ErrorKind::Interrupted => "operation interrupted", + ErrorKind::NoStorageSpace => "no storage space", ErrorKind::Other => "other os error", ErrorKind::UnexpectedEof => "unexpected end of file", } diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index b28c6d85b7c72..fd7a1591624f4 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -174,6 +174,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind { libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, libc::EADDRINUSE => ErrorKind::AddrInUse, libc::ENOENT => ErrorKind::NotFound, + libc::ENOSPC => ErrorKind::NoStorageSpace, libc::EINTR => ErrorKind::Interrupted, libc::EINVAL => ErrorKind::InvalidInput, libc::ETIMEDOUT => ErrorKind::TimedOut, From b6f884977950cb1fba5380a7ba2322ec477cad6d Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Mon, 2 Nov 2020 20:58:12 +0000 Subject: [PATCH 2/2] IntoInnerError: Provide into_parts In particular, IntoIneerError only currently provides .error() which returns a reference, not an owned value. This is not helpful and means that a caller of BufWriter::into_inner cannot acquire an owned io::Error which seems quite wrong. I have made this insta-stable because I think it ought to be very uncontroversial. It doesn't involve promising new facts about the underlying implementation; it just gives a better access to the facts which are already implied. The lack of the usual `into_parts` seems simply an oversight. Signed-off-by: Ian Jackson --- library/std/src/io/buffered/mod.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs index f9caeaf98e2fb..6cd24fe0dc66e 100644 --- a/library/std/src/io/buffered/mod.rs +++ b/library/std/src/io/buffered/mod.rs @@ -126,6 +126,29 @@ impl IntoInnerError { pub fn into_inner(self) -> W { self.0 } + + #[doc(test(attr(cfg(os = "linux"))))] + /// Consumes the [`IntoInnerError`] and returns the error which caused the call to + /// [`BufWriter::into_inner()`] to fail, and the underlying writer. + /// + /// This can be used to simply obtain ownership of the underlying error; it can also be used for + /// advanced error recovery. + /// + /// # Example (requires `/dev/full`, which is available on Linux) + /// ``` + /// use std::io::{BufWriter, ErrorKind, Write}; + /// use std::fs::File; + /// + /// let mut stream = BufWriter::new(File::create("/dev/full").unwrap()); + /// write!(stream, "this cannot be actually written").unwrap(); + /// let into_inner_err = stream.into_inner().expect_err("now we discover the ENOSPC"); + /// let (err, _writer) = into_inner_err.into_parts(); + /// assert_eq!(err.kind(), ErrorKind::NoStorageSpace); + /// ``` + #[stable(feature = "std_io_into_inner_error_into_inner_parts", since = "1.51.0")] + pub fn into_parts(self) -> (Error, W) { + (self.1, self.0) + } } #[stable(feature = "rust1", since = "1.0.0")]