Annotation of /trunk/gzip/patches/gzip-1.3.13-rsync.patch
Parent Directory | Revision Log
Revision 2540 -
(hide 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 | niro | 2540 | 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; |