Daniel Drake dbbf9a2
Index: gzip-1.5/deflate.c
Daniel Drake dbbf9a2
===================================================================
Daniel Drake dbbf9a2
--- gzip-1.5.orig/deflate.c
Daniel Drake dbbf9a2
+++ gzip-1.5/deflate.c
Karel Klíč 2dbffed
@@ -131,6 +131,14 @@
Ivana Varekova 39397c8
 #endif
Ivana Varekova 39397c8
 /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
+#ifndef RSYNC_WIN
Ivana Varekova 39397c8
+#  define RSYNC_WIN 4096
Ivana Varekova 39397c8
+#endif
Ivana Varekova 39397c8
+/* Size of rsync window, must be < MAX_DIST */
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
+#define RSYNC_SUM_MATCH(sum) ((sum) % RSYNC_WIN == 0)
Ivana Varekova 39397c8
+/* Whether window sum matches magic value */
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
 /* ===========================================================================
Ivana Varekova 39397c8
  * Local data used by the "longest match" routines.
Ivana Varekova 39397c8
  */
Karel Klíč 2dbffed
@@ -212,6 +220,8 @@ local int compr_level;
Michal Luscon 54372e3
 unsigned good_match;
Ivana Varekova 39397c8
 /* Use a faster search when the previous match is longer than this */
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
+local ulg rsync_sum;  /* rolling sum of rsync window */
Ivana Varekova 39397c8
+local ulg rsync_chunk_end; /* next rsync sequence point */
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
 /* Values for max_lazy_match, good_match and max_chain_length, depending on
Ivana Varekova 39397c8
  * the desired pack level (0..9). The values given below have been tuned to
Daniel Drake dbbf9a2
@@ -314,6 +324,10 @@ void lm_init (pack_level, flags)
Ivana Varekova 39397c8
 #endif
Ivana Varekova 39397c8
     /* prev will be initialized on the fly */
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
+    /* rsync params */
Ivana Varekova 39397c8
+    rsync_chunk_end = 0xFFFFFFFFUL;
Ivana Varekova 39397c8
+    rsync_sum = 0;
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
     /* Set the default configuration parameters:
Ivana Varekova 39397c8
      */
Ivana Varekova 39397c8
     max_lazy_match   = configuration_table[pack_level].max_lazy;
Daniel Drake dbbf9a2
@@ -550,6 +564,8 @@ local void fill_window()
Ivana Varekova 39397c8
         memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
Ivana Varekova 39397c8
         match_start -= WSIZE;
Ivana Varekova 39397c8
         strstart    -= WSIZE; /* we now have strstart >= MAX_DIST: */
Ivana Varekova 39397c8
+        if (rsync_chunk_end != 0xFFFFFFFFUL)
Ivana Varekova 39397c8
+            rsync_chunk_end -= WSIZE;
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
         block_start -= (long) WSIZE;
Ivana Varekova 39397c8
 
Daniel Drake dbbf9a2
@@ -579,13 +595,46 @@ local void fill_window()
Ivana Varekova 39397c8
     }
