Skip to content

Commit 9e8a0c5

Browse files
committed
Auto merge of #150692 - jhpratt:rollup-kfi61p5, r=jhpratt
Rollup of 3 pull requests Successful merges: - #146863 (Update cell.rs, correct module level doc) - #150547 (std: sys: fs: uefi: Implement rename) - #150684 (Motor OS: fix compile error) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 0d162b2 + d788ec5 commit 9e8a0c5

4 files changed

Lines changed: 100 additions & 16 deletions

File tree

library/core/src/cell.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@
2727
//!
2828
//! ## `Cell<T>`
2929
//!
30-
//! [`Cell<T>`] implements interior mutability by moving values in and out of the cell. That is, an
31-
//! `&mut T` to the inner value can never be obtained, and the value itself cannot be directly
32-
//! obtained without replacing it with something else. Both of these rules ensure that there is
33-
//! never more than one reference pointing to the inner value. This type provides the following
30+
//! [`Cell<T>`] implements interior mutability by moving values in and out of the cell. That is, a
31+
//! `&T` to the inner value can never be obtained, and the value itself cannot be directly
32+
//! obtained without replacing it with something else. This type provides the following
3433
//! methods:
3534
//!
3635
//! - For types that implement [`Copy`], the [`get`](Cell::get) method retrieves the current

library/std/src/sys/fs/motor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
44
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
55
use crate::path::{Path, PathBuf};
66
use crate::sys::fd::FileDesc;
7-
pub use crate::sys::fs::common::exists;
7+
pub use crate::sys::fs::common::{Dir, exists};
88
use crate::sys::time::SystemTime;
99
use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, map_motor_error, unsupported};
1010

library/std/src/sys/fs/uefi.rs

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -394,8 +394,43 @@ pub fn unlink(p: &Path) -> io::Result<()> {
394394
}
395395
}
396396

397-
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
398-
unsupported()
397+
/// The implementation mirrors `mv` implementation in UEFI shell:
398+
/// https://github.com/tianocore/edk2/blob/66346d5edeac2a00d3cf2f2f3b5f66d423c07b3e/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c#L455
399+
///
400+
/// In a nutshell we do the following:
401+
/// 1. Convert both old and new paths to absolute paths.
402+
/// 2. Check that both lie in the same disk.
403+
/// 3. Construct the target path relative to the current disk root.
404+
/// 4. Set this target path as the file_name in the file_info structure.
405+
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
406+
let old_absolute = crate::path::absolute(old)?;
407+
let new_absolute = crate::path::absolute(new)?;
408+
409+
let mut old_components = old_absolute.components();
410+
let mut new_components = new_absolute.components();
411+
412+
let Some(old_disk) = old_components.next() else {
413+
return Err(io::const_error!(io::ErrorKind::InvalidInput, "Old path is not valid"));
414+
};
415+
let Some(new_disk) = new_components.next() else {
416+
return Err(io::const_error!(io::ErrorKind::InvalidInput, "New path is not valid"));
417+
};
418+
419+
// Ensure that paths are on the same device.
420+
if old_disk != new_disk {
421+
return Err(io::const_error!(io::ErrorKind::CrossesDevices, "Cannot rename across device"));
422+
}
423+
424+
// Construct an path relative the current disk root.
425+
let new_relative =
426+
[crate::path::Component::RootDir].into_iter().chain(new_components).collect::<PathBuf>();
427+
428+
let f = uefi_fs::File::from_path(old, file::MODE_READ | file::MODE_WRITE, 0)?;
429+
let file_info = f.file_info()?;
430+
431+
let new_info = file_info.with_file_name(new_relative.as_os_str())?;
432+
433+
f.set_file_info(new_info)
399434
}
400435

401436
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
@@ -760,12 +795,7 @@ mod uefi_fs {
760795
}
761796

