2 * Copyright (c) 2006 Rene Scharfe
15 static const struct commit
*commit
;
16 static size_t base_len
;
18 static unsigned char *zip_dir
;
19 static unsigned int zip_dir_size
;
21 static unsigned int zip_offset
;
22 static unsigned int zip_dir_offset
;
23 static unsigned int zip_dir_entries
;
25 #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
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_dir_header
{
43 unsigned char magic
[4];
44 unsigned char creator_version
[2];
45 unsigned char version
[2];
46 unsigned char flags
[2];
47 unsigned char compression_method
[2];
48 unsigned char mtime
[2];
49 unsigned char mdate
[2];
50 unsigned char crc32
[4];
51 unsigned char compressed_size
[4];
52 unsigned char size
[4];
53 unsigned char filename_length
[2];
54 unsigned char extra_length
[2];
55 unsigned char comment_length
[2];
56 unsigned char disk
[2];
57 unsigned char attr1
[2];
58 unsigned char attr2
[4];
59 unsigned char offset
[4];
60 unsigned char _end
[1];
63 struct zip_dir_trailer
{
64 unsigned char magic
[4];
65 unsigned char disk
[2];
66 unsigned char directory_start_disk
[2];
67 unsigned char entries_on_this_disk
[2];
68 unsigned char entries
[2];
69 unsigned char size
[4];
70 unsigned char offset
[4];
71 unsigned char comment_length
[2];
72 unsigned char _end
[1];
76 * On ARM, padding is added at the end of the struct, so a simple
77 * sizeof(struct ...) reports two bytes more than the payload size
78 * we're interested in.
80 #define ZIP_LOCAL_HEADER_SIZE offsetof(struct zip_local_header, _end)
81 #define ZIP_DIR_HEADER_SIZE offsetof(struct zip_dir_header, _end)
82 #define ZIP_DIR_TRAILER_SIZE offsetof(struct zip_dir_trailer, _end)
84 static void copy_le16(unsigned char *dest
, unsigned int n
)
87 dest
[1] = 0xff & (n
>> 010);
90 static void copy_le32(unsigned char *dest
, unsigned int n
)
93 dest
[1] = 0xff & (n
>> 010);
94 dest
[2] = 0xff & (n
>> 020);
95 dest
[3] = 0xff & (n
>> 030);
98 static void *zlib_deflate(void *data
, unsigned long size
,
99 unsigned long *compressed_size
)
102 unsigned long maxsize
;
106 memset(&stream
, 0, sizeof(stream
));
107 deflateInit(&stream
, zlib_compression_level
);
108 maxsize
= deflateBound(&stream
, size
);
109 buffer
= xmalloc(maxsize
);
111 stream
.next_in
= data
;
112 stream
.avail_in
= size
;
113 stream
.next_out
= buffer
;
114 stream
.avail_out
= maxsize
;
117 result
= deflate(&stream
, Z_FINISH
);
118 } while (result
== Z_OK
);
120 if (result
!= Z_STREAM_END
) {
126 *compressed_size
= stream
.total_out
;
131 static char *construct_path(const char *base
, int baselen
,
132 const char *filename
, int isdir
, int *pathlen
)
134 int filenamelen
= strlen(filename
);
135 int len
= baselen
+ filenamelen
;
140 p
= path
= xmalloc(len
+ 1);
142 memcpy(p
, base
, baselen
);
144 memcpy(p
, filename
, filenamelen
);
155 static int write_zip_entry(const unsigned char *sha1
,
156 const char *base
, int baselen
,
157 const char *filename
, unsigned mode
, int stage
)
159 struct zip_local_header header
;
160 struct zip_dir_header dirent
;
162 unsigned long compressed_size
;
163 unsigned long uncompressed_size
;
165 unsigned long direntsize
;
172 enum object_type type
;
174 void *deflated
= NULL
;
176 crc
= crc32(0, NULL
, 0);
178 path
= construct_path(base
, baselen
, filename
, S_ISDIR(mode
), &pathlen
);
180 fprintf(stderr
, "%s\n", path
);
181 if (pathlen
> 0xffff) {
182 error("path too long (%d chars, SHA1: %s): %s", pathlen
,
183 sha1_to_hex(sha1
), path
);
187 if (S_ISDIR(mode
) || S_ISGITLINK(mode
)) {
190 result
= (S_ISDIR(mode
) ? READ_TREE_RECURSIVE
: 0);
192 uncompressed_size
= 0;
194 } else if (S_ISREG(mode
) || S_ISLNK(mode
)) {
196 attr2
= S_ISLNK(mode
) ? ((mode
| 0777) << 16) :
197 (mode
& 0111) ? ((mode
) << 16) : 0;
198 if (S_ISREG(mode
) && zlib_compression_level
!= 0)
201 buffer
= sha1_file_to_archive(path
+ base_len
, sha1
, mode
,
202 &type
, &size
, commit
);
204 die("cannot read %s", sha1_to_hex(sha1
));
205 crc
= crc32(crc
, buffer
, size
);
207 uncompressed_size
= size
;
208 compressed_size
= size
;
210 error("unsupported file mode: 0%o (SHA1: %s)", mode
,
216 deflated
= zlib_deflate(buffer
, size
, &compressed_size
);
217 if (deflated
&& compressed_size
- 6 < size
) {
218 /* ZLIB --> raw compressed data (see RFC 1950) */
219 /* CMF and FLG ... */
220 out
= (unsigned char *)deflated
+ 2;
221 compressed_size
-= 6; /* ... and ADLER32 */
224 compressed_size
= size
;
228 /* make sure we have enough free space in the dictionary */
229 direntsize
= ZIP_DIR_HEADER_SIZE
+ pathlen
;
230 while (zip_dir_size
< zip_dir_offset
+ direntsize
) {
231 zip_dir_size
+= ZIP_DIRECTORY_MIN_SIZE
;
232 zip_dir
= xrealloc(zip_dir
, zip_dir_size
);
235 copy_le32(dirent
.magic
, 0x02014b50);
236 copy_le16(dirent
.creator_version
,
237 S_ISLNK(mode
) || (S_ISREG(mode
) && (mode
& 0111)) ? 0x0317 : 0);
238 copy_le16(dirent
.version
, 10);
239 copy_le16(dirent
.flags
, 0);
240 copy_le16(dirent
.compression_method
, method
);
241 copy_le16(dirent
.mtime
, zip_time
);
242 copy_le16(dirent
.mdate
, zip_date
);
243 copy_le32(dirent
.crc32
, crc
);
244 copy_le32(dirent
.compressed_size
, compressed_size
);
245 copy_le32(dirent
.size
, uncompressed_size
);
246 copy_le16(dirent
.filename_length
, pathlen
);
247 copy_le16(dirent
.extra_length
, 0);
248 copy_le16(dirent
.comment_length
, 0);
249 copy_le16(dirent
.disk
, 0);
250 copy_le16(dirent
.attr1
, 0);
251 copy_le32(dirent
.attr2
, attr2
);
252 copy_le32(dirent
.offset
, zip_offset
);
253 memcpy(zip_dir
+ zip_dir_offset
, &dirent
, ZIP_DIR_HEADER_SIZE
);
254 zip_dir_offset
+= ZIP_DIR_HEADER_SIZE
;
255 memcpy(zip_dir
+ zip_dir_offset
, path
, pathlen
);
256 zip_dir_offset
+= pathlen
;
259 copy_le32(header
.magic
, 0x04034b50);
260 copy_le16(header
.version
, 10);
261 copy_le16(header
.flags
, 0);
262 copy_le16(header
.compression_method
, method
);
263 copy_le16(header
.mtime
, zip_time
);
264 copy_le16(header
.mdate
, zip_date
);
265 copy_le32(header
.crc32
, crc
);
266 copy_le32(header
.compressed_size
, compressed_size
);
267 copy_le32(header
.size
, uncompressed_size
);
268 copy_le16(header
.filename_length
, pathlen
);
269 copy_le16(header
.extra_length
, 0);
270 write_or_die(1, &header
, ZIP_LOCAL_HEADER_SIZE
);
271 zip_offset
+= ZIP_LOCAL_HEADER_SIZE
;
272 write_or_die(1, path
, pathlen
);
273 zip_offset
+= pathlen
;
274 if (compressed_size
> 0) {
275 write_or_die(1, out
, compressed_size
);
276 zip_offset
+= compressed_size
;
287 static void write_zip_trailer(const unsigned char *sha1
)
289 struct zip_dir_trailer trailer
;
291 copy_le32(trailer
.magic
, 0x06054b50);
292 copy_le16(trailer
.disk
, 0);
293 copy_le16(trailer
.directory_start_disk
, 0);
294 copy_le16(trailer
.entries_on_this_disk
, zip_dir_entries
);
295 copy_le16(trailer
.entries
, zip_dir_entries
);
296 copy_le32(trailer
.size
, zip_dir_offset
);
297 copy_le32(trailer
.offset
, zip_offset
);
298 copy_le16(trailer
.comment_length
, sha1
? 40 : 0);
300 write_or_die(1, zip_dir
, zip_dir_offset
);
301 write_or_die(1, &trailer
, ZIP_DIR_TRAILER_SIZE
);
303 write_or_die(1, sha1_to_hex(sha1
), 40);
306 static void dos_time(time_t *time
, int *dos_date
, int *dos_time
)
308 struct tm
*t
= localtime(time
);
310 *dos_date
= t
->tm_mday
+ (t
->tm_mon
+ 1) * 32 +
311 (t
->tm_year
+ 1900 - 1980) * 512;
312 *dos_time
= t
->tm_sec
/ 2 + t
->tm_min
* 32 + t
->tm_hour
* 2048;
315 int write_zip_archive(struct archiver_args
*args
)
317 int plen
= strlen(args
->base
);
319 dos_time(&args
->time
, &zip_date
, &zip_time
);
321 zip_dir
= xmalloc(ZIP_DIRECTORY_MIN_SIZE
);
322 zip_dir_size
= ZIP_DIRECTORY_MIN_SIZE
;
323 verbose
= args
->verbose
;
324 commit
= args
->commit
;
325 base_len
= args
->base
? strlen(args
->base
) : 0;
327 if (args
->base
&& plen
> 0 && args
->base
[plen
- 1] == '/') {
328 char *base
= xstrdup(args
->base
);
329 int baselen
= strlen(base
);
331 while (baselen
> 0 && base
[baselen
- 1] == '/')
332 base
[--baselen
] = '\0';
333 write_zip_entry(args
->tree
->object
.sha1
, "", 0, base
, 040777, 0);
336 read_tree_recursive(args
->tree
, args
->base
, plen
, 0,
337 args
->pathspec
, write_zip_entry
);
338 write_zip_trailer(args
->commit_sha1
);
345 void *parse_extra_zip_args(int argc
, const char **argv
)
347 for (; argc
> 0; argc
--, argv
++) {
348 const char *arg
= argv
[0];
350 if (arg
[0] == '-' && isdigit(arg
[1]) && arg
[2] == '\0')
351 zlib_compression_level
= arg
[1] - '0';
353 die("Unknown argument for zip format: %s", arg
);