diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2020-03-27 10:30:20 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2020-03-27 10:44:39 +0100 |
commit | 95289f9bbacf67b283f4ce6542407ce7280a388c (patch) | |
tree | c3d7131623cd8f06ba14ec3d17d9dbb1f92a9faa | |
parent | 70a96487b25557c3b1ffcba4b61cc1140e76935a (diff) |
openpgp: Add a no-dependency mechanism to format timestamps.
-rw-r--r-- | Cargo.lock | 1 | ||||
-rw-r--r-- | openpgp/Cargo.toml | 1 | ||||
-rw-r--r-- | openpgp/src/fmt.rs | 52 |
3 files changed, 54 insertions, 0 deletions
@@ -1667,6 +1667,7 @@ dependencies = [ "lalrpop 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "lalrpop-util 0.17.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "memsec 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "nettle 7.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "quickcheck 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/openpgp/Cargo.toml b/openpgp/Cargo.toml index 11ce5934..c63b5ee6 100644 --- a/openpgp/Cargo.toml +++ b/openpgp/Cargo.toml @@ -30,6 +30,7 @@ flate2 = { version = "1.0.1", optional = true } idna = "0.2" lalrpop-util = "0.17" lazy_static = "1.3" +libc = "0.2" memsec = "0.5.6" nettle = "7" quickcheck = { version = "0.9", default-features = false } diff --git a/openpgp/src/fmt.rs b/openpgp/src/fmt.rs index 73d42fa0..6429c79f 100644 --- a/openpgp/src/fmt.rs +++ b/openpgp/src/fmt.rs @@ -261,6 +261,48 @@ pub(crate) fn from_hex(hex: &str, pretty: bool) -> Result<Vec<u8>> { Ok(bytes) } +/// Formats the given time using ISO 8601. +/// +/// This is a no-dependency, best-effort mechanism. If the given time +/// is not representable using unsigned UNIX time, we return the debug +/// formatting. +pub(crate) fn time(t: &std::time::SystemTime) -> String { + extern "C" { + fn strftime( + s: *mut libc::c_char, + max: libc::size_t, + format: *const libc::c_char, + tm: *const libc::tm, + ) -> usize; + } + + let t = match t.duration_since(std::time::UNIX_EPOCH) { + Ok(t) => t.as_secs() as libc::time_t, + Err(_) => return format!("{:?}", t), + }; + let fmt = b"%Y-%m-%dT%H:%M:%SZ\x00"; + assert_eq!(b"2020-03-26T10:08:10Z\x00".len(), 21); + let mut s = [0u8; 21]; + + unsafe { + let mut tm: libc::tm = std::mem::zeroed(); + + #[cfg(unix)] + libc::gmtime_r(&t, &mut tm); + #[cfg(windows)] + libc::gmtime_s(&mut tm, &t); + + strftime(s.as_mut_ptr() as *mut libc::c_char, + s.len(), + fmt.as_ptr() as *const libc::c_char, + &tm); + } + + std::ffi::CStr::from_bytes_with_nul(&s) + .expect("strftime nul terminates string") + .to_string_lossy().into() +} + #[cfg(test)] mod test { #[test] @@ -389,4 +431,14 @@ mod test { type\n\ "); } + + #[test] + fn time() { + use super::time; + use crate::types::Timestamp; + let t = |epoch| -> std::time::SystemTime { + Timestamp::from(epoch).into() + }; + assert_eq!(&time(&t(1585217290)), "2020-03-26T10:08:10Z"); + } } |