Package: zip
Version: 3.0-12
Severity: normal
Tags: patch upstream

How to reproduce:

Prep phase:

porridge@butla:~/tmp$ mkdir dir
porridge@butla:~/tmp$ echo foo > dir/file
porridge@butla:~/tmp$ ln -s file dir/link
porridge@butla:~/tmp$ find dir -ls
 50725398      4 drwxrwxr-x   2 porridge porridge     4096 lut 17 18:01 dir
 50725399      4 -rw-rw-r--   1 porridge porridge        4 lut 17 18:01 dir/file
 50725400      0 lrwxrwxrwx   1 porridge porridge        4 lut 17 18:01 
dir/link -> file
porridge@butla:~/tmp$ zip --verbose --symlink --recurse-paths --filesync 
dir.zip dir
  adding: dir/  (in=0) (out=0) (stored 0%)
  adding: dir/file      (in=4) (out=4) (stored 0%)
  adding: dir/link      (in=4) (out=4) (stored 0%)
total bytes=8, compressed=8 -> 0% savings
porridge@butla:~/tmp$

So far so good, now the unexpected part:

porridge@butla:~/tmp$ zip --verbose --symlink --recurse-paths --filesync 
dir.zip dir
      ok: dir/
      ok: dir/file
updating: dir/link      (in=4) (out=4) (stored 0%)
total bytes=8, compressed=8 -> 0% savings
porridge@butla:~/tmp$ zip --verbose --symlink --recurse-paths --filesync 
dir.zip dir
      ok: dir/
      ok: dir/file
updating: dir/link      (in=4) (out=4) (stored 0%)
total bytes=8, compressed=8 -> 0% savings
porridge@butla:~/tmp$

As you can see, the symlink is always considered to be in need of update.
While the expected behaviour would be:

porridge@butla:~/tmp$ zip --verbose --symlink --recurse-paths --filesync 
dir.zip dir
Archive is current
porridge@butla:~/tmp$


I managed to produce the following patch which seems to fix the issue. It
basically changes the UNIX-specific implementation of the filetime() function
to retrieve the size not just for regular files, but also for symlinks. This
way the `current` flag is set to 1 in zip.c:6018 like for regular files.

The above (expected) behaviour is for a zip package built with this patch.

--- zip-3.0.orig/unix/unix.c
+++ zip-3.0/unix/unix.c
@@ -423,7 +423,7 @@ ulg filetime(f, a, n, t)
     }
   }
   if (n != NULL)
-    *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L;
+    *n = ((s.st_mode & S_IFMT) == S_IFREG || (s.st_mode & S_IFMT) == S_IFLNK) 
? s.st_size : -1L;
   if (t != NULL) {
     t->atime = s.st_atime;
     t->mtime = s.st_mtime;


-- System Information:
Debian Release: 11.2
  APT prefers stable-security
  APT policy: (500, 'stable-security'), (500, 'stable-debug'), (500, 'stable')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.10.0-11-amd64 (SMP w/4 CPU threads)
Locale: LANG=pl_PL.UTF-8, LC_CTYPE=pl_PL.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages zip depends on:
ii  libbz2-1.0  1.0.8-4
ii  libc6       2.31-13+deb11u2

Versions of packages zip recommends:
ii  unzip  6.0-26

zip suggests no packages.

-- no debconf information

Reply via email to