self.state = State::Default;
self.entry.clear_data();
- #[derive(Endian)]
- #[repr(C)]
- struct WithHeader<T: Endian> {
- header: Header,
- data: T,
- }
+ let header: Header = match seq_read_entry_or_eof(&mut self.input).await? {
+ None => return Ok(None),
+ Some(header) => header,
+ };
+
+ if header.htype == format::PXAR_HARDLINK {
+ // The only "dangling" header without an 'Entry' in front of it because it does not
+ // carry its own metadata.
+ self.current_header = header;
+
+ // Hardlinks have no metadata and no additional items.
+ self.entry.metadata = Metadata::default();
+ self.entry.kind = EntryKind::Hardlink(self.read_hardlink().await?);
+
+ Ok(Some(self.entry.take()))
+ } else if header.htype == format::PXAR_ENTRY {
+ self.entry.metadata = Metadata {
+ stat: seq_read_entry(&mut self.input).await?,
+ ..Default::default()
+ };
- let entry: WithHeader<format::Entry> = {
- match seq_read_entry_or_eof(&mut self.input).await? {
- None => return Ok(None),
- Some(entry) => entry,
+ self.current_header = unsafe { mem::zeroed() };
+
+ while self.read_next_item().await? != ItemResult::Entry {}
+
+ if self.entry.is_dir() {
+ self.path_lengths
+ .push(self.entry.path.as_os_str().as_bytes().len());
}
- };
- if entry.header.htype != format::PXAR_ENTRY {
+ Ok(Some(self.entry.take()))
+ } else {
io_bail!(
"expected pxar entry of type 'Entry', got: {:x}",
- entry.header.htype
+ header.htype
);
}
-
- self.current_header = unsafe { mem::zeroed() };
- self.entry.metadata = Metadata {
- stat: entry.data,
- ..Default::default()
- };
-
- while self.read_next_item().await? != ItemResult::Entry {}
-
- if self.entry.is_dir() {
- self.path_lengths
- .push(self.entry.path.as_os_str().as_bytes().len());
- }
-
- Ok(Some(self.entry.take()))
}
async fn read_next_entry(&mut self) -> io::Result<Entry> {
self.entry.kind = EntryKind::Symlink(self.read_symlink().await?);
return Ok(ItemResult::Entry);
}
- format::PXAR_HARDLINK => {
- self.entry.kind = EntryKind::Hardlink(self.read_hardlink().await?);
- return Ok(ItemResult::Entry);
- }
+ format::PXAR_HARDLINK => io_bail!("encountered unexpected hardlink entry"),
format::PXAR_DEVICE => {
self.entry.kind = EntryKind::Device(self.read_device().await?);
return Ok(ItemResult::Entry);
self.check()?;
let file_offset = seq_write_position(&mut self.output).await?;
- self.start_file_do(metadata, file_name).await?;
+ self.start_file_do(Some(metadata), file_name).await?;
seq_write_struct(
&mut self.output,
file_name: &Path,
target: &Path,
) -> io::Result<()> {
- self.add_link(metadata, file_name, target, format::PXAR_SYMLINK)
+ self.add_link(Some(metadata), file_name, target, format::PXAR_SYMLINK)
.await
}
- pub async fn add_hardlink(
- &mut self,
- metadata: &Metadata,
- file_name: &Path,
- target: &Path,
- ) -> io::Result<()> {
- self.add_link(metadata, file_name, target, format::PXAR_HARDLINK)
+ pub async fn add_hardlink(&mut self, file_name: &Path, target: &Path) -> io::Result<()> {
+ self.add_link(None, file_name, target, format::PXAR_HARDLINK)
.await
}
async fn add_link(
&mut self,
- metadata: &Metadata,
+ metadata: Option<&Metadata>,
file_name: &Path,
target: &Path,
htype: u64,
size_of::<format::Device>(),
)
};
- self.add_file_entry(metadata, file_name, Some((format::PXAR_DEVICE, device)))
- .await
+ self.add_file_entry(
+ Some(metadata),
+ file_name,
+ Some((format::PXAR_DEVICE, device)),
+ )
+ .await
}
pub async fn add_fifo(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result<()> {
io_bail!("entry added via add_device must be of type fifo in its metadata");
}
- self.add_file_entry(metadata, file_name, None).await
+ self.add_file_entry(Some(metadata), file_name, None).await
}
pub async fn add_socket(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result<()> {
io_bail!("entry added via add_device must be of type socket in its metadata");
}
- self.add_file_entry(metadata, file_name, None).await
+ self.add_file_entry(Some(metadata), file_name, None).await
}
async fn add_file_entry(
&mut self,
- metadata: &Metadata,
+ metadata: Option<&Metadata>,
file_name: &Path,
entry_htype_data: Option<(u64, &[u8])>,
) -> io::Result<()> {
})
}
- async fn start_file_do(&mut self, metadata: &Metadata, file_name: &[u8]) -> io::Result<()> {
+ async fn start_file_do(
+ &mut self,
+ metadata: Option<&Metadata>,
+ file_name: &[u8],
+ ) -> io::Result<()> {
self.encode_filename(file_name).await?;
- self.encode_metadata(&metadata).await?;
+ if let Some(metadata) = metadata {
+ self.encode_metadata(&metadata).await?;
+ }
Ok(())
}
/// Add a hard link to the archive.
pub async fn add_hardlink<PF: AsRef<Path>, PT: AsRef<Path>>(
&mut self,
- metadata: &Metadata,
file_name: PF,
target: PT,
) -> io::Result<()> {
self.inner
- .add_hardlink(metadata, file_name.as_ref(), target.as_ref())
+ .add_hardlink(file_name.as_ref(), target.as_ref())
.await
}
/// Add a hard link to the archive.
pub fn add_hardlink<PF: AsRef<Path>, PT: AsRef<Path>>(
&mut self,
- metadata: &Metadata,
file_name: PF,
target: PT,
) -> io::Result<()> {
- poll_result_once(
- self.inner
- .add_hardlink(metadata, file_name.as_ref(), target.as_ref()),
- )
+ poll_result_once(self.inner.add_hardlink(file_name.as_ref(), target.as_ref()))
}
/// Add a device node to the archive.