I managed to fix almost half the failures in knownproblems by making
--gnu always be tried rather than only when GZIP_OS_UNIX is found.
Doing the same for --rsyncable and --new-rsyncable probably makes sense
too.

The --new-rsyncable was written for gzip 1.4, while gzip 1.6 does things
a bit different (it's a bit of a hybrid between the original rsyncable
and the 1.4 rsyncable).  I have added a new --16-rsyncable option to
zgz that matches the new behaviour, which fixes this bug.

I have tested both gzip 1.4 and gzip 1.6 with --rsyncable and pristine-tar
now handles both.

-- 
Len Sorensen
>From dd0d04fa27d77c1a808e43a313788b63200e54b5 Mon Sep 17 00:00:00 2001
From: Len Sorensen <lsore...@mythtv64.local.lan>
Date: Thu, 6 Jul 2017 16:52:41 -0400
Subject: [PATCH] Try --gnu all the time and fix current rsyncable

The rsyncable code was not quite in sync with what gzip --rsyncable
actually does on debian.  Resolving this fixes bug 805488.

Only trying --gnu when GZIP_OS_UNIX is found causes a lot of possible
matches to be missed.  Making --gnu always be attemped no matter what
fixes the following knownproblem cases:

abind_1.1.0.orig.tar.gz
arj_3.10.22.orig.tar.gz
commons-configuration_1.6.orig.tar.gz
dot2tex_2.8.5.orig.tar.gz
evolver_2.30c.orig.tar.gz
faad2_2.6.1.orig.tar.gz
intercal_0.28.orig.tar.gz
libapache-session-perl_1.87.orig.tar.gz
libdatetime-event-sunrise-perl_0.0501.orig.tar.gz
libfreezethaw-perl_0.45.orig.tar.gz
libhtml-linkextractor-perl_0.130.orig.tar.gz
libhtml-prototype-perl_1.48.orig.tar.gz
libhttp-browserdetect-perl_0.98.orig.tar.gz
libinline-perl_0.45.orig.tar.gz
libmail-sendeasy-perl_1.2.orig.tar.gz
libmail-sender-perl_0.8.13.orig.tar.gz
libmail-sender-perl_0.8.16.orig.tar.gz
libmarc-lint-perl_1.43.orig.tar.gz
libmp3-tag-perl_0.9714.orig.tar.gz
libnet-daemon-perl_0.43.orig.tar.gz
libnet-ifconfig-wrapper-perl_0.09.orig.tar.gz
libpdf-api2-perl_0.72.003.orig.tar.gz
libpdf-api2-perl_0.73.orig.tar.gz
libpdf-reuse-perl_0.35.orig.tar.gz
libphp-adodb_5.07.orig.tar.gz
libplrpc-perl_0.2020.orig.tar.gz
libpod-simple-wiki-perl_0.08.orig.tar.gz
libreadonly-perl_1.03.orig.tar.gz
libspreadsheet-writeexcel-perl_2.25.orig.tar.gz
libterm-readline-perl-perl_1.0302.orig.tar.gz
libxml-smart-perl_1.6.9.orig.tar.gz
pyparsing_1.5.1.orig.tar.gz
python-kinterbasdb_3.2.orig.tar.gz
rmetrics_260.72.orig.tar.gz
scalpel_1.60.orig.tar.gz
ttf-umefont_401.orig.tar.gz
ttf-umefont_402.orig.tar.gz
unace_1.2b.orig.tar.gz
unrar-nonfree_3.8.5.orig.tar.gz
---
 pristine-gz        | 13 +++++--------
 zgz/gzip/deflate.c | 27 ++++++++++++++++++++-------
 zgz/gzip/gzip.c    |  4 ++--
 zgz/gzip/gzip.h    |  2 +-
 zgz/zgz.c          | 15 ++++++++++-----
 5 files changed, 38 insertions(+), 23 deletions(-)

