From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 3EC8160B2B for ; Thu, 3 Sep 2020 13:40:06 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 3A543185AE for ; Thu, 3 Sep 2020 13:40:06 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [212.186.127.180]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id 454451853B for ; Thu, 3 Sep 2020 13:40:02 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 10117449FA for ; Thu, 3 Sep 2020 13:40:02 +0200 (CEST) From: Dominik Csapak To: pbs-devel@lists.proxmox.com Date: Thu, 3 Sep 2020 13:39:51 +0200 Message-Id: <20200903114000.6932-2-d.csapak@proxmox.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200903114000.6932-1-d.csapak@proxmox.com> References: <20200903114000.6932-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.087 Adjusted score from AWL reputation of From: address KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records RCVD_IN_DNSWL_MED -2.3 Sender listed at https://www.dnswl.org/, medium trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [time.rs] Subject: [pbs-devel] [PATCH proxmox-backup 01/10] tools/systemd/time: let libc normalize time for us X-BeenThere: pbs-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Backup Server development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Sep 2020 11:40:06 -0000 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 --- 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< 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 { @@ -50,12 +32,12 @@ impl TmEditor { pub fn into_epoch(mut self) -> Result { 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