2 * Copyright (c) 2006 Rene Scharfe
10 static unsigned char *zip_dir
;
11 static unsigned int zip_dir_size
;
13 static unsigned int zip_offset
;
14 static unsigned int zip_dir_offset
;
15 static unsigned int zip_dir_entries
;
17 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
19 struct zip_local_header
{
20 unsigned char magic
[4];
21 unsigned char version
[2];
22 unsigned char flags
[2];
23 unsigned char compression_method
[2];
24 unsigned char mtime
[2];
25 unsigned char mdate
[2];
26 unsigned char crc32
[4];
27 unsigned char compressed_size
[4];
28 unsigned char size
[4];
29 unsigned char filename_length
[2];
30 unsigned char extra_length
[2];
31 unsigned char _end
[1];
34 struct zip_dir_header
{
35 unsigned char magic
[4];
36 unsigned char creator_version
[2];
37 unsigned char version
[2];
38 unsigned char flags
[2];
39 unsigned char compression_method
[2];
40 unsigned char mtime
[2];
41 unsigned char mdate
[2];
42 unsigned char crc32
[4];
43 unsigned char compressed_size
[4];
44 unsigned char size
[4];
45 unsigned char filename_length
[2];
46 unsigned char extra_length
[2];
47 unsigned char comment_length
[2];
48 unsigned char disk
[2];
49 unsigned char attr1
[2];
50 unsigned char attr2
[4];
51 unsigned char offset
[4];
52 unsigned char _end
[1];
55 struct zip_dir_trailer
{
56 unsigned char magic
[4];
57 unsigned char disk
[2];
58 unsigned char directory_start_disk
[2];
59 unsigned char entries_on_this_disk
[2];
60 unsigned char entries
[2];
61 unsigned char size
[4];
62 unsigned char offset
[4];
63 unsigned char comment_length
[2];
64 unsigned char _end
[1];
68 * On ARM, padding is added at the end of the struct, so a simple
69 * sizeof(struct ...) reports two bytes more than the payload size
70 * we're interested in.
72 #define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
73 #define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
74 #define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
76 static void copy_le16(unsigned char *dest
, unsigned int n
)
79 dest
[1] = 0xff & (n
>> 010);
82 static void copy_le32(unsigned char *dest
, unsigned int n
)
85 dest
[1] = 0xff & (n
>> 010);
86 dest
[2] = 0xff & (n
>> 020);
87 dest
[3] = 0xff & (n
>> 030);
90 static void *zlib_deflate(void *data
, unsigned long size
,
91 int compression_level
, unsigned long *compressed_size
)
94 unsigned long maxsize
;
98 memset(&stream
, 0, sizeof(stream
));
99 git_deflate_init(&stream
, compression_level
);
100 maxsize
= git_deflate_bound(&stream
, size
);
101 buffer
= xmalloc(maxsize
);
103 stream
.next_in
= data
;
104 stream
.avail_in
= size
;
105 stream
.next_out
= buffer
;
106 stream
.avail_out
= maxsize
;
109 result
= git_deflate(&stream
, Z_FINISH
);
110 } while (result
== Z_OK
);
112 if (result
!= Z_STREAM_END
) {
117 git_deflate_end(&stream
);
118 *compressed_size
= stream
.total_out
;
123 static int write_zip_entry(struct archiver_args
*args
,
124 const unsigned char *sha1
,
125 const char *path
, size_t pathlen
,
128 struct zip_local_header header
;
129 struct zip_dir_header dirent
;
131 unsigned long compressed_size
;
132 unsigned long uncompressed_size
;
134 unsigned long direntsize
;
137 void *deflated
= NULL
;
141 crc
= crc32(0, NULL
, 0);
143 if (pathlen
> 0xffff) {
144 return error("path too long (%d chars, SHA1: %s): %s",
145 (int)pathlen
, sha1_to_hex(sha1
), path
);
148 if (S_ISDIR(mode
) || S_ISGITLINK(mode
)) {
152 uncompressed_size
= 0;
156 } else if (S_ISREG(mode
) || S_ISLNK(mode
)) {
157 enum object_type type
;
158 buffer
= sha1_file_to_archive(args
, path
, sha1
, mode
, &type
, &size
);
160 return error("cannot read %s", sha1_to_hex(sha1
));
163 attr2
= S_ISLNK(mode
) ? ((mode
| 0777) << 16) :
164 (mode
& 0111) ? ((mode
) << 16) : 0;
165 if (S_ISREG(mode
) && args
->compression_level
!= 0)
167 crc
= crc32(crc
, buffer
, size
);
169 uncompressed_size
= size
;
170 compressed_size
= size
;
172 return error("unsupported file mode: 0%o (SHA1: %s)", mode
,
177 deflated
= zlib_deflate(buffer
, size
, args
->compression_level
,
179 if (deflated
&& compressed_size
- 6 < size
) {
180 /* ZLIB --> raw compressed data (see RFC 1950) */
181 /* CMF and FLG ... */
182 out
= (unsigned char *)deflated
+ 2;
183 compressed_size
-= 6; /* ... and ADLER32 */
186 compressed_size
= size
;
190 /* make sure we have enough free space in the dictionary */
191 direntsize
= ZIP_DIR_HEADER_SIZE
+ pathlen
;
192 while (zip_dir_size
< zip_dir_offset
+ direntsize
) {
193 zip_dir_size
+= ZIP_DIRECTORY_MIN_SIZE
;
194 zip_dir
= xrealloc(zip_dir
, zip_dir_size
);
197 copy_le32(dirent
.magic
, 0x02014b50);
198 copy_le16(dirent
.creator_version
,
199 S_ISLNK(mode
) || (S_ISREG(mode
) && (mode
& 0111)) ? 0x0317 : 0);
200 copy_le16(dirent
.version
, 10);
201 copy_le16(dirent
.flags
, 0);
202 copy_le16(dirent
.compression_method
, method
);
203 copy_le16(dirent
.mtime
, zip_time
);
204 copy_le16(dirent
.mdate
, zip_date
);
205 copy_le32(dirent
.crc32
, crc
);
206 copy_le32(dirent
.compressed_size
, compressed_size
);
207 copy_le32(dirent
.size
, uncompressed_size
);
208 copy_le16(dirent
.filename_length
, pathlen
);
209 copy_le16(dirent
.extra_length
, 0);
210 copy_le16(dirent
.comment_length
, 0);
211 copy_le16(dirent
.disk
, 0);
212 copy_le16(dirent
.attr1
, 0);
213 copy_le32(dirent
.attr2
, attr2
);
214 copy_le32(dirent
.offset
, zip_offset
);
215 memcpy(zip_dir
+ zip_dir_offset
, &dirent
, ZIP_DIR_HEADER_SIZE
);
216 zip_dir_offset
+= ZIP_DIR_HEADER_SIZE
;
217 memcpy(zip_dir
+ zip_dir_offset
, path
, pathlen
);
218 zip_dir_offset
+= pathlen
;
221 copy_le32(header
.magic
, 0x04034b50);
222 copy_le16(header
.version
, 10);
223 copy_le16(header
.flags
, 0);
224 copy_le16(header
.compression_method
, method
);
225 copy_le16(header
.mtime
, zip_time
);
226 copy_le16(header
.mdate
, zip_date
);
227 copy_le32(header
.crc32
, crc
);
228 copy_le32(header
.compressed_size
, compressed_size
);
229 copy_le32(header
.size
, uncompressed_size
);
230 copy_le16(header
.filename_length
, pathlen
);
231 copy_le16(header
.extra_length
, 0);
232 write_or_die(1, &header
, ZIP_LOCAL_HEADER_SIZE
);
233 zip_offset
+= ZIP_LOCAL_HEADER_SIZE
;
234 write_or_die(1, path
, pathlen
);
235 zip_offset
+= pathlen
;
236 if (compressed_size
> 0) {
237 write_or_die(1, out
, compressed_size
);
238 zip_offset
+= compressed_size
;
247 static void write_zip_trailer(const unsigned char *sha1
)
249 struct zip_dir_trailer trailer
;
251 copy_le32(trailer
.magic
, 0x06054b50);
252 copy_le16(trailer
.disk
, 0);
253 copy_le16(trailer
.directory_start_disk
, 0);
254 copy_le16(trailer
.entries_on_this_disk
, zip_dir_entries
);
255 copy_le16(trailer
.entries
, zip_dir_entries
);
256 copy_le32(trailer
.size
, zip_dir_offset
);
257 copy_le32(trailer
.offset
, zip_offset
);
258 copy_le16(trailer
.comment_length
, sha1
? 40 : 0);
260 write_or_die(1, zip_dir
, zip_dir_offset
);
261 write_or_die(1, &trailer
, ZIP_DIR_TRAILER_SIZE
);
263 write_or_die(1, sha1_to_hex(sha1
), 40);
266 static void dos_time(time_t *time
, int *dos_date
, int *dos_time
)
268 struct tm
*t
= localtime(time
);
270 *dos_date
= t
->tm_mday
+ (t
->tm_mon
+ 1) * 32 +
271 (t
->tm_year
+ 1900 - 1980) * 512;
272 *dos_time
= t
->tm_sec
/ 2 + t
->tm_min
* 32 + t
->tm_hour
* 2048;
275 static int write_zip_archive(const struct archiver
*ar
,
276 struct archiver_args
*args
)
280 dos_time(&args
->time
, &zip_date
, &zip_time
);
282 zip_dir
= xmalloc(ZIP_DIRECTORY_MIN_SIZE
);
283 zip_dir_size
= ZIP_DIRECTORY_MIN_SIZE
;
285 err
= write_archive_entries(args
, write_zip_entry
);
287 write_zip_trailer(args
->commit_sha1
);
294 static struct archiver zip_archiver
= {
297 ARCHIVER_WANT_COMPRESSION_LEVELS
|ARCHIVER_REMOTE
300 void init_zip_archiver(void)
302 register_archiver(&zip_archiver
);