From: "René Scharfe" <l.s.r@web.de>
To: Peter Krefting <peter@softwolves.pp.se>, Johannes Sixt <j6t@kdbg.org>
Cc: git@vger.kernel.org, Keith Goldfarb <keith@blackthorn-media.com>
Subject: [PATCH v3 4/5] archive-zip: support archives bigger than 4GB
Date: Mon, 24 Apr 2017 19:32:36 +0200 [thread overview]
Message-ID: <02ddca3c-a11f-7c0c-947e-5ca87a62cdee@web.de> (raw)
In-Reply-To: <85f2b6d1-107b-0624-af82-92446f28269e@web.de>
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>
---
archive-zip.c | 32 ++++++++++++++++++++++++++++----
t/t5004-archive-corner-cases.sh | 2 +-
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/archive-zip.c b/archive-zip.c
index 2d52bb3ade..7d6f2a85d0 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -14,7 +14,7 @@ static int zip_time;
/* We only care about the "buf" part here. */
static struct strbuf zip_dir;
-static unsigned int zip_offset;
+static uintmax_t zip_offset;
static uint64_t zip_dir_entries;
static unsigned int max_creator_version;
@@ -145,6 +145,11 @@ static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped)
copy_le16(dest, clamp_max(n, 0xffff, clamped));
}
+static void copy_le32_clamp(unsigned char *dest, uint64_t n, int *clamped)
+{
+ copy_le32(dest, clamp_max(n, 0xffffffff, clamped));
+}
+
static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
{
while (size-- > 0) {
@@ -154,6 +159,12 @@ static int strbuf_add_le(struct strbuf *sb, size_t size, uintmax_t n)
return -!!n;
}
+static uint32_t clamp32(uintmax_t n)
+{
+ const uintmax_t max = 0xffffffff;
+ return (n < max) ? n : max;
+}
+
static void *zlib_deflate_raw(void *data, unsigned long size,
int compression_level,
unsigned long *compressed_size)
@@ -254,6 +265,8 @@ static int write_zip_entry(struct archiver_args *args,
int is_binary = -1;
const char *path_without_prefix = path + args->baselen;
unsigned int creator_version = 0;
+ size_t zip_dir_extra_size = ZIP_EXTRA_MTIME_SIZE;
+ size_t zip64_dir_extra_payload_size = 0;
crc = crc32(0, NULL, 0);
@@ -433,6 +446,11 @@ static int write_zip_entry(struct archiver_args *args,
free(deflated);
free(buffer);
+ if (offset > 0xffffffff) {
+ zip64_dir_extra_payload_size += 8;
+ zip_dir_extra_size += 2 + 2 + zip64_dir_extra_payload_size;
+ }
+
strbuf_add_le(&zip_dir, 4, 0x02014b50); /* magic */
strbuf_add_le(&zip_dir, 2, creator_version);
strbuf_add_le(&zip_dir, 2, 10); /* version */
@@ -444,14 +462,20 @@ static int write_zip_entry(struct archiver_args *args,
strbuf_add_le(&zip_dir, 4, compressed_size);
strbuf_add_le(&zip_dir, 4, size);
strbuf_add_le(&zip_dir, 2, pathlen);
- strbuf_add_le(&zip_dir, 2, ZIP_EXTRA_MTIME_SIZE);
+ strbuf_add_le(&zip_dir, 2, zip_dir_extra_size);
strbuf_add_le(&zip_dir, 2, 0); /* comment length */
strbuf_add_le(&zip_dir, 2, 0); /* disk */
strbuf_add_le(&zip_dir, 2, !is_binary);
strbuf_add_le(&zip_dir, 4, attr2);
- strbuf_add_le(&zip_dir, 4, offset);
+ strbuf_add_le(&zip_dir, 4, clamp32(offset));
strbuf_add(&zip_dir, path, pathlen);
strbuf_add(&zip_dir, &extra, ZIP_EXTRA_MTIME_SIZE);
+ if (zip64_dir_extra_payload_size) {
+ strbuf_add_le(&zip_dir, 2, 0x0001); /* magic */
+ strbuf_add_le(&zip_dir, 2, zip64_dir_extra_payload_size);
+ if (offset >= 0xffffffff)
+ strbuf_add_le(&zip_dir, 8, offset);
+ }
zip_dir_entries++;
return 0;
@@ -494,7 +518,7 @@ static void write_zip_trailer(const unsigned char *sha1)
&clamped);
copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
copy_le32(trailer.size, zip_dir.len);
- copy_le32(trailer.offset, zip_offset);
+ copy_le32_clamp(trailer.offset, zip_offset, &clamped);
copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
write_or_die(1, zip_dir.buf, zip_dir.len);
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index bc052c803a..0ac94b5cc9 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -155,7 +155,7 @@ test_expect_success ZIPINFO 'zip archive with many entries' '
test_cmp expect actual
'
-test_expect_failure EXPENSIVE,UNZIP 'zip archive bigger than 4GB' '
+test_expect_success EXPENSIVE,UNZIP 'zip archive bigger than 4GB' '
# build string containing 65536 characters
s=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef &&
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 &&
--
2.12.2
next prev parent reply other threads:[~2017-04-24 17:32 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-04-21 21:08 Git archive doesn't fully support zip64 Keith Goldfarb
2017-04-22 19:22 ` [PATCH] archive-zip: Add zip64 headers when file size is too large for 32 bits Peter Krefting
2017-04-22 21:52 ` Johannes Sixt
2017-04-22 22:41 ` [PATCH v2] " Peter Krefting
2017-04-23 7:50 ` Johannes Sixt
2017-04-23 14:51 ` Peter Krefting
2017-04-23 19:49 ` Johannes Sixt
2017-04-24 8:04 ` Peter Krefting
2017-04-24 12:04 ` René Scharfe
2017-04-24 17:22 ` [PATCH v3 0/5] archive-zip: support files and archives bigger than 4GB René Scharfe
2017-04-24 17:29 ` [PATCH v3 1/5] archive-zip: add tests for big ZIP archives René Scharfe
2017-04-24 17:30 ` [PATCH v3 2/5] archive-zip: use strbuf for ZIP directory René Scharfe
2017-04-25 4:51 ` Junio C Hamano
2017-04-25 5:28 ` René Scharfe
2017-04-24 17:31 ` [PATCH v3 3/5] archive-zip: write ZIP dir entry directly to strbuf René Scharfe
2017-04-24 17:32 ` René Scharfe [this message]
2017-04-24 18:24 ` [PATCH v3 4/5] archive-zip: support archives bigger than 4GB Peter Krefting
2017-04-24 20:06 ` René Scharfe
2017-04-24 20:39 ` René Scharfe
2017-04-24 21:02 ` Johannes Sixt
2017-04-24 21:41 ` René Scharfe
2017-04-25 7:55 ` Peter Krefting
2017-04-25 16:24 ` René Scharfe
2017-04-26 21:02 ` Peter Krefting
2017-04-26 23:38 ` René Scharfe
2017-04-27 4:57 ` Peter Krefting
2017-04-27 19:54 ` René Scharfe
2017-04-28 8:40 ` Peter Krefting
2017-04-24 17:33 ` [PATCH v3 5/5] archive-zip: support files " René Scharfe
2017-04-24 21:11 ` Keith Goldfarb
2017-04-25 4:46 ` Junio C Hamano
2017-04-25 5:27 ` René Scharfe
2017-04-29 21:00 ` [PATCH v3 0/5] archive-zip: support files and archives " Torsten Bögershausen
2017-04-29 22:28 ` René Scharfe
2017-04-30 5:31 ` Torsten Bögershausen
2017-04-30 7:53 ` René Scharfe
2017-04-30 13:06 ` Torsten Bögershausen
2017-04-30 16:32 ` Johannes Sixt
2017-04-30 16:40 ` René Scharfe
2017-04-30 23:49 ` Junio C Hamano
2017-05-01 8:30 ` René Scharfe
2017-04-23 0:16 ` [PATCH] archive-zip: Add zip64 headers when file size is too large for 32 bits René Scharfe
2017-04-23 6:42 ` Peter Krefting
2017-04-23 7:27 ` Johannes Sixt
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=02ddca3c-a11f-7c0c-947e-5ca87a62cdee@web.de \
--to=l.s.r@web.de \
--cc=git@vger.kernel.org \
--cc=j6t@kdbg.org \
--cc=keith@blackthorn-media.com \
--cc=peter@softwolves.pp.se \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).