[pbs-devel] [PATCH proxmox-backup 01/10] tools/systemd/time: let libc normalize time for us
Dominik Csapak
d.csapak at proxmox.com
Thu Sep 3 13:39:51 CEST 2020
mktime/gmtime can normalize time and even can handle special timezone
cases like the fact that the time 2:30 on specific day/timezone combos
do not exists
we have to convert the signature of all functions that use
normalize_time since mktime/gmtime can return an EOVERFLOW
but if this happens there is no way we can find a good time anyway
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
src/tools/systemd/time.rs | 16 ++---
src/tools/systemd/tm_editor.rs | 114 +++++++++------------------------
2 files changed, 37 insertions(+), 93 deletions(-)
diff --git a/src/tools/systemd/time.rs b/src/tools/systemd/time.rs
index 773a1509..edf26505 100644
--- a/src/tools/systemd/time.rs
+++ b/src/tools/systemd/time.rs
@@ -182,11 +182,11 @@ pub fn compute_next_event(
.find(|d| event.days.contains(WeekDays::from_bits(1<<d).unwrap()))
{
// try next day
- t.add_days(n - day_num, true);
+ t.add_days(n - day_num, true)?;
continue;
} else {
// try next week
- t.add_days(7 - day_num, true);
+ t.add_days(7 - day_num, true)?;
continue;
}
}
@@ -200,11 +200,11 @@ pub fn compute_next_event(
} else {
if let Some(n) = DateTimeValue::find_next(&event.hour, hour) {
// test next hour
- t.set_time(n as libc::c_int, 0, 0);
+ t.set_time(n as libc::c_int, 0, 0)?;
continue;
} else {
// test next day
- t.add_days(1, true);
+ t.add_days(1, true)?;
continue;
}
}
@@ -218,11 +218,11 @@ pub fn compute_next_event(
} else {
if let Some(n) = DateTimeValue::find_next(&event.minute, minute) {
// test next minute
- t.set_min_sec(n as libc::c_int, 0);
+ t.set_min_sec(n as libc::c_int, 0)?;
continue;
} else {
// test next hour
- t.set_time(t.hour() + 1, 0, 0);
+ t.set_time(t.hour() + 1, 0, 0)?;
continue;
}
}
@@ -236,11 +236,11 @@ pub fn compute_next_event(
} else {
if let Some(n) = DateTimeValue::find_next(&event.second, second) {
// test next second
- t.set_sec(n as libc::c_int);
+ t.set_sec(n as libc::c_int)?;
continue;
} else {
// test next min
- t.set_min_sec(t.min() + 1, 0);
+ t.set_min_sec(t.min() + 1, 0)?;
continue;
}
}
diff --git a/src/tools/systemd/tm_editor.rs b/src/tools/systemd/tm_editor.rs
index 3b81d1cb..62f8d1d0 100644
--- a/src/tools/systemd/tm_editor.rs
+++ b/src/tools/systemd/tm_editor.rs
@@ -22,24 +22,6 @@ pub struct TmEditor {
pub changes: TMChanges,
}
-fn is_leap_year(year: libc::c_int) -> bool {
- if year % 4 != 0 { return false; }
- if year % 100 != 0 { return true; }
- if year % 400 != 0 { return false; }
- return true;
-}
-
-fn days_in_month(mon: libc::c_int, year: libc::c_int) -> libc::c_int {
-
- let mon = mon % 12;
-
- static MAP: &[libc::c_int] = &[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
-
- if mon == 1 && is_leap_year(year) { return 29; }
-
- MAP[mon as usize]
-}
-
impl TmEditor {
pub fn new(epoch: i64, utc: bool) -> Result<Self, Error> {
@@ -50,12 +32,12 @@ impl TmEditor {
pub fn into_epoch(mut self) -> Result<i64, Error> {
self.t.tm_year -= 1900;
- let epoch = if self.utc { timegm(self.t)? } else { timelocal(self.t)? };
+ let epoch = if self.utc { timegm(&mut self.t)? } else { timelocal(&mut self.t)? };
Ok(epoch)
}
- pub fn add_days(&mut self, days: libc::c_int, reset_time: bool) {
- if days == 0 { return; }
+ pub fn add_days(&mut self, days: libc::c_int, reset_time: bool) -> Result<(), Error> {
+ if days == 0 { return Ok(()); }
if reset_time {
self.t.tm_hour = 0;
self.t.tm_min = 0;
@@ -65,7 +47,7 @@ impl TmEditor {
self.t.tm_mday += days;
self.t.tm_wday += days;
self.changes.insert(TMChanges::MDAY|TMChanges::WDAY);
- self.wrap_time();
+ self.normalize_time()
}
pub fn hour(&self) -> libc::c_int { self.t.tm_hour }
@@ -77,109 +59,71 @@ impl TmEditor {
(self.t.tm_wday + 6) % 7
}
- pub fn set_time(&mut self, hour: libc::c_int, min: libc::c_int, sec: libc::c_int) {
+ pub fn set_time(&mut self, hour: libc::c_int, min: libc::c_int, sec: libc::c_int) -> Result<(), Error> {
self.t.tm_hour = hour;
self.t.tm_min = min;
self.t.tm_sec = sec;
self.changes.insert(TMChanges::HOUR|TMChanges::MIN|TMChanges::SEC);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_min_sec(&mut self, min: libc::c_int, sec: libc::c_int) {
+ pub fn set_min_sec(&mut self, min: libc::c_int, sec: libc::c_int) -> Result<(), Error> {
self.t.tm_min = min;
self.t.tm_sec = sec;
self.changes.insert(TMChanges::MIN|TMChanges::SEC);
- self.wrap_time();
+ self.normalize_time()
}
- fn wrap_time(&mut self) {
-
- // sec: 0..59
- if self.t.tm_sec >= 60 {
- self.t.tm_min += self.t.tm_sec / 60;
- self.t.tm_sec %= 60;
- self.changes.insert(TMChanges::SEC|TMChanges::MIN);
+ fn normalize_time(&mut self) -> Result<(), Error> {
+ // libc normalizes it for us
+ if self.utc {
+ timegm(&mut self.t)?;
+ } else {
+ timelocal(&mut self.t)?;
}
-
- // min: 0..59
- if self.t.tm_min >= 60 {
- self.t.tm_hour += self.t.tm_min / 60;
- self.t.tm_min %= 60;
- self.changes.insert(TMChanges::MIN|TMChanges::HOUR);
- }
-
- // hour: 0..23
- if self.t.tm_hour >= 24 {
- self.t.tm_mday += self.t.tm_hour / 24;
- self.t.tm_wday += self.t.tm_hour / 24;
- self.t.tm_hour %= 24;
- self.changes.insert(TMChanges::HOUR|TMChanges::MDAY|TMChanges::WDAY);
- }
-
- // Translate to 0..($days_in_mon-1)
- self.t.tm_mday -= 1;
- loop {
- let days_in_mon = days_in_month(self.t.tm_mon, self.t.tm_year);
- if self.t.tm_mday < days_in_mon { break; }
- // Wrap one month
- self.t.tm_mday -= days_in_mon;
- self.t.tm_mon += 1;
- self.changes.insert(TMChanges::MDAY|TMChanges::WDAY|TMChanges::MON);
- }
-
- // Translate back to 1..$days_in_mon
- self.t.tm_mday += 1;
-
- // mon: 0..11
- if self.t.tm_mon >= 12 {
- self.t.tm_year += self.t.tm_mon / 12;
- self.t.tm_mon %= 12;
- self.changes.insert(TMChanges::MON|TMChanges::YEAR);
- }
-
- self.t.tm_wday %= 7;
+ Ok(())
}
- pub fn set_sec(&mut self, v: libc::c_int) {
+ pub fn set_sec(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_sec = v;
self.changes.insert(TMChanges::SEC);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_min(&mut self, v: libc::c_int) {
+ pub fn set_min(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_min = v;
self.changes.insert(TMChanges::MIN);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_hour(&mut self, v: libc::c_int) {
+ pub fn set_hour(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_hour = v;
self.changes.insert(TMChanges::HOUR);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_mday(&mut self, v: libc::c_int) {
+ pub fn set_mday(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_mday = v;
self.changes.insert(TMChanges::MDAY);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_mon(&mut self, v: libc::c_int) {
+ pub fn set_mon(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_mon = v;
self.changes.insert(TMChanges::MON);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_year(&mut self, v: libc::c_int) {
+ pub fn set_year(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_year = v;
self.changes.insert(TMChanges::YEAR);
- self.wrap_time();
+ self.normalize_time()
}
- pub fn set_wday(&mut self, v: libc::c_int) {
+ pub fn set_wday(&mut self, v: libc::c_int) -> Result<(), Error> {
self.t.tm_wday = v;
self.changes.insert(TMChanges::WDAY);
- self.wrap_time();
+ self.normalize_time()
}
}
--
2.20.1
More information about the pbs-devel
mailing list