X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=src%2Fencoder%2Fmod.rs;h=79f6db54fd089fca0158add87b47f1951efc8309;hb=d67488626bf97eaf640129f586f75cb1a1daebc9;hp=20ba1ee7f11d95d2101345f2cbd6ead42a69d104;hpb=c7b0cd2a1afe7c96749f82158041464e97fa5b84;p=pxar.git diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 20ba1ee..79f6db5 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -23,6 +23,17 @@ pub mod sync; #[doc(inline)] pub use sync::Encoder; +/// File reference used to create hard links. +#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub struct LinkOffset(u64); + +impl LinkOffset { + #[inline] + pub fn raw(self) -> u64 { + self.0 + } +} + /// Sequential write interface used by the encoder's state machine. /// /// This is our internal writer trait which is available for `std::io::Write` types in the @@ -310,13 +321,14 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { }) } + /// Return a file offset usable with `add_hardlink`. pub async fn add_file( &mut self, metadata: &Metadata, file_name: &Path, file_size: u64, content: &mut dyn SeqRead, - ) -> io::Result<()> { + ) -> io::Result { let mut file = self.create_file(metadata, file_name, file_size).await?; let mut buf = crate::util::vec_new(4096); loop { @@ -327,15 +339,16 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { file.write_all(&buf[..got]).await?; } } - Ok(()) + Ok(file.file_offset()) } + /// Return a file offset usable with `add_hardlink`. pub async fn add_symlink( &mut self, metadata: &Metadata, file_name: &Path, target: &Path, - ) -> io::Result<()> { + ) -> io::Result { self.add_file_entry( Some(metadata), file_name, @@ -344,14 +357,15 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { .await } + /// Return a file offset usable with `add_hardlink`. pub async fn add_hardlink( &mut self, file_name: &Path, target: &Path, - offset: u64, + offset: LinkOffset, ) -> io::Result<()> { let hardlink = format::Hardlink { - offset, + offset: offset.0, data: target.as_os_str().as_bytes().to_vec(), }; let hardlink = unsafe { @@ -360,20 +374,22 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { size_of::(), ) }; - self.add_file_entry( + let _this_offset: LinkOffset = self.add_file_entry( None, file_name, Some((format::PXAR_HARDLINK, hardlink)), ) - .await + .await?; + Ok(()) } + /// Return a file offset usable with `add_hardlink`. pub async fn add_device( &mut self, metadata: &Metadata, file_name: &Path, device: format::Device, - ) -> io::Result<()> { + ) -> io::Result { if !metadata.is_device() { io_bail!("entry added via add_device must have a device mode in its metadata"); } @@ -393,7 +409,8 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { .await } - pub async fn add_fifo(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result<()> { + /// Return a file offset usable with `add_hardlink`. + pub async fn add_fifo(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result { if !metadata.is_fifo() { io_bail!("entry added via add_device must be of type fifo in its metadata"); } @@ -401,7 +418,8 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { self.add_file_entry(Some(metadata), file_name, None).await } - pub async fn add_socket(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result<()> { + /// Return a file offset usable with `add_hardlink`. + pub async fn add_socket(&mut self, metadata: &Metadata, file_name: &Path) -> io::Result { if !metadata.is_socket() { io_bail!("entry added via add_device must be of type socket in its metadata"); } @@ -409,12 +427,13 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { self.add_file_entry(Some(metadata), file_name, None).await } + /// Return a file offset usable with `add_hardlink`. async fn add_file_entry( &mut self, metadata: Option<&Metadata>, file_name: &Path, entry_htype_data: Option<(u64, &[u8])>, - ) -> io::Result<()> { + ) -> io::Result { self.check()?; let file_offset = seq_write_position(&mut self.output).await?; @@ -434,7 +453,7 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> { size: end_offset - file_offset, }); - Ok(()) + Ok(LinkOffset(file_offset)) } /// Helper @@ -673,6 +692,11 @@ impl<'a> Drop for FileImpl<'a> { } impl<'a> FileImpl<'a> { + /// Get the file offset to be able to reference it with `add_hardlink`. + pub fn file_offset(&self) -> LinkOffset { + LinkOffset(self.goodbye_item.offset) + } + fn check_remaining(&self, size: usize) -> io::Result<()> { if size as u64 > self.remaining_size { io_bail!("attempted to write more than previously allocated");