Skip to content

Commit 394434c

Browse files
committed
uefi: fs: Add file times plumbing
- Add plumbing to allow conversions to and from UEFI Time to Rust SystemTime. - Also add FileTimes implementation. Signed-off-by: Ayush Singh <[email protected]>
1 parent 1df5aff commit 394434c

File tree

2 files changed

+77
-8
lines changed

2 files changed

+77
-8
lines changed

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

+23-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ pub struct File(!);
1717
pub struct FileAttr {
1818
attr: u64,
1919
size: u64,
20+
created: SystemTime,
21+
times: FileTimes,
2022
}
2123

2224
pub struct ReadDir(!);
@@ -31,8 +33,11 @@ pub struct OpenOptions {
3133
create_new: bool,
3234
}
3335

34-
#[derive(Copy, Clone, Debug, Default)]
35-
pub struct FileTimes {}
36+
#[derive(Copy, Clone, Debug)]
37+
pub struct FileTimes {
38+
accessed: SystemTime,
39+
modified: SystemTime,
40+
}
3641

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

6166
pub fn modified(&self) -> io::Result<SystemTime> {
62-
unsupported()
67+
Ok(self.times.modified)
6368
}
6469

6570
pub fn accessed(&self) -> io::Result<SystemTime> {
66-
unsupported()
71+
Ok(self.times.accessed)
6772
}
6873

6974
pub fn created(&self) -> io::Result<SystemTime> {
70-
unsupported()
75+
Ok(self.created)
7176
}
7277
}
7378

@@ -91,8 +96,19 @@ impl FilePermissions {
9196
}
9297

9398
impl FileTimes {
94-
pub fn set_accessed(&mut self, _t: SystemTime) {}
95-
pub fn set_modified(&mut self, _t: SystemTime) {}
99+
pub fn set_accessed(&mut self, t: SystemTime) {
100+
self.accessed = t;
101+
}
102+
103+
pub fn set_modified(&mut self, t: SystemTime) {
104+
self.modified = t;
105+
}
106+
}
107+
108+
impl Default for FileTimes {
109+
fn default() -> Self {
110+
Self { modified: SystemTime::ZERO, accessed: SystemTime::ZERO }
111+
}
96112
}
97113

98114
impl FileType {

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

+54-1
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,22 @@ impl Instant {
4040
}
4141

4242
impl SystemTime {
43+
pub(crate) const ZERO: SystemTime = SystemTime(Duration::ZERO);
44+
45+
pub(crate) const fn new(t: r_efi::efi::Time) -> Self {
46+
Self(system_time_internal::uefi_time_to_duration(t))
47+
}
48+
4349
pub fn now() -> SystemTime {
4450
system_time_internal::now()
4551
.unwrap_or_else(|| panic!("time not implemented on this platform"))
4652
}
4753

54+
#[expect(dead_code)]
55+
pub(crate) const fn to_uefi_time(&self, daylight: u8, timezone: i16) -> r_efi::efi::Time {
56+
system_time_internal::uefi_time_from_duration(self.0, daylight, timezone)
57+
}
58+
4859
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
4960
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
5061
}
@@ -79,7 +90,7 @@ pub(crate) mod system_time_internal {
7990

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

82-
Some(SystemTime(uefi_time_to_duration(t)))
93+
Some(SystemTime::new(t))
8394
}
8495

8596
// This algorithm is based on the one described in the post
@@ -112,6 +123,48 @@ pub(crate) mod system_time_internal {
112123

113124
Duration::new(utc_epoch, t.nanosecond)
114125
}
126+
127+
/// This algorithm is taken from: http://howardhinnant.github.io/date_algorithms.html
128+
pub(crate) const fn uefi_time_from_duration(
129+
dur: crate::time::Duration,
130+
daylight: u8,
131+
timezone: i16,
132+
) -> r_efi::system::Time {
133+
const SECS_IN_MINUTE: u64 = 60;
134+
const SECS_IN_HOUR: u64 = SECS_IN_MINUTE * 60;
135+
const SECS_IN_DAY: u64 = SECS_IN_HOUR * 24;
136+
137+
let secs = dur.as_secs();
138+
let days = secs / SECS_IN_DAY;
139+
let remaining_secs = secs % SECS_IN_DAY;
140+
let z = days + 719468;
141+
let era = z / 146097;
142+
let doe = z - (era * 146097);
143+
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
144+
let mut y = yoe + era * 400;
145+
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
146+
let mp = (5 * doy + 2) / 153;
147+
let d = doy - (153 * mp + 2) / 5 + 1;
148+
let m = if mp < 10 { mp + 3 } else { mp - 9 };
149+
150+
if m <= 2 {
151+
y += 1;
152+
}
153+
154+
r_efi::system::Time {
155+
year: y as u16,
156+
month: m as u8,
157+
day: d as u8,
158+
hour: (remaining_secs / SECS_IN_HOUR) as u8,
159+
minute: ((remaining_secs % SECS_IN_HOUR) / SECS_IN_MINUTE) as u8,
160+
second: ((remaining_secs % SECS_IN_HOUR) % SECS_IN_MINUTE) as u8,
161+
pad1: 0,
162+
nanosecond: dur.subsec_nanos(),
163+
timezone,
164+
daylight,
165+
pad2: 0,
166+
}
167+
}
115168
}
116169

117170
pub(crate) mod instant_internal {

0 commit comments

Comments
 (0)