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 unsigned int zip_dir_entries
;
21 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
22 #define ZIP_STREAM (1 << 3)
23 #define ZIP_UTF8 (1 << 11)
25 struct zip_local_header
{
26 unsigned char magic
[4];
27 unsigned char version
[2];
28 unsigned char flags
[2];
29 unsigned char compression_method
[2];
30 unsigned char mtime
[2];
31 unsigned char mdate
[2];
32 unsigned char crc32
[4];
33 unsigned char compressed_size
[4];
34 unsigned char size
[4];
35 unsigned char filename_length
[2];
36 unsigned char extra_length
[2];
37 unsigned char _end
[1];
40 struct zip_data_desc
{
41 unsigned char magic
[4];
42 unsigned char crc32
[4];
43 unsigned char compressed_size
[4];
44 unsigned char size
[4];
45 unsigned char _end
[1];
48 struct zip_dir_header
{
49 unsigned char magic
[4];
50 unsigned char creator_version
[2];
51 unsigned char version
[2];
52 unsigned char flags
[2];
53 unsigned char compression_method
[2];
54 unsigned char mtime
[2];
55 unsigned char mdate
[2];
56 unsigned char crc32
[4];
57 unsigned char compressed_size
[4];
58 unsigned char size
[4];
59 unsigned char filename_length
[2];
60 unsigned char extra_length
[2];
61 unsigned char comment_length
[2];
62 unsigned char disk
[2];
63 unsigned char attr1
[2];
64 unsigned char attr2
[4];
65 unsigned char offset
[4];
66 unsigned char _end
[1];
69 struct zip_dir_trailer
{
70 unsigned char magic
[4];
71 unsigned char disk
[2];
72 unsigned char directory_start_disk
[2];
73 unsigned char entries_on_this_disk
[2];
74 unsigned char entries
[2];
75 unsigned char size
[4];
76 unsigned char offset
[4];
77 unsigned char comment_length
[2];
78 unsigned char _end
[1];
81 struct zip_extra_mtime
{
82 unsigned char magic
[2];
83 unsigned char extra_size
[2];
84 unsigned char flags
[1];
85 unsigned char mtime
[4];
86 unsigned char _end
[1];
90 * On ARM, padding is added at the end of the struct, so a simple
91 * sizeof(struct ...) reports two bytes more than the payload size
92 * we're interested in.
94 #define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
95 #define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
96 #define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
97 #define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
98 #define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end)
99 #define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
100 (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
102 static void copy_le16(unsigned char *dest
, unsigned int n
)
105 dest
[1] = 0xff & (n
>> 010);
108 static void copy_le32(unsigned char *dest
, unsigned int n
)
111 dest
[1] = 0xff & (n
>> 010);
112 dest
[2] = 0xff & (n
>> 020);
113 dest
[3] = 0xff & (n
>> 030);
116 static void *zlib_deflate_raw(void *data
, unsigned long size
,
117 int compression_level
,
118 unsigned long *compressed_size
)
121 unsigned long maxsize
;
125 git_deflate_init_raw(&stream
, compression_level
);
126 maxsize
= git_deflate_bound(&stream
, size
);
127 buffer
= xmalloc(maxsize
);
129 stream
.next_in
= data
;
130 stream
.avail_in
= size
;
131 stream
.next_out
= buffer
;
132 stream
.avail_out
= maxsize
;
135 result
= git_deflate(&stream
, Z_FINISH
);
136 } while (result
== Z_OK
);
138 if (result
!= Z_STREAM_END
) {
143 git_deflate_end(&stream
);
144 *compressed_size
= stream
.total_out
;
149 static void write_zip_data_desc(unsigned long size
,
150 unsigned long compressed_size
,
153 struct zip_data_desc trailer
;
155 copy_le32(trailer
.magic
, 0x08074b50);
156 copy_le32(trailer
.crc32
, crc
);
157 copy_le32(trailer
.compressed_size
, compressed_size
);
158 copy_le32(trailer
.size
, size
);
159 write_or_die(1, &trailer
, ZIP_DATA_DESC_SIZE
);
162 static void set_zip_dir_data_desc(struct zip_dir_header
*header
,
164 unsigned long compressed_size
,
167 copy_le32(header
->crc32
, crc
);
168 copy_le32(header
->compressed_size
, compressed_size
);
169 copy_le32(header
->size
, size
);
172 static void set_zip_header_data_desc(struct zip_local_header
*header
,
174 unsigned long compressed_size
,
177 copy_le32(header
->crc32
, crc
);
178 copy_le32(header
->compressed_size
, compressed_size
);
179 copy_le32(header
->size
, size
);
182 static int has_only_ascii(const char *s
)
193 static int entry_is_binary(const char *path
, const void *buffer
, size_t size
)
195 struct userdiff_driver
*driver
= userdiff_find_by_path(path
);
197 driver
= userdiff_find_by_name("default");
198 if (driver
->binary
!= -1)
199 return driver
->binary
;
200 return buffer_is_binary(buffer
, size
);
203 #define STREAM_BUFFER_SIZE (1024 * 16)
205 static int write_zip_entry(struct archiver_args
*args
,
206 const unsigned char *sha1
,
207 const char *path
, size_t pathlen
,
210 struct zip_local_header header
;
211 struct zip_dir_header dirent
;
212 struct zip_extra_mtime extra
;
214 unsigned long compressed_size
;
216 unsigned long direntsize
;
219 void *deflated
= NULL
;
221 struct git_istream
*stream
= NULL
;
222 unsigned long flags
= 0;
225 const char *path_without_prefix
= path
+ args
->baselen
;
227 crc
= crc32(0, NULL
, 0);
229 if (!has_only_ascii(path
)) {
233 warning("Path is not valid UTF-8: %s", path
);
236 if (pathlen
> 0xffff) {
237 return error("path too long (%d chars, SHA1: %s): %s",
238 (int)pathlen
, sha1_to_hex(sha1
), path
);
241 if (S_ISDIR(mode
) || S_ISGITLINK(mode
)) {
248 } else if (S_ISREG(mode
) || S_ISLNK(mode
)) {
249 enum object_type type
= sha1_object_info(sha1
, &size
);
252 attr2
= S_ISLNK(mode
) ? ((mode
| 0777) << 16) :
253 (mode
& 0111) ? ((mode
) << 16) : 0;
254 if (S_ISREG(mode
) && args
->compression_level
!= 0 && size
> 0)
257 if (S_ISREG(mode
) && type
== OBJ_BLOB
&& !args
->convert
&&
258 size
> big_file_threshold
) {
259 stream
= open_istream(sha1
, &type
, &size
, NULL
);
261 return error("cannot stream blob %s",
266 buffer
= sha1_file_to_archive(args
, path
, sha1
, mode
,
269 return error("cannot read %s",
271 crc
= crc32(crc
, buffer
, size
);
272 is_binary
= entry_is_binary(path_without_prefix
,
276 compressed_size
= (method
== 0) ? size
: 0;
278 return error("unsupported file mode: 0%o (SHA1: %s)", mode
,
282 if (buffer
&& method
== 8) {
283 out
= deflated
= zlib_deflate_raw(buffer
, size
,
284 args
->compression_level
,
286 if (!out
|| compressed_size
>= size
) {
289 compressed_size
= size
;
293 copy_le16(extra
.magic
, 0x5455);
294 copy_le16(extra
.extra_size
, ZIP_EXTRA_MTIME_PAYLOAD_SIZE
);
295 extra
.flags
[0] = 1; /* just mtime */
296 copy_le32(extra
.mtime
, args
->time
);
298 /* make sure we have enough free space in the dictionary */
299 direntsize
= ZIP_DIR_HEADER_SIZE
+ pathlen
+ ZIP_EXTRA_MTIME_SIZE
;
300 while (zip_dir_size
< zip_dir_offset
+ direntsize
) {
301 zip_dir_size
+= ZIP_DIRECTORY_MIN_SIZE
;
302 zip_dir
= xrealloc(zip_dir
, zip_dir_size
);
305 copy_le32(dirent
.magic
, 0x02014b50);
306 copy_le16(dirent
.creator_version
,
307 S_ISLNK(mode
) || (S_ISREG(mode
) && (mode
& 0111)) ? 0x0317 : 0);
308 copy_le16(dirent
.version
, 10);
309 copy_le16(dirent
.flags
, flags
);
310 copy_le16(dirent
.compression_method
, method
);
311 copy_le16(dirent
.mtime
, zip_time
);
312 copy_le16(dirent
.mdate
, zip_date
);
313 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
314 copy_le16(dirent
.filename_length
, pathlen
);
315 copy_le16(dirent
.extra_length
, ZIP_EXTRA_MTIME_SIZE
);
316 copy_le16(dirent
.comment_length
, 0);
317 copy_le16(dirent
.disk
, 0);
318 copy_le32(dirent
.attr2
, attr2
);
319 copy_le32(dirent
.offset
, zip_offset
);
321 copy_le32(header
.magic
, 0x04034b50);
322 copy_le16(header
.version
, 10);
323 copy_le16(header
.flags
, flags
);
324 copy_le16(header
.compression_method
, method
);
325 copy_le16(header
.mtime
, zip_time
);
326 copy_le16(header
.mdate
, zip_date
);
327 set_zip_header_data_desc(&header
, size
, compressed_size
, crc
);
328 copy_le16(header
.filename_length
, pathlen
);
329 copy_le16(header
.extra_length
, ZIP_EXTRA_MTIME_SIZE
);
330 write_or_die(1, &header
, ZIP_LOCAL_HEADER_SIZE
);
331 zip_offset
+= ZIP_LOCAL_HEADER_SIZE
;
332 write_or_die(1, path
, pathlen
);
333 zip_offset
+= pathlen
;
334 write_or_die(1, &extra
, ZIP_EXTRA_MTIME_SIZE
);
335 zip_offset
+= ZIP_EXTRA_MTIME_SIZE
;
336 if (stream
&& method
== 0) {
337 unsigned char buf
[STREAM_BUFFER_SIZE
];
341 readlen
= read_istream(stream
, buf
, sizeof(buf
));
344 crc
= crc32(crc
, buf
, readlen
);
346 is_binary
= entry_is_binary(path_without_prefix
,
348 write_or_die(1, buf
, readlen
);
350 close_istream(stream
);
354 compressed_size
= size
;
355 zip_offset
+= compressed_size
;
357 write_zip_data_desc(size
, compressed_size
, crc
);
358 zip_offset
+= ZIP_DATA_DESC_SIZE
;
360 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
361 } else if (stream
&& method
== 8) {
362 unsigned char buf
[STREAM_BUFFER_SIZE
];
367 unsigned char compressed
[STREAM_BUFFER_SIZE
* 2];
369 git_deflate_init_raw(&zstream
, args
->compression_level
);
372 zstream
.next_out
= compressed
;
373 zstream
.avail_out
= sizeof(compressed
);
376 readlen
= read_istream(stream
, buf
, sizeof(buf
));
379 crc
= crc32(crc
, buf
, readlen
);
381 is_binary
= entry_is_binary(path_without_prefix
,
384 zstream
.next_in
= buf
;
385 zstream
.avail_in
= readlen
;
386 result
= git_deflate(&zstream
, 0);
388 die("deflate error (%d)", result
);
389 out_len
= zstream
.next_out
- compressed
;
392 write_or_die(1, compressed
, out_len
);
393 compressed_size
+= out_len
;
394 zstream
.next_out
= compressed
;
395 zstream
.avail_out
= sizeof(compressed
);
399 close_istream(stream
);
403 zstream
.next_in
= buf
;
404 zstream
.avail_in
= 0;
405 result
= git_deflate(&zstream
, Z_FINISH
);
406 if (result
!= Z_STREAM_END
)
407 die("deflate error (%d)", result
);
409 git_deflate_end(&zstream
);
410 out_len
= zstream
.next_out
- compressed
;
411 write_or_die(1, compressed
, out_len
);
412 compressed_size
+= out_len
;
413 zip_offset
+= compressed_size
;
415 write_zip_data_desc(size
, compressed_size
, crc
);
416 zip_offset
+= ZIP_DATA_DESC_SIZE
;
418 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
419 } else if (compressed_size
> 0) {
420 write_or_die(1, out
, compressed_size
);
421 zip_offset
+= compressed_size
;
427 copy_le16(dirent
.attr1
, !is_binary
);
429 memcpy(zip_dir
+ zip_dir_offset
, &dirent
, ZIP_DIR_HEADER_SIZE
);
430 zip_dir_offset
+= ZIP_DIR_HEADER_SIZE
;
431 memcpy(zip_dir
+ zip_dir_offset
, path
, pathlen
);
432 zip_dir_offset
+= pathlen
;
433 memcpy(zip_dir
+ zip_dir_offset
, &extra
, ZIP_EXTRA_MTIME_SIZE
);
434 zip_dir_offset
+= ZIP_EXTRA_MTIME_SIZE
;
440 static void write_zip_trailer(const unsigned char *sha1
)
442 struct zip_dir_trailer trailer
;
444 copy_le32(trailer
.magic
, 0x06054b50);
445 copy_le16(trailer
.disk
, 0);
446 copy_le16(trailer
.directory_start_disk
, 0);
447 copy_le16(trailer
.entries_on_this_disk
, zip_dir_entries
);
448 copy_le16(trailer
.entries
, zip_dir_entries
);
449 copy_le32(trailer
.size
, zip_dir_offset
);
450 copy_le32(trailer
.offset
, zip_offset
);
451 copy_le16(trailer
.comment_length
, sha1
? 40 : 0);
453 write_or_die(1, zip_dir
, zip_dir_offset
);
454 write_or_die(1, &trailer
, ZIP_DIR_TRAILER_SIZE
);
456 write_or_die(1, sha1_to_hex(sha1
), 40);
459 static void dos_time(time_t *time
, int *dos_date
, int *dos_time
)
461 struct tm
*t
= localtime(time
);
463 *dos_date
= t
->tm_mday
+ (t
->tm_mon
+ 1) * 32 +
464 (t
->tm_year
+ 1900 - 1980) * 512;
465 *dos_time
= t
->tm_sec
/ 2 + t
->tm_min
* 32 + t
->tm_hour
* 2048;
468 static int write_zip_archive(const struct archiver
*ar
,
469 struct archiver_args
*args
)
473 dos_time(&args
->time
, &zip_date
, &zip_time
);
475 zip_dir
= xmalloc(ZIP_DIRECTORY_MIN_SIZE
);
476 zip_dir_size
= ZIP_DIRECTORY_MIN_SIZE
;
478 err
= write_archive_entries(args
, write_zip_entry
);
480 write_zip_trailer(args
->commit_sha1
);
487 static struct archiver zip_archiver
= {
490 ARCHIVER_WANT_COMPRESSION_LEVELS
|ARCHIVER_REMOTE
493 void init_zip_archiver(void)
495 register_archiver(&zip_archiver
);