From: Christian Ebner <c.ebner@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH v3 pxar 5/6] accessor: add payload checks for split archives
Date: Wed, 12 Jun 2024 10:23:59 +0200 [thread overview]
Message-ID: <20240612082400.110789-6-c.ebner@proxmox.com> (raw)
In-Reply-To: <20240612082400.110789-1-c.ebner@proxmox.com>
Add checks for split variant inputs when accessing the payload
contents via the accessor instance. Both cases, accessing via the
safe `contents` method and via the unsafe `contents_at_range` call
are covered.
To be able to perform the checks, the current range is wrapped into a
`ContentRange` type, which also passed the payload offset and size
as expected from the metadata archive. The corresponding interfaces
have been adapted accordingly.
Signed-off-by: Christian Ebner <c.ebner@proxmox.com>
---
changes since version 2:
- moved cargo fmt hunk to own patch
src/accessor/aio.rs | 15 ++++++++-----
src/accessor/mod.rs | 53 ++++++++++++++++++++++++++++++++++++--------
src/accessor/sync.rs | 16 +++++++------
3 files changed, 62 insertions(+), 22 deletions(-)
diff --git a/src/accessor/aio.rs b/src/accessor/aio.rs
index 73b1025..c86adc5 100644
--- a/src/accessor/aio.rs
+++ b/src/accessor/aio.rs
@@ -7,7 +7,6 @@
use std::future::Future;
use std::io;
use std::mem;
-use std::ops::Range;
use std::os::unix::fs::FileExt;
use std::path::Path;
use std::pin::Pin;
@@ -16,6 +15,7 @@ use std::task::{Context, Poll};
use crate::accessor::{self, cache::Cache, MaybeReady, ReadAt, ReadAtOperation};
use crate::decoder::aio::Decoder;
+use crate::format::ContentRange;
use crate::format::GoodbyeItem;
use crate::util;
use crate::{Entry, PxarVariant};
@@ -153,13 +153,16 @@ impl<T: Clone + ReadAt> Accessor<T> {
///
/// This will provide a reader over an arbitrary range of the archive file, so unless this
/// comes from a actual file entry data, the contents might not make much sense.
- pub unsafe fn open_contents_at_range(&self, range: Range<u64>) -> FileContents<T> {
- FileContents {
- inner: unsafe { self.inner.open_contents_at_range(range) },
+ pub async unsafe fn open_contents_at_range(
+ &self,
+ range: &ContentRange,
+ ) -> io::Result<FileContents<T>> {
+ Ok(FileContents {
+ inner: unsafe { self.inner.open_contents_at_range(range).await? },
at: 0,
buffer: Vec::new(),
future: None,
- }
+ })
}
/// Following a hardlink.
@@ -235,7 +238,7 @@ impl<T: Clone + ReadAt> FileEntry<T> {
}
/// For use with unsafe accessor methods.
- pub fn content_range(&self) -> io::Result<Option<Range<u64>>> {
+ pub fn content_range(&self) -> io::Result<Option<ContentRange>> {
self.inner.content_range()
}
diff --git a/src/accessor/mod.rs b/src/accessor/mod.rs
index 92d689d..9f27dfd 100644
--- a/src/accessor/mod.rs
+++ b/src/accessor/mod.rs
@@ -17,7 +17,7 @@ use endian_trait::Endian;
use crate::binary_tree_array;
use crate::decoder::{self, DecoderImpl};
-use crate::format::{self, FormatVersion, GoodbyeItem};
+use crate::format::{self, ContentRange, FormatVersion, GoodbyeItem, PayloadRef};
use crate::util;
use crate::{Entry, EntryKind, PxarVariant};
@@ -336,11 +336,25 @@ impl<T: Clone + ReadAt> AccessorImpl<T> {
}
/// Allow opening arbitrary contents from a specific range.
- pub unsafe fn open_contents_at_range(&self, range: Range<u64>) -> FileContentsImpl<T> {
+ pub async unsafe fn open_contents_at_range(
+ &self,
+ range: &format::ContentRange,
+ ) -> io::Result<FileContentsImpl<T>> {
if let Some((payload_input, _)) = &self.input.payload() {
- FileContentsImpl::new(payload_input.clone(), range)
+ if let Some(payload_ref) = &range.payload_ref {
+ let header: format::Header =
+ read_entry_at(payload_input, payload_ref.offset).await?;
+ format::check_payload_header_and_size(&header, payload_ref.size)?;
+ }
+ Ok(FileContentsImpl::new(
+ payload_input.clone(),
+ range.content.clone(),
+ ))
} else {
- FileContentsImpl::new(self.input.archive().clone(), range)
+ Ok(FileContentsImpl::new(
+ self.input.archive().clone(),
+ range.content.clone(),
+ ))
}
}
@@ -758,7 +772,7 @@ impl<T: Clone + ReadAt> FileEntryImpl<T> {
}
/// For use with unsafe accessor methods.
- pub fn content_range(&self) -> io::Result<Option<Range<u64>>> {
+ pub fn content_range(&self) -> io::Result<Option<ContentRange>> {
match self.entry.kind {
EntryKind::File { offset: None, .. } => {
io_bail!("cannot open file, reader provided no offset")
@@ -767,7 +781,10 @@ impl<T: Clone + ReadAt> FileEntryImpl<T> {
size,
offset: Some(offset),
payload_offset: None,
- } => Ok(Some(offset..(offset + size))),
+ } => Ok(Some(ContentRange {
+ content: offset..(offset + size),
+ payload_ref: None,
+ })),
// Payload offset beats regular offset if some
EntryKind::File {
size,
@@ -775,7 +792,13 @@ impl<T: Clone + ReadAt> FileEntryImpl<T> {
payload_offset: Some(payload_offset),
} => {
let start_offset = payload_offset + size_of::<format::Header>() as u64;
- Ok(Some(start_offset..start_offset + size))
+ Ok(Some(ContentRange {
+ content: start_offset..start_offset + size,
+ payload_ref: Some(PayloadRef {
+ offset: payload_offset,
+ size,
+ }),
+ }))
}
_ => Ok(None),
}
@@ -786,9 +809,21 @@ impl<T: Clone + ReadAt> FileEntryImpl<T> {
.content_range()?
.ok_or_else(|| io_format_err!("not a file"))?;
if let Some((ref payload_input, _)) = self.input.payload() {
- Ok(FileContentsImpl::new(payload_input.clone(), range))
+ if let Some(payload_ref) = range.payload_ref {
+ let header: format::Header =
+ read_entry_at(payload_input, payload_ref.offset).await?;
+ format::check_payload_header_and_size(&header, payload_ref.size)?;
+ }
+
+ Ok(FileContentsImpl::new(
+ payload_input.clone(),
+ range.content.clone(),
+ ))
} else {
- Ok(FileContentsImpl::new(self.input.archive().clone(), range))
+ Ok(FileContentsImpl::new(
+ self.input.archive().clone(),
+ range.content.clone(),
+ ))
}
}
diff --git a/src/accessor/sync.rs b/src/accessor/sync.rs
index df2ed23..63f0265 100644
--- a/src/accessor/sync.rs
+++ b/src/accessor/sync.rs
@@ -1,7 +1,6 @@
//! Blocking `pxar` random access handling.
use std::io;
-use std::ops::Range;
use std::os::unix::fs::FileExt;
use std::path::Path;
use std::pin::Pin;
@@ -10,7 +9,7 @@ use std::task::Context;
use crate::accessor::{self, cache::Cache, MaybeReady, ReadAt, ReadAtOperation};
use crate::decoder::Decoder;
-use crate::format::GoodbyeItem;
+use crate::format::{ContentRange, GoodbyeItem};
use crate::util::poll_result_once;
use crate::{Entry, PxarVariant};
@@ -142,11 +141,14 @@ impl<T: Clone + ReadAt> Accessor<T> {
///
/// This will provide a reader over an arbitrary range of the archive file, so unless this
/// comes from a actual file entry data, the contents might not make much sense.
- pub unsafe fn open_contents_at_range(&self, range: Range<u64>) -> FileContents<T> {
- FileContents {
- inner: unsafe { self.inner.open_contents_at_range(range) },
+ pub unsafe fn open_contents_at_range(
+ &self,
+ range: &ContentRange,
+ ) -> io::Result<FileContents<T>> {
+ Ok(FileContents {
+ inner: poll_result_once(unsafe { self.inner.open_contents_at_range(range) })?,
at: 0,
- }
+ })
}
/// Following a hardlink.
@@ -291,7 +293,7 @@ impl<T: Clone + ReadAt> FileEntry<T> {
}
/// For use with unsafe accessor methods.
- pub fn content_range(&self) -> io::Result<Option<Range<u64>>> {
+ pub fn content_range(&self) -> io::Result<Option<ContentRange>> {
self.inner.content_range()
}
--
2.39.2
_______________________________________________
pbs-devel mailing list
pbs-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pbs-devel
next prev parent reply other threads:[~2024-06-12 8:24 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-12 8:23 [pbs-devel] [PATCH v3 pxar proxmox-backp 0/6] fix fuse mount performance " Christian Ebner
2024-06-12 8:23 ` [pbs-devel] [PATCH v3 pxar 1/6] accessor: fix minor formatting issue Christian Ebner
2024-06-12 8:23 ` [pbs-devel] [PATCH v3 pxar 2/6] format: add helper for payload header consistency checks Christian Ebner
2024-06-12 8:23 ` [pbs-devel] [PATCH v3 pxar 3/6] format: add helper type ContentRange Christian Ebner
2024-06-12 9:27 ` Fabian Grünbichler
[not found] ` <CAFtnzVcG1CFUhs9WiePBLuDKihHQM8mOiuJKKjhFy+rmuxY4pw@mail.gmail.com>
2024-06-12 11:47 ` Fabian Grünbichler
2024-06-12 11:50 ` Christian Ebner
2024-06-12 8:23 ` [pbs-devel] [PATCH v3 pxar 4/6] decoder: move payload header check for split input Christian Ebner
2024-06-12 8:23 ` Christian Ebner [this message]
2024-06-12 8:24 ` [pbs-devel] [PATCH v3 proxmox-backup 6/6] client: pxar: fix fuse mount performance for split archives Christian Ebner
2024-06-12 9:27 ` [pbs-devel] partially-applied: [PATCH v3 pxar proxmox-backp 0/6] " Fabian Grünbichler
2024-06-12 13:18 ` [pbs-devel] " Christian Ebner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240612082400.110789-6-c.ebner@proxmox.com \
--to=c.ebner@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox