Skip to content

Commit d610cde

Browse files
committed
Implement std::fs::File::set_times
Signed-off-by: Ayush <ayushsingh1325@gmail.com>
1 parent 73852ec commit d610cde

File tree

2 files changed

+99
-19
lines changed

2 files changed

+99
-19
lines changed

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

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::fmt;
55
use crate::hash::Hash;
66
use crate::io::{self, IoSlice, IoSliceMut, ReadBuf, SeekFrom};
77
use crate::path::{Path, PathBuf};
8-
use crate::sys::time::{SystemTime, UNIX_EPOCH};
8+
use crate::sys::time::SystemTime;
99
use crate::sys::unsupported;
1010
use r_efi::protocols::file;
1111

@@ -20,7 +20,8 @@ pub struct FileAttr {
2020
perm: FilePermissions,
2121
file_type: FileType,
2222
created_time: SystemTime,
23-
file_times: FileTimes,
23+
last_accessed_time: SystemTime,
24+
modification_time: SystemTime,
2425
}
2526

2627
pub struct ReadDir {
@@ -55,8 +56,8 @@ pub struct FileType {
5556

5657
#[derive(Copy, Clone, Debug)]
5758
pub struct FileTimes {
58-
last_accessed_time: SystemTime,
59-
modification_time: SystemTime,
59+
last_accessed_time: Option<SystemTime>,
60+
modification_time: Option<SystemTime>,
6061
}
6162

6263
#[derive(Debug)]
@@ -83,12 +84,12 @@ impl FileAttr {
8384

8485
#[inline]
8586
pub fn modified(&self) -> io::Result<SystemTime> {
86-
Ok(self.file_times.modification_time)
87+
Ok(self.modification_time)
8788
}
8889

8990
#[inline]
9091
pub fn accessed(&self) -> io::Result<SystemTime> {
91-
Ok(self.file_times.last_accessed_time)
92+
Ok(self.last_accessed_time)
9293
}
9394

9495
#[inline]
@@ -103,11 +104,9 @@ impl From<&file::Info> for FileAttr {
103104
size: info.file_size,
104105
perm: FilePermissions { attr: info.attribute },
105106
file_type: FileType { attr: info.attribute },
106-
file_times: FileTimes {
107-
last_accessed_time: SystemTime::from(info.last_access_time),
108-
modification_time: SystemTime::from(info.modification_time),
109-
},
110107
created_time: SystemTime::from(info.create_time),
108+
last_accessed_time: SystemTime::from(info.last_access_time),
109+
modification_time: SystemTime::from(info.modification_time),
111110
}
112111
}
113112
}
@@ -177,19 +176,19 @@ impl Iterator for ReadDir {
177176
impl FileTimes {
178177
#[inline]
179178
pub fn set_accessed(&mut self, t: SystemTime) {
180-
self.last_accessed_time = t;
179+
self.last_accessed_time = Some(t);
181180
}
182181

183182
#[inline]
184183
pub fn set_modified(&mut self, t: SystemTime) {
185-
self.modification_time = t;
184+
self.modification_time = Some(t);
186185
}
187186
}
188187

189188
impl Default for FileTimes {
190189
#[inline]
191190
fn default() -> Self {
192-
Self { last_accessed_time: UNIX_EPOCH, modification_time: UNIX_EPOCH }
191+
Self { last_accessed_time: None, modification_time: None }
193192
}
194193
}
195194

@@ -382,8 +381,9 @@ impl File {
382381
self.ptr.set_file_attr(perm.attr)
383382
}
384383

385-
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
386-
unsupported()
384+
#[inline]
385+
pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
386+
self.ptr.set_file_times(times)
387387
}
388388
}
389389

@@ -548,6 +548,7 @@ fn cascade_delete(file: uefi_fs::FileProtocol, path: &Path) -> io::Result<()> {
548548
}
549549

