]> git.proxmox.com Git - pxar.git/commitdiff
fix hardlink format
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Fri, 5 Jun 2020 09:52:40 +0000 (11:52 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Fri, 5 Jun 2020 10:18:55 +0000 (12:18 +0200)
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
src/decoder.rs
src/encoder.rs
src/encoder/aio.rs
src/encoder/sync.rs

index 7c53a2ec9b77f5c65026a4a457cf471ac5a2ad5d..79277b5716cc580c0aca62846fed7fbd7eef2304 100644 (file)
@@ -346,41 +346,43 @@ impl<I: SeqRead> DecoderImpl<I> {
         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> {
@@ -460,10 +462,7 @@ impl<I: SeqRead> DecoderImpl<I> {
                 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);
index 123bab65c338d49d92bf1f40c4fbd3f2b3b16e11..6c1289b1faa32a8b654d47d6af3823f6f58e9836 100644 (file)
@@ -286,7 +286,7 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
         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,
@@ -336,23 +336,18 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
         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,
@@ -382,8 +377,12 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
                 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<()> {
@@ -391,7 +390,7 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
             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<()> {
@@ -399,12 +398,12 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
             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<()> {
@@ -475,9 +474,15 @@ impl<'a, T: SeqWrite + 'a> EncoderImpl<'a, T> {
         })
     }
 
-    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(())
     }
 
index 8f96fc3b645b3b9e009ea67bb9d5d45f95896ec8..c884c1bc70edf12a4c9bc27b1bb26a3596558356 100644 (file)
@@ -147,12 +147,11 @@ impl<'a, T: SeqWrite + 'a> Encoder<'a, T> {
     /// 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
     }
 
index 8a37072ab61f9218bf45d7cc5e5edc39b1694991..9c8445357c562d6691075500dcb75e451507ed7b 100644 (file)
@@ -129,14 +129,10 @@ impl<'a, T: SeqWrite + 'a> Encoder<'a, T> {
     /// 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.