diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index d14d0ad2f0ea6..028b72d140f0b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -382,7 +382,10 @@ pub fn read_to_string>(path: P) -> io::Result { #[stable(feature = "fs_read_write_bytes", since = "1.26.0")] pub fn write, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> { fn inner(path: &Path, contents: &[u8]) -> io::Result<()> { - File::create(path)?.write_all(contents) + let mut file = File::create(path)?; + file.write_all(contents)?; + file.close()?; + Ok(()) } inner(path.as_ref(), contents.as_ref()) } @@ -709,6 +712,11 @@ impl File { OpenOptions::new() } + /// Drops the file, returning any errors encountered. + pub(crate) fn close(self) -> io::Result<()> { + self.inner.close() + } + /// Attempts to sync all OS-internal file content and metadata to disk. /// /// This function will attempt to ensure that all in-memory data reaches the diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 6a0e7a640028b..47366ab694ce9 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -11,13 +11,6 @@ use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::fs; use crate::marker::PhantomData; use crate::mem::ManuallyDrop; -#[cfg(not(any( - target_arch = "wasm32", - target_env = "sgx", - target_os = "hermit", - target_os = "trusty", - target_os = "motor" -)))] use crate::sys::cvt; #[cfg(not(target_os = "trusty"))] use crate::sys_common::{AsInner, FromInner, IntoInner}; @@ -94,6 +87,23 @@ impl OwnedFd { pub fn try_clone(&self) -> crate::io::Result { self.as_fd().try_clone_to_owned() } + + /// Drops the file descriptor, returning any errors encountered. + pub(crate) fn close(self) -> io::Result<()> { + let this = ManuallyDrop::new(self); + let result = unsafe { + #[cfg(not(target_os = "hermit"))] + { + #[cfg(unix)] + crate::sys::fs::debug_assert_fd_is_open(this.fd.as_inner()); + + libc::close(this.fd.as_inner()) + } + #[cfg(target_os = "hermit")] + hermit_abi::close(this.fd.as_inner()) + }; + cvt(result).map(|_| ()) + } } impl BorrowedFd<'_> { diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs index 4fc04b79315f9..48653d2c3e79c 100644 --- a/library/std/src/os/windows/io/handle.rs +++ b/library/std/src/os/windows/io/handle.rs @@ -182,6 +182,12 @@ impl Drop for HandleOrNull { } impl OwnedHandle { + /// Drops the handle, returning any errors encountered. + pub(crate) fn close(self) -> io::Result<()> { + let this = ManuallyDrop::new(self); + cvt(unsafe { sys::c::CloseHandle(this.handle) }).map(|_| ()) + } + /// Creates a new `OwnedHandle` instance that shares the same underlying /// object as the existing `OwnedHandle` instance. #[stable(feature = "io_safety", since = "1.63.0")] diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index 33fff36b35b01..ad4d1eecea7a7 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -103,6 +103,10 @@ const fn max_iov() -> usize { } impl FileDesc { + pub fn close(self) -> io::Result<()> { + self.0.close() + } + #[inline] pub fn try_clone(&self) -> io::Result { self.duplicate() diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index bfd684d295b89..bf237469e4015 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -23,6 +23,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let ret = io::copy(&mut reader, &mut writer)?; writer.set_permissions(perm)?; + writer.close()?; Ok(ret) } diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 21235bcfbd8c5..604a69973391f 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -345,6 +345,10 @@ impl File { Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) })) } + pub fn close(self) -> io::Result<()> { + self.0.close() + } + pub fn file_attr(&self) -> io::Result { let mut stat_val: stat_struct = unsafe { mem::zeroed() }; self.0.fstat(&mut stat_val)?; diff --git a/library/std/src/sys/fs/motor.rs b/library/std/src/sys/fs/motor.rs index f723a23bd5dff..0e4ea95a0cd4c 100644 --- a/library/std/src/sys/fs/motor.rs +++ b/library/std/src/sys/fs/motor.rs @@ -174,6 +174,10 @@ impl File { .map_err(map_motor_error) } + pub fn close(self) -> io::Result<()> { + self.0.close() + } + pub fn file_attr(&self) -> io::Result { moto_rt::fs::get_file_attr(self.as_raw_fd()) .map(|inner| -> FileAttr { FileAttr { inner } }) diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index ec1db262855ad..291bc407e776c 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs @@ -4,7 +4,7 @@ use crate::ffi::{CStr, CString, OsStr, OsString}; use crate::fmt; use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; -use crate::mem::MaybeUninit; +use crate::mem::{ManuallyDrop, MaybeUninit}; use crate::os::raw::{c_int, c_short}; use crate::os::solid::ffi::OsStrExt; use crate::path::{Path, PathBuf}; @@ -333,6 +333,14 @@ impl File { } } + pub fn close(self) -> io::Result<()> { + let this = ManuallyDrop::new(self); + match error::SolidError::err_if_negative(unsafe { abi::SOLID_FS_Close(this.fd.raw()) }) { + Ok(_) => Ok(()), + Err(e) => Err(e.as_io_error()), + } + } + pub fn file_attr(&self) -> io::Result { unsupported() } @@ -620,5 +628,7 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut reader = File::open(from)?; let mut writer = File::create(to)?; - io::copy(&mut reader, &mut writer) + let ret = io::copy(&mut reader, &mut writer)?; + writer.close()?; + Ok(ret) } diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 44f8b6e80f903..49b45e62a5dc8 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -237,6 +237,10 @@ impl File { unsupported() } + pub fn close(self) -> io::Result<()> { + self.0 + } + pub fn file_attr(&self) -> io::Result { self.0 } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 507d093d2b2f6..2c7d49efd148c 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1231,6 +1231,10 @@ impl File { Ok(File(unsafe { FileDesc::from_raw_fd(fd) })) } + pub fn close(self) -> io::Result<()> { + self.0.close() + } + pub fn file_attr(&self) -> io::Result { let fd = self.as_raw_fd(); @@ -2324,11 +2328,12 @@ pub(in crate::sys) use cfm::CachedFileMetadata; pub fn copy(from: &Path, to: &Path) -> io::Result { let (reader, reader_metadata) = open_from(from)?; let (writer, writer_metadata) = open_to_and_set_permissions(to, &reader_metadata)?; + let mut reader = cfm::CachedFileMetadata(reader, reader_metadata); + let mut writer = cfm::CachedFileMetadata(writer, writer_metadata); - io::copy( - &mut cfm::CachedFileMetadata(reader, reader_metadata), - &mut cfm::CachedFileMetadata(writer, writer_metadata), - ) + let ret = io::copy(&mut reader, &mut writer)?; + writer.0.close()?; + Ok(ret) } #[cfg(target_vendor = "apple")] diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index f222151d18e25..091d138a231e0 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -187,6 +187,10 @@ impl File { unsupported() } + pub fn close(self) -> io::Result<()> { + self.0 + } + pub fn file_attr(&self) -> io::Result { self.0 } diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index 381c87c62c688..55cb1d345c036 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -271,6 +271,12 @@ impl File { }) } + pub fn close(self) -> io::Result<()> { + // vexFileClose can't fail. Just implicitly drop `self`. + let _ = self; + Ok(()) + } + pub fn file_attr(&self) -> io::Result { // `vexFileSize` returns -1 upon error, so u64::try_from will fail on error. if let Ok(size) = u64::try_from(unsafe { @@ -537,7 +543,9 @@ pub fn copy(from: &Path, to: &Path) -> io::Result { let mut reader = File::open(from)?; let mut writer = File::create(to)?; - io::copy(&mut reader, &mut writer) + let ret = io::copy(&mut reader, &mut writer)?; + writer.close()?; + Ok(ret) } fn map_fresult(fresult: vex_sdk::FRESULT) -> io::Result<()> { diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index f2d325da35c7d..e4c3fe28bde0c 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -366,6 +366,10 @@ impl File { } } + pub fn close(self) -> io::Result<()> { + self.handle.close() + } + pub fn fsync(&self) -> io::Result<()> { cvt(unsafe { c::FlushFileBuffers(self.handle.as_raw_handle()) })?; Ok(()) diff --git a/library/std/src/sys/pal/windows/handle.rs b/library/std/src/sys/pal/windows/handle.rs index 712f41ba80308..5a09bcea8b2b0 100644 --- a/library/std/src/sys/pal/windows/handle.rs +++ b/library/std/src/sys/pal/windows/handle.rs @@ -77,6 +77,10 @@ impl FromRawHandle for Handle { } impl Handle { + pub fn close(self) -> io::Result<()> { + self.0.close() + } + pub fn read(&self, buf: &mut [u8]) -> io::Result { let res = unsafe { self.synchronous_read(buf.as_mut_ptr().cast(), buf.len(), None) };