diff --git a/pristine-gz b/pristine-gz
index 2f67160..d110eaf 100755
--- a/pristine-gz
+++ b/pristine-gz
@@ -188,13 +188,10 @@ sub reproducegz {
 
   my @try;
 
-  if ($os == $fconstants{GZIP_OS_UNIX}) {
-    # for 98% of the cases the simple heuristic above works
-    # and it was produced by gnu gzip.
-    push @try, [ '--gnu', @args ];
-    push @try, [ '--gnu', @args, '--rsyncable' ];
-    push @try, [ '--gnu', @args, '--new-rsyncable' ];
-  }
+  push @try, [ '--gnu', @args ];
+  push @try, [ '--gnu', @args, '--rsyncable' ];
+  push @try, [ '--gnu', @args, '--new-rsyncable' ];
+  push @try, [ '--gnu', @args, '--16-rsyncable' ];
 
   if ($name =~ /\//) {
     push @args, "--original-name", $name;
@@ -301,7 +298,7 @@ sub gengz {
   my @params = split(' ', $delta->{params});
   while (@params) {
     $_ = shift @params;
-    next if /^(--gnu|--rsyncable|--new-rsyncable|-[nmM1-9])$/;
+    next if /^(--gnu|--rsyncable|--new-rsyncable|--16-rsyncable|-[nmM1-9])$/;
     if (/^(--original-name|--quirk|--osflag)$/) {
       shift @params;
       next;
diff --git a/zgz/gzip/deflate.c b/zgz/gzip/deflate.c
index 780e500..016b757 100644
--- a/zgz/gzip/deflate.c
+++ b/zgz/gzip/deflate.c
@@ -107,11 +107,19 @@ int RSYNC_WIN = 4096;
 /* Whether to enable compatability with Debian's old rsyncable patch. */
 int debian_rsyncable = 1;
 
-void disable_debian_rsyncable () {
+void set_14_rsyncable () {
 	debian_rsyncable = 0;
 	RSYNC_WIN = 8192;
 }
 
+/* gzip 1.6 uses a different rsyncable that is a hybrid between the
+ * original and the gzip 1.4 version
+ */
+void set_16_rsyncable () {
+	debian_rsyncable = 2;
+	RSYNC_WIN = 8192;
+}
+
 #define RSYNC_SUM_MATCH_DEBIAN(sum) ((sum) % RSYNC_WIN == 0)
 #define RSYNC_SUM_MATCH(sum) (((sum) & (RSYNC_WIN - 1)) == 0)
 /* Whether window sum matches magic value */
@@ -532,9 +540,9 @@ static void rsync_roll(unsigned start, unsigned num)
 	rsync_sum += (ulg)window[i];
 	/* Old character out */
 	rsync_sum -= (ulg)window[i - RSYNC_WIN];
-	if (debian_rsyncable && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH_DEBIAN(rsync_sum))
+	if (debian_rsyncable == 1 && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH_DEBIAN(rsync_sum))
 	    rsync_chunk_end = i;
-	if (! debian_rsyncable && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
+	if (debian_rsyncable != 1 && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
 	    rsync_chunk_end = i;
     }
 }
@@ -650,7 +658,7 @@ static void deflate_fast(int pack_level, int rsync)
  * evaluation for matches: a match is finally adopted only if there is
  * no better match at the next window position.
  */
-void gnu_deflate(int pack_level, int rsync, int newrsync)
+void gnu_deflate(int pack_level, int rsync, int rsync14, int rsync16)
 {
     IPos hash_head;          /* head of hash chain */
     IPos prev_match;         /* previous match */
@@ -658,11 +666,16 @@ void gnu_deflate(int pack_level, int rsync, int newrsync)
     int match_available = 0; /* set if previous match exists */
     register unsigned match_length = MIN_MATCH-1; /* length of best match */
 
-    /* The newrsync mode superscedes Debian's old, somewhat broken
+    /* The rsync14 mode superscedes Debian's old, somewhat broken
      * rsync patch. */
-    if (newrsync) {
+    if (rsync14) {
+	    rsync=1;
+	    set_14_rsyncable();
+    }
+    /* The rsync16 mode superscedes the others yet again */
+    if (rsync16) {
 	    rsync=1;
-	    disable_debian_rsyncable();
+	    set_16_rsyncable();
     }
 
     if (pack_level <= 3) {
diff --git a/zgz/gzip/gzip.c b/zgz/gzip/gzip.c
index a9a39dc..41d2175 100644
--- a/zgz/gzip/gzip.c
+++ b/zgz/gzip/gzip.c
@@ -38,7 +38,7 @@ static off_t bytes_in;  /* number of input bytes */
  * Deflate in to out.
  * IN assertions: the input and output buffers are cleared.
  */
-void gnuzip(int in, int out, char *origname, ulg timestamp, int level, int osflag, int rsync, int newrsync)
+void gnuzip(int in, int out, char *origname, ulg timestamp, int level, int osflag, int rsync, int rsync14, int rsync16)
 {
     uch  flags = 0;         /* general purpose bit flags */
     ush  deflate_flags = 0; /* pkzip -es, -en or -ex equivalent */
@@ -76,7 +76,7 @@ void gnuzip(int in, int out, char *origname, ulg timestamp, int level, int osfla
 	} while (*p++);
     }
 
-    gnu_deflate(level, rsync, newrsync);
+    gnu_deflate(level, rsync, rsync14, rsync16);
 
     /* Write the crc and uncompressed size */
     put_long(crc);
diff --git a/zgz/gzip/gzip.h b/zgz/gzip/gzip.h
index 267a2ec..170bfa4 100644
--- a/zgz/gzip/gzip.h
+++ b/zgz/gzip/gzip.h
@@ -129,7 +129,7 @@ extern int file_read(char *buf,  unsigned size);
 
         /* in deflate.c */
 void lm_init(int pack_level, ush *flags);
-void gnu_deflate(int pack_level, int rsync, int newrsync);
+void gnu_deflate(int pack_level, int rsync, int rsync14, int rsync16);
 
         /* in trees.c */
 void ct_init(void);
diff --git a/zgz/zgz.c b/zgz/zgz.c
index a4e3a97..e916873 100644
--- a/zgz/zgz.c
+++ b/zgz/zgz.c
@@ -71,7 +71,7 @@
 #include <getopt.h>
 #include <time.h>
 
-extern void gnuzip(int in, int out, char *origname, unsigned long timestamp, int level, int osflag, int rsync, int newrsync);
+extern void gnuzip(int in, int out, char *origname, unsigned long timestamp, int level, int osflag, int rsync, int rsync14, int rsync16);
 extern void old_bzip2(int level);
 
 #define BUFLEN		(64 * 1024)
@@ -157,6 +157,7 @@ static const struct option longopts[] = {
 	{ "zlib",               no_argument,            0,      'Z' },
 	{ "rsyncable",          no_argument,            0,      'R' },
 	{ "new-rsyncable",      no_argument,            0,      'r' },
+	{ "16-rsyncable",       no_argument,            0,      'D' },
 	{ "no-timestamp",	no_argument,		0,	'm' },
 	{ "force-timestamp",	no_argument,		0,	'M' },
 	{ "timestamp",		required_argument,	0,	'T' },
@@ -190,7 +191,8 @@ main(int argc, char **argv)
 	int level = 6;
 	int osflag = GZIP_OS_UNIX;
 	int rsync = 0;
-	int new_rsync = 0;
+	int rsync14 = 0;
+	int rsync16 = 0;
 	int ch;
 
 	if (strcmp(progname, "gunzip") == 0 ||
@@ -292,7 +294,10 @@ main(int argc, char **argv)
 			rsync = 1;
 			break;
 		case 'r':
-			new_rsync = 1;
+			rsync14 = 1;
+			break;
+		case 'D':
+			rsync16 = 1;
 			break;
 		case 'd':
 			fprintf(stderr, "%s: decompression is not supported on this version\n", progname);
@@ -333,7 +338,7 @@ main(int argc, char **argv)
 			fprintf(stderr, "%s: quirks not supported with --gnu\n", progname);
 			return 1;
 		}
-		gnuzip(STDIN_FILENO, STDOUT_FILENO, origname, timestamp, level, osflag, rsync, new_rsync);
+		gnuzip(STDIN_FILENO, STDOUT_FILENO, origname, timestamp, level, osflag, rsync, rsync14, rsync16);
 	} else if (bzold) {
 		if (quirks) {
 			fprintf(stderr, "%s: quirks not supported with --old-bzip2\n", progname);
@@ -345,7 +350,7 @@ main(int argc, char **argv)
 	} else if (pbzsuse) {
 		rebrain("suse-bzip2", "pbzip2", level);
 	} else {
-		if (rsync || new_rsync) {
+		if (rsync || rsync14 || rsync16) {
 			fprintf(stderr, "%s: --rsyncable not supported with --zlib\n", progname);
 			return 1;
 		}
-- 
2.13.2

Reply via email to