Skip to content

Commit c3c2e1a

Browse files
René Scharfegitster
authored andcommitted
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 <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d3c1472 commit c3c2e1a

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

archive-zip.c

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -111,16 +111,17 @@ static void copy_le32(unsigned char *dest, unsigned int n)
111111
dest[3] = 0xff & (n >> 030);
112112
}
113113

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)
116117
{
117118
git_zstream stream;
118119
unsigned long maxsize;
119120
void *buffer;
120121
int result;
121122

122123
memset(&stream, 0, sizeof(stream));
123-
git_deflate_init(&stream, compression_level);
124+
git_deflate_init_raw(&stream, compression_level);
124125
maxsize = git_deflate_bound(&stream, size);
125126
buffer = xmalloc(maxsize);
126127

@@ -265,14 +266,11 @@ static int write_zip_entry(struct archiver_args *args,
265266
}
266267

267268
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;
276274
method = 0;
277275
compressed_size = size;
278276
}
@@ -353,7 +351,7 @@ static int write_zip_entry(struct archiver_args *args,
353351
unsigned char compressed[STREAM_BUFFER_SIZE * 2];
354352

355353
memset(&zstream, 0, sizeof(zstream));
356-
git_deflate_init(&zstream, args->compression_level);
354+
git_deflate_init_raw(&zstream, args->compression_level);
357355

358356
compressed_size = 0;
359357
zstream.next_out = compressed;
@@ -370,13 +368,10 @@ static int write_zip_entry(struct archiver_args *args,
370368
result = git_deflate(&zstream, 0);
371369
if (result != Z_OK)
372370
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;
377372

378373
if (out_len > 0) {
379-
write_or_die(1, out, out_len);
374+
write_or_die(1, compressed, out_len);
380375
compressed_size += out_len;
381376
zstream.next_out = compressed;
382377
zstream.avail_out = sizeof(compressed);
@@ -394,11 +389,8 @@ static int write_zip_entry(struct archiver_args *args,
394389
die("deflate error (%d)", result);
395390

396391
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);
402394
compressed_size += out_len;
403395
zip_offset += compressed_size;
404396

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ int git_inflate(git_zstream *, int flush);
3434

3535
void git_deflate_init(git_zstream *, int level);
3636
void git_deflate_init_gzip(git_zstream *, int level);
37+
void git_deflate_init_raw(git_zstream *, int level);
3738
void git_deflate_end(git_zstream *);
3839
int git_deflate_abort(git_zstream *);
3940
int git_deflate_end_gently(git_zstream *);

zlib.c

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,8 @@ void git_deflate_init(git_zstream *strm, int level)
168168
strm->z.msg ? strm->z.msg : "no message");
169169
}
170170

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)
172172
{
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;
178173
int status;
179174

180175
zlib_pre_call(strm);
@@ -188,6 +183,24 @@ void git_deflate_init_gzip(git_zstream *strm, int level)
188183
strm->z.msg ? strm->z.msg : "no message");
189184
}
190185

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+
191204
int git_deflate_abort(git_zstream *strm)
192205
{
193206
int status;

0 commit comments

Comments
 (0)