[pbs-devel] [PATCH pxar 4/6] implement Entry v2

Wolfgang Bumiller w.bumiller at proxmox.com
Tue Jul 28 12:33:19 CEST 2020


Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
---
 src/decoder/mod.rs | 21 ++++++++++++++++-----
 src/errors.rs      | 25 -------------------------
 src/format/mod.rs  | 46 ++++++++++++++++++++++++++++++++++------------
 src/lib.rs         | 28 +++++++++++++++-------------
 4 files changed, 65 insertions(+), 55 deletions(-)
 delete mode 100644 src/errors.rs

diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
index 9410942..e5b6d2c 100644
--- a/src/decoder/mod.rs
+++ b/src/decoder/mod.rs
@@ -360,11 +360,22 @@ impl<I: SeqRead> DecoderImpl<I> {
             self.entry.kind = EntryKind::Hardlink(self.read_hardlink().await?);
 
             Ok(Some(self.entry.take()))
-        } else if header.htype == format::PXAR_ENTRY {
-            self.entry.metadata = Metadata {
-                stat: seq_read_entry(&mut self.input).await?,
-                ..Default::default()
-            };
+        } else if header.htype == format::PXAR_ENTRY || header.htype == format::PXAR_ENTRY_V1 {
+            if header.htype == format::PXAR_ENTRY {
+                self.entry.metadata = Metadata {
+                    stat: seq_read_entry(&mut self.input).await?,
+                    ..Default::default()
+                };
+            } else if header.htype == format::PXAR_ENTRY_V1 {
+                let stat: format::Entry_V1 = seq_read_entry(&mut self.input).await?;
+
+                self.entry.metadata = Metadata {
+                    stat: stat.into(),
+                    ..Default::default()
+                };
+            } else {
+                unreachable!();
+            }
 
             self.current_header = unsafe { mem::zeroed() };
 
diff --git a/src/errors.rs b/src/errors.rs
deleted file mode 100644
index 8983e98..0000000
--- a/src/errors.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-use std::error::Error;
-use std::fmt;
-
-#[derive(Clone, Debug)]
-pub enum TimeError {
-    Underflow(std::time::SystemTimeError),
-    Overflow(std::time::Duration),
-}
-
-impl fmt::Display for TimeError {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            TimeError::Underflow(st) => st.fmt(f),
-            TimeError::Overflow(dur) => write!(f, "timestamp out of range: {:?}", dur),
-        }
-    }
-}
-
-impl Error for TimeError {}
-
-impl From<std::time::SystemTimeError> for TimeError {
-    fn from(t: std::time::SystemTimeError) -> Self {
-        TimeError::Underflow(t)
-    }
-}
diff --git a/src/format/mod.rs b/src/format/mod.rs
index 085b8b9..ec61e15 100644
--- a/src/format/mod.rs
+++ b/src/format/mod.rs
@@ -78,7 +78,10 @@ pub mod mode {
     pub const ISVTX  : u64 = 0o0001000;
 }
 
-pub const PXAR_ENTRY: u64 = 0x11da850a1c1cceff;
+/// Beginning of an entry (current version).
+pub const PXAR_ENTRY: u64 = 0xd5956474e588acef;
+/// Previous version of the entry struct
+pub const PXAR_ENTRY_V1: u64 = 0x11da850a1c1cceff;
 pub const PXAR_FILENAME: u64 = 0x16701121063917b3;
 pub const PXAR_SYMLINK: u64 = 0x27f971e7dbf5dc5f;
 pub const PXAR_DEVICE: u64 = 0x9fc9e906586d5ce9;
