Skip to content

Commit bd7f68d

Browse files
committed
std: sys: fs: uefi: Make time in FileAttr optional
At least on OVMF, some files copied over from linux file system seem to have invalid time (year = 1980 and everything else 0). Since Rust allows time to be optional and we can return error, that seems to be the way to go for now. Signed-off-by: Ayush Singh <ayush@beagleboard.org>
1 parent 63b1db0 commit bd7f68d

File tree

2 files changed

+43
-29
lines changed

2 files changed

+43
-29
lines changed

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

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,8 @@ pub struct File(!);
1818
pub struct FileAttr {
1919
attr: u64,
2020
size: u64,
21-
accessed: SystemTime,
22-
modified: SystemTime,
23-
created: SystemTime,
21+
file_time: FileTimes,
22+
created: Option<SystemTime>,
2423
}
2524

2625
pub struct ReadDir(!);
@@ -66,24 +65,31 @@ impl FileAttr {
6665
}
6766

6867
pub fn modified(&self) -> io::Result<SystemTime> {
69-
Ok(self.modified)
68+
self.file_time
69+
.modified
70+
.ok_or(io::const_error!(io::ErrorKind::InvalidData, "modification time is not valid"))
7071
}
7172

7273
pub fn accessed(&self) -> io::Result<SystemTime> {
73-
Ok(self.accessed)
74+
self.file_time
75+
.accessed
76+
.ok_or(io::const_error!(io::ErrorKind::InvalidData, "last access time is not valid"))
7477
}
7578

7679
pub fn created(&self) -> io::Result<SystemTime> {
77-
Ok(self.created)
80+
self.created
81+
.ok_or(io::const_error!(io::ErrorKind::InvalidData, "creation time is not valid"))
7882
}
7983

8084
fn from_uefi(info: helpers::UefiBox<file::Info>) -> Self {
8185
unsafe {
8286
Self {
8387
attr: (*info.as_ptr()).attribute,
8488
size: (*info.as_ptr()).file_size,
85-
modified: uefi_fs::uefi_to_systemtime((*info.as_ptr()).modification_time),
86-
accessed: uefi_fs::uefi_to_systemtime((*info.as_ptr()).last_access_time),
89+
file_time: FileTimes {
90+
modified: uefi_fs::uefi_to_systemtime((*info.as_ptr()).modification_time),
91+
accessed: uefi_fs::uefi_to_systemtime((*info.as_ptr()).last_access_time),
92+
},
8793
created: uefi_fs::uefi_to_systemtime((*info.as_ptr()).create_time),
8894
}
8995
}
@@ -627,7 +633,7 @@ mod uefi_fs {
627633

628634
/// EDK2 FAT driver uses EFI_UNSPECIFIED_TIMEZONE to represent localtime. So for proper
629635
/// conversion to SystemTime, we use the current time to get the timezone in such cases.
630-
pub(crate) fn uefi_to_systemtime(mut time: r_efi::efi::Time) -> SystemTime {
636+
pub(crate) fn uefi_to_systemtime(mut time: r_efi::efi::Time) -> Option<SystemTime> {
631637
time.timezone = if time.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE {
632638
time::system_time_internal::now().unwrap().timezone
633639
} else {

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

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ pub const UNIX_EPOCH: SystemTime = SystemTime::from_uefi(r_efi::efi::Time {
2424
daylight: 0,
2525
pad1: 0,
2626
pad2: 0,
27-
});
27+
})
28+
.unwrap();
2829

2930
const MAX_UEFI_TIME: SystemTime = SystemTime::from_uefi(r_efi::efi::Time {
3031
year: 9999,
@@ -38,7 +39,8 @@ const MAX_UEFI_TIME: SystemTime = SystemTime::from_uefi(r_efi::efi::Time {
3839
daylight: 0,
3940
pad1: 0,
4041
pad2: 0,
41-
});
42+
})
43+
.unwrap();
4244

4345
impl Instant {
4446
pub fn now() -> Instant {
@@ -68,8 +70,11 @@ impl Instant {
6870
}
6971

7072
impl SystemTime {
71-
pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Self {
72-
Self(system_time_internal::from_uefi(&t))
73+
pub(crate) const fn from_uefi(t: r_efi::efi::Time) -> Option<Self> {
74+
match system_time_internal::from_uefi(&t) {
75+
Some(x) => Some(Self(x)),
76+
None => None,
77+
}
7378
}
7479

7580
pub(crate) const fn to_uefi(
@@ -98,7 +103,8 @@ impl SystemTime {
98103
pub fn now() -> SystemTime {
99104
system_time_internal::now()
100105
.map(Self::from_uefi)
101-
.unwrap_or_else(|| panic!("time not implemented on this platform"))
106+
.expect("time not implemented on this platform")
107+
.expect("time incorrectly implemented on this platform")
102108
}
103109

104110
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
@@ -147,20 +153,22 @@ pub(crate) mod system_time_internal {
147153
///
148154
/// The changes are to use 1900-01-01-00:00:00 with timezone -1440 as anchor instead of UNIX
149155
/// epoch used in the original algorithm.
150-
pub(crate) const fn from_uefi(t: &Time) -> Duration {
151-
assert!(t.month <= 12 && t.month != 0);
152-
assert!(t.year >= 1900 && t.year <= 9999);
153-
assert!(t.day <= 31 && t.day != 0);
154-
155-
assert!(t.second < 60);
156-
assert!(t.minute < 60);
157-
assert!(t.hour < 24);
158-
assert!(t.nanosecond < 1_000_000_000);
159-
160-
assert!(
161-
(t.timezone <= 1440 && t.timezone >= -1440)
162-
|| t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE
163-
);
156+
pub(crate) const fn from_uefi(t: &Time) -> Option<Duration> {
157+
if !(t.month <= 12
158+
&& t.month != 0
159+
&& t.year >= 1900
160+
&& t.year <= 9999
161+
&& t.day <= 31
162+
&& t.day != 0
163+
&& t.second < 60
164+
&& t.minute <= 60
165+
&& t.hour < 24
166+
&& t.nanosecond < 1_000_000_000
167+
&& ((t.timezone <= 1440 && t.timezone >= -1440)
168+
|| t.timezone == r_efi::efi::UNSPECIFIED_TIMEZONE))
169+
{
170+
return None;
171+
}
164172

165173
const YEAR_BASE: u32 = 4800; /* Before min year, multiple of 400. */
166174

@@ -188,7 +196,7 @@ pub(crate) mod system_time_internal {
188196
// Calculate the offset from 1/1/1900 at timezone -1440 min
189197
let epoch = localtime_epoch.checked_add_signed(normalized_timezone).unwrap();
190198

191-
Duration::new(epoch, t.nanosecond)
199+
Some(Duration::new(epoch, t.nanosecond))
192200
}
193201

194202
/// This algorithm is a modified version of the one described in the post:

0 commit comments

Comments
 (0)