]> git.proxmox.com Git - pxar.git/commitdiff
decoder: handle fifos and sockets properly
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 22 Apr 2020 09:01:23 +0000 (11:01 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 22 Apr 2020 09:02:02 +0000 (11:02 +0200)
These are the only items which don't get "finalized" by a
dedicated packet (like a PAYLOAD or DEVICE), so for these we
need to check at the next FILENAME or GOODBYE entry.

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
src/decoder.rs
src/format.rs
src/lib.rs

index ba894cffd704151f49b9ba88813f2d543f775230..486b394942da3ef0db1acd3bc05dfd509aed80b5 100644 (file)
@@ -158,7 +158,13 @@ pub(crate) struct DecoderImpl<T> {
 enum State {
     Begin,
     Default,
-    InPayload { offset: u64 },
+    InPayload {
+        offset: u64,
+    },
+
+    /// file entries with no data (fifo, socket)
+    InSpecialFile,
+
     InGoodbyeTable,
     InDirectory,
     Eof,
@@ -242,6 +248,11 @@ impl<I: SeqRead> DecoderImpl<I> {
                     self.state = State::Default;
                     continue;
                 }
+                State::InSpecialFile => {
+                    self.entry.clear_data();
+                    self.state = State::InDirectory;
+                    self.entry.kind = EntryKind::Directory;
+                }
                 State::InDirectory => {
                     // We're at the next FILENAME or GOODBYE item.
                 }
@@ -469,9 +480,21 @@ impl<I: SeqRead> DecoderImpl<I> {
                 return Ok(ItemResult::Entry);
             }
             format::PXAR_FILENAME | format::PXAR_GOODBYE => {
-                self.state = State::InDirectory;
-                self.entry.kind = EntryKind::Directory;
-                return Ok(ItemResult::Entry);
+                if self.entry.metadata.is_fifo() {
+                    self.state = State::InSpecialFile;
+                    self.entry.kind = EntryKind::Fifo;
+                    return Ok(ItemResult::Entry);
+                } else if self.entry.metadata.is_socket() {
+                    self.state = State::InSpecialFile;
+                    self.entry.kind = EntryKind::Socket;
+                    return Ok(ItemResult::Entry);
+                } else {
+                    // As a shortcut this is copy-pasted to `next_do`'s `InSpecialFile` case.
+                    // Keep in mind when editing this!
+                    self.state = State::InDirectory;
+                    self.entry.kind = EntryKind::Directory;
+                    return Ok(ItemResult::Entry);
+                }
             }
             _ => io_bail!("unexpected entry type: {:x}", self.current_header.htype),
         }
index ca4ad3e238f02eeb61bbc72a48f4e70307aed6ef..dcf68935bfcd14209b9d365049ebbd1f62b22595 100644 (file)
@@ -198,6 +198,16 @@ impl Entry {
     pub fn is_regular_file(&self) -> bool {
         (self.mode & mode::IFMT) == mode::IFREG
     }
+
+    /// Check whether this is a named pipe (FIFO).
+    pub fn is_fifo(&self) -> bool {
+        (self.mode & mode::IFMT) == mode::IFIFO
+    }
+
+    /// Check whether this is a named socket.
+    pub fn is_socket(&self) -> bool {
+        (self.mode & mode::IFMT) == mode::IFSOCK
+    }
 }
 
 impl From<&std::fs::Metadata> for Entry {
index 0017188338969a1bff5d1313812d0ddcb0db7f06..c251e8f73954b2cfeb62947a64f2df38ecead484 100644 (file)
@@ -101,6 +101,18 @@ impl Metadata {
         self.stat.is_regular_file()
     }
 
+    /// Check whether this is a named pipe (FIFO).
+    #[inline]
+    pub fn is_fifo(&self) -> bool {
+        self.stat.is_fifo()
+    }
+
+    /// Check whether this is a named socket.
+    #[inline]
+    pub fn is_socket(&self) -> bool {
+        self.stat.is_socket()
+    }
+
     /// Get the mtime as duration since the epoch.
     pub fn mtime_as_duration(&self) -> std::time::Duration {
         self.stat.mtime_as_duration()
@@ -156,6 +168,12 @@ pub enum EntryKind {
     /// Device node.
     Device(format::Device),
 
+    /// Named unix socket.
+    Socket,
+
+    /// Named pipe.
+    Fifo,
+
     /// Regular file.
     File { size: u64, offset: Option<u64> },