Ivana Varekova 39397c8
 }
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
+local void rsync_roll(start, num)
Ivana Varekova 39397c8
+    unsigned start;
Ivana Varekova 39397c8
+    unsigned num;
Ivana Varekova 39397c8
+{
Ivana Varekova 39397c8
+    unsigned i;
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
+    if (start < RSYNC_WIN) {
Ivana Varekova 39397c8
+       /* before window fills. */
Ivana Varekova 39397c8
+       for (i = start; i < RSYNC_WIN; i++) {
Ivana Varekova 39397c8
+           if (i == start + num) return;
Ivana Varekova 39397c8
+           rsync_sum += (ulg)window[i];
Ivana Varekova 39397c8
+       }
Ivana Varekova 39397c8
+       num -= (RSYNC_WIN - start);
Ivana Varekova 39397c8
+       start = RSYNC_WIN;
Ivana Varekova 39397c8
+    }
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
+    /* buffer after window full */
Ivana Varekova 39397c8
+    for (i = start; i < start+num; i++) {
Ivana Varekova 39397c8
+       /* New character in */
Ivana Varekova 39397c8
+       rsync_sum += (ulg)window[i];
Ivana Varekova 39397c8
+       /* Old character out */
Ivana Varekova 39397c8
+       rsync_sum -= (ulg)window[i - RSYNC_WIN];
Ivana Varekova 39397c8
+       if (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
Ivana Varekova 39397c8
+           rsync_chunk_end = i;
Ivana Varekova 39397c8
+    }
Ivana Varekova 39397c8
+}
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
+/* ===========================================================================
Ivana Varekova 39397c8
+ * Set rsync_chunk_end if window sum matches magic value.
Ivana Varekova 39397c8
+ */
Ivana Varekova 39397c8
+#define RSYNC_ROLL(s, n) \
Ivana Varekova 39397c8
+   do { if (rsync) rsync_roll((s), (n)); } while(0)
Ivana Varekova 39397c8
+
Ivana Varekova 39397c8
 /* ===========================================================================
Ivana Varekova 39397c8
  * Flush the current block, with given end-of-file flag.
Ivana Varekova 39397c8
  * IN assertion: strstart is set to the end of the current match.
Ivana Varekova 39397c8
  */
Ivana Varekova 39397c8
 #define FLUSH_BLOCK(eof) \
Ivana Varekova 39397c8
    flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
Ivana Varekova 39397c8
-                (char*)NULL, (long)strstart - block_start, (eof))
Ivana Varekova 39397c8
+                (char*)NULL, (long)strstart - block_start, flush-1, (eof)) 
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
 /* ===========================================================================
Ivana Varekova 39397c8
  * Processes a new input file and return its compressed length. This
Daniel Drake dbbf9a2
@@ -596,7 +645,7 @@ local void fill_window()
Ivana Varekova 39397c8
 local off_t deflate_fast()
Ivana Varekova 39397c8
 {
Ivana Varekova 39397c8
     IPos hash_head; /* head of the hash chain */
Ivana Varekova 39397c8
-    int flush;      /* set if current block must be flushed */
Ivana Varekova 39397c8
+    int flush;      /* set if current block must be flushed, 2=>and padded  */ 
Ivana Varekova 39397c8
     unsigned match_length = 0;  /* length of best match */
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
     prev_length = MIN_MATCH-1;
Daniel Drake dbbf9a2
@@ -625,7 +674,8 @@ local off_t deflate_fast()
Michal Luscon 54372e3
             flush = ct_tally(strstart-match_start, match_length - MIN_MATCH);
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
             lookahead -= match_length;
Michal Luscon 54372e3
-
Michal Luscon 54372e3
+            
Michal Luscon 54372e3
+            RSYNC_ROLL(strstart, match_length);
Michal Luscon 54372e3
             /* Insert new strings in the hash table only if the match length
Ivana Varekova 39397c8
              * is not too large. This saves time but degrades compression.
Ivana Varekova 39397c8
              */
Daniel Drake dbbf9a2
@@ -654,9 +704,14 @@ local off_t deflate_fast()
Ivana Varekova 39397c8
             /* No match, output a literal byte */
Ivana Varekova 39397c8
             Tracevv((stderr,"%c",window[strstart]));
Ivana Varekova 39397c8
             flush = ct_tally (0, window[strstart]);
Ivana Varekova 39397c8
+            RSYNC_ROLL(strstart, 1);
Ivana Varekova 39397c8
             lookahead--;
Michal Luscon 54372e3
             strstart++;
Ivana Varekova 39397c8
         }
Michal Luscon 54372e3
+        if (rsync && strstart > rsync_chunk_end) {                                                        
Ivana Varekova 39397c8
+            rsync_chunk_end = 0xFFFFFFFFUL;                                                               
Ivana Varekova 39397c8
+            flush = 2;                                                                                    
Michal Luscon 54372e3
+       }  
Ivana Varekova 39397c8
         if (flush) FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
         /* Make sure that we always have enough lookahead, except
Daniel Drake dbbf9a2
@@ -730,6 +785,7 @@ off_t deflate()
Ivana Varekova 39397c8
              */
