~ubuntu-branches/debian/sid/git/sid

« back to all changes in this revision

Viewing changes to archive-zip.c

  • Committer: Package Import Robot
  • Author(s): Jonathan Nieder
  • Date: 2013-06-12 07:50:53 UTC
  • mfrom: (1.2.19) (2.1.31 experimental)
  • Revision ID: package-import@ubuntu.com-20130612075053-uue9xe0dq0rvm44y
Tags: 1:1.8.3.1-1
* merge branch debian-experimental
* new upstream point release (see RelNotes/1.8.3.1.txt).
* debian/watch: use xz-compressed tarballs from kernel.org.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 */
4
4
#include "cache.h"
5
5
#include "archive.h"
 
6
#include "streaming.h"
 
7
#include "utf8.h"
6
8
 
7
9
static int zip_date;
8
10
static int zip_time;
15
17
static unsigned int zip_dir_entries;
16
18
 
17
19
#define ZIP_DIRECTORY_MIN_SIZE  (1024 * 1024)
 
20
#define ZIP_STREAM      (1 <<  3)
 
21
#define ZIP_UTF8        (1 << 11)
18
22
 
19
23
struct zip_local_header {
20
24
        unsigned char magic[4];
31
35
        unsigned char _end[1];
32
36
};
33
37
 
 
38
struct zip_data_desc {
 
39
        unsigned char magic[4];
 
40
        unsigned char crc32[4];
 
41
        unsigned char compressed_size[4];
 
42
        unsigned char size[4];
 
43
        unsigned char _end[1];
 
44
};
 
45
 
34
46
struct zip_dir_header {
35
47
        unsigned char magic[4];
36
48
        unsigned char creator_version[2];
64
76
        unsigned char _end[1];
65
77
};
66
78
 
 
79
struct zip_extra_mtime {
 
80
        unsigned char magic[2];
 
81
        unsigned char extra_size[2];
 
82
        unsigned char flags[1];
 
83
        unsigned char mtime[4];
 
84
        unsigned char _end[1];
 
85
};
 
86
 
67
87
/*
68
88
 * On ARM, padding is added at the end of the struct, so a simple
69
89
 * sizeof(struct ...) reports two bytes more than the payload size
70
90
 * we're interested in.
71
91
 */
72
92
#define ZIP_LOCAL_HEADER_SIZE   offsetof(struct zip_local_header, _end)
 
93
#define ZIP_DATA_DESC_SIZE      offsetof(struct zip_data_desc, _end)
73
94
#define ZIP_DIR_HEADER_SIZE     offsetof(struct zip_dir_header, _end)
74
95
#define ZIP_DIR_TRAILER_SIZE    offsetof(struct zip_dir_trailer, _end)
 
96
#define ZIP_EXTRA_MTIME_SIZE    offsetof(struct zip_extra_mtime, _end)
 
97
#define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \
 
98
        (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags))
75
99
 
76
100
static void copy_le16(unsigned char *dest, unsigned int n)
77
101
{
87
111
        dest[3] = 0xff & (n >> 030);
88
112
}
89
113
 
90
 
static void *zlib_deflate(void *data, unsigned long size,
91
 
                int compression_level, unsigned long *compressed_size)
 
114
static void *zlib_deflate_raw(void *data, unsigned long size,
 
115
                              int compression_level,
 
116
                              unsigned long *compressed_size)
92
117
{
93
118
        git_zstream stream;
94
119
        unsigned long maxsize;
96
121
        int result;
97
122
 
98
123
        memset(&stream, 0, sizeof(stream));
99
 
        git_deflate_init(&stream, compression_level);
 
124
        git_deflate_init_raw(&stream, compression_level);
100
125
        maxsize = git_deflate_bound(&stream, size);
101
126
        buffer = xmalloc(maxsize);
102
127
 
120
145
        return buffer;
121
146
}
122
147
 
 
148
static void write_zip_data_desc(unsigned long size,
 
149
                                unsigned long compressed_size,
 
150
                                unsigned long crc)
 
151
{
 
152
        struct zip_data_desc trailer;
 
153
 
 
154
        copy_le32(trailer.magic, 0x08074b50);
 
155
        copy_le32(trailer.crc32, crc);
 
156
        copy_le32(trailer.compressed_size, compressed_size);
 
157
        copy_le32(trailer.size, size);
 
158
        write_or_die(1, &trailer, ZIP_DATA_DESC_SIZE);
 
159
}
 
