@@ -16,7 +16,9 @@ static unsigned int zip_dir_size;
16
16
17
17
static unsigned int zip_offset ;
18
18
static unsigned int zip_dir_offset ;
19
- static unsigned int zip_dir_entries ;
19
+ static uint64_t zip_dir_entries ;
20
+
21
+ static unsigned int max_creator_version ;
20
22
21
23
#define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024)
22
24
#define ZIP_STREAM (1 << 3)
@@ -86,6 +88,28 @@ struct zip_extra_mtime {
86
88
unsigned char _end [1 ];
87
89
};
88
90
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 ];
103
+ };
104
+
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 ];
111
+ };
112
+
89
113
/*
90
114
* On ARM, padding is added at the end of the struct, so a simple
91
115
* sizeof(struct ...) reports two bytes more than the payload size
@@ -98,6 +122,12 @@ struct zip_extra_mtime {
98
122
#define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end)
99
123
#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
100
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)
101
131
102
132
static void copy_le16 (unsigned char * dest , unsigned int n )
103
133
{
@@ -113,6 +143,31 @@ static void copy_le32(unsigned char *dest, unsigned int n)
113
143
dest [3 ] = 0xff & (n >> 030 );
114
144
}
115
145
146
+ static void copy_le64 (unsigned char * dest , uint64_t n )
147
+ {
148
+ dest [0 ] = 0xff & 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 );
156
+ }
157
+
158
+ static uint64_t clamp_max (uint64_t n , uint64_t max , int * clamped )
159
+ {
160
+ if (n <= max )
161
+ return n ;
162
+ * clamped = 1 ;
163
+ return max ;
164
+ }
165
+
166
+ static void copy_le16_clamp (unsigned char * dest , uint64_t n , int * clamped )
167
+ {
168
+ copy_le16 (dest , clamp_max (n , 0xffff , clamped ));
169
+ }
170
+
116
171
static void * zlib_deflate_raw (void * data , unsigned long size ,
117
172
int compression_level ,
118
173
unsigned long * compressed_size )
@@ -223,6 +278,7 @@ static int write_zip_entry(struct archiver_args *args,
223
278
unsigned long size ;
224
279
int is_binary = -1 ;
225
280
const char * path_without_prefix = path + args -> baselen ;
281
+ unsigned int creator_version = 0 ;
226
282
227
283
crc = crc32 (0 , NULL , 0 );
228
284
@@ -251,6 +307,8 @@ static int write_zip_entry(struct archiver_args *args,
251
307
method = 0 ;
252
308
attr2 = S_ISLNK (mode ) ? ((mode | 0777 ) << 16 ) :
253
309
(mode & 0111 ) ? ((mode ) << 16 ) : 0 ;
310
+ if (S_ISLNK (mode ) || (mode & 0111 ))
311
+ creator_version = 0x0317 ;
254
312
if (S_ISREG (mode ) && args -> compression_level != 0 && size > 0 )
255
313
method = 8 ;
256
314
@@ -279,6 +337,9 @@ static int write_zip_entry(struct archiver_args *args,
279
337
sha1_to_hex (sha1 ));
280
338
}
281
339
340
+ if (creator_version > max_creator_version )
341
+ max_creator_version = creator_version ;
342
+
282
343
if (buffer && method == 8 ) {
283
344
out = deflated = zlib_deflate_raw (buffer , size ,
284
345
args -> compression_level ,
@@ -303,8 +364,7 @@ static int write_zip_entry(struct archiver_args *args,
303
364
}
304
365
305
366
copy_le32 (dirent .magic , 0x02014b50 );
306
- copy_le16 (dirent .creator_version ,
307
- S_ISLNK (mode ) || (S_ISREG (mode ) && (mode & 0111 )) ? 0x0317 : 0 );
367
+ copy_le16 (dirent .creator_version , creator_version );
308
368
copy_le16 (dirent .version , 10 );
309
369
copy_le16 (dirent .flags , flags );
310
370
copy_le16 (dirent .compression_method , method );
@@ -437,20 +497,49 @@ static int write_zip_entry(struct archiver_args *args,
437
497
return 0 ;
438
498
}
439
499
500
+ static void write_zip64_trailer (void )
501
+ {
502
+ struct zip64_dir_trailer trailer64 ;
503
+ struct zip64_dir_trailer_locator locator64 ;
504
+
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 );
515
+
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 );
520
+
521
+ write_or_die (1 , & trailer64 , ZIP64_DIR_TRAILER_SIZE );
522
+ write_or_die (1 , & locator64 , ZIP64_DIR_TRAILER_LOCATOR_SIZE );
523
+ }
524
+
440
525
static void write_zip_trailer (const unsigned char * sha1 )
441
526
{
442
527
struct zip_dir_trailer trailer ;
528
+ int clamped = 0 ;
443
529
444
530
copy_le32 (trailer .magic , 0x06054b50 );
445
531
copy_le16 (trailer .disk , 0 );
446
532
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 );
533
+ copy_le16_clamp (trailer .entries_on_this_disk , zip_dir_entries ,
534
+ & clamped );
535
+ copy_le16_clamp (trailer .entries , zip_dir_entries , & clamped );
449
536
copy_le32 (trailer .size , zip_dir_offset );
450
537
copy_le32 (trailer .offset , zip_offset );
451
538
copy_le16 (trailer .comment_length , sha1 ? GIT_SHA1_HEXSZ : 0 );
452
539
453
540
write_or_die (1 , zip_dir , zip_dir_offset );
541
+ if (clamped )
542
+ write_zip64_trailer ();
454
543
write_or_die (1 , & trailer , ZIP_DIR_TRAILER_SIZE );
455
544
if (sha1 )
456
545
write_or_die (1 , sha1_to_hex (sha1 ), GIT_SHA1_HEXSZ );
0 commit comments