From d056f59704cdd283733fa8a896e45f1731725cbb Mon Sep 17 00:00:00 2001 From: matwatson Date: Sun, 21 Sep 2025 14:14:29 -0700 Subject: [PATCH 1/3] corrected Cell module level doc replaced `&mut T` with `&T` to finally state "a &T to the inner value can never be obtained" --- library/core/src/cell.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 9b53b75ebee80..1b3126700ff3b 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -27,10 +27,9 @@ //! //! ## `Cell` //! -//! [`Cell`] implements interior mutability by moving values in and out of the cell. That is, an -//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly -//! obtained without replacing it with something else. Both of these rules ensure that there is -//! never more than one reference pointing to the inner value. This type provides the following +//! [`Cell`] implements interior mutability by moving values in and out of the cell. That is, a +//! `&T` to the inner value can never be obtained, and the value itself cannot be directly +//! obtained without replacing it with something else. This type provides the following //! methods: //! //! - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current From b725981fe266f483da0232ec9abcce8fe43331df Mon Sep 17 00:00:00 2001 From: Ayush Singh Date: Wed, 31 Dec 2025 13:17:55 +0530 Subject: [PATCH 2/3] std: sys: fs: uefi: Implement rename - Using the file_name field in `EFI_FILE_INFO` works for renaming, even when changing directories. - Does not work for cross-device rename, but that is already expected behaviour according to the docs: "This will not work if the new name is on a different mount point." - Also add some helper code for dealing with UefiBox. - Tested using OVMF in qemu. Signed-off-by: Ayush Singh --- library/std/src/sys/fs/uefi.rs | 48 ++++++++++++++++---- library/std/src/sys/pal/uefi/helpers.rs | 59 ++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 1c65e3e2b1554..b38d86afb093b 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -385,8 +385,43 @@ pub fn unlink(p: &Path) -> io::Result<()> { } } -pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { - unsupported() +/// The implementation mirrors `mv` implementation in UEFI shell: +/// https://github.com/tianocore/edk2/blob/66346d5edeac2a00d3cf2f2f3b5f66d423c07b3e/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c#L455 +/// +/// In a nutshell we do the following: +/// 1. Convert both old and new paths to absolute paths. +/// 2. Check that both lie in the same disk. +/// 3. Construct the target path relative to the current disk root. +/// 4. Set this target path as the file_name in the file_info structure. +pub fn rename(old: &Path, new: &Path) -> io::Result<()> { + let old_absolute = crate::path::absolute(old)?; + let new_absolute = crate::path::absolute(new)?; + + let mut old_components = old_absolute.components(); + let mut new_components = new_absolute.components(); + + let Some(old_disk) = old_components.next() else { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "Old path is not valid")); + }; + let Some(new_disk) = new_components.next() else { + return Err(io::const_error!(io::ErrorKind::InvalidInput, "New path is not valid")); + }; + + // Ensure that paths are on the same device. + if old_disk != new_disk { + return Err(io::const_error!(io::ErrorKind::CrossesDevices, "Cannot rename across device")); + } + + // Construct an path relative the current disk root. + let new_relative = + [crate::path::Component::RootDir].into_iter().chain(new_components).collect::(); + + let f = uefi_fs::File::from_path(old, file::MODE_READ | file::MODE_WRITE, 0)?; + let file_info = f.file_info()?; + + let new_info = file_info.with_file_name(new_relative.as_os_str())?; + + f.set_file_info(new_info) } pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { @@ -751,12 +786,7 @@ mod uefi_fs { } pub(crate) fn file_name_from_uefi(info: &UefiBox) -> OsString { - let file_name = { - let size = unsafe { (*info.as_ptr()).size }; - let strlen = (size as usize - crate::mem::size_of::>() - 1) / 2; - unsafe { crate::slice::from_raw_parts((*info.as_ptr()).file_name.as_ptr(), strlen) } - }; - - OsString::from_wide(file_name) + let fname = info.file_name(); + OsString::from_wide(&fname[..fname.len() - 1]) } } diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index d059be010e98b..10749b5519d6b 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -10,7 +10,7 @@ //! - More information about protocols can be found [here](https://edk2-docs.gitbook.io/edk-ii-uefi-driver-writer-s-guide/3_foundation/36_protocols_and_handles) use r_efi::efi::{self, Guid}; -use r_efi::protocols::{device_path, device_path_to_text, service_binding, shell}; +use r_efi::protocols::{device_path, device_path_to_text, file, service_binding, shell}; use crate::alloc::Layout; use crate::ffi::{OsStr, OsString}; @@ -787,7 +787,7 @@ impl UefiBox { match NonNull::new(ptr.cast()) { Some(inner) => Ok(Self { inner, size: len }), - None => Err(io::Error::new(io::ErrorKind::OutOfMemory, "Allocation failed")), + None => Err(const_error!(io::ErrorKind::OutOfMemory, "Allocation failed")), } } @@ -814,3 +814,58 @@ impl Drop for UefiBox { unsafe { crate::alloc::dealloc(self.inner.as_ptr().cast(), layout) }; } } + +impl UefiBox { + fn size(&self) -> u64 { + unsafe { (*self.as_ptr()).size } + } + + fn set_size(&mut self, s: u64) { + unsafe { (*self.as_mut_ptr()).size = s } + } + + // Length of string (including NULL), not number of bytes. + fn file_name_len(&self) -> usize { + (self.size() as usize - size_of::>()) / size_of::() + } + + pub(crate) fn file_name(&self) -> &[u16] { + unsafe { + crate::slice::from_raw_parts((*self.as_ptr()).file_name.as_ptr(), self.file_name_len()) + } + } + + fn file_name_mut(&mut self) -> &mut [u16] { + unsafe { + crate::slice::from_raw_parts_mut( + (*self.as_mut_ptr()).file_name.as_mut_ptr(), + self.file_name_len(), + ) + } + } + + pub(crate) fn with_file_name(mut self, name: &OsStr) -> io::Result { + // os_string_to_raw returns NULL terminated string. So no need to handle it separately. + let fname = os_string_to_raw(name) + .ok_or(const_error!(io::ErrorKind::OutOfMemory, "Allocation failed"))?; + let new_size = size_of::>() + fname.len() * size_of::(); + + // Reuse the current structure if the new name can fit in it. + if self.size() >= new_size as u64 { + self.file_name_mut()[..fname.len()].copy_from_slice(&fname); + self.set_size(new_size as u64); + + return Ok(self); + } + + let mut new_box = UefiBox::new(new_size)?; + + unsafe { + crate::ptr::copy_nonoverlapping(self.as_ptr(), new_box.as_mut_ptr(), 1); + } + new_box.set_size(new_size as u64); + new_box.file_name_mut().copy_from_slice(&fname); + + Ok(new_box) + } +} From 3f1dd92cc7e5c97b54b58e70ad9d904ce08e372c Mon Sep 17 00:00:00 2001 From: "U. Lasiotus" Date: Sun, 4 Jan 2026 16:55:57 -0800 Subject: [PATCH 3/3] Motor OS: fix compile error PR https://github.com/rust-lang/rust/pull/146341 introduced a compilation error. This fixes it. --- library/std/src/sys/fs/motor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/fs/motor.rs b/library/std/src/sys/fs/motor.rs index 8f3336e2fa96d..2ae01db24be5c 100644 --- a/library/std/src/sys/fs/motor.rs +++ b/library/std/src/sys/fs/motor.rs @@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::{Path, PathBuf}; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::exists; +pub use crate::sys::fs::common::{Dir, exists}; use crate::sys::time::SystemTime; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, map_motor_error, unsupported};