2 * Copyright (c) 2006 Rene Scharfe
9 #include "xdiff-interface.h"
14 static unsigned char *zip_dir
;
15 static unsigned int zip_dir_size
;
17 static unsigned int zip_offset
;
18 static unsigned int zip_dir_offset
;
19 static uint64_t zip_dir_entries
;
21 static unsigned int max_creator_version
;
23 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
24 #define ZIP_STREAM (1 << 3)
25 #define ZIP_UTF8 (1 << 11)
27 struct zip_local_header
{
28 unsigned char magic
[4];
29 unsigned char version
[2];
30 unsigned char flags
[2];
31 unsigned char compression_method
[2];
32 unsigned char mtime
[2];
33 unsigned char mdate
[2];
34 unsigned char crc32
[4];
35 unsigned char compressed_size
[4];
36 unsigned char size
[4];
37 unsigned char filename_length
[2];
38 unsigned char extra_length
[2];
39 unsigned char _end
[1];
42 struct zip_data_desc
{
43 unsigned char magic
[4];
44 unsigned char crc32
[4];
45 unsigned char compressed_size
[4];
46 unsigned char size
[4];
47 unsigned char _end
[1];
50 struct zip_dir_header
{
51 unsigned char magic
[4];
52 unsigned char creator_version
[2];
53 unsigned char version
[2];
54 unsigned char flags
[2];
55 unsigned char compression_method
[2];
56 unsigned char mtime
[2];
57 unsigned char mdate
[2];
58 unsigned char crc32
[4];
59 unsigned char compressed_size
[4];
60 unsigned char size
[4];
61 unsigned char filename_length
[2];
62 unsigned char extra_length
[2];
63 unsigned char comment_length
[2];
64 unsigned char disk
[2];
65 unsigned char attr1
[2];
66 unsigned char attr2
[4];
67 unsigned char offset
[4];
68 unsigned char _end
[1];
71 struct zip_dir_trailer
{
72 unsigned char magic
[4];
73 unsigned char disk
[2];
74 unsigned char directory_start_disk
[2];
75 unsigned char entries_on_this_disk
[2];
76 unsigned char entries
[2];
77 unsigned char size
[4];
78 unsigned char offset
[4];
79 unsigned char comment_length
[2];
80 unsigned char _end
[1];
83 struct zip_extra_mtime
{
84 unsigned char magic
[2];
85 unsigned char extra_size
[2];
86 unsigned char flags
[1];
87 unsigned char mtime
[4];
88 unsigned char _end
[1];
91 struct zip64_dir_trailer
{
92 unsigned char magic
[4];
93 unsigned char record_size
[8];
94 unsigned char creator_version
[2];
95 unsigned char version
[2];
96 unsigned char disk
[4];
97 unsigned char directory_start_disk
[4];
98 unsigned char entries_on_this_disk
[8];
99 unsigned char entries
[8];
100 unsigned char size
[8];
101 unsigned char offset
[8];
102 unsigned char _end
[1];
105 struct zip64_dir_trailer_locator
{
106 unsigned char magic
[4];
107 unsigned char disk
[4];
108 unsigned char offset
[8];
109 unsigned char number_of_disks
[4];
110 unsigned char _end
[1];
114 * On ARM, padding is added at the end of the struct, so a simple
115 * sizeof(struct ...) reports two bytes more than the payload size
116 * we're interested in.
118 #define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
119 #define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
120 #define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
121 #define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
122 #define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end)
123 #define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
124 (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
125 #define ZIP64_DIR_TRAILER_SIZE offsetof(struct zip64_dir_trailer, _end)
126 #define ZIP64_DIR_TRAILER_RECORD_SIZE \
127 (ZIP64_DIR_TRAILER_SIZE - \
128 offsetof(struct zip64_dir_trailer, creator_version))
129 #define ZIP64_DIR_TRAILER_LOCATOR_SIZE \
130 offsetof(struct zip64_dir_trailer_locator, _end)
132 static void copy_le16(unsigned char *dest
, unsigned int n
)
135 dest
[1] = 0xff & (n
>> 010);
138 static void copy_le32(unsigned char *dest
, unsigned int n
)
141 dest
[1] = 0xff & (n
>> 010);
142 dest
[2] = 0xff & (n
>> 020);
143 dest
[3] = 0xff & (n
>> 030);
146 static void copy_le64(unsigned char *dest
, uint64_t n
)
149 dest
[1] = 0xff & (n
>> 010);
150 dest
[2] = 0xff & (n
>> 020);
151 dest
[3] = 0xff & (n
>> 030);
152 dest
[4] = 0xff & (n
>> 040);
153 dest
[5] = 0xff & (n
>> 050);
154 dest
[6] = 0xff & (n
>> 060);
155 dest
[7] = 0xff & (n
>> 070);
158 static uint64_t clamp_max(uint64_t n
, uint64_t max
, int *clamped
)
166 static void copy_le16_clamp(unsigned char *dest
, uint64_t n
, int *clamped
)
168 copy_le16(dest
, clamp_max(n
, 0xffff, clamped
));
171 static void *zlib_deflate_raw(void *data
, unsigned long size
,
172 int compression_level
,
173 unsigned long *compressed_size
)
176 unsigned long maxsize
;
180 git_deflate_init_raw(&stream
, compression_level
);
181 maxsize
= git_deflate_bound(&stream
, size
);
182 buffer
= xmalloc(maxsize
);
184 stream
.next_in
= data
;
185 stream
.avail_in
= size
;
186 stream
.next_out
= buffer
;
187 stream
.avail_out
= maxsize
;
190 result
= git_deflate(&stream
, Z_FINISH
);
191 } while (result
== Z_OK
);
193 if (result
!= Z_STREAM_END
) {
198 git_deflate_end(&stream
);
199 *compressed_size
= stream
.total_out
;
204 static void write_zip_data_desc(unsigned long size
,
205 unsigned long compressed_size
,
208 struct zip_data_desc trailer
;
210 copy_le32(trailer
.magic
, 0x08074b50);
211 copy_le32(trailer
.crc32
, crc
);
212 copy_le32(trailer
.compressed_size
, compressed_size
);
213 copy_le32(trailer
.size
, size
);
214 write_or_die(1, &trailer
, ZIP_DATA_DESC_SIZE
);
217 static void set_zip_dir_data_desc(struct zip_dir_header
*header
,
219 unsigned long compressed_size
,
222 copy_le32(header
->crc32
, crc
);
223 copy_le32(header
->compressed_size
, compressed_size
);
224 copy_le32(header
->size
, size
);
227 static void set_zip_header_data_desc(struct zip_local_header
*header
,
229 unsigned long compressed_size
,
232 copy_le32(header
->crc32
, crc
);
233 copy_le32(header
->compressed_size
, compressed_size
);
234 copy_le32(header
->size
, size
);
237 static int has_only_ascii(const char *s
)
248 static int entry_is_binary(const char *path
, const void *buffer
, size_t size
)
250 struct userdiff_driver
*driver
= userdiff_find_by_path(path
);
252 driver
= userdiff_find_by_name("default");
253 if (driver
->binary
!= -1)
254 return driver
->binary
;
255 return buffer_is_binary(buffer
, size
);
258 #define STREAM_BUFFER_SIZE (1024 * 16)
260 static int write_zip_entry(struct archiver_args
*args
,
261 const unsigned char *sha1
,
262 const char *path
, size_t pathlen
,
265 struct zip_local_header header
;
266 struct zip_dir_header dirent
;
267 struct zip_extra_mtime extra
;
269 unsigned long compressed_size
;
271 unsigned long direntsize
;
274 void *deflated
= NULL
;
276 struct git_istream
*stream
= NULL
;
277 unsigned long flags
= 0;
280 const char *path_without_prefix
= path
+ args
->baselen
;
281 unsigned int creator_version
= 0;
283 crc
= crc32(0, NULL
, 0);
285 if (!has_only_ascii(path
)) {
289 warning("Path is not valid UTF-8: %s", path
);
292 if (pathlen
> 0xffff) {
293 return error("path too long (%d chars, SHA1: %s): %s",
294 (int)pathlen
, sha1_to_hex(sha1
), path
);
297 if (S_ISDIR(mode
) || S_ISGITLINK(mode
)) {
304 } else if (S_ISREG(mode
) || S_ISLNK(mode
)) {
305 enum object_type type
= sha1_object_info(sha1
, &size
);
308 attr2
= S_ISLNK(mode
) ? ((mode
| 0777) << 16) :
309 (mode
& 0111) ? ((mode
) << 16) : 0;
310 if (S_ISLNK(mode
) || (mode
& 0111))
311 creator_version
= 0x0317;
312 if (S_ISREG(mode
) && args
->compression_level
!= 0 && size
> 0)
315 if (S_ISREG(mode
) && type
== OBJ_BLOB
&& !args
->convert
&&
316 size
> big_file_threshold
) {
317 stream
= open_istream(sha1
, &type
, &size
, NULL
);
319 return error("cannot stream blob %s",
324 buffer
= sha1_file_to_archive(args
, path
, sha1
, mode
,
327 return error("cannot read %s",
329 crc
= crc32(crc
, buffer
, size
);
330 is_binary
= entry_is_binary(path_without_prefix
,
334 compressed_size
= (method
== 0) ? size
: 0;
336 return error("unsupported file mode: 0%o (SHA1: %s)", mode
,
340 if (creator_version
> max_creator_version
)
341 max_creator_version
= creator_version
;
343 if (buffer
&& method
== 8) {
344 out
= deflated
= zlib_deflate_raw(buffer
, size
,
345 args
->compression_level
,
347 if (!out
|| compressed_size
>= size
) {
350 compressed_size
= size
;
354 copy_le16(extra
.magic
, 0x5455);
355 copy_le16(extra
.extra_size
, ZIP_EXTRA_MTIME_PAYLOAD_SIZE
);
356 extra
.flags
[0] = 1; /* just mtime */
357 copy_le32(extra
.mtime
, args
->time
);
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
);
366 copy_le32(dirent
.magic
, 0x02014b50);
367 copy_le16(dirent
.creator_version
, creator_version
);
368 copy_le16(dirent
.version
, 10);
369 copy_le16(dirent
.flags
, flags
);
370 copy_le16(dirent
.compression_method
, method
);
371 copy_le16(dirent
.mtime
, zip_time
);
372 copy_le16(dirent
.mdate
, zip_date
);
373 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
374 copy_le16(dirent
.filename_length
, pathlen
);
375 copy_le16(dirent
.extra_length
, ZIP_EXTRA_MTIME_SIZE
);
376 copy_le16(dirent
.comment_length
, 0);
377 copy_le16(dirent
.disk
, 0);
378 copy_le32(dirent
.attr2
, attr2
);
379 copy_le32(dirent
.offset
, zip_offset
);
381 copy_le32(header
.magic
, 0x04034b50);
382 copy_le16(header
.version
, 10);
383 copy_le16(header
.flags
, flags
);
384 copy_le16(header
.compression_method
, method
);
385 copy_le16(header
.mtime
, zip_time
);
386 copy_le16(header
.mdate
, zip_date
);
387 set_zip_header_data_desc(&header
, size
, compressed_size
, crc
);
388 copy_le16(header
.filename_length
, pathlen
);
389 copy_le16(header
.extra_length
, ZIP_EXTRA_MTIME_SIZE
);
390 write_or_die(1, &header
, ZIP_LOCAL_HEADER_SIZE
);
391 zip_offset
+= ZIP_LOCAL_HEADER_SIZE
;
392 write_or_die(1, path
, pathlen
);
393 zip_offset
+= pathlen
;
394 write_or_die(1, &extra
, ZIP_EXTRA_MTIME_SIZE
);
395 zip_offset
+= ZIP_EXTRA_MTIME_SIZE
;
396 if (stream
&& method
== 0) {
397 unsigned char buf
[STREAM_BUFFER_SIZE
];
401 readlen
= read_istream(stream
, buf
, sizeof(buf
));
404 crc
= crc32(crc
, buf
, readlen
);
406 is_binary
= entry_is_binary(path_without_prefix
,
408 write_or_die(1, buf
, readlen
);
410 close_istream(stream
);
414 compressed_size
= size
;
415 zip_offset
+= compressed_size
;
417 write_zip_data_desc(size
, compressed_size
, crc
);
418 zip_offset
+= ZIP_DATA_DESC_SIZE
;
420 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
421 } else if (stream
&& method
== 8) {
422 unsigned char buf
[STREAM_BUFFER_SIZE
];
427 unsigned char compressed
[STREAM_BUFFER_SIZE
* 2];
429 git_deflate_init_raw(&zstream
, args
->compression_level
);
432 zstream
.next_out
= compressed
;
433 zstream
.avail_out
= sizeof(compressed
);
436 readlen
= read_istream(stream
, buf
, sizeof(buf
));
439 crc
= crc32(crc
, buf
, readlen
);
441 is_binary
= entry_is_binary(path_without_prefix
,
444 zstream
.next_in
= buf
;
445 zstream
.avail_in
= readlen
;
446 result
= git_deflate(&zstream
, 0);
448 die("deflate error (%d)", result
);
449 out_len
= zstream
.next_out
- compressed
;
452 write_or_die(1, compressed
, out_len
);
453 compressed_size
+= out_len
;
454 zstream
.next_out
= compressed
;
455 zstream
.avail_out
= sizeof(compressed
);
459 close_istream(stream
);
463 zstream
.next_in
= buf
;
464 zstream
.avail_in
= 0;
465 result
= git_deflate(&zstream
, Z_FINISH
);
466 if (result
!= Z_STREAM_END
)
467 die("deflate error (%d)", result
);
469 git_deflate_end(&zstream
);
470 out_len
= zstream
.next_out
- compressed
;
471 write_or_die(1, compressed
, out_len
);
472 compressed_size
+= out_len
;
473 zip_offset
+= compressed_size
;
475 write_zip_data_desc(size
, compressed_size
, crc
);
476 zip_offset
+= ZIP_DATA_DESC_SIZE
;
478 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
479 } else if (compressed_size
> 0) {
480 write_or_die(1, out
, compressed_size
);
481 zip_offset
+= compressed_size
;
487 copy_le16(dirent
.attr1
, !is_binary
);
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
;
500 static void write_zip64_trailer(void)
502 struct zip64_dir_trailer trailer64
;
503 struct zip64_dir_trailer_locator locator64
;
505 copy_le32(trailer64
.magic
, 0x06064b50);
506 copy_le64(trailer64
.record_size
, ZIP64_DIR_TRAILER_RECORD_SIZE
);
507 copy_le16(trailer64
.creator_version
, max_creator_version
);
508 copy_le16(trailer64
.version
, 45);
509 copy_le32(trailer64
.disk
, 0);
510 copy_le32(trailer64
.directory_start_disk
, 0);
511 copy_le64(trailer64
.entries_on_this_disk
, zip_dir_entries
);
512 copy_le64(trailer64
.entries
, zip_dir_entries
);
513 copy_le64(trailer64
.size
, zip_dir_offset
);
514 copy_le64(trailer64
.offset
, zip_offset
);
516 copy_le32(locator64
.magic
, 0x07064b50);
517 copy_le32(locator64
.disk
, 0);
518 copy_le64(locator64
.offset
, zip_offset
+ zip_dir_offset
);
519 copy_le32(locator64
.number_of_disks
, 1);
521 write_or_die(1, &trailer64
, ZIP64_DIR_TRAILER_SIZE
);
522 write_or_die(1, &locator64
, ZIP64_DIR_TRAILER_LOCATOR_SIZE
);
525 static void write_zip_trailer(const unsigned char *sha1
)
527 struct zip_dir_trailer trailer
;
530 copy_le32(trailer
.magic
, 0x06054b50);
531 copy_le16(trailer
.disk
, 0);
532 copy_le16(trailer
.directory_start_disk
, 0);
533 copy_le16_clamp(trailer
.entries_on_this_disk
, zip_dir_entries
,
535 copy_le16_clamp(trailer
.entries
, zip_dir_entries
, &clamped
);
536 copy_le32(trailer
.size
, zip_dir_offset
);
537 copy_le32(trailer
.offset
, zip_offset
);
538 copy_le16(trailer
.comment_length
, sha1
? GIT_SHA1_HEXSZ
: 0);
540 write_or_die(1, zip_dir
, zip_dir_offset
);
542 write_zip64_trailer();
543 write_or_die(1, &trailer
, ZIP_DIR_TRAILER_SIZE
);
545 write_or_die(1, sha1_to_hex(sha1
), GIT_SHA1_HEXSZ
);
548 static void dos_time(time_t *time
, int *dos_date
, int *dos_time
)
550 struct tm
*t
= localtime(time
);
552 *dos_date
= t
->tm_mday
+ (t
->tm_mon
+ 1) * 32 +
553 (t
->tm_year
+ 1900 - 1980) * 512;
554 *dos_time
= t
->tm_sec
/ 2 + t
->tm_min
* 32 + t
->tm_hour
* 2048;
557 static int archive_zip_config(const char *var
, const char *value
, void *data
)
559 return userdiff_config(var
, value
);
562 static int write_zip_archive(const struct archiver
*ar
,
563 struct archiver_args
*args
)
567 git_config(archive_zip_config
, NULL
);
569 dos_time(&args
->time
, &zip_date
, &zip_time
);
571 zip_dir
= xmalloc(ZIP_DIRECTORY_MIN_SIZE
);
572 zip_dir_size
= ZIP_DIRECTORY_MIN_SIZE
;
574 err
= write_archive_entries(args
, write_zip_entry
);
576 write_zip_trailer(args
->commit_sha1
);
583 static struct archiver zip_archiver
= {
586 ARCHIVER_WANT_COMPRESSION_LEVELS
|ARCHIVER_REMOTE
589 void init_zip_archiver(void)
591 register_archiver(&zip_archiver
);