Ivana Varekova 39397c8
             lookahead -= prev_length-1;
Ivana Varekova 39397c8
             prev_length -= 2;
Ivana Varekova 39397c8
+            RSYNC_ROLL(strstart, prev_length+1);
Ivana Varekova 39397c8
             do {
Ivana Varekova 39397c8
                 strstart++;
Ivana Varekova 39397c8
                 INSERT_STRING(strstart, hash_head);
Daniel Drake dbbf9a2
@@ -742,24 +798,40 @@ off_t deflate()
Ivana Varekova 39397c8
             match_available = 0;
Ivana Varekova 39397c8
             match_length = MIN_MATCH-1;
Ivana Varekova 39397c8
             strstart++;
Ivana Varekova 39397c8
-            if (flush) FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
+            if (rsync && strstart > rsync_chunk_end) {
Ivana Varekova 39397c8
+                rsync_chunk_end = 0xFFFFFFFFUL;
Ivana Varekova 39397c8
+                flush = 2;
Ivana Varekova 39397c8
+            }
Ivana Varekova 39397c8
+            if (flush) FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
         } else if (match_available) {
Ivana Varekova 39397c8
             /* If there was no match at the previous position, output a
Ivana Varekova 39397c8
              * single literal. If there was a match but the current match
Ivana Varekova 39397c8
              * is longer, truncate the previous match to a single literal.
Ivana Varekova 39397c8
              */
Ivana Varekova 39397c8
             Tracevv((stderr,"%c",window[strstart-1]));
Ivana Varekova 39397c8
-            if (ct_tally (0, window[strstart-1])) {
Ivana Varekova 39397c8
-                FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
+            flush = ct_tally (0, window[strstart-1]);
Ivana Varekova 39397c8
+            if (rsync && strstart > rsync_chunk_end) {
Ivana Varekova 39397c8
+                rsync_chunk_end = 0xFFFFFFFFUL;
Ivana Varekova 39397c8
+                flush = 2;
Ivana Varekova 39397c8
             }
Ivana Varekova 39397c8
+            if (flush) FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
+            RSYNC_ROLL(strstart, 1);
Ivana Varekova 39397c8
             strstart++;
Ivana Varekova 39397c8
             lookahead--;
Ivana Varekova 39397c8
         } else {
Ivana Varekova 39397c8
             /* There is no previous match to compare with, wait for
Ivana Varekova 39397c8
              * the next step to decide.
Ivana Varekova 39397c8
              */
Ivana Varekova 39397c8
+            if (rsync && strstart > rsync_chunk_end) {
Ivana Varekova 39397c8
+                /* Reset huffman tree */
Ivana Varekova 39397c8
+                rsync_chunk_end = 0xFFFFFFFFUL;
Ivana Varekova 39397c8
+                flush = 2;
Ivana Varekova 39397c8
+                FLUSH_BLOCK(0), block_start = strstart;
Ivana Varekova 39397c8
+            }             
Ivana Varekova 39397c8
+             
Ivana Varekova 39397c8
             match_available = 1;
Ivana Varekova 39397c8
+            RSYNC_ROLL(strstart, 1);  
Ivana Varekova 39397c8
             strstart++;
Ivana Varekova 39397c8
             lookahead--;
Ivana Varekova 39397c8
         }
Daniel Drake dbbf9a2
Index: gzip-1.5/doc/gzip.texi
Daniel Drake dbbf9a2
===================================================================
Daniel Drake dbbf9a2
--- gzip-1.5.orig/doc/gzip.texi
Daniel Drake dbbf9a2
+++ gzip-1.5/doc/gzip.texi
Karel Klíč 2dbffed
@@ -353,6 +353,14 @@ specified on the command line are direct
Karel Klíč 2dbffed
 into the directory and compress all the files it finds there (or
Karel Klíč 2dbffed
 decompress them in the case of @command{gunzip}).
Karel Klíč 2dbffed
 
Karel Klíč 2dbffed
+@item --rsyncable
Karel Klíč 2dbffed
+While compressing, synchronize the output occasionally based on the
Karel Klíč 2dbffed
+input.  This reduces compression by about 1 percent most cases, but
Karel Klíč 2dbffed
+means that the @code{rsync} program can take advantage of similarities
Karel Klíč 2dbffed
+in the uncompressed input when syncronizing two files compressed with
Karel Klíč 2dbffed
+this flag.  @code{gunzip} cannot tell the difference between a
Karel Klíč 2dbffed
+compressed file created with this option, and one created without it.
Karel Klíč 2dbffed
+
Karel Klíč 2dbffed
 @item --suffix @var{suf}
Karel Klíč 2dbffed
 @itemx -S @var{suf}
Karel Klíč 2dbffed
 Use suffix @var{suf} instead of @samp{.gz}.  Any suffix can be
Daniel Drake dbbf9a2
Index: gzip-1.5/gzip.c
Daniel Drake dbbf9a2
===================================================================
Daniel Drake dbbf9a2
--- gzip-1.5.orig/gzip.c
Daniel Drake dbbf9a2
+++ gzip-1.5/gzip.c
Daniel Drake dbbf9a2
@@ -213,6 +213,7 @@ int  ofd;                  /* output fil
Ivana Varekova 7047be9
 unsigned insize;           /* valid bytes in inbuf */
Ivana Varekova 7047be9
 unsigned inptr;            /* index of next byte to be processed in inbuf */
Ivana Varekova 7047be9
 unsigned outcnt;           /* bytes in output buffer */
Ivana Varekova 7047be9
+int rsync = 0;             /* make ryncable chunks */
Ivana Varekova 7047be9
 
Karel Klíč 2dbffed
 static int handled_sig[] =
Karel Klíč 2dbffed
   {
Daniel Drake dbbf9a2
@@ -270,7 +271,7 @@ static const struct option longopts[] =
Ivana Varekova 7047be9
     {"best",       0, 0, '9'}, /* compress better */
Ivana Varekova 7047be9
     {"lzw",        0, 0, 'Z'}, /* make output compatible with old compress */
Ivana Varekova 7047be9
     {"bits",       1, 0, 'b'}, /* max number of bits per code (implies -Z) */
Michal Luscon 54372e3
-
Michal Luscon 54372e3
+    {"rsyncable",  0, 0, 'R'}, /* make rsync-friendly archive */ 
Ivana Varekova 7047be9
     { 0, 0, 0, 0 }
Ivana Varekova 7047be9
 };
Ivana Varekova 7047be9
 
Daniel Drake dbbf9a2
@@ -353,6 +354,7 @@ local void help()
Ivana Varekova 7047be9
  "  -Z, --lzw         produce output compatible with old compress",
Ivana Varekova 7047be9
  "  -b, --bits=BITS   max number of bits per code (implies -Z)",
Ivana Varekova 7047be9
 #endif
Ivana Varekova 7047be9
+ "    --rsyncable   Make rsync-friendly archive",  
Ivana Varekova 7047be9
  "",
Ivana Varekova 7047be9
  "With no FILE, or when FILE is -, read standard input.",
Ivana Varekova 7047be9
  "",
Daniel Drake dbbf9a2
@@ -482,6 +484,9 @@ int main (int argc, char **argv)
Michal Luscon 54372e3
             recursive = 1;
Ivana Varekova 7047be9
 #endif
Michal Luscon 54372e3
             break;
Michal Luscon 54372e3
+            
Ivana Varekova 7047be9
+        case 'R':
Michal Luscon 54372e3
+            rsync = 1; break;
Michal Luscon 54372e3
         case 'S':
Ivana Varekova 7047be9
 #ifdef NO_MULTIPLE_DOTS
Ivana Varekova 7047be9
             if (*optarg == '.') optarg++;
Daniel Drake dbbf9a2
Index: gzip-1.5/gzip.h
Daniel Drake dbbf9a2
===================================================================
Daniel Drake dbbf9a2
--- gzip-1.5.orig/gzip.h
Daniel Drake dbbf9a2
+++ gzip-1.5/gzip.h
Daniel Drake dbbf9a2
@@ -140,6 +140,7 @@ EXTERN(uch, window);         /* Sliding
Ivana Varekova 39397c8
 extern unsigned insize; /* valid bytes in inbuf */
Ivana Varekova 39397c8
 extern unsigned inptr;  /* index of next byte to be processed in inbuf */
Ivana Varekova 39397c8
 extern unsigned outcnt; /* bytes in output buffer */
Ivana Varekova 39397c8
+extern int rsync;  /* deflate into rsyncable chunks */ 
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
 extern off_t bytes_in;   /* number of input bytes */
Ivana Varekova 39397c8
 extern off_t bytes_out;  /* number of output bytes */
Daniel Drake dbbf9a2
@@ -287,7 +288,7 @@ extern off_t deflate (void);
Ivana Varekova 39397c8
         /* in trees.c */
Michal Luscon 54372e3
 extern void ct_init     (ush *attr, int *method);
Michal Luscon 54372e3
 extern int  ct_tally    (int dist, int lc);
Michal Luscon 54372e3
-extern off_t flush_block (char *buf, ulg stored_len, int eof);
Michal Luscon 54372e3
+extern off_t flush_block (char *buf, ulg stored_len, int pad, int eof);
Ivana Varekova 39397c8
 
Ivana Varekova 39397c8
         /* in bits.c */
Michal Luscon 54372e3
 extern void     bi_init    (file_t zipfile);
Daniel Drake dbbf9a2
Index: gzip-1.5/trees.c
Daniel Drake dbbf9a2
===================================================================
Daniel Drake dbbf9a2
--- gzip-1.5.orig/trees.c
Daniel Drake dbbf9a2
+++ gzip-1.5/trees.c
Karel Klíč 2dbffed
@@ -856,9 +856,10 @@ local void send_all_trees(lcodes, dcodes
Karel Klíč 2dbffed
  * trees or store, and output the encoded block to the zip file. This function
Karel Klíč 2dbffed
  * returns the total compressed length for the file so far.
Karel Klíč 2dbffed
  */
Karel Klíč 2dbffed
-off_t flush_block(buf, stored_len, eof)
Karel Klíč 2dbffed
+off_t flush_block(buf, stored_len, pad, eof)  
Karel Klíč 2dbffed
     char *buf;        /* input block, or NULL if too old */
Karel Klíč 2dbffed
     ulg stored_len;   /* length of input block */
Karel Klíč 2dbffed
+    int pad;          /* pad output to byte boundary */ 
Karel Klíč 2dbffed
     int eof;          /* true if this is the last block for a file */
Karel Klíč 2dbffed
 {
Karel Klíč 2dbffed
     ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
Karel Klíč 2dbffed
@@ -951,6 +952,10 @@ off_t flush_block(buf, stored_len, eof)
Karel Klíč 2dbffed
         Assert (input_len == bytes_in, "bad input size");
Karel Klíč 2dbffed
         bi_windup();
Karel Klíč 2dbffed
         compressed_len += 7;  /* align on byte boundary */
Karel Klíč 2dbffed
+    } else if (pad && (compressed_len % 8) != 0) {
Karel Klíč 2dbffed
+        send_bits((STORED_BLOCK<<1)+eof, 3);  /* send block type */
Karel Klíč 2dbffed
+        compressed_len = (compressed_len + 3 + 7) & ~7L;
Karel Klíč 2dbffed
+        copy_block(buf, 0, 1); /* with header */
Karel Klíč 2dbffed
     }
Ivana Varekova 39397c8
 
Karel Klíč 2dbffed
     return compressed_len >> 3;