Skip to content

Commit d3217bf

Browse files
committed
std: sys: fs: uefi: Implement set_times and set_perm
- Tested on QEMU OVMF. Signed-off-by: Ayush Singh <[email protected]>
1 parent 0ad2cd3 commit d3217bf

File tree

2 files changed

+46
-10
lines changed

2 files changed

+46
-10
lines changed

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

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use crate::path::{Path, PathBuf};
99
use crate::sys::time::SystemTime;
1010
use crate::sys::{helpers, unsupported};
1111

12-
#[expect(dead_code)]
1312
const FILE_PERMISSIONS_MASK: u64 = r_efi::protocols::file::READ_ONLY;
1413

1514
pub struct File(!);
@@ -103,7 +102,6 @@ impl FilePermissions {
103102
Self(attr & r_efi::protocols::file::READ_ONLY != 0)
104103
}
105104

106-
#[expect(dead_code)]
107105
const fn to_attr(&self) -> u64 {
108106
if self.0 { r_efi::protocols::file::READ_ONLY } else { 0 }
109107
}
@@ -360,16 +358,40 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
360358
unsupported()
361359
}
362360

363-
pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
364-
unsupported()
361+
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
362+
let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?;
363+
let mut file_info = f.file_info()?;
364+
365+
unsafe {
366+
(*file_info.as_mut_ptr()).attribute =
367+
((*file_info.as_ptr()).attribute & !FILE_PERMISSIONS_MASK) | perm.to_attr()
368+
};
369+
370+
f.set_file_info(file_info)
365371
}
366372

367-
pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> {
368-
unsupported()
373+
pub fn set_times(p: &Path, times: FileTimes) -> io::Result<()> {
374+
// UEFI does not support symlinks
375+
set_times_nofollow(p, times)
369376
}
370377

371-
pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> {
372-
unsupported()
378+
pub fn set_times_nofollow(p: &Path, times: FileTimes) -> io::Result<()> {
379+
let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?;
380+
let mut file_info = f.file_info()?;
381+
382+
if let Some(x) = times.accessed {
383+
unsafe {
384+
(*file_info.as_mut_ptr()).last_access_time = uefi_fs::systemtime_to_uefi(x);
385+
}
386+
}
387+
388+
if let Some(x) = times.modified {
389+
unsafe {
390+
(*file_info.as_mut_ptr()).modification_time = uefi_fs::systemtime_to_uefi(x);
391+
}
392+
}
393+
394+
f.set_file_info(file_info)
373395
}
374396

375397
pub fn rmdir(p: &Path) -> io::Result<()> {
@@ -554,6 +576,17 @@ mod uefi_fs {
554576
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(info) }
555577
}
556578

579+
pub(crate) fn set_file_info(&self, mut info: UefiBox<file::Info>) -> io::Result<()> {
580+
let file_ptr = self.0.as_ptr();
581+
let mut info_id = file::INFO_ID;
582+
583+
let r = unsafe {
584+
((*file_ptr).set_info)(file_ptr, &mut info_id, info.len(), info.as_mut_ptr().cast())
585+
};
586+
587+
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
588+
}
589+
557590
pub(crate) fn delete(self) -> io::Result<()> {
558591
let file_ptr = self.0.as_ptr();
559592
let r = unsafe { ((*file_ptr).delete)(file_ptr) };
@@ -637,8 +670,7 @@ mod uefi_fs {
637670
}
638671

639672
/// Convert to UEFI Time with the current timezone.
640-
#[expect(dead_code)]
641-
fn systemtime_to_uefi(time: SystemTime) -> r_efi::efi::Time {
673+
pub(crate) fn systemtime_to_uefi(time: SystemTime) -> r_efi::efi::Time {
642674
let now = time::system_time_internal::now().unwrap();
643675
time.to_uefi_loose(now.timezone, now.daylight)
644676
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,10 @@ impl<T> UefiBox<T> {
802802
pub(crate) fn as_ptr(&self) -> *const T {
803803
self.inner.as_ptr().cast()
804804
}
805+
806+
pub(crate) const fn len(&self) -> usize {
807+
self.size
808+
}
805809
}
806810

807811
impl<T> Drop for UefiBox<T> {

0 commit comments

Comments
 (0)