+use std::io::{self, Read, Write};
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 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);
}
}
}
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(),
})
}
pub struct FileEntryImpl<T: Clone + ReadAt> {
input: T,
entry: Entry,
- decoder: Option<DecoderImpl<SeqReadAtAdapter<T>>>,
end_offset: u64,
}
}
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),
)),
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,
})
}
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
}
- 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() },
path,
kind: EntryKind::EndOfDirectory,
metadata: Metadata::default(),
- offset,
},
path_lengths: Vec::new(),
state: State::Begin,
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()));
}
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);
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,
path: PathBuf,
metadata: Metadata,
kind: EntryKind,
- offset: Option<u64>,
}
/// General accessors.
fn clear_data(&mut self) {
self.metadata = Metadata::default();
self.kind = EntryKind::EndOfDirectory;
- self.offset = None;
}
fn internal_default() -> Self {
path: PathBuf::default(),
metadata: Metadata::default(),
kind: EntryKind::EndOfDirectory,
- offset: None,
}
}
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 {