762797
pub(crate) fn file_name_from_uefi(info: &UefiBox<file::Info>) -> OsString {
763-
let file_name = {
764-
let size = unsafe { (*info.as_ptr()).size };
765-
let strlen = (size as usize - crate::mem::size_of::<file::Info<0>>() - 1) / 2;
766-
unsafe { crate::slice::from_raw_parts((*info.as_ptr()).file_name.as_ptr(), strlen) }
767-
};
768-
769-
OsString::from_wide(file_name)
798+
let fname = info.file_name();
799+
OsString::from_wide(&fname[..fname.len() - 1])
770800
}
771801
}

library/std/src/sys/pal/uefi/helpers.rs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! - 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)
1111
1212
use r_efi::efi::{self, Guid};
13-
use r_efi::protocols::{device_path, device_path_to_text, service_binding, shell};
13+
use r_efi::protocols::{device_path, device_path_to_text, file, service_binding, shell};
1414

1515
use crate::alloc::Layout;
1616
use crate::ffi::{OsStr, OsString};
@@ -791,7 +791,7 @@ impl<T> UefiBox<T> {
791791

792792
match NonNull::new(ptr.cast()) {
793793
Some(inner) => Ok(Self { inner, size: len }),
794-
None => Err(io::Error::new(io::ErrorKind::OutOfMemory, "Allocation failed")),
794+
None => Err(const_error!(io::ErrorKind::OutOfMemory, "Allocation failed")),
795795
}
796796
}
797797

@@ -818,3 +818,58 @@ impl<T> Drop for UefiBox<T> {
818818
unsafe { crate::alloc::dealloc(self.inner.as_ptr().cast(), layout) };
819819
}
820820
}
821+
822+
impl UefiBox<file::Info> {
823+
fn size(&self) -> u64 {
824+
unsafe { (*self.as_ptr()).size }
825+
}
826+
827+
fn set_size(&mut self, s: u64) {
828+
unsafe { (*self.as_mut_ptr()).size = s }
829+
}
830+
831+
// Length of string (including NULL), not number of bytes.
832+
fn file_name_len(&self) -> usize {
833+
(self.size() as usize - size_of::<file::Info<0>>()) / size_of::<u16>()
834+
}
835+
836+
pub(crate) fn file_name(&self) -> &[u16] {
837+
unsafe {
838+
crate::slice::from_raw_parts((*self.as_ptr()).file_name.as_ptr(), self.file_name_len())
839+
}
840+
}
841+
842+
fn file_name_mut(&mut self) -> &mut [u16] {
843+
unsafe {
844+
crate::slice::from_raw_parts_mut(
845+
(*self.as_mut_ptr()).file_name.as_mut_ptr(),
846+
self.file_name_len(),
847+
)
848+
}
849+
}
850+
851+
pub(crate) fn with_file_name(mut self, name: &OsStr) -> io::Result<Self> {
852+
// os_string_to_raw returns NULL terminated string. So no need to handle it separately.
853+
let fname = os_string_to_raw(name)
854+
.ok_or(const_error!(io::ErrorKind::OutOfMemory, "Allocation failed"))?;
855+
let new_size = size_of::<file::Info<0>>() + fname.len() * size_of::<u16>();
856+
857+
// Reuse the current structure if the new name can fit in it.
858+
if self.size() >= new_size as u64 {
859+
self.file_name_mut()[..fname.len()].copy_from_slice(&fname);
860+
self.set_size(new_size as u64);
861+
862+
return Ok(self);
863+
}
864+
865+
let mut new_box = UefiBox::new(new_size)?;
866+
867+
unsafe {
868+
crate::ptr::copy_nonoverlapping(self.as_ptr(), new_box.as_mut_ptr(), 1);
869+
}
870+
new_box.set_size(new_size as u64);
871+
new_box.file_name_mut().copy_from_slice(&fname);
872+
873+
Ok(new_box)
874+
}
875+
}

0 commit comments

Comments
 (0)