mirror of
git://git.proxmox.com/git/pxar.git
synced 2025-01-08 01:17:40 +03:00
pxarcmd example: implement 'cat'
and fix FileContentImpl offsets Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
dc4a2854c0
commit
c76d3f980b
@ -1,3 +1,4 @@
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -25,16 +26,27 @@ fn main() -> Result<(), Error> {
|
||||
let mut accessor = Accessor::open(file)?;
|
||||
let mut dir = accessor.open_root_ref()?;
|
||||
|
||||
let mut buf = Vec::new();
|
||||
|
||||
for file in args {
|
||||
let entry = dir
|
||||
.lookup(&file)?
|
||||
.ok_or_else(|| format_err!("no such file in archive: {:?}", file))?;
|
||||
if file.as_bytes().ends_with(b"/") {
|
||||
for file in entry.enter_directory()?.read_dir() {
|
||||
println!("{:?}", file?.file_name());
|
||||
|
||||
if cmd == "ls" {
|
||||
if file.as_bytes().ends_with(b"/") {
|
||||
for file in entry.enter_directory()?.read_dir() {
|
||||
println!("{:?}", file?.file_name());
|
||||
}
|
||||
} else {
|
||||
println!("{:?}", entry.metadata());
|
||||
}
|
||||
} else if cmd == "cat" {
|
||||
buf.clear();
|
||||
entry.contents()?.read_to_end(&mut buf)?;
|
||||
io::stdout().write_all(&buf)?;
|
||||
} else {
|
||||
println!("{:?}", entry.metadata());
|
||||
bail!("unknown command: {}", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -272,11 +272,10 @@ impl<T: Clone + ReadAt> DirectoryImpl<T> {
|
||||
}
|
||||
|
||||
async fn lookup_self(&self) -> io::Result<FileEntryImpl<T>> {
|
||||
let (entry, decoder) = self.decode_one_entry(self.entry_range(), None).await?;
|
||||
let (entry, _decoder) = self.decode_one_entry(self.entry_range(), None).await?;
|
||||
Ok(FileEntryImpl {
|
||||
input: self.input.clone(),
|
||||
entry,
|
||||
decoder: Some(decoder),
|
||||
end_offset: self.end_offset(),
|
||||
})
|
||||
}
|
||||
@ -400,7 +399,6 @@ impl<T: Clone + ReadAt> DirectoryImpl<T> {
|
||||
pub struct FileEntryImpl<T: Clone + ReadAt> {
|
||||
input: T,
|
||||
entry: Entry,
|
||||
decoder: Option<DecoderImpl<SeqReadAtAdapter<T>>>,
|
||||
end_offset: u64,
|
||||
}
|
||||
|
||||
@ -415,12 +413,14 @@ impl<T: Clone + ReadAt> FileEntryImpl<T> {
|
||||
}
|
||||
|
||||
pub async fn contents(&self) -> io::Result<FileContentsImpl<T>> {
|
||||
let offset = self
|
||||
.entry
|
||||
.offset
|
||||
.ok_or_else(|| io_format_err!("cannot open file, reader provided no offset"))?;
|
||||
match self.entry.kind {
|
||||
EntryKind::File { size } => Ok(FileContentsImpl::new(
|
||||
EntryKind::File { offset: None, .. } => {
|
||||
io_bail!("cannot open file, reader provided no offset")
|
||||
}
|
||||
EntryKind::File {
|
||||
size,
|
||||
offset: Some(offset),
|
||||
} => Ok(FileContentsImpl::new(
|
||||
self.input.clone(),
|
||||
offset..(offset + size),
|
||||
)),
|
||||
@ -494,16 +494,14 @@ impl<'a, T: Clone + ReadAt> DirEntryImpl<'a, T> {
|
||||
|
||||
pub async fn get_entry(&self) -> io::Result<FileEntryImpl<T>> {
|
||||
let end_offset = self.entry_range.end;
|
||||
let (entry, decoder) = self
|
||||
let (entry, _decoder) = self
|
||||
.dir
|
||||
.decode_one_entry(self.entry_range.clone(), Some(&self.file_name))
|
||||
.await?;
|
||||
let decoder = if entry.is_dir() { Some(decoder) } else { None };
|
||||
|
||||
Ok(FileEntryImpl {
|
||||
input: self.dir.input.clone(),
|
||||
entry,
|
||||
decoder,
|
||||
end_offset,
|
||||
})
|
||||
}
|
||||
@ -538,7 +536,9 @@ impl<T: Clone + ReadAt> FileContentsImpl<T> {
|
||||
buf = &mut buf[..(remaining as usize)];
|
||||
}
|
||||
|
||||
(&self.input as &dyn ReadAt).read_at(buf, offset).await
|
||||
(&self.input as &dyn ReadAt)
|
||||
.read_at(buf, self.range.start + offset)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,11 +185,7 @@ impl<T: SeqRead> DecoderImpl<T> {
|
||||
Self::new_full(input, "/".into()).await
|
||||
}
|
||||
|
||||
pub(crate) async fn new_full(mut input: T, path: PathBuf) -> io::Result<Self> {
|
||||
let offset = (&mut input as &mut dyn SeqRead)
|
||||
.position()
|
||||
.await
|
||||
.transpose()?;
|
||||
pub(crate) async fn new_full(input: T, path: PathBuf) -> io::Result<Self> {
|
||||
let this = DecoderImpl {
|
||||
input,
|
||||
current_header: unsafe { mem::zeroed() },
|
||||
@ -197,7 +193,6 @@ impl<T: SeqRead> DecoderImpl<T> {
|
||||
path,
|
||||
kind: EntryKind::EndOfDirectory,
|
||||
metadata: Metadata::default(),
|
||||
offset,
|
||||
},
|
||||
path_lengths: Vec::new(),
|
||||
state: State::Begin,
|
||||
@ -239,11 +234,6 @@ impl<T: SeqRead> DecoderImpl<T> {
|
||||
format::PXAR_GOODBYE => {
|
||||
if self.with_goodbye_tables {
|
||||
self.entry.kind = EntryKind::EndOfDirectory;
|
||||
let offset = (&mut self.input as &mut dyn SeqRead)
|
||||
.position()
|
||||
.await
|
||||
.transpose()?;
|
||||
self.entry.offset = offset;
|
||||
self.state = State::InPayload;
|
||||
return Ok(Some(self.entry.take()));
|
||||
}
|
||||
@ -432,8 +422,13 @@ impl<T: SeqRead> DecoderImpl<T> {
|
||||
return Ok(ItemResult::Entry);
|
||||
}
|
||||
format::PXAR_PAYLOAD => {
|
||||
let offset = (&mut self.input as &mut dyn SeqRead)
|
||||
.position()
|
||||
.await
|
||||
.transpose()?;
|
||||
self.entry.kind = EntryKind::File {
|
||||
size: self.current_header.content_size(),
|
||||
offset,
|
||||
};
|
||||
self.state = State::InPayload;
|
||||
return Ok(ItemResult::Entry);
|
||||
|
12
src/lib.rs
12
src/lib.rs
@ -80,7 +80,7 @@ pub enum EntryKind {
|
||||
Device(format::Device),
|
||||
|
||||
/// Regular file.
|
||||
File { size: u64 },
|
||||
File { size: u64, offset: Option<u64> },
|
||||
|
||||
/// Directory entry. When iterating through an archive, the contents follow next.
|
||||
Directory,
|
||||
@ -97,7 +97,6 @@ pub struct Entry {
|
||||
path: PathBuf,
|
||||
metadata: Metadata,
|
||||
kind: EntryKind,
|
||||
offset: Option<u64>,
|
||||
}
|
||||
|
||||
/// General accessors.
|
||||
@ -106,7 +105,6 @@ impl Entry {
|
||||
fn clear_data(&mut self) {
|
||||
self.metadata = Metadata::default();
|
||||
self.kind = EntryKind::EndOfDirectory;
|
||||
self.offset = None;
|
||||
}
|
||||
|
||||
fn internal_default() -> Self {
|
||||
@ -114,7 +112,6 @@ impl Entry {
|
||||
path: PathBuf::default(),
|
||||
metadata: Metadata::default(),
|
||||
kind: EntryKind::EndOfDirectory,
|
||||
offset: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,13 +121,6 @@ impl Entry {
|
||||
this
|
||||
}
|
||||
|
||||
/// If the underlying I/O implementation supports seeking, this will be filled with the start
|
||||
/// offset of this entry, allowing one to jump back to this entry later on.
|
||||
#[inline]
|
||||
pub fn offset(&self) -> Option<u64> {
|
||||
self.offset
|
||||
}
|
||||
|
||||
/// Get the full path of this file within the current pxar directory structure.
|
||||
#[inline]
|
||||
pub fn path(&self) -> &Path {
|
||||
|
Loading…
Reference in New Issue
Block a user