and fix FileContentImpl offsets
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
+use std::io::{self, Read, Write};
use std::os::unix::ffi::OsStrExt;
use std::sync::Arc;
use std::os::unix::ffi::OsStrExt;
use std::sync::Arc;
let mut accessor = Accessor::open(file)?;
let mut dir = accessor.open_root_ref()?;
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))?;
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)?;
- println!("{:?}", entry.metadata());
+ bail!("unknown command: {}", cmd);
}
async fn lookup_self(&self) -> io::Result<FileEntryImpl<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,
Ok(FileEntryImpl {
input: self.input.clone(),
entry,
- decoder: Some(decoder),
end_offset: self.end_offset(),
})
}
end_offset: self.end_offset(),
})
}
pub struct FileEntryImpl<T: Clone + ReadAt> {
input: T,
entry: Entry,
pub struct FileEntryImpl<T: Clone + ReadAt> {
input: T,
entry: Entry,
- decoder: Option<DecoderImpl<SeqReadAtAdapter<T>>>,
}
pub async fn contents(&self) -> io::Result<FileContentsImpl<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"))?;
- 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),
)),
self.input.clone(),
offset..(offset + size),
)),
pub async fn get_entry(&self) -> io::Result<FileEntryImpl<T>> {
let end_offset = self.entry_range.end;
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?;
.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,
Ok(FileEntryImpl {
input: self.dir.input.clone(),
entry,
buf = &mut buf[..(remaining as usize)];
}
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
Self::new_full(input, "/".into()).await
}
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() },
let this = DecoderImpl {
input,
current_header: unsafe { mem::zeroed() },
path,
kind: EntryKind::EndOfDirectory,
metadata: Metadata::default(),
path,
kind: EntryKind::EndOfDirectory,
metadata: Metadata::default(),
},
path_lengths: Vec::new(),
state: State::Begin,
},
path_lengths: Vec::new(),
state: State::Begin,
format::PXAR_GOODBYE => {
if self.with_goodbye_tables {
self.entry.kind = EntryKind::EndOfDirectory;
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()));
}
self.state = State::InPayload;
return Ok(Some(self.entry.take()));
}
return Ok(ItemResult::Entry);
}
format::PXAR_PAYLOAD => {
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(),
self.entry.kind = EntryKind::File {
size: self.current_header.content_size(),
};
self.state = State::InPayload;
return Ok(ItemResult::Entry);
};
self.state = State::InPayload;
return Ok(ItemResult::Entry);
Device(format::Device),
/// Regular file.
Device(format::Device),
/// Regular file.
+ File { size: u64, offset: Option<u64> },
/// Directory entry. When iterating through an archive, the contents follow next.
Directory,
/// Directory entry. When iterating through an archive, the contents follow next.
Directory,
path: PathBuf,
metadata: Metadata,
kind: EntryKind,
path: PathBuf,
metadata: Metadata,
kind: EntryKind,
fn clear_data(&mut self) {
self.metadata = Metadata::default();
self.kind = EntryKind::EndOfDirectory;
fn clear_data(&mut self) {
self.metadata = Metadata::default();
self.kind = EntryKind::EndOfDirectory;
}
fn internal_default() -> Self {
}
fn internal_default() -> Self {
path: PathBuf::default(),
metadata: Metadata::default(),
kind: EntryKind::EndOfDirectory,
path: PathBuf::default(),
metadata: Metadata::default(),
kind: EntryKind::EndOfDirectory,
- /// 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 {
/// Get the full path of this file within the current pxar directory structure.
#[inline]
pub fn path(&self) -> &Path {