160
 
 
161
static void set_zip_dir_data_desc(struct zip_dir_header *header,
 
162
                                  unsigned long size,
 
163
                                  unsigned long compressed_size,
 
164
                                  unsigned long crc)
 
165
{
 
166
        copy_le32(header->crc32, crc);
 
167
        copy_le32(header->compressed_size, compressed_size);
 
168
        copy_le32(header->size, size);
 
169
}
 
170
 
 
171
static void set_zip_header_data_desc(struct zip_local_header *header,
 
172
                                     unsigned long size,
 
173
                                     unsigned long compressed_size,
 
174
                                     unsigned long crc)
 
175
{
 
176
        copy_le32(header->crc32, crc);
 
177
        copy_le32(header->compressed_size, compressed_size);
 
178
        copy_le32(header->size, size);
 
179
}
 
180
 
 
181
static int has_only_ascii(const char *s)
 
182
{
 
183
        for (;;) {
 
184
                int c = *s++;
 
185
                if (c == '\0')
 
186
                        return 1;
 
187
                if (!isascii(c))
 
188
                        return 0;
 
189
        }
 
190
}
 
191
 
 
192
#define STREAM_BUFFER_SIZE (1024 * 16)
 
193
 
123
194
static int write_zip_entry(struct archiver_args *args,
124
 
                const unsigned char *sha1, const char *path, size_t pathlen,
125
 
                unsigned int mode, void *buffer, unsigned long size)
 
195
                           const unsigned char *sha1,
 
196
                           const char *path, size_t pathlen,
 
197
                           unsigned int mode)
126
198
{
127
199
        struct zip_local_header header;
128
200
        struct zip_dir_header dirent;
 
201
        struct zip_extra_mtime extra;
129
202
        unsigned long attr2;
130
203
        unsigned long compressed_size;
131
 
        unsigned long uncompressed_size;
132
204
        unsigned long crc;
133
205
        unsigned long direntsize;
134
206
        int method;
135
207
        unsigned char *out;
136
208
        void *deflated = NULL;
 
209
        void *buffer;
 
210
        struct git_istream *stream = NULL;
 
211
        unsigned long flags = 0;
 
212
        unsigned long size;
137
213
 
138
214
        crc = crc32(0, NULL, 0);
139
215
 
 
216
        if (!has_only_ascii(path)) {
 
217
                if (is_utf8(path))
 
218
                        flags |= ZIP_UTF8;
 
219
                else
 
220
                        warning("Path is not valid UTF-8: %s", path);
 
221
        }
 
222
 
140
223
        if (pathlen > 0xffff) {
141
224
                return error("path too long (%d chars, SHA1: %s): %s",
142
225
                                (int)pathlen, sha1_to_hex(sha1), path);
146
229
                method = 0;
147
230
                attr2 = 16;
148
231
                out = NULL;
149
 
                uncompressed_size = 0;
 
232
                size = 0;
150
233
                compressed_size = 0;
 
234
                buffer = NULL;
 
235
                size = 0;
151
236
        } else if (S_ISREG(mode) || S_ISLNK(mode)) {
 
237
                enum object_type type = sha1_object_info(sha1, &size);
 
238
 
152
239
                method = 0;
153
240
                attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) :
154
241
                        (mode & 0111) ? ((mode) << 16) : 0;
155
 
                if (S_ISREG(mode) && args->compression_level != 0)
 
242
                if (S_ISREG(mode) && args->compression_level != 0 && size > 0)
156
243
                        method = 8;
157
 
                crc = crc32(crc, buffer, size);
158
 
                out = buffer;
159
 
                uncompressed_size = size;
160
 
                compressed_size = size;
 
244
 
 
245
                if (S_ISREG(mode) && type == OBJ_BLOB && !args->convert &&
 
246
                    size > big_file_threshold) {
 
247
                        stream = open_istream(sha1, &type, &size, NULL);
 
248
                        if (!stream)
 
249
                                return error("cannot stream blob %s",
 
250
                                             sha1_to_hex(sha1));
 
251
                        flags |= ZIP_STREAM;
 
252
                        out = buffer = NULL;
 
253
                } else {
 
254
                        buffer = sha1_file_to_archive(args, path, sha1, mode,
 
255
                                                      &type, &size);
 
256
                        if (!buffer)
 
257
                                return error("cannot read %s",
 
258
                                             sha1_to_hex(sha1));
 
259
                        crc = crc32(crc, buffer, size);
 
260
                        out = buffer;
 
261
                }
 
262
                compressed_size = (method == 0) ? size : 0;
161
263
        } else {
162
264
                return error("unsupported file mode: 0%o (SHA1: %s)", mode,
163
265
                                sha1_to_hex(sha1));
164
266
        }
