2 * Copyright (c) 2006 Rene Scharfe
11 static unsigned char *zip_dir
;
12 static unsigned int zip_dir_size
;
14 static unsigned int zip_offset
;
15 static unsigned int zip_dir_offset
;
16 static unsigned int zip_dir_entries
;
18 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
19 #define ZIP_STREAM (8)
21 struct zip_local_header
{
22 unsigned char magic
[4];
23 unsigned char version
[2];
24 unsigned char flags
[2];
25 unsigned char compression_method
[2];
26 unsigned char mtime
[2];
27 unsigned char mdate
[2];
28 unsigned char crc32
[4];
29 unsigned char compressed_size
[4];
30 unsigned char size
[4];
31 unsigned char filename_length
[2];
32 unsigned char extra_length
[2];
33 unsigned char _end
[1];
36 struct zip_data_desc
{
37 unsigned char magic
[4];
38 unsigned char crc32
[4];
39 unsigned char compressed_size
[4];
40 unsigned char size
[4];
41 unsigned char _end
[1];
44 struct zip_dir_header
{
45 unsigned char magic
[4];
46 unsigned char creator_version
[2];
47 unsigned char version
[2];
48 unsigned char flags
[2];
49 unsigned char compression_method
[2];
50 unsigned char mtime
[2];
51 unsigned char mdate
[2];
52 unsigned char crc32
[4];
53 unsigned char compressed_size
[4];
54 unsigned char size
[4];
55 unsigned char filename_length
[2];
56 unsigned char extra_length
[2];
57 unsigned char comment_length
[2];
58 unsigned char disk
[2];
59 unsigned char attr1
[2];
60 unsigned char attr2
[4];
61 unsigned char offset
[4];
62 unsigned char _end
[1];
65 struct zip_dir_trailer
{
66 unsigned char magic
[4];
67 unsigned char disk
[2];
68 unsigned char directory_start_disk
[2];
69 unsigned char entries_on_this_disk
[2];
70 unsigned char entries
[2];
71 unsigned char size
[4];
72 unsigned char offset
[4];
73 unsigned char comment_length
[2];
74 unsigned char _end
[1];
78 * On ARM, padding is added at the end of the struct, so a simple
79 * sizeof(struct ...) reports two bytes more than the payload size
80 * we're interested in.
82 #define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
83 #define ZIP_DATA_DESC_SIZE offsetof(struct zip_data_desc, _end)
84 #define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
85 #define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
87 static void copy_le16(unsigned char *dest
, unsigned int n
)
90 dest
[1] = 0xff & (n
>> 010);
93 static void copy_le32(unsigned char *dest
, unsigned int n
)
96 dest
[1] = 0xff & (n
>> 010);
97 dest
[2] = 0xff & (n
>> 020);
98 dest
[3] = 0xff & (n
>> 030);
101 static void *zlib_deflate(void *data
, unsigned long size
,
102 int compression_level
, unsigned long *compressed_size
)
105 unsigned long maxsize
;
109 memset(&stream
, 0, sizeof(stream
));
110 git_deflate_init(&stream
, compression_level
);
111 maxsize
= git_deflate_bound(&stream
, size
);
112 buffer
= xmalloc(maxsize
);
114 stream
.next_in
= data
;
115 stream
.avail_in
= size
;
116 stream
.next_out
= buffer
;
117 stream
.avail_out
= maxsize
;
120 result
= git_deflate(&stream
, Z_FINISH
);
121 } while (result
== Z_OK
);
123 if (result
!= Z_STREAM_END
) {
128 git_deflate_end(&stream
);
129 *compressed_size
= stream
.total_out
;
134 static void write_zip_data_desc(unsigned long size
,
135 unsigned long compressed_size
,
138 struct zip_data_desc trailer
;
140 copy_le32(trailer
.magic
, 0x08074b50);
141 copy_le32(trailer
.crc32
, crc
);
142 copy_le32(trailer
.compressed_size
, compressed_size
);
143 copy_le32(trailer
.size
, size
);
144 write_or_die(1, &trailer
, ZIP_DATA_DESC_SIZE
);
147 static void set_zip_dir_data_desc(struct zip_dir_header
*header
,
149 unsigned long compressed_size
,
152 copy_le32(header
->crc32
, crc
);
153 copy_le32(header
->compressed_size
, compressed_size
);
154 copy_le32(header
->size
, size
);
157 static void set_zip_header_data_desc(struct zip_local_header
*header
,
159 unsigned long compressed_size
,
162 copy_le32(header
->crc32
, crc
);
163 copy_le32(header
->compressed_size
, compressed_size
);
164 copy_le32(header
->size
, size
);
167 #define STREAM_BUFFER_SIZE (1024 * 16)
169 static int write_zip_entry(struct archiver_args
*args
,
170 const unsigned char *sha1
,
171 const char *path
, size_t pathlen
,
174 struct zip_local_header header
;
175 struct zip_dir_header dirent
;
177 unsigned long compressed_size
;
179 unsigned long direntsize
;
182 void *deflated
= NULL
;
184 struct git_istream
*stream
= NULL
;
185 unsigned long flags
= 0;
188 crc
= crc32(0, NULL
, 0);
190 if (pathlen
> 0xffff) {
191 return error("path too long (%d chars, SHA1: %s): %s",
192 (int)pathlen
, sha1_to_hex(sha1
), path
);
195 if (S_ISDIR(mode
) || S_ISGITLINK(mode
)) {
203 } else if (S_ISREG(mode
) || S_ISLNK(mode
)) {
204 enum object_type type
= sha1_object_info(sha1
, &size
);
207 attr2
= S_ISLNK(mode
) ? ((mode
| 0777) << 16) :
208 (mode
& 0111) ? ((mode
) << 16) : 0;
209 if (S_ISREG(mode
) && args
->compression_level
!= 0 && size
> 0)
211 compressed_size
= size
;
213 if (S_ISREG(mode
) && type
== OBJ_BLOB
&& !args
->convert
&&
214 size
> big_file_threshold
) {
215 stream
= open_istream(sha1
, &type
, &size
, NULL
);
217 return error("cannot stream blob %s",
222 buffer
= sha1_file_to_archive(args
, path
, sha1
, mode
,
225 return error("cannot read %s",
227 crc
= crc32(crc
, buffer
, size
);
231 return error("unsupported file mode: 0%o (SHA1: %s)", mode
,
235 if (buffer
&& method
== 8) {
236 deflated
= zlib_deflate(buffer
, size
, args
->compression_level
,
238 if (deflated
&& compressed_size
- 6 < size
) {
239 /* ZLIB --> raw compressed data (see RFC 1950) */
240 /* CMF and FLG ... */
241 out
= (unsigned char *)deflated
+ 2;
242 compressed_size
-= 6; /* ... and ADLER32 */
245 compressed_size
= size
;
249 /* make sure we have enough free space in the dictionary */
250 direntsize
= ZIP_DIR_HEADER_SIZE
+ pathlen
;
251 while (zip_dir_size
< zip_dir_offset
+ direntsize
) {
252 zip_dir_size
+= ZIP_DIRECTORY_MIN_SIZE
;
253 zip_dir
= xrealloc(zip_dir
, zip_dir_size
);
256 copy_le32(dirent
.magic
, 0x02014b50);
257 copy_le16(dirent
.creator_version
,
258 S_ISLNK(mode
) || (S_ISREG(mode
) && (mode
& 0111)) ? 0x0317 : 0);
259 copy_le16(dirent
.version
, 10);
260 copy_le16(dirent
.flags
, flags
);
261 copy_le16(dirent
.compression_method
, method
);
262 copy_le16(dirent
.mtime
, zip_time
);
263 copy_le16(dirent
.mdate
, zip_date
);
264 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
265 copy_le16(dirent
.filename_length
, pathlen
);
266 copy_le16(dirent
.extra_length
, 0);
267 copy_le16(dirent
.comment_length
, 0);
268 copy_le16(dirent
.disk
, 0);
269 copy_le16(dirent
.attr1
, 0);
270 copy_le32(dirent
.attr2
, attr2
);
271 copy_le32(dirent
.offset
, zip_offset
);
273 copy_le32(header
.magic
, 0x04034b50);
274 copy_le16(header
.version
, 10);
275 copy_le16(header
.flags
, flags
);
276 copy_le16(header
.compression_method
, method
);
277 copy_le16(header
.mtime
, zip_time
);
278 copy_le16(header
.mdate
, zip_date
);
279 if (flags
& ZIP_STREAM
)
280 set_zip_header_data_desc(&header
, 0, 0, 0);
282 set_zip_header_data_desc(&header
, size
, compressed_size
, crc
);
283 copy_le16(header
.filename_length
, pathlen
);
284 copy_le16(header
.extra_length
, 0);
285 write_or_die(1, &header
, ZIP_LOCAL_HEADER_SIZE
);
286 zip_offset
+= ZIP_LOCAL_HEADER_SIZE
;
287 write_or_die(1, path
, pathlen
);
288 zip_offset
+= pathlen
;
289 if (stream
&& method
== 0) {
290 unsigned char buf
[STREAM_BUFFER_SIZE
];
294 readlen
= read_istream(stream
, buf
, sizeof(buf
));
297 crc
= crc32(crc
, buf
, readlen
);
298 write_or_die(1, buf
, readlen
);
300 close_istream(stream
);
304 compressed_size
= size
;
305 zip_offset
+= compressed_size
;
307 write_zip_data_desc(size
, compressed_size
, crc
);
308 zip_offset
+= ZIP_DATA_DESC_SIZE
;
310 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
311 } else if (stream
&& method
== 8) {
312 unsigned char buf
[STREAM_BUFFER_SIZE
];
317 unsigned char compressed
[STREAM_BUFFER_SIZE
* 2];
319 memset(&zstream
, 0, sizeof(zstream
));
320 git_deflate_init(&zstream
, args
->compression_level
);
323 zstream
.next_out
= compressed
;
324 zstream
.avail_out
= sizeof(compressed
);
327 readlen
= read_istream(stream
, buf
, sizeof(buf
));
330 crc
= crc32(crc
, buf
, readlen
);
332 zstream
.next_in
= buf
;
333 zstream
.avail_in
= readlen
;
334 result
= git_deflate(&zstream
, 0);
336 die("deflate error (%d)", result
);
338 if (!compressed_size
)
340 out_len
= zstream
.next_out
- out
;
343 write_or_die(1, out
, out_len
);
344 compressed_size
+= out_len
;
345 zstream
.next_out
= compressed
;
346 zstream
.avail_out
= sizeof(compressed
);
350 close_istream(stream
);
354 zstream
.next_in
= buf
;
355 zstream
.avail_in
= 0;
356 result
= git_deflate(&zstream
, Z_FINISH
);
357 if (result
!= Z_STREAM_END
)
358 die("deflate error (%d)", result
);
360 git_deflate_end(&zstream
);
362 if (!compressed_size
)
364 out_len
= zstream
.next_out
- out
- 4;
365 write_or_die(1, out
, out_len
);
366 compressed_size
+= out_len
;
367 zip_offset
+= compressed_size
;
369 write_zip_data_desc(size
, compressed_size
, crc
);
370 zip_offset
+= ZIP_DATA_DESC_SIZE
;
372 set_zip_dir_data_desc(&dirent
, size
, compressed_size
, crc
);
373 } else if (compressed_size
> 0) {
374 write_or_die(1, out
, compressed_size
);
375 zip_offset
+= compressed_size
;
381 memcpy(zip_dir
+ zip_dir_offset
, &dirent
, ZIP_DIR_HEADER_SIZE
);
382 zip_dir_offset
+= ZIP_DIR_HEADER_SIZE
;
383 memcpy(zip_dir
+ zip_dir_offset
, path
, pathlen
);
384 zip_dir_offset
+= pathlen
;
390 static void write_zip_trailer(const unsigned char *sha1
)
392 struct zip_dir_trailer trailer
;
394 copy_le32(trailer
.magic
, 0x06054b50);
395 copy_le16(trailer
.disk
, 0);
396 copy_le16(trailer
.directory_start_disk
, 0);
397 copy_le16(trailer
.entries_on_this_disk
, zip_dir_entries
);
398 copy_le16(trailer
.entries
, zip_dir_entries
);
399 copy_le32(trailer
.size
, zip_dir_offset
);
400 copy_le32(trailer
.offset
, zip_offset
);
401 copy_le16(trailer
.comment_length
, sha1
? 40 : 0);
403 write_or_die(1, zip_dir
, zip_dir_offset
);
404 write_or_die(1, &trailer
, ZIP_DIR_TRAILER_SIZE
);
406 write_or_die(1, sha1_to_hex(sha1
), 40);
409 static void dos_time(time_t *time
, int *dos_date
, int *dos_time
)
411 struct tm
*t
= localtime(time
);
413 *dos_date
= t
->tm_mday
+ (t
->tm_mon
+ 1) * 32 +
414 (t
->tm_year
+ 1900 - 1980) * 512;
415 *dos_time
= t
->tm_sec
/ 2 + t
->tm_min
* 32 + t
->tm_hour
* 2048;
418 static int write_zip_archive(const struct archiver
*ar
,
419 struct archiver_args
*args
)
423 dos_time(&args
->time
, &zip_date
, &zip_time
);
425 zip_dir
= xmalloc(ZIP_DIRECTORY_MIN_SIZE
);
426 zip_dir_size
= ZIP_DIRECTORY_MIN_SIZE
;
428 err
= write_archive_entries(args
, write_zip_entry
);
430 write_zip_trailer(args
->commit_sha1
);
437 static struct archiver zip_archiver
= {
440 ARCHIVER_WANT_COMPRESSION_LEVELS
|ARCHIVER_REMOTE
443 void init_zip_archiver(void)
445 register_archiver(&zip_archiver
);