From 718a207ab3c8eb73948b8acbd9ab6e79585628a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bardon?= Date: Sun, 19 Apr 2026 20:36:19 +0200 Subject: [PATCH 1/2] Add `Entry::set_path_bytes` This allows mapping paths when unpacking an archive. --- src/entry.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/entry.rs b/src/entry.rs index fbc2efb9..3a90fadd 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -88,6 +88,14 @@ impl<'a, R: Read> Entry<'a, R> { self.fields.path_bytes() } + /// Sets the raw bytes listed for this entry. + /// + /// Subsequent calls to [`path_bytes`][Self::path_bytes] will return the + /// provided value. + pub fn set_path_bytes(&mut self, path_bytes: Vec) { + self.fields.long_pathname = Some(path_bytes); + } + /// Returns the link name for this entry, if any is found. /// /// This method may fail if the pathname is not valid Unicode and this is From 06ea113b018af846b39a397f349b8b3e6677f7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Bardon?= Date: Sun, 19 Apr 2026 22:27:45 +0200 Subject: [PATCH 2/2] Add `Archive::unpack_mapped` This allows mapping paths while extracting, if [alexcrichton/tar-rs#448] gets merged. See the above pull request for rationale regarding this addition. [alexcrichton/tar-rs#448]: https://github.com/alexcrichton/tar-rs/pull/448 --- src/archive.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/archive.rs b/src/archive.rs index a3ae6f01..68db456d 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -120,7 +120,18 @@ impl Archive { /// ``` pub fn unpack>(&mut self, dst: P) -> io::Result<()> { let me: &mut Archive = self; - me._unpack(dst.as_ref()) + me._unpack(dst.as_ref(), |_| {}) + } + + /// Same as [`unpack`][Self::unpack], but allows mapping entries during the + /// iteration. + pub fn unpack_mapped>( + &mut self, + dst: P, + map_entry: impl Fn(&mut Entry), + ) -> io::Result<()> { + let me: &mut Archive = self; + me._unpack(dst.as_ref(), map_entry) } /// Set the mask of the permission bits when unpacking this entry. @@ -226,7 +237,7 @@ impl Archive { }) } - fn _unpack(&mut self, dst: &Path) -> io::Result<()> { + fn _unpack(&mut self, dst: &Path, map_entry: impl Fn(&mut Entry)) -> io::Result<()> { if dst.symlink_metadata().is_err() { fs::create_dir_all(dst) .map_err(|e| TarError::new(format!("failed to create `{}`", dst.display()), e))?; @@ -245,6 +256,11 @@ impl Archive { let mut directories = Vec::new(); for entry in self._entries(None)? { let mut file = entry.map_err(|e| TarError::new("failed to iterate over archive", e))?; + + // Map the entry if needed (e.g. to map its path). + // In most cases, this will be a no-op. + map_entry(&mut file); + if file.header().entry_type() == crate::EntryType::Directory { directories.push(file); } else {