Contents of /trunk/gzip/patches/gzip-1.3.13-rsync.patch
Parent Directory | Revision Log
Revision 2540 -
(show annotations)
(download)
Mon Feb 2 13:54:11 2015 UTC (9 years, 7 months ago) by niro
File size: 11321 byte(s)
Mon Feb 2 13:54:11 2015 UTC (9 years, 7 months ago) by niro
File size: 11321 byte(s)
-added rsyncable patches
1 | Index: gzip-1.5/deflate.c |
2 | =================================================================== |
3 | --- gzip-1.5.orig/deflate.c |
4 | +++ gzip-1.5/deflate.c |
5 | @@ -131,6 +131,14 @@ |
6 | #endif |
7 | /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ |
8 | |
9 | +#ifndef RSYNC_WIN |
10 | +# define RSYNC_WIN 4096 |
11 | +#endif |
12 | +/* Size of rsync window, must be < MAX_DIST */ |
13 | + |
14 | +#define RSYNC_SUM_MATCH(sum) ((sum) % RSYNC_WIN == 0) |
15 | +/* Whether window sum matches magic value */ |
16 | + |
17 | /* =========================================================================== |
18 | * Local data used by the "longest match" routines. |
19 | */ |
20 | @@ -212,6 +220,8 @@ local int compr_level; |
21 | unsigned good_match; |
22 | /* Use a faster search when the previous match is longer than this */ |
23 | |
24 | +local ulg rsync_sum; /* rolling sum of rsync window */ |
25 | +local ulg rsync_chunk_end; /* next rsync sequence point */ |
26 | |
27 | /* Values for max_lazy_match, good_match and max_chain_length, depending on |
28 | * the desired pack level (0..9). The values given below have been tuned to |
29 | @@ -314,6 +324,10 @@ void lm_init (pack_level, flags) |
30 | #endif |
31 | /* prev will be initialized on the fly */ |
32 | |
33 | + /* rsync params */ |
34 | + rsync_chunk_end = 0xFFFFFFFFUL; |
35 | + rsync_sum = 0; |
36 | + |
37 | /* Set the default configuration parameters: |
38 | */ |
39 | max_lazy_match = configuration_table[pack_level].max_lazy; |
40 | @@ -550,6 +564,8 @@ local void fill_window() |
41 | memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE); |
42 | match_start -= WSIZE; |
43 | strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */ |
44 | + if (rsync_chunk_end != 0xFFFFFFFFUL) |
45 | + rsync_chunk_end -= WSIZE; |
46 | |
47 | block_start -= (long) WSIZE; |
48 | |
49 | @@ -579,13 +595,46 @@ local void fill_window() |
50 | } |
51 | } |
52 | |
53 | +local void rsync_roll(start, num) |
54 | + unsigned start; |
55 | + unsigned num; |
56 | +{ |
57 | + unsigned i; |
58 | + |
59 | + if (start < RSYNC_WIN) { |
60 | + /* before window fills. */ |
61 | + for (i = start; i < RSYNC_WIN; i++) { |
62 | + if (i == start + num) return; |
63 | + rsync_sum += (ulg)window[i]; |
64 | + } |
65 | + num -= (RSYNC_WIN - start); |
66 | + start = RSYNC_WIN; |
67 | + } |
68 | + |
69 | + /* buffer after window full */ |
70 | + for (i = start; i < start+num; i++) { |
71 | + /* New character in */ |
72 | + rsync_sum += (ulg)window[i]; |
73 | + /* Old character out */ |
74 | + rsync_sum -= (ulg)window[i - RSYNC_WIN]; |
75 | + if (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum)) |
76 | + rsync_chunk_end = i; |
77 | + } |
78 | +} |
79 | + |
80 | +/* =========================================================================== |
81 | + * Set rsync_chunk_end if window sum matches magic value. |
82 | + */ |
83 | +#define RSYNC_ROLL(s, n) \ |
84 | + do { if (rsync) rsync_roll((s), (n)); } while(0) |
85 | + |
86 | /* =========================================================================== |
87 | * Flush the current block, with given end-of-file flag. |
88 | * IN assertion: strstart is set to the end of the current match. |
89 | */ |
90 | #define FLUSH_BLOCK(eof) \ |
91 | flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \ |
92 | - (char*)NULL, (long)strstart - block_start, (eof)) |
93 | + (char*)NULL, (long)strstart - block_start, flush-1, (eof)) |
94 | |
95 | /* =========================================================================== |
96 | * Processes a new input file and return its compressed length. This |
97 | @@ -596,7 +645,7 @@ local void fill_window() |
98 | local off_t deflate_fast() |
99 | { |
100 | IPos hash_head; /* head of the hash chain */ |
101 | - int flush; /* set if current block must be flushed */ |
102 | + int flush; /* set if current block must be flushed, 2=>and padded */ |
103 | unsigned match_length = 0; /* length of best match */ |
104 | |
105 | prev_length = MIN_MATCH-1; |
106 | @@ -625,7 +674,8 @@ local off_t deflate_fast() |
107 | flush = ct_tally(strstart-match_start, match_length - MIN_MATCH); |
108 | |
109 | lookahead -= match_length; |
110 | - |
111 | + |
112 | + RSYNC_ROLL(strstart, match_length); |
113 | /* Insert new strings in the hash table only if the match length |
114 | * is not too large. This saves time but degrades compression. |
115 | */ |
116 | @@ -654,9 +704,14 @@ local off_t deflate_fast() |
117 | /* No match, output a literal byte */ |
118 | Tracevv((stderr,"%c",window[strstart])); |
119 | flush = ct_tally (0, window[strstart]); |
120 | + RSYNC_ROLL(strstart, 1); |
121 | lookahead--; |
122 | strstart++; |
123 | } |
124 | + if (rsync && strstart > rsync_chunk_end) { |
125 | + rsync_chunk_end = 0xFFFFFFFFUL; |
126 | + flush = 2; |
127 | + } |
128 | if (flush) FLUSH_BLOCK(0), block_start = strstart; |
129 | |
130 | /* Make sure that we always have enough lookahead, except |
131 | @@ -730,6 +785,7 @@ off_t deflate() |
132 | */ |
133 | lookahead -= prev_length-1; |
134 | prev_length -= 2; |
135 | + RSYNC_ROLL(strstart, prev_length+1); |
136 | do { |
137 | strstart++; |
138 | INSERT_STRING(strstart, hash_head); |
139 | @@ -742,24 +798,40 @@ off_t deflate() |
140 | match_available = 0; |
141 | match_length = MIN_MATCH-1; |
142 | strstart++; |
143 | - if (flush) FLUSH_BLOCK(0), block_start = strstart; |
144 | |
145 | + if (rsync && strstart > rsync_chunk_end) { |
146 | + rsync_chunk_end = 0xFFFFFFFFUL; |
147 | + flush = 2; |
148 | + } |
149 | + if (flush) FLUSH_BLOCK(0), block_start = strstart; |
150 | } else if (match_available) { |
151 | /* If there was no match at the previous position, output a |
152 | * single literal. If there was a match but the current match |
153 | * is longer, truncate the previous match to a single literal. |
154 | */ |
155 | Tracevv((stderr,"%c",window[strstart-1])); |
156 | - if (ct_tally (0, window[strstart-1])) { |
157 | - FLUSH_BLOCK(0), block_start = strstart; |
158 | + flush = ct_tally (0, window[strstart-1]); |
159 | + if (rsync && strstart > rsync_chunk_end) { |
160 | + rsync_chunk_end = 0xFFFFFFFFUL; |
161 | + flush = 2; |
162 | } |
163 | + if (flush) FLUSH_BLOCK(0), block_start = strstart; |
164 | + RSYNC_ROLL(strstart, 1); |
165 | strstart++; |
166 | lookahead--; |
167 | } else { |
168 | /* There is no previous match to compare with, wait for |
169 | * the next step to decide. |
170 | */ |
171 | + if (rsync && strstart > rsync_chunk_end) { |
172 | + /* Reset huffman tree */ |
173 | + rsync_chunk_end = 0xFFFFFFFFUL; |
174 | + flush = 2; |
175 | + FLUSH_BLOCK(0), block_start = strstart; |
176 | + } |
177 | + |
178 | match_available = 1; |
179 | + RSYNC_ROLL(strstart, 1); |
180 | strstart++; |
181 | lookahead--; |
182 | } |
183 | Index: gzip-1.5/doc/gzip.texi |
184 | =================================================================== |
185 | --- gzip-1.5.orig/doc/gzip.texi |
186 | +++ gzip-1.5/doc/gzip.texi |
187 | @@ -353,6 +353,14 @@ specified on the command line are direct |
188 | into the directory and compress all the files it finds there (or |
189 | decompress them in the case of @command{gunzip}). |
190 | |
191 | +@item --rsyncable |
192 | +While compressing, synchronize the output occasionally based on the |
193 | +input. This reduces compression by about 1 percent most cases, but |
194 | +means that the @code{rsync} program can take advantage of similarities |
195 | +in the uncompressed input when syncronizing two files compressed with |
196 | +this flag. @code{gunzip} cannot tell the difference between a |
197 | +compressed file created with this option, and one created without it. |
198 | + |
199 | @item --suffix @var{suf} |
200 | @itemx -S @var{suf} |
201 | Use suffix @var{suf} instead of @samp{.gz}. Any suffix can be |
202 | Index: gzip-1.5/gzip.c |
203 | =================================================================== |
204 | --- gzip-1.5.orig/gzip.c |
205 | +++ gzip-1.5/gzip.c |
206 | @@ -213,6 +213,7 @@ int ofd; /* output fil |
207 | unsigned insize; /* valid bytes in inbuf */ |
208 | unsigned inptr; /* index of next byte to be processed in inbuf */ |
209 | unsigned outcnt; /* bytes in output buffer */ |
210 | +int rsync = 0; /* make ryncable chunks */ |
211 | |
212 | static int handled_sig[] = |
213 | { |
214 | @@ -270,7 +271,7 @@ static const struct option longopts[] = |
215 | {"best", 0, 0, '9'}, /* compress better */ |
216 | {"lzw", 0, 0, 'Z'}, /* make output compatible with old compress */ |
217 | {"bits", 1, 0, 'b'}, /* max number of bits per code (implies -Z) */ |
218 | - |
219 | + {"rsyncable", 0, 0, 'R'}, /* make rsync-friendly archive */ |
220 | { 0, 0, 0, 0 } |
221 | }; |
222 | |
223 | @@ -353,6 +354,7 @@ local void help() |
224 | " -Z, --lzw produce output compatible with old compress", |
225 | " -b, --bits=BITS max number of bits per code (implies -Z)", |
226 | #endif |
227 | + " --rsyncable Make rsync-friendly archive", |
228 | "", |
229 | "With no FILE, or when FILE is -, read standard input.", |
230 | "", |
231 | @@ -482,6 +484,9 @@ int main (int argc, char **argv) |
232 | recursive = 1; |
233 | #endif |
234 | break; |
235 | + |
236 | + case 'R': |
237 | + rsync = 1; break; |
238 | case 'S': |
239 | #ifdef NO_MULTIPLE_DOTS |
240 | if (*optarg == '.') optarg++; |
241 | Index: gzip-1.5/gzip.h |
242 | =================================================================== |
243 | --- gzip-1.5.orig/gzip.h |
244 | +++ gzip-1.5/gzip.h |
245 | @@ -140,6 +140,7 @@ EXTERN(uch, window); /* Sliding |
246 | extern unsigned insize; /* valid bytes in inbuf */ |
247 | extern unsigned inptr; /* index of next byte to be processed in inbuf */ |
248 | extern unsigned outcnt; /* bytes in output buffer */ |
249 | +extern int rsync; /* deflate into rsyncable chunks */ |
250 | |
251 | extern off_t bytes_in; /* number of input bytes */ |
252 | extern off_t bytes_out; /* number of output bytes */ |
253 | @@ -287,7 +288,7 @@ extern off_t deflate (void); |
254 | /* in trees.c */ |
255 | extern void ct_init (ush *attr, int *method); |
256 | extern int ct_tally (int dist, int lc); |
257 | -extern off_t flush_block (char *buf, ulg stored_len, int eof); |
258 | +extern off_t flush_block (char *buf, ulg stored_len, int pad, int eof); |
259 | |
260 | /* in bits.c */ |
261 | extern void bi_init (file_t zipfile); |
262 | Index: gzip-1.5/trees.c |
263 | =================================================================== |
264 | --- gzip-1.5.orig/trees.c |
265 | +++ gzip-1.5/trees.c |
266 | @@ -856,9 +856,10 @@ local void send_all_trees(lcodes, dcodes |
267 | * trees or store, and output the encoded block to the zip file. This function |
268 | * returns the total compressed length for the file so far. |
269 | */ |
270 | -off_t flush_block(buf, stored_len, eof) |
271 | +off_t flush_block(buf, stored_len, pad, eof) |
272 | char *buf; /* input block, or NULL if too old */ |
273 | ulg stored_len; /* length of input block */ |
274 | + int pad; /* pad output to byte boundary */ |
275 | int eof; /* true if this is the last block for a file */ |
276 | { |
277 | ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ |
278 | @@ -951,6 +952,10 @@ off_t flush_block(buf, stored_len, eof) |
279 | Assert (input_len == bytes_in, "bad input size"); |
280 | bi_windup(); |
281 | compressed_len += 7; /* align on byte boundary */ |
282 | + } else if (pad && (compressed_len % 8) != 0) { |
283 | + send_bits((STORED_BLOCK<<1)+eof, 3); /* send block type */ |
284 | + compressed_len = (compressed_len + 3 + 7) & ~7L; |
285 | + copy_block(buf, 0, 1); /* with header */ |
286 | } |
287 | |
288 | return compressed_len >> 3; |