From: Dominik Csapak <d.csapak@proxmox.com>
To: Proxmox Backup Server development discussion
<pbs-devel@lists.proxmox.com>,
Filip Schauer <f.schauer@proxmox.com>
Subject: Re: [pbs-devel] [PATCH v2 proxmox 1/1] fix #4995: compression: Include symlinks in zip file restore
Date: Fri, 24 Nov 2023 08:56:59 +0100 [thread overview]
Message-ID: <0f719e51-3407-4923-bd22-502efb4bca4d@proxmox.com> (raw)
In-Reply-To: <20231123130652.416129-2-f.schauer@proxmox.com>
a few high level comments (did not look too closely on the code):
* if we change the function/struct parameters anyway wouldn't it make more sense
to add a 'filetype' enum instead of having a 'is_file' bool and a symlink option?
i used the bool because we only had files + dirs, but now we add a third type,
but imho representing the types properly would be better
we even could put the content into the various enum parts
(or even make the ZipEntry an enum altogether?)
i know this refactoring is much more work than slapping just a new parameter on,
but it makes it easier to understand the code and expand it if we need it
(honestly i probably should have done so initially when adding the code)
* what i'm missing here a bit is the source on how to encode symlinks in zip.
the "official" zip spec[0] only talks about (symbolic) links in the description
of a "-UNIX Extra Field" but you simply encode it here into the content
how did you arrive at that solution?
(also generally a commit message is a good idea ;) )
* for these things i'd also like a short comment (does not have to be in the
commit message) on which systems you did test this, e.g. zipinfo/zip/unar on linux
explorer on windows, mac (?), etc.
* if you want to go the extra mile, i guess this would be a good time to add tests
that create a new zip from test data, to see if they don't break with your changes
0: https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.9.TXT
On 11/23/23 14:06, Filip Schauer wrote:
> Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
> ---
> proxmox-compression/src/zip.rs | 46 ++++++++++++++++++++++++++--------
> 1 file changed, 35 insertions(+), 11 deletions(-)
>
> diff --git a/proxmox-compression/src/zip.rs b/proxmox-compression/src/zip.rs
> index d2d3fd8..e30f50a 100644
> --- a/proxmox-compression/src/zip.rs
> +++ b/proxmox-compression/src/zip.rs
> @@ -204,6 +204,7 @@ pub struct ZipEntry {
> offset: u64,
> is_file: bool,
> is_utf8_filename: bool,
> + symlink_target: Option<OsString>,
> }
>
> impl ZipEntry {
> @@ -211,7 +212,13 @@ impl ZipEntry {
> ///
> /// if is_file is false the path will contain an trailing separator,
> /// so that the zip file understands that it is a directory
> - pub fn new<P: AsRef<Path>>(path: P, mtime: i64, mode: u16, is_file: bool) -> Self {
> + pub fn new<P: AsRef<Path>>(
> + path: P,
> + mtime: i64,
> + mode: u16,
> + is_file: bool,
> + symlink_target: Option<P>,
> + ) -> Self {
> let mut relpath = PathBuf::new();
>
> for comp in path.as_ref().components() {
> @@ -226,6 +233,7 @@ impl ZipEntry {
>
> let filename: OsString = relpath.into();
> let is_utf8_filename = filename.to_str().is_some();
> + let symlink_target_osstr = symlink_target.map(|x| x.as_ref().into());
>
> Self {
> filename,
> @@ -237,6 +245,7 @@ impl ZipEntry {
> offset: 0,
> is_file,
> is_utf8_filename,
> + symlink_target: symlink_target_osstr,
> }
> }
>
> @@ -360,7 +369,9 @@ impl ZipEntry {
> comment_len: 0,
> start_disk: 0,
> internal_flags: 0,
> - external_flags: (self.mode as u32) << 16 | (!self.is_file as u32) << 4,
> + external_flags: (self.mode as u32) << 16
> + | (self.symlink_target.is_some() as u32) << 5
> + | (!self.is_file as u32) << 4,
> offset,
> },
> )
> @@ -486,23 +497,30 @@ impl<W: AsyncWrite + Unpin> ZipEncoder<W> {
> .ok_or_else(|| format_err!("had no target during add entry"))?;
> entry.offset = self.byte_count.try_into()?;
> self.byte_count += entry.write_local_header(&mut target).await?;
> - if let Some(content) = content {
> - let mut reader = HashWrapper::new(content);
> +
> + if content.is_some() || entry.symlink_target.is_some() {
> let mut enc = DeflateEncoder::with_quality(target, Level::Fastest);
>
> - enc.compress(&mut reader).await?;
> + if let Some(content) = content {
> + let mut reader = HashWrapper::new(content);
> + enc.compress(&mut reader).await?;
> + entry.crc32 = reader.finish().0;
> + } else if let Some(symlink_target) = entry.symlink_target.as_ref() {
> + let cursor = std::io::Cursor::new(symlink_target.as_bytes());
> + let mut reader = HashWrapper::new(cursor);
> + enc.compress(&mut reader).await?;
> + entry.crc32 = reader.finish().0;
> + }
> +
> let total_in = enc.total_in();
> let total_out = enc.total_out();
> target = enc.into_inner();
>
> - let (crc32, _reader) = reader.finish();
> -
> self.byte_count += total_out as usize;
> entry.compressed_size = total_out;
> entry.uncompressed_size = total_in;
> -
> - entry.crc32 = crc32;
> }
> +
> self.byte_count += entry.write_data_descriptor(&mut target).await?;
> self.target = Some(target);
>
> @@ -658,10 +676,16 @@ where
>
> if entry.file_type().is_file() {
> let file = tokio::fs::File::open(entry.path()).await?;
> - let ze = ZipEntry::new(entry_path_no_base, mtime, mode, true);
> + let ze = ZipEntry::new(entry_path_no_base, mtime, mode, true, None);
> Ok(Some((ze, Some(file))))
> } else if entry.file_type().is_dir() {
> - let ze = ZipEntry::new(entry_path_no_base, mtime, mode, false);
> + let ze = ZipEntry::new(entry_path_no_base, mtime, mode, false, None);
> + let content: Option<tokio::fs::File> = None;
> + Ok(Some((ze, content)))
> + } else if entry.file_type().is_symlink() {
> + let target = std::fs::read_link(entry.path())?;
> + let ze =
> + ZipEntry::new(entry_path_no_base, mtime, mode, true, Some(target.as_ref()));
> let content: Option<tokio::fs::File> = None;
> Ok(Some((ze, content)))
> } else {
next prev parent reply other threads:[~2023-11-24 7:57 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-23 13:06 [pbs-devel] [PATCH v2 many] fix #4995: " Filip Schauer
2023-11-23 13:06 ` [pbs-devel] [PATCH v2 proxmox 1/1] fix #4995: compression: " Filip Schauer
2023-11-24 7:56 ` Dominik Csapak [this message]
2023-11-24 11:03 ` Lukas Wagner
2023-12-14 14:50 ` Filip Schauer
2023-11-23 13:06 ` [pbs-devel] [PATCH v2 backup 1/1] fix #4995: pxar: " Filip Schauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0f719e51-3407-4923-bd22-502efb4bca4d@proxmox.com \
--to=d.csapak@proxmox.com \
--cc=f.schauer@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal