archive-zip: support archives bigger than 4GB
Add a zip64 extended information extra field to the central directory and emit the zip64 end of central directory records as well as locator if the offset of an entry within the archive exceeds 4GB. Signed-off-by: Rene Scharfe <l.s.r@web.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
René Scharfe committed
Apr 24, 2017 at 19:32 UTC
af95749f9b06467e7536da24432b00989a7c8c5a
2 files changed
+29
-5
archive-zip.c
+28
-4
@@ -14,7 +14,7 @@ static int zip_time;
14
/* We only care about the "buf" part here. */
15
static struct strbuf zip_dir;
16
17
-static unsigned int zip_offset;
17
+static uintmax_t zip_offset;
18
static uint64_t zip_dir_entries;
19
20
static unsigned int max_creator_version;
@@ -145,6 +145,11 @@ static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped)
145
copy_le16(dest, clamp_max(n, 0xffff, clamped));
146
}
147
148
+static void copy_le32_clamp(unsigned char *dest, uint64_t n, int *clamped)
149
+{
150
+ copy_le32(dest, clamp_max(n, 0xffffffff, clamped));
151
+}
152
+
153
static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
154
{
155
while (size-- > 0) {
@@ -154,6 +159,12 @@ static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
159
return -!!n;
160
}
161
162
+static uint32_t clamp32(uintmax_t n)
163
+{
164
+ const uintmax_t max = 0xffffffff;
165
+ return (n < max) ? n : max;
166
+}
167
+
168
static void *zlib_deflate_raw(void *data, unsigned long size,
169
int compression_level,
170
unsigned long *compressed_size)
@@ -254,6 +265,8 @@ static int write_zip_entry(struct archiver_args *args,
265
int is_binary = -1;
266
const char *path_without_prefix = path + args->baselen;
267
unsigned int creator_version = 0;
268
+ size_t zip_dir_extra_size = ZIP_EXTRA_MTIME_SIZE;
269
+ size_t zip64_dir_extra_payload_size = 0;
270
271
crc = crc32(0, NULL, 0);
272
@@ -433,6 +446,11 @@ static int write_zip_entry(struct archiver_args *args,
446
free(deflated);
447
free(buffer);
448
449
+ if (offset > 0xffffffff) {
450
+ zip64_dir_extra_payload_size += 8;
451
+ zip_dir_extra_size += 2 + 2 + zip64_dir_extra_payload_size;
452
+ }
453
+
454
strbuf_add_le(&zip_dir, 4, 0x02014b50); /* magic */
455
strbuf_add_le(&zip_dir, 2, creator_version);
456
strbuf_add_le(&zip_dir, 2, 10); /* version */
@@ -444,14 +462,20 @@ static int write_zip_entry(struct archiver_args *args,
462
strbuf_add_le(&zip_dir, 4, compressed_size);
463
strbuf_add_le(&zip_dir, 4, size);
464
strbuf_add_le(&zip_dir, 2, pathlen);
447
- strbuf_add_le(&zip_dir, 2, ZIP_EXTRA_MTIME_SIZE);
465
+ strbuf_add_le(&zip_dir, 2, zip_dir_extra_size);
466
strbuf_add_le(&zip_dir, 2, 0); /* comment length */
467
strbuf_add_le(&zip_dir, 2, 0); /* disk */
468
strbuf_add_le(&zip_dir, 2, !is_binary);
469
strbuf_add_le(&zip_dir, 4, attr2);
452
- strbuf_add_le(&zip_dir, 4, offset);
470
+ strbuf_add_le(&zip_dir, 4, clamp32(offset));
471
strbuf_add(&zip_dir, path, pathlen);
472
strbuf_add(&zip_dir, &extra, ZIP_EXTRA_MTIME_SIZE);
473
+ if (zip64_dir_extra_payload_size) {
474
+ strbuf_add_le(&zip_dir, 2, 0x0001); /* magic */
475
+ strbuf_add_le(&zip_dir, 2, zip64_dir_extra_payload_size);
476
+ if (offset >= 0xffffffff)
477
+ strbuf_add_le(&zip_dir, 8, offset);
478
+ }
479
zip_dir_entries++;
480
481
return 0;
@@ -494,7 +518,7 @@ static void write_zip_trailer(const unsigned char *sha1)
518
&clamped);
519
copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
520
copy_le32(trailer.size, zip_dir.len);
497
- copy_le32(trailer.offset, zip_offset);
521
+ copy_le32_clamp(trailer.offset, zip_offset, &clamped);
522
copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
523
524
write_or_die(1, zip_dir.buf, zip_dir.len);
t/t5004-archive-corner-cases.sh
+1
-1
@@ -155,7 +155,7 @@ test_expect_success ZIPINFO 'zip archive with many entries' '
155
test_cmp expect actual
156
'
157
158
-test_expect_failure EXPENSIVE,UNZIP 'zip archive bigger than 4GB' '
158
+test_expect_success EXPENSIVE,UNZIP 'zip archive bigger than 4GB' '
159
# build string containing 65536 characters
160
s=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef &&
161
s=$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s$s &&