Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uefi: fs: Add file times plumbing #138918

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions library/std/src/sys/fs/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub struct File(!);
pub struct FileAttr {
attr: u64,
size: u64,
created: SystemTime,
times: FileTimes,
}

pub struct ReadDir(!);
Expand All @@ -31,8 +33,11 @@ pub struct OpenOptions {
create_new: bool,
}

#[derive(Copy, Clone, Debug, Default)]
pub struct FileTimes {}
#[derive(Copy, Clone, Debug)]
pub struct FileTimes {
accessed: SystemTime,
modified: SystemTime,
}

#[derive(Clone, PartialEq, Eq, Debug)]
// Bool indicates if file is readonly
Expand All @@ -59,15 +64,15 @@ impl FileAttr {
}

pub fn modified(&self) -> io::Result<SystemTime> {
unsupported()
Ok(self.times.modified)
}

pub fn accessed(&self) -> io::Result<SystemTime> {
unsupported()
Ok(self.times.accessed)
}

pub fn created(&self) -> io::Result<SystemTime> {
unsupported()
Ok(self.created)
}
}

Expand All @@ -91,8 +96,19 @@ impl FilePermissions {
}

impl FileTimes {
pub fn set_accessed(&mut self, _t: SystemTime) {}
pub fn set_modified(&mut self, _t: SystemTime) {}
pub fn set_accessed(&mut self, t: SystemTime) {
self.accessed = t;
}

pub fn set_modified(&mut self, t: SystemTime) {
self.modified = t;
}
}

impl Default for FileTimes {
fn default() -> Self {
Self { modified: SystemTime::ZERO, accessed: SystemTime::ZERO }
}
}

impl FileType {
Expand Down
59 changes: 58 additions & 1 deletion library/std/src/sys/pal/uefi/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,22 @@ impl Instant {
}

impl SystemTime {
pub(crate) const ZERO: SystemTime = SystemTime(Duration::ZERO);

pub(crate) const fn new(t: r_efi::efi::Time) -> Self {
Self(system_time_internal::uefi_time_to_duration(t))
}

pub fn now() -> SystemTime {
system_time_internal::now()
.unwrap_or_else(|| panic!("time not implemented on this platform"))
}

#[expect(dead_code)]
pub(crate) const fn to_uefi_time(&self, daylight: u8, timezone: i16) -> r_efi::efi::Time {
system_time_internal::uefi_time_from_duration(self.0, daylight, timezone)
}

pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
}
Expand Down Expand Up @@ -79,7 +90,7 @@ pub(crate) mod system_time_internal {

let t = unsafe { t.assume_init() };

Some(SystemTime(uefi_time_to_duration(t)))
Some(SystemTime::new(t))
}

// This algorithm is based on the one described in the post
Expand Down Expand Up @@ -112,6 +123,52 @@ pub(crate) mod system_time_internal {

Duration::new(utc_epoch, t.nanosecond)
}

/// This algorithm is taken from: http://howardhinnant.github.io/date_algorithms.html
pub(crate) const fn uefi_time_from_duration(
dur: crate::time::Duration,
daylight: u8,
timezone: i16,
) -> r_efi::system::Time {
const SECS_IN_MINUTE: u64 = 60;
const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60;
const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24;

let secs = if timezone == r_efi::efi::UNSPECIFIED_TIMEZONE {
dur.as_secs()
} else {
dur.as_secs().checked_add_signed(-timezone as i64).unwrap()
};
let days = secs / SECS_IN_DAY;
let remaining_secs = secs % SECS_IN_DAY;
let z = days + 719468;
let era = z / 146097;
let doe = z - (era * 146097);
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
let mut y = yoe + era * 400;
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
let mp = (5 * doy + 2) / 153;
let d = doy - (153 * mp + 2) / 5 + 1;
let m = if mp < 10 { mp + 3 } else { mp - 9 };

if m <= 2 {
y += 1;
}

r_efi::system::Time {
year: y as u16,
month: m as u8,
day: d as u8,
hour: (remaining_secs / SECS_IN_HOUR) as u8,
minute: ((remaining_secs % SECS_IN_HOUR) / SECS_IN_MINUTE) as u8,
second: ((remaining_secs % SECS_IN_HOUR) % SECS_IN_MINUTE) as u8,
pad1: 0,
nanosecond: dur.subsec_nanos(),
timezone,
daylight,
pad2: 0,
}
}
}

pub(crate) mod instant_internal {
Expand Down
Loading