Add support for gzip --rsyncable output produced by gzip 1.4.
authorJoey Hess <joey@kitenet.net>
Sun, 7 Aug 2011 01:02:59 +0000 (21:02 -0400)
committerJoey Hess <joey@kitenet.net>
Sun, 7 Aug 2011 01:02:59 +0000 (21:02 -0400)
This differs from prior --rsyncable output, which was made by a debian
specific patch and used a different rsync window size, and reset huffman
encodings less often.

debian/changelog
pristine-gz
pristine-tar.spec
zgz/gzip/deflate.c
zgz/gzip/gzip.c
zgz/gzip/gzip.h
zgz/zgz.c

index 033733e..a9aa665 100644 (file)
@@ -1,5 +1,9 @@
 pristine-tar (1.14) UNRELEASED; urgency=low
 
+  * Add support for gzip --rsyncable output produced by gzip 1.4.
+    This differs from prior --rsyncable output, which was made by a debian
+    specific patch and used a different rsync window size, and reset
+    huffman encodings less often.
   * Clarify man page.
 
  -- Joey Hess <joeyh@debian.org>  Thu, 07 Jul 2011 12:17:00 -0400
index d809807..69fa1a4 100755 (executable)
@@ -192,6 +192,7 @@ sub reproducegz {
                # and it was produced by gnu gzip.
                push @try, ['--gnu', @args];
                push @try, ['--gnu', @args, '--rsyncable'];
+               push @try, ['--gnu', @args, '--new-rsyncable'];
        }
 
        if ($name =~ /\//) {
@@ -285,7 +286,7 @@ sub gengz {
        my @params=split(' ', $delta->{params});
        while (@params) {
                $_=shift @params;
-               next if /^(--gnu|--rsyncable|-[nmM1-9])$/;
+               next if /^(--gnu|--rsyncable|--new-rsyncable|-[nmM1-9])$/;
                if (/^(--original-name|--quirk|--osflag)$/) {
                        shift @params;
                        next;
index ee1a5c8..0a1b95b 100644 (file)
@@ -1,5 +1,5 @@
 Name: pristine-tar
-Version: 1.13
+Version: 1.14
 Release: 2%{?dist}
 Summary: regenerate pristine tarballs
 
index 93571db..8f9bb06 100644 (file)
 #endif
 /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
 
-#ifndef RSYNC_WIN
-#  define RSYNC_WIN 4096
-#endif
+int RSYNC_WIN = 4096;
 /* Size of rsync window, must be < MAX_DIST */
 
-#define RSYNC_SUM_MATCH(sum) ((sum) % RSYNC_WIN == 0)
+/* Whether to enable compatability with Debian's old rsyncable patch. */
+int debian_rsyncable = 1;
+
+void disable_debian_rsyncable () {
+       debian_rsyncable = 0;
+       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 */
 
 /* ===========================================================================
@@ -525,7 +532,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 (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
+       if (debian_rsyncable && 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))
            rsync_chunk_end = i;
     }
 }
@@ -614,10 +623,15 @@ static void deflate_fast(int pack_level, int rsync)
             lookahead--;
            strstart++;
         }
-       if (rsync && strstart > rsync_chunk_end) {
+       if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
            rsync_chunk_end = 0xFFFFFFFFUL;
            flush = 2;
        }
+       if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
+           flush = 1;
+           ct_init();
+           rsync_chunk_end = 0xFFFFFFFFUL;
+       }
         if (flush) FLUSH_BLOCK(0), block_start = strstart;
 
         /* Make sure that we always have enough lookahead, except
@@ -636,7 +650,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)
+void gnu_deflate(int pack_level, int rsync, int newrsync)
 {
     IPos hash_head;          /* head of hash chain */
     IPos prev_match;         /* previous match */
@@ -644,6 +658,13 @@ void gnu_deflate(int pack_level, int rsync)
     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
+     * rsync patch. */
+    if (newrsync) {
+           rsync=1;
+           disable_debian_rsyncable();
+    }
+
     if (pack_level <= 3) {
         deflate_fast(pack_level, rsync); /* optimized for speed */
         return;
@@ -705,10 +726,15 @@ void gnu_deflate(int pack_level, int rsync)
             match_length = MIN_MATCH-1;
             strstart++;
 
-           if (rsync && strstart > rsync_chunk_end) {
+           if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
                rsync_chunk_end = 0xFFFFFFFFUL;
                flush = 2;
            }
+           if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
+               ct_init();
+               rsync_chunk_end = 0xFFFFFFFFUL;
+               flush = 1;
+           }
             if (flush) FLUSH_BLOCK(0), block_start = strstart;
         } else if (match_available) {
             /* If there was no match at the previous position, output a
@@ -717,10 +743,15 @@ void gnu_deflate(int pack_level, int rsync)
              */
             Tracevv((stderr,"%c",window[strstart-1]));
            flush = ct_tally (pack_level, 0, window[strstart-1]);
-           if (rsync && strstart > rsync_chunk_end) {
+           if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
                rsync_chunk_end = 0xFFFFFFFFUL;
                flush = 2;
            }
+           if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
+               ct_init();
+               rsync_chunk_end = 0xFFFFFFFFUL;
+               flush = 1;
+           }
             if (flush) FLUSH_BLOCK(0), block_start = strstart;
            RSYNC_ROLL(strstart, 1);
             strstart++;
@@ -729,12 +760,18 @@ void gnu_deflate(int pack_level, int rsync)
             /* There is no previous match to compare with, wait for
              * the next step to decide.
              */
-           if (rsync && strstart > rsync_chunk_end) {
+           if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
                /* Reset huffman tree */
                rsync_chunk_end = 0xFFFFFFFFUL;
                flush = 2;
                FLUSH_BLOCK(0), block_start = strstart;
            }
+           if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
+               ct_init();
+               /* Reset huffman tree */
+               rsync_chunk_end = 0xFFFFFFFFUL;
+               FLUSH_BLOCK(0), block_start = strstart;
+           }
             match_available = 1;
            RSYNC_ROLL(strstart, 1);
             strstart++;
index 0a9a578..a9a39dc 100644 (file)
@@ -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)
+void gnuzip(int in, int out, char *origname, ulg timestamp, int level, int osflag, int rsync, int newrsync)
 {
     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);
+    gnu_deflate(level, rsync, newrsync);
 
     /* Write the crc and uncompressed size */
     put_long(crc);
index bb80877..267a2ec 100644 (file)
@@ -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);
+void gnu_deflate(int pack_level, int rsync, int newrsync);
 
         /* in trees.c */
 void ct_init(void);
index 29f814b..f2eb05b 100644 (file)
--- a/zgz/zgz.c
+++ b/zgz/zgz.c
@@ -72,7 +72,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);
+extern void gnuzip(int in, int out, char *origname, unsigned long timestamp, int level, int osflag, int rsync, int newrsync);
 extern void old_bzip2(int level);
 
 #define BUFLEN         (64 * 1024)