550550
mod uefi_fs {
551+
use super::FileTimes;
551552
use super::{DirEntry, FileAttr};
552553
use crate::default::Default;
553554
use crate::ffi::OsStr;
@@ -891,6 +892,34 @@ mod uefi_fs {
891892
}
892893
}
893894

895+
pub fn set_file_times(&self, file_times: FileTimes) -> io::Result<()> {
896+
let mut old_info = self.get_file_info()?;
897+
898+
if let Some(t) = file_times.last_accessed_time {
899+
old_info.last_access_time = super::super::time::uefi_time_from_duration(
900+
t.get_duration(),
901+
old_info.last_access_time.daylight,
902+
old_info.last_access_time.timezone,
903+
);
904+
}
905+
if let Some(t) = file_times.modification_time {
906+
old_info.modification_time = super::super::time::uefi_time_from_duration(
907+
t.get_duration(),
908+
old_info.modification_time.daylight,
909+
old_info.modification_time.timezone,
910+
);
911+
}
912+
913+
unsafe {
914+
Self::set_info_raw(
915+
self.inner.as_ptr(),
916+
file::INFO_ID,
917+
old_info.layout().size(),
918+
old_info.as_mut() as *mut _ as *mut crate::ffi::c_void,
919+
)
920+
}
921+
}
922+
894923
// Delete a file.
895924
pub fn delete(self) -> io::Result<()> {
896925
// Deleting the file makes the pointer invalid. Thus calling drop on it later will
@@ -899,6 +928,7 @@ mod uefi_fs {
899928
unsafe { Self::delete_raw(file.inner.as_ptr()) }
900929
}
901930

931+
#[inline]
902932
unsafe fn open_raw(
903933
rootfs: *mut file::Protocol,
904934
file_opened: *mut *mut file::Protocol,
@@ -910,21 +940,25 @@ mod uefi_fs {
910940
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
911941
}
912942

943+
#[inline]
913944
unsafe fn set_position_raw(protocol: *mut file::Protocol, pos: u64) -> io::Result<()> {
914945
let r = unsafe { ((*protocol).set_position)(protocol, pos) };
915946
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
916947
}
917948

949+
#[inline]
918950
unsafe fn get_position_raw(protocol: *mut file::Protocol, pos: *mut u64) -> io::Result<()> {
919951
let r = unsafe { ((*protocol).get_position)(protocol, pos) };
920952
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
921953
}
922954

955+
#[inline]
923956
unsafe fn flush_raw(protocol: *mut file::Protocol) -> io::Result<()> {
924957
let r = unsafe { ((*protocol).flush)(protocol) };
925958
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
926959
}
927960

961+
#[inline]
928962
unsafe fn write_raw(
929963
protocol: *mut file::Protocol,
930964
buf_size: *mut usize,
@@ -939,6 +973,7 @@ mod uefi_fs {
939973
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
940974
}
941975

976+
#[inline]
942977
unsafe fn read_raw(
943978
protocol: *mut file::Protocol,
944979
buf_size: *mut usize,
@@ -948,6 +983,7 @@ mod uefi_fs {
948983
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
949984
}
950985

986+
#[inline]
951987
unsafe fn get_info_raw(
952988
protocol: *mut file::Protocol,
953989
mut info_guid: r_efi::efi::Guid,
@@ -958,6 +994,7 @@ mod uefi_fs {
958994
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
959995
}
960996

997+
#[inline]
961998
unsafe fn set_info_raw(
962999
protocol: *mut file::Protocol,
9631000
mut info_guid: r_efi::efi::Guid,
@@ -968,13 +1005,15 @@ mod uefi_fs {
9681005
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
9691006
}
9701007

1008+
#[inline]
9711009
unsafe fn delete_raw(protocol: *mut file::Protocol) -> io::Result<()> {
9721010
let r = unsafe { ((*protocol).delete)(protocol) };
9731011
if r.is_error() { Err(status_to_io_error(r)) } else { Ok(()) }
9741012
}
9751013
}
9761014

9771015
impl Drop for FileProtocol {
1016+
#[inline]
9781017
fn drop(&mut self) {
9791018
let protocol = self.inner.as_ptr();
9801019
// Always returns EFI_SUCCESS

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

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@ pub struct Instant(Duration);
1414
pub struct SystemTime(Duration);
1515

1616
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::ZERO);
17+
1718
const NS_PER_SEC: u64 = 1_000_000_000;
19+
const SEC_IN_MIN: u64 = 60;
20+
const SEC_IN_HOUR: u64 = SEC_IN_MIN * 60;
21+
const SEC_IN_DAY: u64 = SEC_IN_HOUR * 24;
22+
const SEC_IN_YEAR: u64 = SEC_IN_DAY * 365;
1823

1924
impl Instant {
2025
pub fn now() -> Instant {
@@ -112,6 +117,10 @@ impl SystemTime {
112117
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
113118
Some(SystemTime(self.0.checked_sub(*other)?))
114119
}
120+
121+
pub(crate) fn get_duration(&self) -> Duration {
122+
self.0
123+
}
115124
}
116125

117126
impl From<r_efi::system::Time> for SystemTime {
@@ -123,10 +132,6 @@ impl From<r_efi::system::Time> for SystemTime {
123132

124133
// FIXME: Don't know how to use Daylight Saving thing
125134
fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration {
126-
const SEC_IN_MIN: u64 = 60;
127-
const SEC_IN_HOUR: u64 = SEC_IN_MIN * 60;
128-
const SEC_IN_DAY: u64 = SEC_IN_HOUR * 24;
129-
const SEC_IN_YEAR: u64 = SEC_IN_DAY * 365;
130135
const MONTH_DAYS: [u64; 12] = [0, 31, 59, 90, 120, 151, 181, 211, 242, 272, 303, 333];
131136

132137
let localtime_epoch: u64 = u64::from(t.year - 1970) * SEC_IN_YEAR
@@ -142,6 +147,42 @@ fn uefi_time_to_duration(t: r_efi::system::Time) -> Duration {
142147
Duration::new(utc_epoch, t.nanosecond)
143148
}
144149

150+
// This algorithm is taken from: http://howardhinnant.github.io/date_algorithms.html
151+
pub fn uefi_time_from_duration(dur: Duration, daylight: u8, timezone: i16) -> r_efi::system::Time {
152+
let secs = dur.as_secs();
153+
154+
let days = secs / SEC_IN_DAY;
155+
let remaining_secs = secs % SEC_IN_DAY;
156+
157+
let z = days + 719468;
158+
let era = z / 146097;
159+
let doe = z - (era * 146097);
160+
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
161+
let mut y = yoe + era * 400;
162+
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
163+
let mp = (5 * doy + 2) / 153;
164+
let d = doy - (153 * mp + 2) / 5 + 1;
165+
let m = if mp < 10 { mp + 3 } else { mp - 9 };
166+
167+
if m <= 2 {
168+
y += 1;
169+
}
170+
171+
r_efi::system::Time {
172+
year: y as u16,
173+
month: m as u8,
174+
day: d as u8,
175+
hour: (remaining_secs / SEC_IN_HOUR) as u8,
176+
minute: ((remaining_secs % SEC_IN_HOUR) / SEC_IN_MIN) as u8,
177+
second: ((remaining_secs % SEC_IN_HOUR) % SEC_IN_MIN) as u8,
178+
pad1: 0,
179+
nanosecond: dur.subsec_nanos(),
180+
timezone,
181+
daylight,
182+
pad2: 0,
183+
}
184+
}
185+
145186
// Returns the Frequency in Mhz
146187
// Mostly based on [`edk2/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c`](https://github.com/tianocore/edk2/blob/master/UefiCpuPkg/Library/CpuTimerLib/CpuTimerLib.c)
147188
// Currently implemented only for x86_64 but can be extended for other arch if they ever support

0 commit comments

Comments
 (0)