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
}