archive-zip: use deflateInit2() to ask for raw compressed data

We use the function git_deflate_init() -- which wraps the zlib function deflateInit() -- to initialize compression of ZIP file entries. This results in compressed data prefixed with a two-bytes long header and followed by a four-bytes trailer. ZIP file entries consist of ZIP headers and raw compressed data instead, so we remove the zlib wrapper before writing the result. We can ask zlib for the the raw compressed data without the unwanted parts in the first place by using deflateInit2() and specifying a negative number of bits to size the window. For that purpose, factor out the function do_git_deflate_init() and add git_deflate_init_raw(), which wraps it. Then use the latter in archive-zip.c and get rid of the code that stripped the zlib header and trailer. Also rename the helper function zlib_deflate() to zlib_deflate_raw() to reflect the change. Thus we avoid generating data that we throw away anyway, the code becomes shorter and some magic constants are removed. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>

René Scharfe committed Mar 15, 2013 at 23:21 UTC c3c2e1a09b84dc932d90fa09d1632e5efa34c940
3 files changed +34 -28
archive-zip.c
+14 -22
@@ -111,8 +111,9 @@ static void copy_le32(unsigned char *dest, unsigned int n)
111 dest[3] = 0xff & (n >> 030);
112 }
113
114 -static void *zlib_deflate(void *data, unsigned long size,
115 - int compression_level, unsigned long *compressed_size)
114 +static void *zlib_deflate_raw(void *data, unsigned long size,
115 + int compression_level,
116 + unsigned long *compressed_size)
117 {
118 git_zstream stream;
119 unsigned long maxsize;
@@ -120,7 +121,7 @@ static void *zlib_deflate(void *data, unsigned long size,
121 int result;
122
123 memset(&stream, 0, sizeof(stream));
123 - git_deflate_init(&stream, compression_level);
124 + git_deflate_init_raw(&stream, compression_level);
125 maxsize = git_deflate_bound(&stream, size);
126 buffer = xmalloc(maxsize);
127
@@ -265,14 +266,11 @@ static int write_zip_entry(struct archiver_args *args,
266 }
267
268 if (buffer && method == 8) {
268 - deflated = zlib_deflate(buffer, size, args->compression_level,
269 - &compressed_size);
270 - if (deflated && compressed_size - 6 < size) {
271 - /* ZLIB --> raw compressed data (see RFC 1950) */
272 - /* CMF and FLG ... */
273 - out = (unsigned char *)deflated + 2;
274 - compressed_size -= 6; /* ... and ADLER32 */
275 - } else {
269 + out = deflated = zlib_deflate_raw(buffer, size,
270 + args->compression_level,
271 + &compressed_size);
272 + if (!out || compressed_size >= size) {
273 + out = buffer;
274 method = 0;
275 compressed_size = size;
276 }
@@ -353,7 +351,7 @@ static int write_zip_entry(struct archiver_args *args,
351 unsigned char compressed[STREAM_BUFFER_SIZE * 2];
352
353 memset(&zstream, 0, sizeof(zstream));
356 - git_deflate_init(&zstream, args->compression_level);
354 + git_deflate_init_raw(&zstream, args->compression_level);
355
356 compressed_size = 0;
357 zstream.next_out = compressed;
@@ -370,13 +368,10 @@ static int write_zip_entry(struct archiver_args *args,
368 result = git_deflate(&zstream, 0);
369 if (result != Z_OK)
370 die("deflate error (%d)", result);
373 - out = compressed;
374 - if (!compressed_size)
375 - out += 2;
376 - out_len = zstream.next_out - out;
371 + out_len = zstream.next_out - compressed;
372
373 if (out_len > 0) {
379 - write_or_die(1, out, out_len);
374 + write_or_die(1, compressed, out_len);
375 compressed_size += out_len;
376 zstream.next_out = compressed;
377 zstream.avail_out = sizeof(compressed);
@@ -394,11 +389,8 @@ static int write_zip_entry(struct archiver_args *args,
389 die("deflate error (%d)", result);
390
391 git_deflate_end(&zstream);
397 - out = compressed;
398 - if (!compressed_size)
399 - out += 2;
400 - out_len = zstream.next_out - out - 4;
401 - write_or_die(1, out, out_len);
392 + out_len = zstream.next_out - compressed;
393 + write_or_die(1, compressed, out_len);
394 compressed_size += out_len;
395 zip_offset += compressed_size;
396
cache.h
+1
@@ -34,6 +34,7 @@ int git_inflate(git_zstream *, int flush);
34
35 void git_deflate_init(git_zstream *, int level);
36 void git_deflate_init_gzip(git_zstream *, int level);
37 +void git_deflate_init_raw(git_zstream *, int level);
38 void git_deflate_end(git_zstream *);
39 int git_deflate_abort(git_zstream *);
40 int git_deflate_end_gently(git_zstream *);
zlib.c
+19 -6
@@ -168,13 +168,8 @@ void git_deflate_init(git_zstream *strm, int level)
168 strm->z.msg ? strm->z.msg : "no message");
169 }
170
171 -void git_deflate_init_gzip(git_zstream *strm, int level)
171 +static void do_git_deflate_init(git_zstream *strm, int level, int windowBits)
172 {
173 - /*
174 - * Use default 15 bits, +16 is to generate gzip header/trailer
175 - * instead of the zlib wrapper.
176 - */
177 - const int windowBits = 15 + 16;
173 int status;
174
175 zlib_pre_call(strm);
@@ -188,6 +183,24 @@ void git_deflate_init_gzip(git_zstream *strm, int level)
183 strm->z.msg ? strm->z.msg : "no message");
184 }
185
186 +void git_deflate_init_gzip(git_zstream *strm, int level)
187 +{
188 + /*
189 + * Use default 15 bits, +16 is to generate gzip header/trailer
190 + * instead of the zlib wrapper.
191 + */
192 + return do_git_deflate_init(strm, level, 15 + 16);
193 +}
194 +
195 +void git_deflate_init_raw(git_zstream *strm, int level)
196 +{
197 + /*
198 + * Use default 15 bits, negate the value to get raw compressed
199 + * data without zlib header and trailer.
200 + */
201 + return do_git_deflate_init(strm, level, -15);
202 +}
203 +
204 int git_deflate_abort(git_zstream *strm)
205 {
206 int status;