@@ -300,7 +303,7 @@ fn test_statx_timestamp() {
 #[derive(Clone, Debug, Default, Endian)]
 #[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))]
 #[repr(C)]
-pub struct Entry {
+pub struct Entry_V1 {
     pub mode: u64,
     pub flags: u64,
     pub uid: u32,
@@ -308,6 +311,29 @@ pub struct Entry {
     pub mtime: u64,
 }
 
+impl Into<Entry> for Entry_V1 {
+    fn into(self) -> Entry {
+        Entry {
+            mode: self.mode,
+            flags: self.flags,
+            uid: self.uid,
+            gid: self.gid,
+            mtime: StatxTimestamp::from_duration_since_epoch(Duration::from_nanos(self.mtime)),
+        }
+    }
+}
+
+#[derive(Clone, Debug, Default, Endian)]
+#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))]
+#[repr(C)]
+pub struct Entry {
+    pub mode: u64,
+    pub flags: u64,
+    pub uid: u32,
+    pub gid: u32,
+    pub mtime: StatxTimestamp,
+}
+
 /// Builder pattern methods.
 impl Entry {
     pub const fn mode(self, mode: u64) -> Self {
@@ -326,7 +352,7 @@ impl Entry {
         Self { gid, ..self }
     }
 
-    pub const fn mtime(self, mtime: u64) -> Self {
+    pub const fn mtime(self, mtime: StatxTimestamp) -> Self {
         Self { mtime, ..self }
     }
 
@@ -363,9 +389,10 @@ impl Entry {
 
 /// Convenience accessor methods.
 impl Entry {
-    /// Get the mtime as duration since the epoch.
-    pub fn mtime_as_duration(&self) -> std::time::Duration {
-        std::time::Duration::from_nanos(self.mtime)
+    /// Get the mtime as duration since the epoch. an `Ok` value is a positive duration, an `Err`
+    /// value is a negative duration.
+    pub fn mtime_as_duration(&self) -> SignedDuration {
+        self.mtime.to_duration()
     }
 
     /// Get the file type portion of the mode bitfield.
@@ -449,12 +476,7 @@ impl From<&std::fs::Metadata> for Entry {
             .mode(meta.mode() as u64);
 
         let this = match meta.modified() {
-            Ok(mtime) => this.mtime(
-                mtime
-                    .duration_since(std::time::SystemTime::UNIX_EPOCH)
-                    .map(|dur| dur.as_nanos() as u64)
-                    .unwrap_or(0u64),
-            ),
+            Ok(mtime) => this.mtime(mtime.into()),
             Err(_) => this,
         };
 
diff --git a/src/lib.rs b/src/lib.rs
index 5d1b781..a58ec30 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,6 @@
 //!
 //! This implements a reader and writer for the proxmox archive format (.pxar).
 
-use std::convert::TryFrom;
 use std::ffi::OsStr;
 use std::mem;
 use std::path::{Path, PathBuf};
@@ -20,7 +19,6 @@ pub mod accessor;
 pub mod binary_tree_array;
 pub mod decoder;
 pub mod encoder;
-pub mod errors;
 
 /// Reexport of `format::Entry`. Since this conveys mostly information found via the `stat` syscall
 /// we mostly use this name for public interfaces.
@@ -125,8 +123,9 @@ impl Metadata {
         self.stat.is_socket()
     }
 
-    /// Get the mtime as duration since the epoch.
-    pub fn mtime_as_duration(&self) -> std::time::Duration {
+    /// Get the mtime as duration since the epoch. an `Ok` value is a positive duration, an `Err`
+    /// value is a negative duration.
+    pub fn mtime_as_duration(&self) -> format::SignedDuration {
         self.stat.mtime_as_duration()
     }
 
@@ -165,7 +164,7 @@ impl MetadataBuilder {
                     flags: 0,
                     uid: 0,
                     gid: 0,
-                    mtime: 0,
+                    mtime: format::StatxTimestamp::zero(),
                 },
                 xattrs: Vec::new(),
                 acl: Acl {
@@ -198,17 +197,20 @@ impl MetadataBuilder {
         self
     }
 
-    /// Set the modification time from a system time.
-    pub fn mtime(self, mtime: std::time::SystemTime) -> Result<Self, errors::TimeError> {
-        self.mtime_unix(mtime.duration_since(std::time::SystemTime::UNIX_EPOCH)?)
+    /// Set the modification time from a statx timespec value.
+    pub fn mtime_full(mut self, mtime: format::StatxTimestamp) -> Self {
+        self.inner.stat.mtime = mtime;
+        self
     }
 
     /// Set the modification time from a duration since the epoch (`SystemTime::UNIX_EPOCH`).
-    pub fn mtime_unix(mut self, mtime: std::time::Duration) -> Result<Self, errors::TimeError> {
-        let nanos =
-            u64::try_from(mtime.as_nanos()).map_err(|_| errors::TimeError::Overflow(mtime))?;
-        self.inner.stat.mtime = nanos;
-        Ok(self)
+    pub fn mtime_unix(self, mtime: std::time::Duration) -> Self {
+        self.mtime_full(format::StatxTimestamp::from_duration_since_epoch(mtime))
+    }
+
+    /// Set the modification time from a system time.
+    pub fn mtime(self, mtime: std::time::SystemTime) -> Self {
+        self.mtime_full(mtime.into())
     }
 
     /// Set the ownership information.
-- 
2.20.1






More information about the pbs-devel mailing list