5
0
mirror of git://git.proxmox.com/git/pxar.git synced 2025-02-03 21:47:00 +03:00

decoder: handle fifos and sockets properly

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>
This commit is contained in:
Wolfgang Bumiller 2020-04-22 11:01:23 +02:00
parent af35697966
commit 2287d8b26c
3 changed files with 55 additions and 4 deletions

View 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),
}

View 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 {

View 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> },