archive-zip: use strbuf for ZIP directory

Keep the ZIP central directory, which is written after all archive entries, in a strbuf instead of a custom-managed buffer. It contains binary data, so we can't (and don't want to) use the full range of strbuf functions and we don't need the terminating NUL, but the result is shorter and simpler code. 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:30 UTC c061a149709195e0ec914a5d6ba173042e4197f9
1 file changed +11 -25
archive-zip.c
+11 -25
@@ -11,16 +11,14 @@
11 static int zip_date;
12 static int zip_time;
13
14 -static unsigned char *zip_dir;
15 -static unsigned int zip_dir_size;
14 +/* We only care about the "buf" part here. */
15 +static struct strbuf zip_dir;
16
17 static unsigned int zip_offset;
18 -static unsigned int zip_dir_offset;
18 static uint64_t zip_dir_entries;
19
20 static unsigned int max_creator_version;
21
23 -#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
22 #define ZIP_STREAM (1 << 3)
23 #define ZIP_UTF8 (1 << 11)
24
@@ -268,7 +266,6 @@ static int write_zip_entry(struct archiver_args *args,
266 unsigned long attr2;
267 unsigned long compressed_size;
268 unsigned long crc;
271 - unsigned long direntsize;
269 int method;
270 unsigned char *out;
271 void *deflated = NULL;
@@ -356,13 +353,6 @@ static int write_zip_entry(struct archiver_args *args,
353 extra.flags[0] = 1; /* just mtime */
354 copy_le32(extra.mtime, args->time);
355
359 - /* make sure we have enough free space in the dictionary */
360 - direntsize = ZIP_DIR_HEADER_SIZE + pathlen + ZIP_EXTRA_MTIME_SIZE;
361 - while (zip_dir_size < zip_dir_offset + direntsize) {
362 - zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
363 - zip_dir = xrealloc(zip_dir, zip_dir_size);
364 - }
365 -
356 copy_le32(dirent.magic, 0x02014b50);
357 copy_le16(dirent.creator_version, creator_version);
358 copy_le16(dirent.version, 10);
@@ -486,12 +476,9 @@ static int write_zip_entry(struct archiver_args *args,
476
477 copy_le16(dirent.attr1, !is_binary);
478
489 - memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
490 - zip_dir_offset += ZIP_DIR_HEADER_SIZE;
491 - memcpy(zip_dir + zip_dir_offset, path, pathlen);
492 - zip_dir_offset += pathlen;
493 - memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE);
494 - zip_dir_offset += ZIP_EXTRA_MTIME_SIZE;
479 + strbuf_add(&zip_dir, &dirent, ZIP_DIR_HEADER_SIZE);
480 + strbuf_add(&zip_dir, path, pathlen);
481 + strbuf_add(&zip_dir, &extra, ZIP_EXTRA_MTIME_SIZE);
482 zip_dir_entries++;
483
484 return 0;
@@ -510,12 +497,12 @@ static void write_zip64_trailer(void)
497 copy_le32(trailer64.directory_start_disk, 0);
498 copy_le64(trailer64.entries_on_this_disk, zip_dir_entries);
499 copy_le64(trailer64.entries, zip_dir_entries);
513 - copy_le64(trailer64.size, zip_dir_offset);
500 + copy_le64(trailer64.size, zip_dir.len);
501 copy_le64(trailer64.offset, zip_offset);
502
503 copy_le32(locator64.magic, 0x07064b50);
504 copy_le32(locator64.disk, 0);
518 - copy_le64(locator64.offset, zip_offset + zip_dir_offset);
505 + copy_le64(locator64.offset, zip_offset + zip_dir.len);
506 copy_le32(locator64.number_of_disks, 1);
507
508 write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE);
@@ -533,11 +520,11 @@ static void write_zip_trailer(const unsigned char *sha1)
520 copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries,
521 &clamped);
522 copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped);
536 - copy_le32(trailer.size, zip_dir_offset);
523 + copy_le32(trailer.size, zip_dir.len);
524 copy_le32(trailer.offset, zip_offset);
525 copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0);
526
540 - write_or_die(1, zip_dir, zip_dir_offset);
527 + write_or_die(1, zip_dir.buf, zip_dir.len);
528 if (clamped)
529 write_zip64_trailer();
530 write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE);
@@ -568,14 +555,13 @@ static int write_zip_archive(const struct archiver *ar,
555
556 dos_time(&args->time, &zip_date, &zip_time);
557
571 - zip_dir = xmalloc(ZIP_DIRECTORY_MIN_SIZE);
572 - zip_dir_size = ZIP_DIRECTORY_MIN_SIZE;
558 + strbuf_init(&zip_dir, 0);
559
560 err = write_archive_entries(args, write_zip_entry);
561 if (!err)
562 write_zip_trailer(args->commit_sha1);
563
578 - free(zip_dir);
564 + strbuf_release(&zip_dir);
565
566 return err;
567 }