From 833eca6d2f2e16774480cc232f998726a8a08dc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Gr=C3=BCnbichler?= Date: Fri, 11 Sep 2020 14:34:36 +0200 Subject: [PATCH] use non-panicky timestamp_opt where appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit by either printing the original, out-of-range timestamp as-is, or bailing with a proper error message instead of panicking. Signed-off-by: Fabian Grünbichler --- src/backup/fixed_index.rs | 7 +++++-- src/bin/proxmox-backup-client.rs | 18 +++++++++++++++--- src/tools/format.rs | 9 ++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/backup/fixed_index.rs b/src/backup/fixed_index.rs index 5d6cc1ff..309f4503 100644 --- a/src/backup/fixed_index.rs +++ b/src/backup/fixed_index.rs @@ -6,7 +6,7 @@ use super::chunk_store::*; use super::{IndexFile, ChunkReadInfo}; use crate::tools::{self, epoch_now_u64}; -use chrono::{Local, TimeZone}; +use chrono::{Local, LocalResult, TimeZone}; use std::fs::File; use std::io::Write; use std::os::unix::io::AsRawFd; @@ -150,7 +150,10 @@ impl FixedIndexReader { println!("ChunkSize: {}", self.chunk_size); println!( "CTime: {}", - Local.timestamp(self.ctime as i64, 0).format("%c") + match Local.timestamp_opt(self.ctime as i64, 0) { + LocalResult::Single(ctime) => ctime.format("%c").to_string(), + _ => (self.ctime as i64).to_string(), + } ); println!("UUID: {:?}", self.uuid); } diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs index 1e9cc680..25376bc9 100644 --- a/src/bin/proxmox-backup-client.rs +++ b/src/bin/proxmox-backup-client.rs @@ -8,7 +8,7 @@ use std::sync::{Arc, Mutex}; use std::task::Context; use anyhow::{bail, format_err, Error}; -use chrono::{Local, DateTime, Utc, TimeZone}; +use chrono::{Local, LocalResult, DateTime, Utc, TimeZone}; use futures::future::FutureExt; use futures::stream::{StreamExt, TryStreamExt}; use serde_json::{json, Value}; @@ -257,7 +257,11 @@ pub async fn api_datastore_latest_snapshot( list.sort_unstable_by(|a, b| b.backup_time.cmp(&a.backup_time)); - let backup_time = Utc.timestamp(list[0].backup_time, 0); + let backup_time = match Utc.timestamp_opt(list[0].backup_time, 0) { + LocalResult::Single(time) => time, + _ => bail!("last snapshot of backup group {:?} has invalid timestmap {}.", + group.group_path(), list[0].backup_time), + }; Ok((group.backup_type().to_owned(), group.backup_id().to_owned(), backup_time)) } @@ -986,7 +990,15 @@ async fn create_backup( } } - let backup_time = Utc.timestamp(backup_time_opt.unwrap_or_else(|| Utc::now().timestamp()), 0); + let backup_time = match backup_time_opt { + Some(timestamp) => { + match Utc.timestamp_opt(timestamp, 0) { + LocalResult::Single(time) => time, + _ => bail!("Invalid backup-time parameter: {}", timestamp), + } + }, + _ => Utc::now(), + }; let client = connect(repo.host(), repo.user())?; record_repository(&repo); diff --git a/src/tools/format.rs b/src/tools/format.rs index aa67ea38..1e593ff3 100644 --- a/src/tools/format.rs +++ b/src/tools/format.rs @@ -1,6 +1,6 @@ use anyhow::{Error}; use serde_json::Value; -use chrono::{Local, TimeZone}; +use chrono::{Local, TimeZone, LocalResult}; pub fn strip_server_file_expenstion(name: &str) -> String { @@ -25,8 +25,11 @@ pub fn render_epoch(value: &Value, _record: &Value) -> Result { if value.is_null() { return Ok(String::new()); } let text = match value.as_i64() { Some(epoch) => { - Local.timestamp(epoch, 0).format("%c").to_string() - } + match Local.timestamp_opt(epoch, 0) { + LocalResult::Single(epoch) => epoch.format("%c").to_string(), + _ => epoch.to_string(), + } + }, None => { value.to_string() }