* [pve-devel] [RFC proxmox-backup] avoid chrono dependency
@ 2020-09-13 14:42 Dietmar Maurer
0 siblings, 0 replies; only message in thread
From: Dietmar Maurer @ 2020-09-13 14:42 UTC (permalink / raw)
To: pve-devel
depend on proxmox 0.3.7
---
Cargo.toml | 3 +-
examples/download-speed.rs | 4 +-
examples/upload-speed.rs | 2 +-
src/api2/admin/datastore.rs | 28 ++---
src/api2/backup.rs | 2 +-
src/api2/node/time.rs | 10 +-
src/api2/reader.rs | 5 +-
src/backup/backup_info.rs | 56 ++++------
src/backup/catalog.rs | 11 +-
src/backup/crypt_config.rs | 5 +-
src/backup/datastore.rs | 3 +-
src/backup/fixed_index.rs | 15 +--
src/backup/key_derivation.rs | 17 ++-
src/backup/manifest.rs | 2 +-
src/backup/prune.rs | 29 +++--
src/bin/proxmox-backup-client.rs | 58 +++++-----
src/bin/proxmox_backup_client/benchmark.rs | 3 +-
src/bin/proxmox_backup_client/key.rs | 5 +-
src/client/backup_reader.rs | 5 +-
src/client/backup_writer.rs | 5 +-
src/client/http_client.rs | 5 +-
src/client/pull.rs | 2 +-
src/pxar/tools.rs | 10 +-
src/server/upid.rs | 3 +-
src/server/worker_task.rs | 11 +-
src/tools/file_logger.rs | 7 +-
src/tools/format.rs | 10 +-
src/tools/systemd.rs | 1 -
src/tools/systemd/time.rs | 5 +-
src/tools/systemd/tm_editor.rs | 119 ---------------------
30 files changed, 146 insertions(+), 295 deletions(-)
delete mode 100644 src/tools/systemd/tm_editor.rs
diff --git a/Cargo.toml b/Cargo.toml
index 0625ffb..17d9bb8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -18,7 +18,6 @@ apt-pkg-native = "0.3.1" # custom patched version
base64 = "0.12"
bitflags = "1.2.1"
bytes = "0.5"
-chrono = "0.4" # Date and time library for Rust
crc32fast = "1"
endian_trait = { version = "0.6", features = ["arrays"] }
anyhow = "1.0"
@@ -39,7 +38,7 @@ pam-sys = "0.5"
percent-encoding = "2.1"
pin-utils = "0.1.0"
pathpatterns = "0.1.2"
-proxmox = { version = "0.3.5", features = [ "sortable-macro", "api-macro", "websocket" ] }
+proxmox = { version = "0.3.7", features = [ "sortable-macro", "api-macro", "websocket" ] }
#proxmox = { git = "ssh://gitolite3@proxdev.maurer-it.com/rust/proxmox", version = "0.1.2", features = [ "sortable-macro", "api-macro" ] }
#proxmox = { path = "../proxmox/proxmox", features = [ "sortable-macro", "api-macro", "websocket" ] }
proxmox-fuse = "0.1.0"
diff --git a/examples/download-speed.rs b/examples/download-speed.rs
index 694c55d..0ec6cb6 100644
--- a/examples/download-speed.rs
+++ b/examples/download-speed.rs
@@ -2,8 +2,6 @@ use std::io::Write;
use anyhow::{Error};
-use chrono::{DateTime, Utc};
-
use proxmox_backup::api2::types::Userid;
use proxmox_backup::client::{HttpClient, HttpClientOptions, BackupReader};
@@ -36,7 +34,7 @@ async fn run() -> Result<(), Error> {
let client = HttpClient::new(host, username, options)?;
- let backup_time = "2019-06-28T10:49:48Z".parse::<DateTime<Utc>>()?;
+ let backup_time = proxmox::tools::time::parse_rfc3339("2019-06-28T10:49:48Z")?;
let client = BackupReader::start(client, None, "store2", "host", "elsa", backup_time, true)
.await?;
diff --git a/examples/upload-speed.rs b/examples/upload-speed.rs
index d67e9da..6be29b0 100644
--- a/examples/upload-speed.rs
+++ b/examples/upload-speed.rs
@@ -16,7 +16,7 @@ async fn upload_speed() -> Result<f64, Error> {
let client = HttpClient::new(host, username, options)?;
- let backup_time = chrono::Utc::now();
+ let backup_time = proxmox::tools::time::time()?;
let client = BackupWriter::start(client, None, datastore, "host", "speedtest", backup_time, false, true).await?;
diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index be2796d..acfc265 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -172,7 +172,7 @@ fn list_groups(
let result_item = GroupListItem {
backup_type: group.backup_type().to_string(),
backup_id: group.backup_id().to_string(),
- last_backup: info.backup_dir.backup_time().timestamp(),
+ last_backup: info.backup_dir.backup_time(),
backup_count: list.len() as u64,
files: info.files.clone(),
owner: Some(owner),
@@ -230,7 +230,7 @@ pub fn list_snapshot_files(
let datastore = DataStore::lookup_datastore(&store)?;
- let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let snapshot = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & (PRIV_DATASTORE_AUDIT | PRIV_DATASTORE_READ)) != 0;
if !allowed { check_backup_owner(&datastore, snapshot.group(), &userid)?; }
@@ -280,7 +280,7 @@ fn delete_snapshot(
let user_info = CachedUserInfo::new()?;
let user_privs = user_info.lookup_privs(&userid, &["datastore", &store]);
- let snapshot = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let snapshot = BackupDir::new(backup_type, backup_id, backup_time);
let datastore = DataStore::lookup_datastore(&store)?;
@@ -403,7 +403,7 @@ pub fn list_snapshots (
let result_item = SnapshotListItem {
backup_type: group.backup_type().to_string(),
backup_id: group.backup_id().to_string(),
- backup_time: info.backup_dir.backup_time().timestamp(),
+ backup_time: info.backup_dir.backup_time(),
comment,
verification,
files,
@@ -490,7 +490,7 @@ pub fn verify(
match (backup_type, backup_id, backup_time) {
(Some(backup_type), Some(backup_id), Some(backup_time)) => {
worker_id = format!("{}_{}_{}_{:08X}", store, backup_type, backup_id, backup_time);
- let dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let dir = BackupDir::new(backup_type, backup_id, backup_time);
backup_dir = Some(dir);
}
(Some(backup_type), Some(backup_id), None) => {
@@ -673,7 +673,7 @@ fn prune(
prune_result.push(json!({
"backup-type": group.backup_type(),
"backup-id": group.backup_id(),
- "backup-time": backup_time.timestamp(),
+ "backup-time": backup_time,
"keep": keep,
}));
}
@@ -714,7 +714,7 @@ fn prune(
prune_result.push(json!({
"backup-type": group.backup_type(),
"backup-id": group.backup_id(),
- "backup-time": backup_time.timestamp(),
+ "backup-time": backup_time,
"keep": keep,
}));
@@ -897,7 +897,7 @@ fn download_file(
let backup_id = tools::required_string_param(¶m, "backup-id")?;
let backup_time = tools::required_integer_param(¶m, "backup-time")?;
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
@@ -970,7 +970,7 @@ fn download_file_decoded(
let backup_id = tools::required_string_param(¶m, "backup-id")?;
let backup_time = tools::required_integer_param(¶m, "backup-time")?;
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
@@ -1083,7 +1083,7 @@ fn upload_backup_log(
let backup_id = tools::required_string_param(¶m, "backup-id")?;
let backup_time = tools::required_integer_param(¶m, "backup-time")?;
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let userid: Userid = rpcenv.get_user().unwrap().parse()?;
check_backup_owner(&datastore, backup_dir.group(), &userid)?;
@@ -1159,7 +1159,7 @@ fn catalog(
let user_info = CachedUserInfo::new()?;
let user_privs = user_info.lookup_privs(&userid, &["datastore", &store]);
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
@@ -1276,7 +1276,7 @@ fn pxar_file_download(
let backup_id = tools::required_string_param(¶m, "backup-id")?;
let backup_time = tools::required_integer_param(¶m, "backup-time")?;
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
@@ -1417,7 +1417,7 @@ fn get_notes(
let user_info = CachedUserInfo::new()?;
let user_privs = user_info.lookup_privs(&userid, &["datastore", &store]);
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
@@ -1470,7 +1470,7 @@ fn set_notes(
let user_info = CachedUserInfo::new()?;
let user_privs = user_info.lookup_privs(&userid, &["datastore", &store]);
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let allowed = (user_privs & PRIV_DATASTORE_READ) != 0;
if !allowed { check_backup_owner(&datastore, backup_dir.group(), &userid)?; }
diff --git a/src/api2/backup.rs b/src/api2/backup.rs
index 9420b14..c00f9be 100644
--- a/src/api2/backup.rs
+++ b/src/api2/backup.rs
@@ -114,7 +114,7 @@ async move {
}
let last_backup = BackupInfo::last_backup(&datastore.base_path(), &backup_group, true).unwrap_or(None);
- let backup_dir = BackupDir::new_with_group(backup_group.clone(), backup_time)?;
+ let backup_dir = BackupDir::new_with_group(backup_group.clone(), backup_time);
let _last_guard = if let Some(last) = &last_backup {
if backup_dir.backup_time() <= last.backup_dir.backup_time() {
diff --git a/src/api2/node/time.rs b/src/api2/node/time.rs
index a5afa40..49fe873 100644
--- a/src/api2/node/time.rs
+++ b/src/api2/node/time.rs
@@ -1,4 +1,3 @@
-use chrono::prelude::*;
use anyhow::{bail, format_err, Error};
use serde_json::{json, Value};
@@ -57,10 +56,11 @@ fn read_etc_localtime() -> Result<String, Error> {
)]
/// Read server time and time zone settings.
fn get_time(_param: Value) -> Result<Value, Error> {
- let datetime = Local::now();
- let offset = datetime.offset();
- let time = datetime.timestamp();
- let localtime = time + (offset.fix().local_minus_utc() as i64);
+ let time = proxmox::tools::time::time()?;
+ let tm = proxmox::tools::time::localtime(time)?;
+ let offset = tm.tm_gmtoff;
+
+ let localtime = time + offset;
Ok(json!({
"timezone": read_etc_localtime()?,
diff --git a/src/api2/reader.rs b/src/api2/reader.rs
index 5252d2e..c3dfa1a 100644
--- a/src/api2/reader.rs
+++ b/src/api2/reader.rs
@@ -1,4 +1,3 @@
-//use chrono::{Local, TimeZone};
use anyhow::{bail, format_err, Error};
use futures::*;
use hyper::header::{self, HeaderValue, UPGRADE};
@@ -83,12 +82,12 @@ fn upgrade_to_backup_reader_protocol(
let env_type = rpcenv.env_type();
- let backup_dir = BackupDir::new(backup_type, backup_id, backup_time)?;
+ let backup_dir = BackupDir::new(backup_type, backup_id, backup_time);
let path = datastore.base_path();
//let files = BackupInfo::list_files(&path, &backup_dir)?;
- let worker_id = format!("{}_{}_{}_{:08X}", store, backup_type, backup_id, backup_dir.backup_time().timestamp());
+ let worker_id = format!("{}_{}_{}_{:08X}", store, backup_type, backup_id, backup_dir.backup_time());
WorkerTask::spawn("reader", Some(worker_id), userid.clone(), true, move |worker| {
let mut env = ReaderEnvironment::new(
diff --git a/src/backup/backup_info.rs b/src/backup/backup_info.rs
index 023625f..63e8ee9 100644
--- a/src/backup/backup_info.rs
+++ b/src/backup/backup_info.rs
@@ -2,11 +2,8 @@ use crate::tools;
use anyhow::{bail, format_err, Error};
use regex::Regex;
-use std::convert::TryFrom;
use std::os::unix::io::RawFd;
-use chrono::{DateTime, LocalResult, TimeZone, SecondsFormat, Utc};
-
use std::path::{PathBuf, Path};
use lazy_static::lazy_static;
@@ -106,8 +103,8 @@ impl BackupGroup {
tools::scandir(libc::AT_FDCWD, &path, &BACKUP_DATE_REGEX, |l2_fd, backup_time, file_type| {
if file_type != nix::dir::Type::Directory { return Ok(()); }
- let dt = backup_time.parse::<DateTime<Utc>>()?;
- let backup_dir = BackupDir::new(self.backup_type.clone(), self.backup_id.clone(), dt.timestamp())?;
+ let timestamp = proxmox::tools::time::parse_rfc3339(backup_time)?;
+ let backup_dir = BackupDir::new(self.backup_type.clone(), self.backup_id.clone(), timestamp);
let files = list_backup_files(l2_fd, backup_time)?;
list.push(BackupInfo { backup_dir, files });
@@ -117,7 +114,7 @@ impl BackupGroup {
Ok(list)
}
- pub fn last_successful_backup(&self, base_path: &Path) -> Result<Option<DateTime<Utc>>, Error> {
+ pub fn last_successful_backup(&self, base_path: &Path) -> Result<Option<i64>, Error> {
let mut last = None;
@@ -143,11 +140,11 @@ impl BackupGroup {
}
}
- let dt = backup_time.parse::<DateTime<Utc>>()?;
- if let Some(last_dt) = last {
- if dt > last_dt { last = Some(dt); }
+ let timestamp = proxmox::tools::time::parse_rfc3339(backup_time)?;
+ if let Some(last_timestamp) = last {
+ if timestamp > last_timestamp { last = Some(timestamp); }
} else {
- last = Some(dt);
+ last = Some(timestamp);
}
Ok(())
@@ -204,34 +201,29 @@ pub struct BackupDir {
/// Backup group
group: BackupGroup,
/// Backup timestamp
- backup_time: DateTime<Utc>,
+ backup_time: i64,
}
impl BackupDir {
- pub fn new<T, U>(backup_type: T, backup_id: U, timestamp: i64) -> Result<Self, Error>
+ pub fn new<T, U>(backup_type: T, backup_id: U, backup_time: i64) -> Self
where
T: Into<String>,
U: Into<String>,
{
let group = BackupGroup::new(backup_type.into(), backup_id.into());
- BackupDir::new_with_group(group, timestamp)
+ BackupDir::new_with_group(group, backup_time)
}
- pub fn new_with_group(group: BackupGroup, timestamp: i64) -> Result<Self, Error> {
- let backup_time = match Utc.timestamp_opt(timestamp, 0) {
- LocalResult::Single(time) => time,
- _ => bail!("can't create BackupDir with invalid backup time {}", timestamp),
- };
-
- Ok(Self { group, backup_time })
+ pub fn new_with_group(group: BackupGroup, backup_time: i64) -> Self {
+ Self { group, backup_time }
}
pub fn group(&self) -> &BackupGroup {
&self.group
}
- pub fn backup_time(&self) -> DateTime<Utc> {
+ pub fn backup_time(&self) -> i64 {
self.backup_time
}
@@ -244,8 +236,9 @@ impl BackupDir {
relative_path
}
- pub fn backup_time_to_string(backup_time: DateTime<Utc>) -> String {
- backup_time.to_rfc3339_opts(SecondsFormat::Secs, true)
+ pub fn backup_time_to_string(backup_time: i64) -> String {
+ // fixme: can this fail? (avoid unwrap)
+ proxmox::tools::time::epoch_to_rfc3339_utc(backup_time).unwrap()
}
}
@@ -260,8 +253,8 @@ impl std::str::FromStr for BackupDir {
.ok_or_else(|| format_err!("unable to parse backup snapshot path '{}'", path))?;
let group = BackupGroup::new(cap.get(1).unwrap().as_str(), cap.get(2).unwrap().as_str());
- let backup_time = cap.get(3).unwrap().as_str().parse::<DateTime<Utc>>()?;
- BackupDir::try_from((group, backup_time.timestamp()))
+ let backup_time = proxmox::tools::time::parse_rfc3339(cap.get(3).unwrap().as_str())?;
+ Ok(BackupDir { group, backup_time })
}
}
@@ -274,14 +267,6 @@ impl std::fmt::Display for BackupDir {
}
}
-impl TryFrom<(BackupGroup, i64)> for BackupDir {
- type Error = Error;
-
- fn try_from((group, timestamp): (BackupGroup, i64)) -> Result<Self, Error> {
- BackupDir::new_with_group(group, timestamp)
- }
-}
-
/// Detailed Backup Information, lists files inside a BackupDir
#[derive(Debug, Clone)]
pub struct BackupInfo {
@@ -339,8 +324,9 @@ impl BackupInfo {
tools::scandir(l1_fd, backup_id, &BACKUP_DATE_REGEX, |l2_fd, backup_time, file_type| {
if file_type != nix::dir::Type::Directory { return Ok(()); }
- let dt = backup_time.parse::<DateTime<Utc>>()?;
- let backup_dir = BackupDir::new(backup_type, backup_id, dt.timestamp())?;
+ let timestamp = proxmox::tools::time::parse_rfc3339(backup_time)?;
+
+ let backup_dir = BackupDir::new(backup_type, backup_id, timestamp);
let files = list_backup_files(l2_fd, backup_time)?;
diff --git a/src/backup/catalog.rs b/src/backup/catalog.rs
index 85a3262..a1610b6 100644
--- a/src/backup/catalog.rs
+++ b/src/backup/catalog.rs
@@ -5,7 +5,6 @@ use std::io::{Read, Write, Seek, SeekFrom};
use std::os::unix::ffi::OsStrExt;
use anyhow::{bail, format_err, Error};
-use chrono::offset::{TimeZone, Local, LocalResult};
use pathpatterns::{MatchList, MatchType};
use proxmox::tools::io::ReadExt;
@@ -533,10 +532,12 @@ impl <R: Read + Seek> CatalogReader<R> {
self.dump_dir(&path, pos)?;
}
CatalogEntryType::File => {
- let mtime_string = match Local.timestamp_opt(mtime as i64, 0) {
- LocalResult::Single(time) => time.to_rfc3339_opts(chrono::SecondsFormat::Secs, false),
- _ => (mtime as i64).to_string(),
- };
+ let mut mtime_string = mtime.to_string();
+ if let Ok(localtime) = proxmox::tools::time::localtime(mtime as i64) {
+ if let Ok(s) = proxmox::tools::time::strftime("%FT%TZ", &localtime) {
+ mtime_string = s;
+ }
+ }
println!(
"{} {:?} {} {}",
diff --git a/src/backup/crypt_config.rs b/src/backup/crypt_config.rs
index c30fb5f..d2660f3 100644
--- a/src/backup/crypt_config.rs
+++ b/src/backup/crypt_config.rs
@@ -10,7 +10,6 @@
use std::io::Write;
use anyhow::{bail, Error};
-use chrono::{Local, DateTime};
use openssl::hash::MessageDigest;
use openssl::pkcs5::pbkdf2_hmac;
use openssl::symm::{decrypt_aead, Cipher, Crypter, Mode};
@@ -216,10 +215,10 @@ impl CryptConfig {
pub fn generate_rsa_encoded_key(
&self,
rsa: openssl::rsa::Rsa<openssl::pkey::Public>,
- created: DateTime<Local>,
+ created: i64,
) -> Result<Vec<u8>, Error> {
- let modified = Local::now();
+ let modified = proxmox::tools::time::time()?;
let key_config = super::KeyConfig { kdf: None, created, modified, data: self.enc_key.to_vec() };
let data = serde_json::to_string(&key_config)?.as_bytes().to_vec();
diff --git a/src/backup/datastore.rs b/src/backup/datastore.rs
index ebe4748..46a5069 100644
--- a/src/backup/datastore.rs
+++ b/src/backup/datastore.rs
@@ -6,7 +6,6 @@ use std::convert::TryFrom;
use anyhow::{bail, format_err, Error};
use lazy_static::lazy_static;
-use chrono::{DateTime, Utc};
use serde_json::Value;
use proxmox::tools::fs::{replace_file, CreateOptions};
@@ -242,7 +241,7 @@ impl DataStore {
/// Returns the time of the last successful backup
///
/// Or None if there is no backup in the group (or the group dir does not exist).
- pub fn last_successful_backup(&self, backup_group: &BackupGroup) -> Result<Option<DateTime<Utc>>, Error> {
+ pub fn last_successful_backup(&self, backup_group: &BackupGroup) -> Result<Option<i64>, Error> {
let base_path = self.base_path();
let mut group_path = base_path.clone();
group_path.push(backup_group.group_path());
diff --git a/src/backup/fixed_index.rs b/src/backup/fixed_index.rs
index 309f450..e1b47ad 100644
--- a/src/backup/fixed_index.rs
+++ b/src/backup/fixed_index.rs
@@ -6,7 +6,6 @@ use super::chunk_store::*;
use super::{IndexFile, ChunkReadInfo};
use crate::tools::{self, epoch_now_u64};
-use chrono::{Local, LocalResult, TimeZone};
use std::fs::File;
use std::io::Write;
use std::os::unix::io::AsRawFd;
@@ -148,13 +147,15 @@ impl FixedIndexReader {
pub fn print_info(&self) {
println!("Size: {}", self.size);
println!("ChunkSize: {}", self.chunk_size);
- println!(
- "CTime: {}",
- match Local.timestamp_opt(self.ctime as i64, 0) {
- LocalResult::Single(ctime) => ctime.format("%c").to_string(),
- _ => (self.ctime as i64).to_string(),
+
+ let mut ctime_str = self.ctime.to_string();
+ if let Ok(localtime) = proxmox::tools::time::localtime(self.ctime as i64) {
+ if let Ok(s) = proxmox::tools::time::strftime("%c", &localtime) {
+ ctime_str = s;
}
- );
+ }
+
+ println!("CTime: {}", ctime_str);
println!("UUID: {:?}", self.uuid);
}
}
diff --git a/src/backup/key_derivation.rs b/src/backup/key_derivation.rs
index ac27da6..6362047 100644
--- a/src/backup/key_derivation.rs
+++ b/src/backup/key_derivation.rs
@@ -1,7 +1,6 @@
use anyhow::{bail, format_err, Context, Error};
use serde::{Deserialize, Serialize};
-use chrono::{Local, DateTime};
use proxmox::tools::fs::{file_get_contents, replace_file, CreateOptions};
use proxmox::try_block;
@@ -61,10 +60,10 @@ impl KeyDerivationConfig {
#[derive(Deserialize, Serialize, Debug)]
pub struct KeyConfig {
pub kdf: Option<KeyDerivationConfig>,
- #[serde(with = "proxmox::tools::serde::date_time_as_rfc3339")]
- pub created: DateTime<Local>,
- #[serde(with = "proxmox::tools::serde::date_time_as_rfc3339")]
- pub modified: DateTime<Local>,
+ #[serde(with = "proxmox::tools::serde::epoch_as_rfc3339")]
+ pub created: i64,
+ #[serde(with = "proxmox::tools::serde::epoch_as_rfc3339")]
+ pub modified: i64,
#[serde(with = "proxmox::tools::serde::bytes_as_base64")]
pub data: Vec<u8>,
}
@@ -136,7 +135,7 @@ pub fn encrypt_key_with_passphrase(
enc_data.extend_from_slice(&tag);
enc_data.extend_from_slice(&encrypted_key);
- let created = Local::now();
+ let created = proxmox::tools::time::time()?;
Ok(KeyConfig {
kdf: Some(kdf),
@@ -149,7 +148,7 @@ pub fn encrypt_key_with_passphrase(
pub fn load_and_decrypt_key(
path: &std::path::Path,
passphrase: &dyn Fn() -> Result<Vec<u8>, Error>,
-) -> Result<([u8;32], DateTime<Local>), Error> {
+) -> Result<([u8;32], i64), Error> {
do_load_and_decrypt_key(path, passphrase)
.with_context(|| format!("failed to load decryption key from {:?}", path))
}
@@ -157,14 +156,14 @@ pub fn load_and_decrypt_key(
fn do_load_and_decrypt_key(
path: &std::path::Path,
passphrase: &dyn Fn() -> Result<Vec<u8>, Error>,
-) -> Result<([u8;32], DateTime<Local>), Error> {
+) -> Result<([u8;32], i64), Error> {
decrypt_key(&file_get_contents(&path)?, passphrase)
}
pub fn decrypt_key(
mut keydata: &[u8],
passphrase: &dyn Fn() -> Result<Vec<u8>, Error>,
-) -> Result<([u8;32], DateTime<Local>), Error> {
+) -> Result<([u8;32], i64), Error> {
let key_config: KeyConfig = serde_json::from_reader(&mut keydata)?;
let raw_data = key_config.data;
diff --git a/src/backup/manifest.rs b/src/backup/manifest.rs
index ed5e2a2..609cc99 100644
--- a/src/backup/manifest.rs
+++ b/src/backup/manifest.rs
@@ -103,7 +103,7 @@ impl BackupManifest {
Self {
backup_type: snapshot.group().backup_type().into(),
backup_id: snapshot.group().backup_id().into(),
- backup_time: snapshot.backup_time().timestamp(),
+ backup_time: snapshot.backup_time(),
files: Vec::new(),
unprotected: json!({}),
signature: None,
diff --git a/src/backup/prune.rs b/src/backup/prune.rs
index f7a87c5..ce60129 100644
--- a/src/backup/prune.rs
+++ b/src/backup/prune.rs
@@ -2,13 +2,11 @@ use anyhow::{Error};
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
-use chrono::{DateTime, Timelike, Datelike, Local};
-
use super::{BackupDir, BackupInfo};
enum PruneMark { Keep, KeepPartial, Remove }
-fn mark_selections<F: Fn(DateTime<Local>, &BackupInfo) -> String> (
+fn mark_selections<F: Fn(libc::tm, &BackupInfo) -> String> (
mark: &mut HashMap<PathBuf, PruneMark>,
list: &Vec<BackupInfo>,
keep: usize,
@@ -21,7 +19,8 @@ fn mark_selections<F: Fn(DateTime<Local>, &BackupInfo) -> String> (
for info in list {
let backup_id = info.backup_dir.relative_path();
if let Some(PruneMark::Keep) = mark.get(&backup_id) {
- let local_time = info.backup_dir.backup_time().with_timezone(&Local);
+ // fixme: avoid unwrap here?
+ let local_time = proxmox::tools::time::localtime(info.backup_dir.backup_time()).unwrap();
let sel_id: String = select_id(local_time, &info);
already_included.insert(sel_id);
}
@@ -30,7 +29,8 @@ fn mark_selections<F: Fn(DateTime<Local>, &BackupInfo) -> String> (
for info in list {
let backup_id = info.backup_dir.relative_path();
if let Some(_) = mark.get(&backup_id) { continue; }
- let local_time = info.backup_dir.backup_time().with_timezone(&Local);
+ // fixme: avoid unwrap here?
+ let local_time = proxmox::tools::time::localtime(info.backup_dir.backup_time()).unwrap();
let sel_id: String = select_id(local_time, &info);
if already_included.contains(&sel_id) { continue; }
@@ -181,6 +181,7 @@ pub fn compute_prune_info(
remove_incomplete_snapshots(&mut mark, &list);
+ // fixme: avoid unwrap
if let Some(keep_last) = options.keep_last {
mark_selections(&mut mark, &list, keep_last as usize, |_local_time, info| {
BackupDir::backup_time_to_string(info.backup_dir.backup_time())
@@ -189,36 +190,34 @@ pub fn compute_prune_info(
if let Some(keep_hourly) = options.keep_hourly {
mark_selections(&mut mark, &list, keep_hourly as usize, |local_time, _info| {
- format!("{}/{}/{}/{}", local_time.year(), local_time.month(),
- local_time.day(), local_time.hour())
+ proxmox::tools::time::strftime("%Y/%m/%d/%H", &local_time).unwrap()
});
}
if let Some(keep_daily) = options.keep_daily {
mark_selections(&mut mark, &list, keep_daily as usize, |local_time, _info| {
- format!("{}/{}/{}", local_time.year(), local_time.month(), local_time.day())
+ proxmox::tools::time::strftime("%Y/%m/%d", &local_time).unwrap()
});
}
if let Some(keep_weekly) = options.keep_weekly {
mark_selections(&mut mark, &list, keep_weekly as usize, |local_time, _info| {
- let iso_week = local_time.iso_week();
- let week = iso_week.week();
- // Note: This year number might not match the calendar year number.
- let iso_week_year = iso_week.year();
- format!("{}/{}", iso_week_year, week)
+ // Note: Use iso-week year/week here. This year number
+ // might not match the calendar year number.
+ proxmox::tools::time::strftime("%G/%V", &local_time).unwrap()
});
}
if let Some(keep_monthly) = options.keep_monthly {
mark_selections(&mut mark, &list, keep_monthly as usize, |local_time, _info| {
- format!("{}/{}", local_time.year(), local_time.month())
+ proxmox::tools::time::strftime("%Y/%m", &local_time).unwrap()
});
}
if let Some(keep_yearly) = options.keep_yearly {
mark_selections(&mut mark, &list, keep_yearly as usize, |local_time, _info| {
- format!("{}/{}", local_time.year(), local_time.year())
+ // fixme: why "%Y/%Y"
+ proxmox::tools::time::strftime("%Y/%Y", &local_time).unwrap()
});
}
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index fa13203..bd488b4 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -8,7 +8,6 @@ use std::sync::{Arc, Mutex};
use std::task::Context;
use anyhow::{bail, format_err, Error};
-use chrono::{Local, LocalResult, DateTime, Utc, TimeZone};
use futures::future::FutureExt;
use futures::stream::{StreamExt, TryStreamExt};
use serde_json::{json, Value};
@@ -246,7 +245,7 @@ pub async fn api_datastore_latest_snapshot(
client: &HttpClient,
store: &str,
group: BackupGroup,
-) -> Result<(String, String, DateTime<Utc>), Error> {
+) -> Result<(String, String, i64), Error> {
let list = api_datastore_list_snapshots(client, store, Some(group.clone())).await?;
let mut list: Vec<SnapshotListItem> = serde_json::from_value(list)?;
@@ -257,11 +256,7 @@ pub async fn api_datastore_latest_snapshot(
list.sort_unstable_by(|a, b| b.backup_time.cmp(&a.backup_time));
- 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),
- };
+ let backup_time = list[0].backup_time;
Ok((group.backup_type().to_owned(), group.backup_id().to_owned(), backup_time))
}
@@ -377,7 +372,7 @@ async fn list_backup_groups(param: Value) -> Result<Value, Error> {
let render_last_backup = |_v: &Value, record: &Value| -> Result<String, Error> {
let item: GroupListItem = serde_json::from_value(record.to_owned())?;
- let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.last_backup)?;
+ let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.last_backup);
Ok(snapshot.relative_path().to_str().unwrap().to_owned())
};
@@ -448,7 +443,7 @@ async fn list_snapshots(param: Value) -> Result<Value, Error> {
let render_snapshot_path = |_v: &Value, record: &Value| -> Result<String, Error> {
let item: SnapshotListItem = serde_json::from_value(record.to_owned())?;
- let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time)?;
+ let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time);
Ok(snapshot.relative_path().to_str().unwrap().to_owned())
};
@@ -506,7 +501,7 @@ async fn forget_snapshots(param: Value) -> Result<Value, Error> {
let result = client.delete(&path, Some(json!({
"backup-type": snapshot.group().backup_type(),
"backup-id": snapshot.group().backup_id(),
- "backup-time": snapshot.backup_time().timestamp(),
+ "backup-time": snapshot.backup_time(),
}))).await?;
record_repository(&repo);
@@ -643,7 +638,7 @@ async fn list_snapshot_files(param: Value) -> Result<Value, Error> {
let mut result = client.get(&path, Some(json!({
"backup-type": snapshot.group().backup_type(),
"backup-id": snapshot.group().backup_id(),
- "backup-time": snapshot.backup_time().timestamp(),
+ "backup-time": snapshot.backup_time(),
}))).await?;
record_repository(&repo);
@@ -990,15 +985,9 @@ async fn create_backup(
}
}
- 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 backup_time = backup_time_opt.unwrap_or_else(|| {
+ proxmox::tools::time::time().unwrap()
+ });
let client = connect(repo.host(), repo.user())?;
record_repository(&repo);
@@ -1007,9 +996,12 @@ async fn create_backup(
println!("Client name: {}", proxmox::tools::nodename());
- let start_time = Local::now();
+ let start_time = std::time::Instant::now();
- println!("Starting protocol: {}", start_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, false));
+ { // Note:: limit scope, because libc::tm is not Send
+ let localtime = proxmox::tools::time::localtime(proxmox::tools::time::time()?)?;
+ println!("Starting backup protocol: {}", proxmox::tools::time::strftime("%c", &localtime)?);
+ }
let (crypt_config, rsa_encrypted_key) = match keydata {
None => (None, None),
@@ -1047,7 +1039,7 @@ async fn create_backup(
None
};
- let snapshot = BackupDir::new(backup_type, backup_id, backup_time.timestamp())?;
+ let snapshot = BackupDir::new(backup_type, backup_id, backup_time);
let mut manifest = BackupManifest::new(snapshot);
let mut catalog = None;
@@ -1162,11 +1154,12 @@ async fn create_backup(
client.finish().await?;
- let end_time = Local::now();
- let elapsed = end_time.signed_duration_since(start_time);
- println!("Duration: {}", elapsed);
+ let end_time = std::time::Instant::now();
+ let elapsed = end_time.duration_since(start_time);
+ println!("Duration: {:.2}s", elapsed.as_secs_f64());
- println!("End Time: {}", end_time.to_rfc3339_opts(chrono::SecondsFormat::Secs, false));
+ let localtime = proxmox::tools::time::localtime(proxmox::tools::time::time()?)?;
+ println!("End Time: {}", proxmox::tools::time::strftime("%c", &localtime)?);
Ok(Value::Null)
}
@@ -1504,7 +1497,7 @@ async fn upload_log(param: Value) -> Result<Value, Error> {
let args = json!({
"backup-type": snapshot.group().backup_type(),
"backup-id": snapshot.group().backup_id(),
- "backup-time": snapshot.backup_time().timestamp(),
+ "backup-time": snapshot.backup_time(),
});
let body = hyper::Body::from(raw_data);
@@ -1572,7 +1565,7 @@ async fn prune_async(mut param: Value) -> Result<Value, Error> {
let render_snapshot_path = |_v: &Value, record: &Value| -> Result<String, Error> {
let item: PruneListItem = serde_json::from_value(record.to_owned())?;
- let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time)?;
+ let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time);
Ok(snapshot.relative_path().to_str().unwrap().to_owned())
};
@@ -1764,9 +1757,8 @@ async fn complete_backup_snapshot_do(param: &HashMap<String, String>) -> Vec<Str
if let (Some(backup_id), Some(backup_type), Some(backup_time)) =
(item["backup-id"].as_str(), item["backup-type"].as_str(), item["backup-time"].as_i64())
{
- if let Ok(snapshot) = BackupDir::new(backup_type, backup_id, backup_time) {
- result.push(snapshot.relative_path().to_str().unwrap().to_owned());
- }
+ let snapshot = BackupDir::new(backup_type, backup_id, backup_time);
+ result.push(snapshot.relative_path().to_str().unwrap().to_owned());
}
}
}
@@ -1800,7 +1792,7 @@ async fn complete_server_file_name_do(param: &HashMap<String, String>) -> Vec<St
let query = tools::json_object_to_query(json!({
"backup-type": snapshot.group().backup_type(),
"backup-id": snapshot.group().backup_id(),
- "backup-time": snapshot.backup_time().timestamp(),
+ "backup-time": snapshot.backup_time(),
})).unwrap();
let path = format!("api2/json/admin/datastore/{}/files?{}", repo.store(), query);
diff --git a/src/bin/proxmox_backup_client/benchmark.rs b/src/bin/proxmox_backup_client/benchmark.rs
index 9830c18..215da50 100644
--- a/src/bin/proxmox_backup_client/benchmark.rs
+++ b/src/bin/proxmox_backup_client/benchmark.rs
@@ -3,7 +3,6 @@ use std::sync::Arc;
use anyhow::{Error};
use serde_json::Value;
-use chrono::Utc;
use serde::Serialize;
use proxmox::api::{ApiMethod, RpcEnvironment};
@@ -212,7 +211,7 @@ async fn test_upload_speed(
verbose: bool,
) -> Result<(), Error> {
- let backup_time = Utc::now();
+ let backup_time = proxmox::tools::time::time()?;
let client = connect(repo.host(), repo.user())?;
record_repository(&repo);
diff --git a/src/bin/proxmox_backup_client/key.rs b/src/bin/proxmox_backup_client/key.rs
index 30afa4e..14b4767 100644
--- a/src/bin/proxmox_backup_client/key.rs
+++ b/src/bin/proxmox_backup_client/key.rs
@@ -1,7 +1,6 @@
use std::path::PathBuf;
use anyhow::{bail, format_err, Error};
-use chrono::Local;
use serde::{Deserialize, Serialize};
use proxmox::api::api;
@@ -112,7 +111,7 @@ fn create(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error> {
match kdf {
Kdf::None => {
- let created = Local::now();
+ let created = proxmox::tools::time::time()?;
store_key_config(
&path,
@@ -180,7 +179,7 @@ fn change_passphrase(kdf: Option<Kdf>, path: Option<String>) -> Result<(), Error
match kdf {
Kdf::None => {
- let modified = Local::now();
+ let modified = proxmox::tools::time::time()?;
store_key_config(
&path,
diff --git a/src/client/backup_reader.rs b/src/client/backup_reader.rs
index d418571..5f002e2 100644
--- a/src/client/backup_reader.rs
+++ b/src/client/backup_reader.rs
@@ -4,7 +4,6 @@ use std::fs::File;
use std::sync::Arc;
use std::os::unix::fs::OpenOptionsExt;
-use chrono::{DateTime, Utc};
use futures::future::AbortHandle;
use serde_json::{json, Value};
@@ -41,14 +40,14 @@ impl BackupReader {
datastore: &str,
backup_type: &str,
backup_id: &str,
- backup_time: DateTime<Utc>,
+ backup_time: i64,
debug: bool,
) -> Result<Arc<BackupReader>, Error> {
let param = json!({
"backup-type": backup_type,
"backup-id": backup_id,
- "backup-time": backup_time.timestamp(),
+ "backup-time": backup_time,
"store": datastore,
"debug": debug,
});
diff --git a/src/client/backup_writer.rs b/src/client/backup_writer.rs
index 64c3cf2..e071911 100644
--- a/src/client/backup_writer.rs
+++ b/src/client/backup_writer.rs
@@ -4,7 +4,6 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex};
use anyhow::{bail, format_err, Error};
-use chrono::{DateTime, Utc};
use futures::*;
use futures::stream::Stream;
use futures::future::AbortHandle;
@@ -51,7 +50,7 @@ impl BackupWriter {
datastore: &str,
backup_type: &str,
backup_id: &str,
- backup_time: DateTime<Utc>,
+ backup_time: i64,
debug: bool,
benchmark: bool
) -> Result<Arc<BackupWriter>, Error> {
@@ -59,7 +58,7 @@ impl BackupWriter {
let param = json!({
"backup-type": backup_type,
"backup-id": backup_id,
- "backup-time": backup_time.timestamp(),
+ "backup-time": backup_time,
"store": datastore,
"debug": debug,
"benchmark": benchmark
diff --git a/src/client/http_client.rs b/src/client/http_client.rs
index ae3704d..f1b8287 100644
--- a/src/client/http_client.rs
+++ b/src/client/http_client.rs
@@ -2,7 +2,6 @@ use std::io::Write;
use std::task::{Context, Poll};
use std::sync::{Arc, Mutex};
-use chrono::Utc;
use anyhow::{bail, format_err, Error};
use futures::*;
use http::Uri;
@@ -199,7 +198,7 @@ fn store_ticket_info(prefix: &str, server: &str, username: &str, ticket: &str, t
let mut data = file_get_json(&path, Some(json!({})))?;
- let now = Utc::now().timestamp();
+ let now = proxmox::tools::time::time()?;
data[server][username] = json!({ "timestamp": now, "ticket": ticket, "token": token});
@@ -230,7 +229,7 @@ fn load_ticket_info(prefix: &str, server: &str, userid: &Userid) -> Option<(Stri
// usually /run/user/<uid>/...
let path = base.place_runtime_file("tickets").ok()?;
let data = file_get_json(&path, None).ok()?;
- let now = Utc::now().timestamp();
+ let now = proxmox::tools::time::time().ok()?;
let ticket_lifetime = tools::ticket::TICKET_LIFETIME - 60;
let uinfo = data[server][userid.as_str()].as_object()?;
let timestamp = uinfo["timestamp"].as_i64()?;
diff --git a/src/client/pull.rs b/src/client/pull.rs
index ab7e989..2428051 100644
--- a/src/client/pull.rs
+++ b/src/client/pull.rs
@@ -347,7 +347,7 @@ pub async fn pull_group(
let mut remote_snapshots = std::collections::HashSet::new();
for item in list {
- let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time)?;
+ let snapshot = BackupDir::new(item.backup_type, item.backup_id, item.backup_time);
// in-progress backups can't be synced
if let None = item.size {
diff --git a/src/pxar/tools.rs b/src/pxar/tools.rs
index 2eed0f8..9be9148 100644
--- a/src/pxar/tools.rs
+++ b/src/pxar/tools.rs
@@ -115,12 +115,12 @@ fn mode_string(entry: &Entry) -> String {
}
fn format_mtime(mtime: &StatxTimestamp) -> String {
- use chrono::offset::TimeZone;
-
- match chrono::Local.timestamp_opt(mtime.secs, mtime.nanos) {
- chrono::LocalResult::Single(mtime) => mtime.format("%Y-%m-%d %H:%M:%S").to_string(),
- _ => format!("{}.{}", mtime.secs, mtime.nanos),
+ if let Ok(localtime) = proxmox::tools::time::localtime(mtime.secs) {
+ if let Ok(s) = proxmox::tools::time::strftime("%Y-%m-%d %H:%M:%S", &localtime) {
+ return s;
+ }
}
+ format!("{}.{}", mtime.secs, mtime.nanos)
}
pub fn format_single_line_entry(entry: &Entry) -> String {
diff --git a/src/server/upid.rs b/src/server/upid.rs
index 9fc5085..d0f0d16 100644
--- a/src/server/upid.rs
+++ b/src/server/upid.rs
@@ -1,7 +1,6 @@
use std::sync::atomic::{AtomicUsize, Ordering};
use anyhow::{bail, Error};
-use chrono::Local;
use proxmox::api::schema::{ApiStringFormat, Schema, StringSchema};
use proxmox::const_regex;
@@ -89,7 +88,7 @@ impl UPID {
Ok(UPID {
pid,
pstart: procfs::PidStat::read_from_pid(nix::unistd::Pid::from_raw(pid))?.starttime,
- starttime: Local::now().timestamp(),
+ starttime: proxmox::tools::time::time()?,
task_id,
worker_type: worker_type.to_owned(),
worker_id,
diff --git a/src/server/worker_task.rs b/src/server/worker_task.rs
index 28e62ba..21e407f 100644
--- a/src/server/worker_task.rs
+++ b/src/server/worker_task.rs
@@ -5,7 +5,6 @@ use std::panic::UnwindSafe;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex};
-use chrono::Local;
use anyhow::{bail, format_err, Error};
use futures::*;
use lazy_static::lazy_static;
@@ -231,9 +230,7 @@ pub fn upid_read_status(upid: &UPID) -> Result<TaskState, Error> {
let mut iter = last_line.splitn(2, ": ");
if let Some(time_str) = iter.next() {
- if let Ok(endtime) = chrono::DateTime::parse_from_rfc3339(time_str) {
- let endtime = endtime.timestamp();
-
+ if let Ok(endtime) = proxmox::tools::time::parse_rfc3339(time_str) {
if let Some(rest) = iter.next().and_then(|rest| rest.strip_prefix("TASK ")) {
if let Ok(state) = TaskState::from_endtime_and_message(endtime, rest) {
status = state;
@@ -364,8 +361,9 @@ fn update_active_workers(new_upid: Option<&UPID>) -> Result<Vec<TaskListInfo>, E
},
None => {
println!("Detected stopped UPID {}", upid_str);
+ let now = proxmox::tools::time::time()?;
let status = upid_read_status(&upid)
- .unwrap_or_else(|_| TaskState::Unknown { endtime: Local::now().timestamp() });
+ .unwrap_or_else(|_| TaskState::Unknown { endtime: now });
finish_list.push(TaskListInfo {
upid, upid_str, state: Some(status)
});
@@ -589,7 +587,8 @@ impl WorkerTask {
pub fn create_state(&self, result: &Result<(), Error>) -> TaskState {
let warn_count = self.data.lock().unwrap().warn_count;
- let endtime = Local::now().timestamp();
+ // fixme: avoid unwrap
+ let endtime = proxmox::tools::time::time().unwrap();
if let Err(err) = result {
TaskState::Error { message: err.to_string(), endtime }
diff --git a/src/tools/file_logger.rs b/src/tools/file_logger.rs
index c0fcab7..c8aae5e 100644
--- a/src/tools/file_logger.rs
+++ b/src/tools/file_logger.rs
@@ -1,5 +1,4 @@
use anyhow::{Error};
-use chrono::Local;
use std::io::Write;
/// Log messages with timestamps into files
@@ -56,7 +55,11 @@ impl FileLogger {
stdout.write_all(b"\n").unwrap();
}
- let line = format!("{}: {}\n", Local::now().to_rfc3339(), msg);
+ // fixme: avoid unwrap
+ let now = proxmox::tools::time::time().unwrap();
+ let rfc3339 = proxmox::tools::time::epoch_to_rfc3339(now).unwrap();
+
+ let line = format!("{}: {}\n", rfc3339, msg);
self.file.write_all(line.as_bytes()).unwrap();
}
}
diff --git a/src/tools/format.rs b/src/tools/format.rs
index 1e593ff..f09a922 100644
--- a/src/tools/format.rs
+++ b/src/tools/format.rs
@@ -1,6 +1,5 @@
use anyhow::{Error};
use serde_json::Value;
-use chrono::{Local, TimeZone, LocalResult};
pub fn strip_server_file_expenstion(name: &str) -> String {
@@ -25,10 +24,13 @@ pub fn render_epoch(value: &Value, _record: &Value) -> Result<String, Error> {
if value.is_null() { return Ok(String::new()); }
let text = match value.as_i64() {
Some(epoch) => {
- match Local.timestamp_opt(epoch, 0) {
- LocalResult::Single(epoch) => epoch.format("%c").to_string(),
- _ => epoch.to_string(),
+ let mut epoch_string = epoch.to_string();
+ if let Ok(localtime) = proxmox::tools::time::localtime(epoch as i64) {
+ if let Ok(s) = proxmox::tools::time::strftime("%c", &localtime) {
+ epoch_string = s;
+ }
}
+ epoch_string
},
None => {
value.to_string()
diff --git a/src/tools/systemd.rs b/src/tools/systemd.rs
index 9a6439d..8f0a66d 100644
--- a/src/tools/systemd.rs
+++ b/src/tools/systemd.rs
@@ -2,7 +2,6 @@ pub mod types;
pub mod config;
mod parse_time;
-pub mod tm_editor;
pub mod time;
use anyhow::{bail, Error};
diff --git a/src/tools/systemd/time.rs b/src/tools/systemd/time.rs
index f76731f..1961d4b 100644
--- a/src/tools/systemd/time.rs
+++ b/src/tools/systemd/time.rs
@@ -3,8 +3,9 @@ use std::convert::TryInto;
use anyhow::Error;
use bitflags::bitflags;
+use proxmox::tools::time::TmEditor;
+
pub use super::parse_time::*;
-use super::tm_editor::*;
bitflags!{
#[derive(Default)]
@@ -161,7 +162,7 @@ pub fn compute_next_event(
let all_days = event.days.is_empty() || event.days.is_all();
- let mut t = TmEditor::new(last, utc)?;
+ let mut t = TmEditor::with_epoch(last, utc)?;
let mut count = 0;
diff --git a/src/tools/systemd/tm_editor.rs b/src/tools/systemd/tm_editor.rs
deleted file mode 100644
index 770bb28..0000000
--- a/src/tools/systemd/tm_editor.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-use anyhow::Error;
-
-use proxmox::tools::time::*;
-
-pub struct TmEditor {
- utc: bool,
- t: libc::tm,
-}
-
-impl TmEditor {
-
- pub fn new(epoch: i64, utc: bool) -> Result<Self, Error> {
- let t = if utc { gmtime(epoch)? } else { localtime(epoch)? };
- Ok(Self { utc, t })
- }
-
- pub fn into_epoch(mut self) -> Result<i64, Error> {
- let epoch = if self.utc { timegm(&mut self.t)? } else { timelocal(&mut self.t)? };
- Ok(epoch)
- }
-
- /// increases the year by 'years' and resets all smaller fields to their minimum
- pub fn add_years(&mut self, years: libc::c_int) -> Result<(), Error> {
- if years == 0 { return Ok(()); }
- self.t.tm_mon = 0;
- self.t.tm_mday = 1;
- self.t.tm_hour = 0;
- self.t.tm_min = 0;
- self.t.tm_sec = 0;
- self.t.tm_year += years;
- self.normalize_time()
- }
-
- /// increases the month by 'months' and resets all smaller fields to their minimum
- pub fn add_months(&mut self, months: libc::c_int) -> Result<(), Error> {
- if months == 0 { return Ok(()); }
- self.t.tm_mday = 1;
- self.t.tm_hour = 0;
- self.t.tm_min = 0;
- self.t.tm_sec = 0;
- self.t.tm_mon += months;
- self.normalize_time()
- }
-
- /// increases the day by 'days' and resets all smaller fields to their minimum
- pub fn add_days(&mut self, days: libc::c_int) -> Result<(), Error> {
- if days == 0 { return Ok(()); }
- self.t.tm_hour = 0;
- self.t.tm_min = 0;
- self.t.tm_sec = 0;
- self.t.tm_mday += days;
- self.normalize_time()
- }
-
- pub fn year(&self) -> libc::c_int { self.t.tm_year + 1900 } // see man mktime
- pub fn month(&self) -> libc::c_int { self.t.tm_mon + 1 }
- pub fn day(&self) -> libc::c_int { self.t.tm_mday }
- pub fn hour(&self) -> libc::c_int { self.t.tm_hour }
- pub fn min(&self) -> libc::c_int { self.t.tm_min }
- pub fn sec(&self) -> libc::c_int { self.t.tm_sec }
-
- // Note: tm_wday (0-6, Sunday = 0) => convert to Sunday = 6
- pub fn day_num(&self) -> libc::c_int {
- (self.t.tm_wday + 6) % 7
- }
-
- 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.normalize_time()
- }
-
- 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.normalize_time()
- }
-
- fn normalize_time(&mut self) -> Result<(), Error> {
- // libc normalizes it for us
- if self.utc {
- timegm(&mut self.t)?;
- } else {
- timelocal(&mut self.t)?;
- }
- Ok(())
- }
-
- pub fn set_sec(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_sec = v;
- self.normalize_time()
- }
-
- pub fn set_min(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_min = v;
- self.normalize_time()
- }
-
- pub fn set_hour(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_hour = v;
- self.normalize_time()
- }
-
- pub fn set_mday(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_mday = v;
- self.normalize_time()
- }
-
- pub fn set_mon(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_mon = v - 1;
- self.normalize_time()
- }
-
- pub fn set_year(&mut self, v: libc::c_int) -> Result<(), Error> {
- self.t.tm_year = v - 1900;
- self.normalize_time()
- }
-}
--
2.20.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-09-13 14:43 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-13 14:42 [pve-devel] [RFC proxmox-backup] avoid chrono dependency Dietmar Maurer
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal