diff -u -r ../gzip-1.3.12.orig/deflate.c ./deflate.c
old
|
new
|
|
135 | 135 | #endif |
136 | 136 | /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ |
137 | 137 | |
| 138 | #ifndef RSYNC_WIN |
| 139 | # define RSYNC_WIN 4096 |
| 140 | #endif |
| 141 | /* Size of rsync window, must be < MAX_DIST */ |
| 142 | |
| 143 | #define RSYNC_SUM_MATCH(sum) ((sum) % RSYNC_WIN == 0) |
| 144 | /* Whether window sum matches magic value */ |
| 145 | |
138 | 146 | /* =========================================================================== |
139 | 147 | * Local data used by the "longest match" routines. |
140 | 148 | */ |
… |
… |
|
216 | 224 | unsigned near good_match; |
217 | 225 | /* Use a faster search when the previous match is longer than this */ |
218 | 226 | |
| 227 | local ulg rsync_sum; /* rolling sum of rsync window */ |
| 228 | local ulg rsync_chunk_end; /* next rsync sequence point */ |
219 | 229 | |
220 | 230 | /* Values for max_lazy_match, good_match and max_chain_length, depending on |
221 | 231 | * the desired pack level (0..9). The values given below have been tuned to |
… |
… |
|
314 | 324 | #endif |
315 | 325 | /* prev will be initialized on the fly */ |
316 | 326 | |
| 327 | /* rsync params */ |
| 328 | rsync_chunk_end = 0xFFFFFFFFUL; |
| 329 | rsync_sum = 0; |
| 330 | |
317 | 331 | /* Set the default configuration parameters: |
318 | 332 | */ |
319 | 333 | max_lazy_match = configuration_table[pack_level].max_lazy; |
… |
… |
|
550 | 564 | memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE); |
551 | 565 | match_start -= WSIZE; |
552 | 566 | strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ |
| 567 | if (rsync_chunk_end != 0xFFFFFFFFUL) |
| 568 | rsync_chunk_end -= WSIZE; |
553 | 569 | |
554 | 570 | block_start -= (long) WSIZE; |
555 | 571 | |
… |
… |
|
577 | 593 | } |
578 | 594 | } |
579 | 595 | |
| 596 | local void rsync_roll(start, num) |
| 597 | unsigned start; |
| 598 | unsigned num; |
| 599 | { |
| 600 | unsigned i; |
| 601 | |
| 602 | if (start < RSYNC_WIN) { |
| 603 | /* before window fills. */ |
| 604 | for (i = start; i < RSYNC_WIN; i++) { |
| 605 | if (i == start + num) return; |
| 606 | rsync_sum += (ulg)window[i]; |
| 607 | } |
| 608 | num -= (RSYNC_WIN - start); |
| 609 | start = RSYNC_WIN; |
| 610 | } |
| 611 | |
| 612 | /* buffer after window full */ |
| 613 | for (i = start; i < start+num; i++) { |
| 614 | /* New character in */ |
| 615 | rsync_sum += (ulg)window[i]; |
| 616 | /* Old character out */ |
| 617 | rsync_sum -= (ulg)window[i - RSYNC_WIN]; |
| 618 | if (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum)) |
| 619 | rsync_chunk_end = i; |
| 620 | } |
| 621 | } |
| 622 | |
| 623 | /* =========================================================================== |
| 624 | * Set rsync_chunk_end if window sum matches magic value. |
| 625 | */ |
| 626 | #define RSYNC_ROLL(s, n) \ |
| 627 | do { if (rsync) rsync_roll((s), (n)); } while(0) |
| 628 | |
580 | 629 | /* =========================================================================== |
581 | 630 | * Flush the current block, with given end-of-file flag. |
582 | 631 | * IN assertion: strstart is set to the end of the current match. |
583 | 632 | */ |
584 | 633 | #define FLUSH_BLOCK(eof) \ |
585 | 634 | flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \ |
586 | | (char*)NULL, (long)strstart - block_start, (eof)) |
| 635 | (char*)NULL, (long)strstart - block_start, flush-1, (eof)) |
587 | 636 | |
588 | 637 | /* =========================================================================== |
589 | 638 | * Processes a new input file and return its compressed length. This |
… |
… |
|
594 | 643 | local off_t deflate_fast() |
595 | 644 | { |
596 | 645 | IPos hash_head; /* head of the hash chain */ |
597 | | int flush; /* set if current block must be flushed */ |
| 646 | int flush; /* set if current block must be flushed, 2=>and padded */ |
598 | 647 | unsigned match_length = 0; /* length of best match */ |
599 | 648 | |
600 | 649 | prev_length = MIN_MATCH-1; |
… |
… |
|
624 | 673 | |
625 | 674 | lookahead -= match_length; |
626 | 675 | |
| 676 | RSYNC_ROLL(strstart, match_length); |
627 | 677 | /* Insert new strings in the hash table only if the match length |
628 | 678 | * is not too large. This saves time but degrades compression. |
629 | 679 | */ |
… |
… |
|
652 | 702 | /* No match, output a literal byte */ |
653 | 703 | Tracevv((stderr,"%c",window[strstart])); |
654 | 704 | flush = ct_tally (0, window[strstart]); |
| 705 | RSYNC_ROLL(strstart, 1); |
655 | 706 | lookahead--; |
656 | 707 | strstart++; |
657 | 708 | } |
| 709 | if (rsync && strstart > rsync_chunk_end) { |
| 710 | rsync_chunk_end = 0xFFFFFFFFUL; |
| 711 | flush = 2; |
| 712 | } |
658 | 713 | if (flush) FLUSH_BLOCK(0), block_start = strstart; |
659 | 714 | |
660 | 715 | /* Make sure that we always have enough lookahead, except |
… |
… |
|
728 | 783 | */ |
729 | 784 | lookahead -= prev_length-1; |
730 | 785 | prev_length -= 2; |
| 786 | RSYNC_ROLL(strstart, prev_length+1); |
731 | 787 | do { |
732 | 788 | strstart++; |
733 | 789 | INSERT_STRING(strstart, hash_head); |
… |
… |
|
740 | 796 | match_available = 0; |
741 | 797 | match_length = MIN_MATCH-1; |
742 | 798 | strstart++; |
743 | | if (flush) FLUSH_BLOCK(0), block_start = strstart; |
744 | 799 | |
| 800 | if (rsync && strstart > rsync_chunk_end) { |
| 801 | rsync_chunk_end = 0xFFFFFFFFUL; |
| 802 | flush = 2; |
| 803 | } |
| 804 | if (flush) FLUSH_BLOCK(0), block_start = strstart; |
745 | 805 | } else if (match_available) { |
746 | 806 | /* If there was no match at the previous position, output a |
747 | 807 | * single literal. If there was a match but the current match |
748 | 808 | * is longer, truncate the previous match to a single literal. |
749 | 809 | */ |
750 | 810 | Tracevv((stderr,"%c",window[strstart-1])); |
751 | | if (ct_tally (0, window[strstart-1])) { |
752 | | FLUSH_BLOCK(0), block_start = strstart; |
753 | | } |
| 811 | flush = ct_tally (0, window[strstart-1]); |
| 812 | if (rsync && strstart > rsync_chunk_end) { |
| 813 | rsync_chunk_end = 0xFFFFFFFFUL; |
| 814 | flush = 2; |
| 815 | } |
| 816 | if (flush) FLUSH_BLOCK(0), block_start = strstart; |
| 817 | RSYNC_ROLL(strstart, 1); |
754 | 818 | strstart++; |
755 | 819 | lookahead--; |
756 | 820 | } else { |
757 | 821 | /* There is no previous match to compare with, wait for |
758 | 822 | * the next step to decide. |
759 | 823 | */ |
| 824 | if (rsync && strstart > rsync_chunk_end) { |
| 825 | /* Reset huffman tree */ |
| 826 | rsync_chunk_end = 0xFFFFFFFFUL; |
| 827 | flush = 2; |
| 828 | FLUSH_BLOCK(0), block_start = strstart; |
| 829 | } |
760 | 830 | match_available = 1; |
| 831 | RSYNC_ROLL(strstart, 1); |
761 | 832 | strstart++; |
762 | 833 | lookahead--; |
763 | 834 | } |
diff -u -r ../gzip-1.3.12.orig/doc/gzip.texi ./doc/gzip.texi
old
|
new
|
|
350 | 350 | into the directory and compress all the files it finds there (or |
351 | 351 | decompress them in the case of @command{gunzip}). |
352 | 352 | |
| 353 | @item --rsyncable |
| 354 | While compressing, synchronize the output occasionally based on the |
| 355 | input. This reduces compression by about 1 percent most cases, but |
| 356 | means that the @command{rsync} program can take advantage of similarities |
| 357 | in the uncompressed input when syncronizing two files compressed with |
| 358 | this flag. @command{gunzip} cannot tell the difference between a |
| 359 | compressed file created with this option, and one created without it. |
| 360 | |
353 | 361 | @item --suffix @var{suf} |
354 | 362 | @itemx -S @var{suf} |
355 | 363 | Use suffix @var{suf} instead of @samp{.gz}. Any suffix can be |
diff -u -r ../gzip-1.3.12.orig/gzip.c ./gzip.c
old
|
new
|
|
231 | 231 | unsigned insize; /* valid bytes in inbuf */ |
232 | 232 | unsigned inptr; /* index of next byte to be processed in inbuf */ |
233 | 233 | unsigned outcnt; /* bytes in output buffer */ |
| 234 | int rsync = 0; /* make ryncable chunks */ |
234 | 235 | |
235 | 236 | struct option longopts[] = |
236 | 237 | { |
… |
… |
|
260 | 261 | {"best", 0, 0, '9'}, /* compress better */ |
261 | 262 | {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */ |
262 | 263 | {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */ |
| 264 | {"rsyncable", 0, 0, 'R'}, /* make rsync-friendly archive */ |
263 | 265 | { 0, 0, 0, 0 } |
264 | 266 | }; |
265 | 267 | |
… |
… |
|
341 | 343 | " -Z, --lzw produce output compatible with old compress", |
342 | 344 | " -b, --bits=BITS max number of bits per code (implies -Z)", |
343 | 345 | #endif |
| 346 | " --rsyncable Make rsync-friendly archive", |
344 | 347 | "", |
345 | 348 | "With no FILE, or when FILE is -, read standard input.", |
346 | 349 | "", |
… |
… |
|
469 | 472 | recursive = 1; |
470 | 473 | #endif |
471 | 474 | break; |
| 475 | case 'R': |
| 476 | rsync = 1; break; |
472 | 477 | case 'S': |
473 | 478 | #ifdef NO_MULTIPLE_DOTS |
474 | 479 | if (*optarg == '.') optarg++; |
diff -u -r ../gzip-1.3.12.orig/gzip.h ./gzip.h
old
|
new
|
|
158 | 158 | extern unsigned insize; /* valid bytes in inbuf */ |
159 | 159 | extern unsigned inptr; /* index of next byte to be processed in inbuf */ |
160 | 160 | extern unsigned outcnt; /* bytes in output buffer */ |
| 161 | extern int rsync; /* deflate into rsyncable chunks */ |
161 | 162 | |
162 | 163 | extern off_t bytes_in; /* number of input bytes */ |
163 | 164 | extern off_t bytes_out; /* number of output bytes */ |
… |
… |
|
306 | 307 | /* in trees.c */ |
307 | 308 | void ct_init OF((ush *attr, int *method)); |
308 | 309 | int ct_tally OF((int dist, int lc)); |
309 | | off_t flush_block OF((char *buf, ulg stored_len, int eof)); |
| 310 | off_t flush_block OF((char *buf, ulg stored_len, int pad, int eof)); |
310 | 311 | |
311 | 312 | /* in bits.c */ |
312 | 313 | void bi_init OF((file_t zipfile)); |
diff -u -r ../gzip-1.3.12.orig/trees.c ./trees.c
old
|
new
|
|
860 | 860 | * trees or store, and output the encoded block to the zip file. This function |
861 | 861 | * returns the total compressed length for the file so far. |
862 | 862 | */ |
863 | | off_t flush_block(buf, stored_len, eof) |
| 863 | off_t flush_block(buf, stored_len, pad, eof) |
864 | 864 | char *buf; /* input block, or NULL if too old */ |
865 | 865 | ulg stored_len; /* length of input block */ |
| 866 | int pad; /* pad output to byte boundary */ |
866 | 867 | int eof; /* true if this is the last block for a file */ |
867 | 868 | { |
868 | 869 | ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ |
… |
… |
|
955 | 956 | Assert (input_len == bytes_in, "bad input size"); |
956 | 957 | bi_windup(); |
957 | 958 | compressed_len += 7; /* align on byte boundary */ |
| 959 | } else if (pad && (compressed_len % 8) != 0) { |
| 960 | send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */ |
| 961 | compressed_len = (compressed_len + 3 + 7) & ~7L; |
| 962 | copy_block(buf, 0, 1); /* with header */ |
958 | 963 | } |
959 | 964 | |
960 | 965 | return compressed_len >> 3; |