@@ -145,7 +145,6 @@ static const struct option longopts[] = {
        { "no-name",            no_argument,            0,      'n' },
        { "name",               no_argument,            0,      'N' },
        { "quiet",              no_argument,            0,      'q' },
-       { "recursive",          no_argument,            0,      'r' },
        { "fast",               no_argument,            0,      '1' },
        { "best",               no_argument,            0,      '9' },
        { "ascii",              no_argument,            0,      'a' },
@@ -154,6 +153,7 @@ static const struct option longopts[] = {
        { "old-bzip2",          no_argument,            0,      'O' },
        { "zlib",               no_argument,            0,      'Z' },
        { "rsyncable",          no_argument,            0,      'R' },
+       { "new-rsyncable",      no_argument,            0,      'r' },
        { "no-timestamp",       no_argument,            0,      'm' },
        { "force-timestamp",    no_argument,            0,      'M' },
        { "timestamp",          required_argument,      0,      'T' },
@@ -185,6 +185,7 @@ main(int argc, char **argv)
        int level = 6;
        int osflag = GZIP_OS_UNIX;
        int rsync = 0;
+       int new_rsync = 0;
        int ch;
 
        if (strcmp(progname, "gunzip") == 0 ||
@@ -280,8 +281,7 @@ main(int argc, char **argv)
                        rsync = 1;
                        break;
                case 'r':
-                       fprintf(stderr, "%s: recursive is not supported on this version\n", progname);
-                       usage();
+                       new_rsync = 1;
                        break;
                case 'd':
                        fprintf(stderr, "%s: decompression is not supported on this version\n", progname);
@@ -322,7 +322,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);
+               gnuzip(STDIN_FILENO, STDOUT_FILENO, origname, timestamp, level, osflag, rsync, new_rsync);
        } else if (bzold) {
                if (quirks) {
                        fprintf(stderr, "%s: quirks not supported with --old-bzip\n", progname);
@@ -330,7 +330,7 @@ main(int argc, char **argv)
                }
                old_bzip2(level);
        } else {
-               if (rsync) {
+               if (rsync || new_rsync) {
                        fprintf(stderr, "%s: --rsyncable not supported with --zlib\n", progname);
                        return 1;
                }
@@ -528,6 +528,7 @@ usage(void)
     " -T --timestamp SECONDS   set the timestamp to the specified number of seconds\n"
     " \ngnu-specific options:\n"
     " -R --rsyncable           make rsync-friendly archive\n"
+    " -r --new-rsyncable       make rsync-friendly archive (new version)\n"
     " \nzlib-specific options:\n"
     " -k --quirk QUIRK         enable a format quirk (buggy-bsd, ntfs, perl)\n");
        exit(0);