165
267
 
166
 
        if (method == 8) {
167
 
                deflated = zlib_deflate(buffer, size, args->compression_level,
168
 
                                &compressed_size);
169
 
                if (deflated && compressed_size - 6 < size) {
170
 
                        /* ZLIB --> raw compressed data (see RFC 1950) */
171
 
                        /* CMF and FLG ... */
172
 
                        out = (unsigned char *)deflated + 2;
173
 
                        compressed_size -= 6;   /* ... and ADLER32 */
174
 
                } else {
 
268
        if (buffer && method == 8) {
 
269
                out = deflated = zlib_deflate_raw(buffer, size,
 
270
                                                  args->compression_level,
 
271
                                                  &compressed_size);
 
272
                if (!out || compressed_size >= size) {
 
273
                        out = buffer;
175
274
                        method = 0;
176
275
                        compressed_size = size;
177
276
                }
178
277
        }
179
278
 
 
279
        copy_le16(extra.magic, 0x5455);
 
280
        copy_le16(extra.extra_size, ZIP_EXTRA_MTIME_PAYLOAD_SIZE);
 
281
        extra.flags[0] = 1;     /* just mtime */
 
282
        copy_le32(extra.mtime, args->time);
 
283
 
180
284
        /* make sure we have enough free space in the dictionary */
181
 
        direntsize = ZIP_DIR_HEADER_SIZE + pathlen;
 
285
        direntsize = ZIP_DIR_HEADER_SIZE + pathlen + ZIP_EXTRA_MTIME_SIZE;
182
286
        while (zip_dir_size < zip_dir_offset + direntsize) {
183
287
                zip_dir_size += ZIP_DIRECTORY_MIN_SIZE;
184
288
                zip_dir = xrealloc(zip_dir, zip_dir_size);
188
292
        copy_le16(dirent.creator_version,
189
293
                S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0);
190
294
        copy_le16(dirent.version, 10);
191
 
        copy_le16(dirent.flags, 0);
 
295
        copy_le16(dirent.flags, flags);
192
296
        copy_le16(dirent.compression_method, method);
193
297
        copy_le16(dirent.mtime, zip_time);
194
298
        copy_le16(dirent.mdate, zip_date);
195
 
        copy_le32(dirent.crc32, crc);
196
 
        copy_le32(dirent.compressed_size, compressed_size);
197
 
        copy_le32(dirent.size, uncompressed_size);
 
299
        set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
198
300
        copy_le16(dirent.filename_length, pathlen);
199
 
        copy_le16(dirent.extra_length, 0);
 
301
        copy_le16(dirent.extra_length, ZIP_EXTRA_MTIME_SIZE);
200
302
        copy_le16(dirent.comment_length, 0);
201
303
        copy_le16(dirent.disk, 0);
202
304
        copy_le16(dirent.attr1, 0);
203
305
        copy_le32(dirent.attr2, attr2);
204
306
        copy_le32(dirent.offset, zip_offset);
205
 
        memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
206
 
        zip_dir_offset += ZIP_DIR_HEADER_SIZE;
207
 
        memcpy(zip_dir + zip_dir_offset, path, pathlen);
208
 
        zip_dir_offset += pathlen;
209
 
        zip_dir_entries++;
210
307
 
211
308
        copy_le32(header.magic, 0x04034b50);
212
309
        copy_le16(header.version, 10);
213
 
        copy_le16(header.flags, 0);
 
310
        copy_le16(header.flags, flags);
214
311
        copy_le16(header.compression_method, method);
215
312
        copy_le16(header.mtime, zip_time);
216
313
        copy_le16(header.mdate, zip_date);
217
 
        copy_le32(header.crc32, crc);
218
 
        copy_le32(header.compressed_size, compressed_size);
219
 
        copy_le32(header.size, uncompressed_size);
 
314
        set_zip_header_data_desc(&header, size, compressed_size, crc);
220
315
        copy_le16(header.filename_length, pathlen);
221
 
        copy_le16(header.extra_length, 0);
 
316
        copy_le16(header.extra_length, ZIP_EXTRA_MTIME_SIZE);
222
317
        write_or_die(1, &header, ZIP_LOCAL_HEADER_SIZE);
223
318
        zip_offset += ZIP_LOCAL_HEADER_SIZE;
224
319
        write_or_die(1, path, pathlen);
225
320
        zip_offset += pathlen;
226
 
        if (compressed_size > 0) {
 
321
        write_or_die(1, &extra, ZIP_EXTRA_MTIME_SIZE);
 
322
        zip_offset += ZIP_EXTRA_MTIME_SIZE;
 
323
        if (stream && method == 0) {
 
324
                unsigned char buf[STREAM_BUFFER_SIZE];
 
325
                ssize_t readlen;
 
326
 
 
327
                for (;;) {
 
328
                        readlen = read_istream(stream, buf, sizeof(buf));
 
329
                        if (readlen <= 0)
 
330
                                break;
 
331
                        crc = crc32(crc, buf, readlen);
 
332
                        write_or_die(1, buf, readlen);
 
333
                }
 
334
                close_istream(stream);
 
335
                if (readlen)
 
336
                        return readlen;
 
337
 
 
338
                compressed_size = size;
 
339
                zip_offset += compressed_size;
 
340
 
 
341
                write_zip_data_desc(size, compressed_size, crc);
 
342
                zip_offset += ZIP_DATA_DESC_SIZE;
 
343
 
 
344
                set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
 
345
        } else if (stream && method == 8) {
 
346
                unsigned char buf[STREAM_BUFFER_SIZE];
 
347
                ssize_t readlen;
 
348
                git_zstream zstream;
 
349
                int result;
 
350
                size_t out_len;
 
351
                unsigned char compressed[STREAM_BUFFER_SIZE * 2];
 
352
 
 
353
                memset(&zstream, 0, sizeof(zstream));
 
354
                git_deflate_init_raw(&zstream, args->compression_level);
 
355
 
 
356
                compressed_size = 0;
 
357
                zstream.next_out = compressed;
 
358
                zstream.avail_out = sizeof(compressed);
 
359
 
 
360
                for (;;) {
 
361
                        readlen = read_istream(stream, buf, sizeof(buf));
 
362
                        if (readlen <= 0)
 
363
                                break;
 
364
                        crc = crc32(crc, buf, readlen);
 
365
 
 
366
                        zstream.next_in = buf;
 
367
                        zstream.avail_in = readlen;
 
368
                        result = git_deflate(&zstream, 0);
 
369
                        if (result != Z_OK)
 
370
                                die("deflate error (%d)", result);
 
371
                        out_len = zstream.next_out - compressed;
 
372
 
 
373
                        if (out_len > 0) {
 
374
                                write_or_die(1, compressed, out_len);
 
375
                                compressed_size += out_len;
 
376
                                zstream.next_out = compressed;
 
377
                                zstream.avail_out = sizeof(compressed);
 
378
                        }
 
379
 
 
380
                }
 
381
                close_istream(stream);
 
382
                if (readlen)
 
383
                        return readlen;
 
384
 
 
385
                zstream.next_in = buf;
 
386
                zstream.avail_in = 0;
 
387
                result = git_deflate(&zstream, Z_FINISH);
 
388
                if (result != Z_STREAM_END)
 
389
                        die("deflate error (%d)", result);
 
390
 
 
391
                git_deflate_end(&zstream);
 
392
                out_len = zstream.next_out - compressed;
 
393
                write_or_die(1, compressed, out_len);
 
394
                compressed_size += out_len;
 
395
                zip_offset += compressed_size;
 
396
 
 
397
                write_zip_data_desc(size, compressed_size, crc);
 
398
                zip_offset += ZIP_DATA_DESC_SIZE;
 
399
 
 
400
                set_zip_dir_data_desc(&dirent, size, compressed_size, crc);
 
401
        } else if (compressed_size > 0) {
227
402
                write_or_die(1, out, compressed_size);
228
403
                zip_offset += compressed_size;
229
404
        }
230
405
 
231
406
        free(deflated);
 
407
        free(buffer);
 
408
 
 
409
        memcpy(zip_dir + zip_dir_offset, &dirent, ZIP_DIR_HEADER_SIZE);
 
410
        zip_dir_offset += ZIP_DIR_HEADER_SIZE;
 
411
        memcpy(zip_dir + zip_dir_offset, path, pathlen);
 
412
        zip_dir_offset += pathlen;
 
413
        memcpy(zip_dir + zip_dir_offset, &extra, ZIP_EXTRA_MTIME_SIZE);
 
414
        zip_dir_offset += ZIP_EXTRA_MTIME_SIZE;
 
415
        zip_dir_entries++;
232
416
 
233
417
        return 0;
234
418
}