* [pbs-devel] [PATCH pxar] fix `decode_entry` on special files
@ 2020-12-15 10:37 Wolfgang Bumiller
2020-12-15 11:08 ` Dominik Csapak
0 siblings, 1 reply; 3+ messages in thread
From: Wolfgang Bumiller @ 2020-12-15 10:37 UTC (permalink / raw)
To: pbs-devel
When using the random accessor to access FIFOs or sockets,
the ranged reader limits the data to only that entry, and
the `decode_entry` will never see a `PAYLOAD` or
`GOODBYE_TABLE` item to finish the entry.
Instead, it'll reach EOF and we need to handle this.
The accessor now tells the decoder to expect EOF as a valid
condition for ending the entry.
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
The included testcase previously failed with
"failed to decode entry for fifo0"
src/accessor/mod.rs | 2 +-
src/decoder/mod.rs | 52 +++++++++++++++++++++++++++++++++++---------
tests/simple/main.rs | 46 +++++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 11 deletions(-)
diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs
index 0ab03a6..d02dc13 100644
--- a/src/accessor/mod.rs
+++ b/src/accessor/mod.rs
@@ -229,7 +229,7 @@ async fn get_decoder<T: ReadAt>(
entry_range: Range<u64>,
path: PathBuf,
) -> io::Result<DecoderImpl<SeqReadAtAdapter<T>>> {
- Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path).await?)
+ Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path, true).await?)
}
// NOTE: This performs the Decoder::read_next_item() behavior! Keep in mind when changing!
diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
index fcc2dd9..2a5e79a 100644
--- a/src/decoder/mod.rs
+++ b/src/decoder/mod.rs
@@ -155,6 +155,10 @@ pub(crate) struct DecoderImpl<T> {
path_lengths: Vec<usize>,
state: State,
with_goodbye_tables: bool,
+
+ /// The random access code uses decoders for sub-ranges which may not end in a `PAYLOAD` for
+ /// entries like FIFOs or sockets, so there we explicitly allow an item to terminate with EOF.
+ eof_after_entry: bool,
}
enum State {
@@ -191,14 +195,18 @@ pub(crate) enum ItemResult {
impl<I: SeqRead> DecoderImpl<I> {
pub async fn new(input: I) -> io::Result<Self> {
- Self::new_full(input, "/".into()).await
+ Self::new_full(input, "/".into(), false).await
}
pub(crate) fn input(&self) -> &I {
&self.input
}
- pub(crate) async fn new_full(input: I, path: PathBuf) -> io::Result<Self> {
+ pub(crate) async fn new_full(
+ input: I,
+ path: PathBuf,
+ eof_after_entry: bool,
+ ) -> io::Result<Self> {
let this = DecoderImpl {
input,
current_header: unsafe { mem::zeroed() },
@@ -210,6 +218,7 @@ impl<I: SeqRead> DecoderImpl<I> {
path_lengths: Vec::new(),
state: State::Begin,
with_goodbye_tables: false,
+ eof_after_entry,
};
// this.read_next_entry().await?;
@@ -383,7 +392,14 @@ impl<I: SeqRead> DecoderImpl<I> {
self.current_header = unsafe { mem::zeroed() };
- while self.read_next_item().await? != ItemResult::Entry {}
+ loop {
+ match self.read_next_item_or_eof().await? {
+ Some(ItemResult::Entry) => break,
+ Some(ItemResult::Attribute) => continue,
+ None if self.eof_after_entry => break,
+ None => io_bail!("unexpected EOF in entry"),
+ }
+ }
if self.entry.is_dir() {
self.path_lengths
@@ -402,24 +418,40 @@ impl<I: SeqRead> DecoderImpl<I> {
.ok_or_else(|| io_format_err!("unexpected EOF"))
}
+ async fn read_next_item(&mut self) -> io::Result<ItemResult> {
+ match self.read_next_item_or_eof().await? {
+ Some(item) => Ok(item),
+ None => io_bail!("unexpected EOF"),
+ }
+ }
+
+ // NOTE: The random accessor will decode FIFOs and Sockets in a decoder instance with a ranged
+ // reader so there is no PAYLOAD or GOODBYE TABLE to "end" an entry.
+ //
// NOTE: This behavior method is also recreated in the accessor's `get_decoder_at_filename`
// function! Keep in mind when changing!
- async fn read_next_item(&mut self) -> io::Result<ItemResult> {
- self.read_next_header().await?;
- self.read_current_item().await
+ async fn read_next_item_or_eof(&mut self) -> io::Result<Option<ItemResult>> {
+ match self.read_next_header_or_eof().await? {
+ Some(()) => self.read_current_item().await.map(Some),
+ None => Ok(None),
+ }
}
- async fn read_next_header(&mut self) -> io::Result<()> {
+ async fn read_next_header_or_eof(&mut self) -> io::Result<Option<()>> {
let dest = unsafe {
std::slice::from_raw_parts_mut(
&mut self.current_header as *mut Header as *mut u8,
size_of_val(&self.current_header),
)
};
- seq_read_exact(&mut self.input, dest).await?;
- self.current_header.check_header_size()?;
- Ok(())
+ match seq_read_exact_or_eof(&mut self.input, dest).await? {
+ Some(()) => {
+ self.current_header.check_header_size()?;
+ Ok(Some(()))
+ }
+ None => Ok(None),
+ }
}
/// Read the next item, the header is already loaded.
diff --git a/tests/simple/main.rs b/tests/simple/main.rs
index c73ca10..f15a0f5 100644
--- a/tests/simple/main.rs
+++ b/tests/simple/main.rs
@@ -42,6 +42,9 @@ fn test1() {
assert!(!file.is_empty(), "encoder did not write any data");
+ // may be useful for testing...
+ // std::fs::write("myarchive.pxar", &file).expect("failed to write out test archive");
+
let mut input = &file[..];
let mut decoder = decoder::Decoder::from_std(&mut input).expect("failed to create decoder");
let decoded_fs =
@@ -53,6 +56,7 @@ fn test1() {
.expect("failed to create random access reader for encoded archive");
check_bunzip2(&accessor);
+ check_run_special_files(&accessor);
}
fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
@@ -85,3 +89,45 @@ fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
assert_eq!(content, "This is the bzip2 executable");
}
+
+fn check_run_special_files(accessor: &accessor::Accessor<&[u8]>) {
+ let rundir = accessor
+ .open_root()
+ .expect("failed to open root of encoded archive")
+ .lookup("run")
+ .expect("failed to open /run in encoded archive")
+ .expect("missing /run in encoded archive")
+ .enter_directory()
+ .expect("expected /run to be a directory in the test archive");
+
+ assert_eq!(rundir.entry_count(), 2, "expected 2 entries in /run");
+
+ let mut rd = rundir.read_dir();
+ let fifo0 = rd
+ .next()
+ .expect("expected 'fifo0' entry in rundir")
+ .expect("failed to get first (fifo0) entry in test archive /run directory");
+ assert_eq!(
+ fifo0.file_name(),
+ Path::new("fifo0"),
+ "expected first file in /run to be fifo0"
+ );
+
+ let _entry = fifo0
+ .decode_entry()
+ .expect("failed to decode entry for fifo0");
+
+ let sock0 = rd
+ .next()
+ .expect("expected 'sock0' entry in rundir")
+ .expect("failed to get second (sock0) entry in test archive /run directory");
+ assert_eq!(
+ sock0.file_name(),
+ Path::new("sock0"),
+ "expected second file in /run to be sock0"
+ );
+
+ let _entry = sock0
+ .decode_entry()
+ .expect("failed to decode entry for sock0");
+}
--
2.20.1
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [pbs-devel] [PATCH pxar] fix `decode_entry` on special files
2020-12-15 10:37 [pbs-devel] [PATCH pxar] fix `decode_entry` on special files Wolfgang Bumiller
@ 2020-12-15 11:08 ` Dominik Csapak
2020-12-15 12:18 ` [pbs-devel] applied: " Wolfgang Bumiller
0 siblings, 1 reply; 3+ messages in thread
From: Dominik Csapak @ 2020-12-15 11:08 UTC (permalink / raw)
To: Proxmox Backup Server development discussion, Wolfgang Bumiller
looks good AFAICT
fixes the problem with fifo/sockets
Tested-By: Dominik Csapak <d.csapak@proxmox.com>
On 12/15/20 11:37 AM, Wolfgang Bumiller wrote:
> When using the random accessor to access FIFOs or sockets,
> the ranged reader limits the data to only that entry, and
> the `decode_entry` will never see a `PAYLOAD` or
> `GOODBYE_TABLE` item to finish the entry.
> Instead, it'll reach EOF and we need to handle this.
> The accessor now tells the decoder to expect EOF as a valid
> condition for ending the entry.
>
> Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> ---
>
> The included testcase previously failed with
> "failed to decode entry for fifo0"
>
> src/accessor/mod.rs | 2 +-
> src/decoder/mod.rs | 52 +++++++++++++++++++++++++++++++++++---------
> tests/simple/main.rs | 46 +++++++++++++++++++++++++++++++++++++++
> 3 files changed, 89 insertions(+), 11 deletions(-)
>
> diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs
> index 0ab03a6..d02dc13 100644
> --- a/src/accessor/mod.rs
> +++ b/src/accessor/mod.rs
> @@ -229,7 +229,7 @@ async fn get_decoder<T: ReadAt>(
> entry_range: Range<u64>,
> path: PathBuf,
> ) -> io::Result<DecoderImpl<SeqReadAtAdapter<T>>> {
> - Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path).await?)
> + Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path, true).await?)
> }
>
> // NOTE: This performs the Decoder::read_next_item() behavior! Keep in mind when changing!
> diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
> index fcc2dd9..2a5e79a 100644
> --- a/src/decoder/mod.rs
> +++ b/src/decoder/mod.rs
> @@ -155,6 +155,10 @@ pub(crate) struct DecoderImpl<T> {
> path_lengths: Vec<usize>,
> state: State,
> with_goodbye_tables: bool,
> +
> + /// The random access code uses decoders for sub-ranges which may not end in a `PAYLOAD` for
> + /// entries like FIFOs or sockets, so there we explicitly allow an item to terminate with EOF.
> + eof_after_entry: bool,
> }
>
> enum State {
> @@ -191,14 +195,18 @@ pub(crate) enum ItemResult {
>
> impl<I: SeqRead> DecoderImpl<I> {
> pub async fn new(input: I) -> io::Result<Self> {
> - Self::new_full(input, "/".into()).await
> + Self::new_full(input, "/".into(), false).await
> }
>
> pub(crate) fn input(&self) -> &I {
> &self.input
> }
>
> - pub(crate) async fn new_full(input: I, path: PathBuf) -> io::Result<Self> {
> + pub(crate) async fn new_full(
> + input: I,
> + path: PathBuf,
> + eof_after_entry: bool,
> + ) -> io::Result<Self> {
> let this = DecoderImpl {
> input,
> current_header: unsafe { mem::zeroed() },
> @@ -210,6 +218,7 @@ impl<I: SeqRead> DecoderImpl<I> {
> path_lengths: Vec::new(),
> state: State::Begin,
> with_goodbye_tables: false,
> + eof_after_entry,
> };
>
> // this.read_next_entry().await?;
> @@ -383,7 +392,14 @@ impl<I: SeqRead> DecoderImpl<I> {
>
> self.current_header = unsafe { mem::zeroed() };
>
> - while self.read_next_item().await? != ItemResult::Entry {}
> + loop {
> + match self.read_next_item_or_eof().await? {
> + Some(ItemResult::Entry) => break,
> + Some(ItemResult::Attribute) => continue,
> + None if self.eof_after_entry => break,
> + None => io_bail!("unexpected EOF in entry"),
> + }
> + }
>
> if self.entry.is_dir() {
> self.path_lengths
> @@ -402,24 +418,40 @@ impl<I: SeqRead> DecoderImpl<I> {
> .ok_or_else(|| io_format_err!("unexpected EOF"))
> }
>
> + async fn read_next_item(&mut self) -> io::Result<ItemResult> {
> + match self.read_next_item_or_eof().await? {
> + Some(item) => Ok(item),
> + None => io_bail!("unexpected EOF"),
> + }
> + }
> +
> + // NOTE: The random accessor will decode FIFOs and Sockets in a decoder instance with a ranged
> + // reader so there is no PAYLOAD or GOODBYE TABLE to "end" an entry.
> + //
> // NOTE: This behavior method is also recreated in the accessor's `get_decoder_at_filename`
> // function! Keep in mind when changing!
> - async fn read_next_item(&mut self) -> io::Result<ItemResult> {
> - self.read_next_header().await?;
> - self.read_current_item().await
> + async fn read_next_item_or_eof(&mut self) -> io::Result<Option<ItemResult>> {
> + match self.read_next_header_or_eof().await? {
> + Some(()) => self.read_current_item().await.map(Some),
> + None => Ok(None),
> + }
> }
>
> - async fn read_next_header(&mut self) -> io::Result<()> {
> + async fn read_next_header_or_eof(&mut self) -> io::Result<Option<()>> {
> let dest = unsafe {
> std::slice::from_raw_parts_mut(
> &mut self.current_header as *mut Header as *mut u8,
> size_of_val(&self.current_header),
> )
> };
> - seq_read_exact(&mut self.input, dest).await?;
> - self.current_header.check_header_size()?;
>
> - Ok(())
> + match seq_read_exact_or_eof(&mut self.input, dest).await? {
> + Some(()) => {
> + self.current_header.check_header_size()?;
> + Ok(Some(()))
> + }
> + None => Ok(None),
> + }
> }
>
> /// Read the next item, the header is already loaded.
> diff --git a/tests/simple/main.rs b/tests/simple/main.rs
> index c73ca10..f15a0f5 100644
> --- a/tests/simple/main.rs
> +++ b/tests/simple/main.rs
> @@ -42,6 +42,9 @@ fn test1() {
>
> assert!(!file.is_empty(), "encoder did not write any data");
>
> + // may be useful for testing...
> + // std::fs::write("myarchive.pxar", &file).expect("failed to write out test archive");
> +
> let mut input = &file[..];
> let mut decoder = decoder::Decoder::from_std(&mut input).expect("failed to create decoder");
> let decoded_fs =
> @@ -53,6 +56,7 @@ fn test1() {
> .expect("failed to create random access reader for encoded archive");
>
> check_bunzip2(&accessor);
> + check_run_special_files(&accessor);
> }
>
> fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
> @@ -85,3 +89,45 @@ fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
>
> assert_eq!(content, "This is the bzip2 executable");
> }
> +
> +fn check_run_special_files(accessor: &accessor::Accessor<&[u8]>) {
> + let rundir = accessor
> + .open_root()
> + .expect("failed to open root of encoded archive")
> + .lookup("run")
> + .expect("failed to open /run in encoded archive")
> + .expect("missing /run in encoded archive")
> + .enter_directory()
> + .expect("expected /run to be a directory in the test archive");
> +
> + assert_eq!(rundir.entry_count(), 2, "expected 2 entries in /run");
> +
> + let mut rd = rundir.read_dir();
> + let fifo0 = rd
> + .next()
> + .expect("expected 'fifo0' entry in rundir")
> + .expect("failed to get first (fifo0) entry in test archive /run directory");
> + assert_eq!(
> + fifo0.file_name(),
> + Path::new("fifo0"),
> + "expected first file in /run to be fifo0"
> + );
> +
> + let _entry = fifo0
> + .decode_entry()
> + .expect("failed to decode entry for fifo0");
> +
> + let sock0 = rd
> + .next()
> + .expect("expected 'sock0' entry in rundir")
> + .expect("failed to get second (sock0) entry in test archive /run directory");
> + assert_eq!(
> + sock0.file_name(),
> + Path::new("sock0"),
> + "expected second file in /run to be sock0"
> + );
> +
> + let _entry = sock0
> + .decode_entry()
> + .expect("failed to decode entry for sock0");
> +}
>
^ permalink raw reply [flat|nested] 3+ messages in thread
* [pbs-devel] applied: [PATCH pxar] fix `decode_entry` on special files
2020-12-15 11:08 ` Dominik Csapak
@ 2020-12-15 12:18 ` Wolfgang Bumiller
0 siblings, 0 replies; 3+ messages in thread
From: Wolfgang Bumiller @ 2020-12-15 12:18 UTC (permalink / raw)
To: Dominik Csapak; +Cc: Proxmox Backup Server development discussion
thanks for testing, applied
On Tue, Dec 15, 2020 at 12:08:53PM +0100, Dominik Csapak wrote:
> looks good AFAICT
> fixes the problem with fifo/sockets
>
> Tested-By: Dominik Csapak <d.csapak@proxmox.com>
>
> On 12/15/20 11:37 AM, Wolfgang Bumiller wrote:
> > When using the random accessor to access FIFOs or sockets,
> > the ranged reader limits the data to only that entry, and
> > the `decode_entry` will never see a `PAYLOAD` or
> > `GOODBYE_TABLE` item to finish the entry.
> > Instead, it'll reach EOF and we need to handle this.
> > The accessor now tells the decoder to expect EOF as a valid
> > condition for ending the entry.
> >
> > Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
> > ---
> >
> > The included testcase previously failed with
> > "failed to decode entry for fifo0"
> >
> > src/accessor/mod.rs | 2 +-
> > src/decoder/mod.rs | 52 +++++++++++++++++++++++++++++++++++---------
> > tests/simple/main.rs | 46 +++++++++++++++++++++++++++++++++++++++
> > 3 files changed, 89 insertions(+), 11 deletions(-)
> >
> > diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs
> > index 0ab03a6..d02dc13 100644
> > --- a/src/accessor/mod.rs
> > +++ b/src/accessor/mod.rs
> > @@ -229,7 +229,7 @@ async fn get_decoder<T: ReadAt>(
> > entry_range: Range<u64>,
> > path: PathBuf,
> > ) -> io::Result<DecoderImpl<SeqReadAtAdapter<T>>> {
> > - Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path).await?)
> > + Ok(DecoderImpl::new_full(SeqReadAtAdapter::new(input, entry_range), path, true).await?)
> > }
> > // NOTE: This performs the Decoder::read_next_item() behavior! Keep in mind when changing!
> > diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs
> > index fcc2dd9..2a5e79a 100644
> > --- a/src/decoder/mod.rs
> > +++ b/src/decoder/mod.rs
> > @@ -155,6 +155,10 @@ pub(crate) struct DecoderImpl<T> {
> > path_lengths: Vec<usize>,
> > state: State,
> > with_goodbye_tables: bool,
> > +
> > + /// The random access code uses decoders for sub-ranges which may not end in a `PAYLOAD` for
> > + /// entries like FIFOs or sockets, so there we explicitly allow an item to terminate with EOF.
> > + eof_after_entry: bool,
> > }
> > enum State {
> > @@ -191,14 +195,18 @@ pub(crate) enum ItemResult {
> > impl<I: SeqRead> DecoderImpl<I> {
> > pub async fn new(input: I) -> io::Result<Self> {
> > - Self::new_full(input, "/".into()).await
> > + Self::new_full(input, "/".into(), false).await
> > }
> > pub(crate) fn input(&self) -> &I {
> > &self.input
> > }
> > - pub(crate) async fn new_full(input: I, path: PathBuf) -> io::Result<Self> {
> > + pub(crate) async fn new_full(
> > + input: I,
> > + path: PathBuf,
> > + eof_after_entry: bool,
> > + ) -> io::Result<Self> {
> > let this = DecoderImpl {
> > input,
> > current_header: unsafe { mem::zeroed() },
> > @@ -210,6 +218,7 @@ impl<I: SeqRead> DecoderImpl<I> {
> > path_lengths: Vec::new(),
> > state: State::Begin,
> > with_goodbye_tables: false,
> > + eof_after_entry,
> > };
> > // this.read_next_entry().await?;
> > @@ -383,7 +392,14 @@ impl<I: SeqRead> DecoderImpl<I> {
> > self.current_header = unsafe { mem::zeroed() };
> > - while self.read_next_item().await? != ItemResult::Entry {}
> > + loop {
> > + match self.read_next_item_or_eof().await? {
> > + Some(ItemResult::Entry) => break,
> > + Some(ItemResult::Attribute) => continue,
> > + None if self.eof_after_entry => break,
> > + None => io_bail!("unexpected EOF in entry"),
> > + }
> > + }
> > if self.entry.is_dir() {
> > self.path_lengths
> > @@ -402,24 +418,40 @@ impl<I: SeqRead> DecoderImpl<I> {
> > .ok_or_else(|| io_format_err!("unexpected EOF"))
> > }
> > + async fn read_next_item(&mut self) -> io::Result<ItemResult> {
> > + match self.read_next_item_or_eof().await? {
> > + Some(item) => Ok(item),
> > + None => io_bail!("unexpected EOF"),
> > + }
> > + }
> > +
> > + // NOTE: The random accessor will decode FIFOs and Sockets in a decoder instance with a ranged
> > + // reader so there is no PAYLOAD or GOODBYE TABLE to "end" an entry.
> > + //
> > // NOTE: This behavior method is also recreated in the accessor's `get_decoder_at_filename`
> > // function! Keep in mind when changing!
> > - async fn read_next_item(&mut self) -> io::Result<ItemResult> {
> > - self.read_next_header().await?;
> > - self.read_current_item().await
> > + async fn read_next_item_or_eof(&mut self) -> io::Result<Option<ItemResult>> {
> > + match self.read_next_header_or_eof().await? {
> > + Some(()) => self.read_current_item().await.map(Some),
> > + None => Ok(None),
> > + }
> > }
> > - async fn read_next_header(&mut self) -> io::Result<()> {
> > + async fn read_next_header_or_eof(&mut self) -> io::Result<Option<()>> {
> > let dest = unsafe {
> > std::slice::from_raw_parts_mut(
> > &mut self.current_header as *mut Header as *mut u8,
> > size_of_val(&self.current_header),
> > )
> > };
> > - seq_read_exact(&mut self.input, dest).await?;
> > - self.current_header.check_header_size()?;
> > - Ok(())
> > + match seq_read_exact_or_eof(&mut self.input, dest).await? {
> > + Some(()) => {
> > + self.current_header.check_header_size()?;
> > + Ok(Some(()))
> > + }
> > + None => Ok(None),
> > + }
> > }
> > /// Read the next item, the header is already loaded.
> > diff --git a/tests/simple/main.rs b/tests/simple/main.rs
> > index c73ca10..f15a0f5 100644
> > --- a/tests/simple/main.rs
> > +++ b/tests/simple/main.rs
> > @@ -42,6 +42,9 @@ fn test1() {
> > assert!(!file.is_empty(), "encoder did not write any data");
> > + // may be useful for testing...
> > + // std::fs::write("myarchive.pxar", &file).expect("failed to write out test archive");
> > +
> > let mut input = &file[..];
> > let mut decoder = decoder::Decoder::from_std(&mut input).expect("failed to create decoder");
> > let decoded_fs =
> > @@ -53,6 +56,7 @@ fn test1() {
> > .expect("failed to create random access reader for encoded archive");
> > check_bunzip2(&accessor);
> > + check_run_special_files(&accessor);
> > }
> > fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
> > @@ -85,3 +89,45 @@ fn check_bunzip2(accessor: &accessor::Accessor<&[u8]>) {
> > assert_eq!(content, "This is the bzip2 executable");
> > }
> > +
> > +fn check_run_special_files(accessor: &accessor::Accessor<&[u8]>) {
> > + let rundir = accessor
> > + .open_root()
> > + .expect("failed to open root of encoded archive")
> > + .lookup("run")
> > + .expect("failed to open /run in encoded archive")
> > + .expect("missing /run in encoded archive")
> > + .enter_directory()
> > + .expect("expected /run to be a directory in the test archive");
> > +
> > + assert_eq!(rundir.entry_count(), 2, "expected 2 entries in /run");
> > +
> > + let mut rd = rundir.read_dir();
> > + let fifo0 = rd
> > + .next()
> > + .expect("expected 'fifo0' entry in rundir")
> > + .expect("failed to get first (fifo0) entry in test archive /run directory");
> > + assert_eq!(
> > + fifo0.file_name(),
> > + Path::new("fifo0"),
> > + "expected first file in /run to be fifo0"
> > + );
> > +
> > + let _entry = fifo0
> > + .decode_entry()
> > + .expect("failed to decode entry for fifo0");
> > +
> > + let sock0 = rd
> > + .next()
> > + .expect("expected 'sock0' entry in rundir")
> > + .expect("failed to get second (sock0) entry in test archive /run directory");
> > + assert_eq!(
> > + sock0.file_name(),
> > + Path::new("sock0"),
> > + "expected second file in /run to be sock0"
> > + );
> > +
> > + let _entry = sock0
> > + .decode_entry()
> > + .expect("failed to decode entry for sock0");
> > +}
> >
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2020-12-15 12:18 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-15 10:37 [pbs-devel] [PATCH pxar] fix `decode_entry` on special files Wolfgang Bumiller
2020-12-15 11:08 ` Dominik Csapak
2020-12-15 12:18 ` [pbs-devel] applied: " Wolfgang Bumiller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox