]> git.ipfire.org Git - thirdparty/git.git/commitdiff
archive-zip: use deflateInit2() to ask for raw compressed data
authorRené Scharfe <rene.scharfe@lsrfire.ath.cx>
Fri, 15 Mar 2013 22:21:51 +0000 (23:21 +0100)
committerJunio C Hamano <gitster@pobox.com>
Sun, 17 Mar 2013 05:07:02 +0000 (22:07 -0700)
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>
archive-zip.c
cache.h
zlib.c

index a8d119305ff5c0161e7239a8ad70a92c76122631..b2c4fe0e9f9816a6cb79aa8f7a0cb59ae5bf7f8d 100644 (file)
@@ -111,8 +111,9 @@ static void copy_le32(unsigned char *dest, unsigned int n)
        dest[3] = 0xff & (n >> 030);
 }
 
-static void *zlib_deflate(void *data, unsigned long size,
-               int compression_level, unsigned long *compressed_size)
+static void *zlib_deflate_raw(void *data, unsigned long size,
+                             int compression_level,
+                             unsigned long *compressed_size)
 {
        git_zstream stream;
        unsigned long maxsize;
@@ -120,7 +121,7 @@ static void *zlib_deflate(void *data, unsigned long size,
        int result;
 
        memset(&stream, 0, sizeof(stream));
-       git_deflate_init(&stream, compression_level);
+       git_deflate_init_raw(&stream, compression_level);
        maxsize = git_deflate_bound(&stream, size);
        buffer = xmalloc(maxsize);
 
@@ -265,14 +266,11 @@ static int write_zip_entry(struct archiver_args *args,
        }
 
        if (buffer && method == 8) {
-               deflated = zlib_deflate(buffer, size, args->compression_level,
-                               &compressed_size);
-               if (deflated && compressed_size - 6 < size) {
-                       /* ZLIB --> raw compressed data (see RFC 1950) */
-                       /* CMF and FLG ... */
-                       out = (unsigned char *)deflated + 2;
-                       compressed_size -= 6;   /* ... and ADLER32 */
-               } else {
+               out = deflated = zlib_deflate_raw(buffer, size,
+                                                 args->compression_level,
+                                                 &compressed_size);
+               if (!out || compressed_size >= size) {
+                       out = buffer;
                        method = 0;
                        compressed_size = size;
                }
@@ -353,7 +351,7 @@ static int write_zip_entry(struct archiver_args *args,
                unsigned char compressed[STREAM_BUFFER_SIZE * 2];
 
                memset(&zstream, 0, sizeof(zstream));
-               git_deflate_init(&zstream, args->compression_level);
+               git_deflate_init_raw(&zstream, args->compression_level);
 
                compressed_size = 0;
                zstream.next_out = compressed;
@@ -370,13 +368,10 @@ static int write_zip_entry(struct archiver_args *args,
                        result = git_deflate(&zstream, 0);
                        if (result != Z_OK)
                                die("deflate error (%d)", result);
-                       out = compressed;
-                       if (!compressed_size)
-                               out += 2;
-                       out_len = zstream.next_out - out;
+                       out_len = zstream.next_out - compressed;
 
                        if (out_len > 0) {
-                               write_or_die(1, out, out_len);
+                               write_or_die(1, compressed, out_len);
                                compressed_size += out_len;
                                zstream.next_out = compressed;
                                zstream.avail_out = sizeof(compressed);
@@ -394,11 +389,8 @@ static int write_zip_entry(struct archiver_args *args,
                        die("deflate error (%d)", result);
 
                git_deflate_end(&zstream);
-               out = compressed;
-               if (!compressed_size)
-                       out += 2;
-               out_len = zstream.next_out - out - 4;
-               write_or_die(1, out, out_len);
+               out_len = zstream.next_out - compressed;
+               write_or_die(1, compressed, out_len);
                compressed_size += out_len;
                zip_offset += compressed_size;
 
diff --git a/cache.h b/cache.h
index c257953fa798110e0f4be9258f4f88f2d7952bdb..8e7538692c887539331d25569bb8b8087694e9ca 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -34,6 +34,7 @@ int git_inflate(git_zstream *, int flush);
 
 void git_deflate_init(git_zstream *, int level);
 void git_deflate_init_gzip(git_zstream *, int level);
+void git_deflate_init_raw(git_zstream *, int level);
 void git_deflate_end(git_zstream *);
 int git_deflate_abort(git_zstream *);
 int git_deflate_end_gently(git_zstream *);
diff --git a/zlib.c b/zlib.c
index 2b2c0c780e3fca6217c688298053a01aad724505..bbaa0815ed55a425e458773a58a0eb9aca8453eb 100644 (file)
--- a/zlib.c
+++ b/zlib.c
@@ -168,13 +168,8 @@ void git_deflate_init(git_zstream *strm, int level)
            strm->z.msg ? strm->z.msg : "no message");
 }
 
-void git_deflate_init_gzip(git_zstream *strm, int level)
+static void do_git_deflate_init(git_zstream *strm, int level, int windowBits)
 {
-       /*
-        * Use default 15 bits, +16 is to generate gzip header/trailer
-        * instead of the zlib wrapper.
-        */
-       const int windowBits = 15 + 16;
        int status;
 
        zlib_pre_call(strm);
@@ -188,6 +183,24 @@ void git_deflate_init_gzip(git_zstream *strm, int level)
            strm->z.msg ? strm->z.msg : "no message");
 }
 
+void git_deflate_init_gzip(git_zstream *strm, int level)
+{
+       /*
+        * Use default 15 bits, +16 is to generate gzip header/trailer
+        * instead of the zlib wrapper.
+        */
+       return do_git_deflate_init(strm, level, 15 + 16);
+}
+
+void git_deflate_init_raw(git_zstream *strm, int level)
+{
+       /*
+        * Use default 15 bits, negate the value to get raw compressed
+        * data without zlib header and trailer.
+        */
+       return do_git_deflate_init(strm, level, -15);
+}
+
 int git_deflate_abort(git_zstream *strm)
 {
        int status;