~sergei.glushchenko/+junk/page-scan-hack

« back to all changes in this revision

Viewing changes to src/libarchive/libarchive/archive_write_set_format_zip.c

merge parallel compression branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-
 
2
 * Copyright (c) 2008 Anselm Strauss
 
3
 * Copyright (c) 2009 Joerg Sonnenberger
 
4
 * All rights reserved.
 
5
 *
 
6
 * Redistribution and use in source and binary forms, with or without
 
7
 * modification, are permitted provided that the following conditions
 
8
 * are met:
 
9
 * 1. Redistributions of source code must retain the above copyright
 
10
 *    notice, this list of conditions and the following disclaimer.
 
11
 * 2. Redistributions in binary form must reproduce the above copyright
 
12
 *    notice, this list of conditions and the following disclaimer in the
 
13
 *    documentation and/or other materials provided with the distribution.
 
14
 *
 
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 
16
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
17
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
18
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 
19
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
20
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
21
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
22
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
23
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
25
 */
 
26
 
 
27
/*
 
28
 * Development supported by Google Summer of Code 2008.
 
29
 */
 
30
 
 
31
/*
 
32
 * The current implementation is very limited:
 
33
 *
 
34
 *   - No encryption support.
 
35
 *   - No ZIP64 support.
 
36
 *   - No support for splitting and spanning.
 
37
 *   - Only supports regular file and folder entries.
 
38
 *
 
39
 * Note that generally data in ZIP files is little-endian encoded,
 
40
 * with some exceptions.
 
41
 *
 
42
 * TODO: Since Libarchive is generally 64bit oriented, but this implementation
 
43
 * does not yet support sizes exceeding 32bit, it is highly fragile for
 
44
 * big archives. This should change when ZIP64 is finally implemented, otherwise
 
45
 * some serious checking has to be done.
 
46
 *
 
47
 */
 
48
 
 
49
#include "archive_platform.h"
 
50
__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_format_zip.c 201168 2009-12-29 06:15:32Z kientzle $");
 
51
 
 
52
#ifdef HAVE_ERRNO_H
 
53
#include <errno.h>
 
54
#endif
 
55
#include <stdio.h>
 
56
#ifdef HAVE_STDLIB_H
 
57
#include <stdlib.h>
 
58
#endif
 
59
#ifdef HAVE_STRING_H
 
60
#include <string.h>
 
61
#endif
 
62
#ifdef HAVE_ZLIB_H
 
63
#include <zlib.h>
 
64
#endif
 
65
 
 
66
#include "archive.h"
 
67
#include "archive_endian.h"
 
68
#include "archive_entry.h"
 
69
#include "archive_private.h"
 
70
#include "archive_write_private.h"
 
71
 
 
72
#ifndef HAVE_ZLIB_H
 
73
#include "archive_crc32.h"
 
74
#endif
 
75
 
 
76
#define ZIP_SIGNATURE_LOCAL_FILE_HEADER 0x04034b50
 
77
#define ZIP_SIGNATURE_DATA_DESCRIPTOR 0x08074b50
 
78
#define ZIP_SIGNATURE_FILE_HEADER 0x02014b50
 
79
#define ZIP_SIGNATURE_CENTRAL_DIRECTORY_END 0x06054b50
 
80
#define ZIP_SIGNATURE_EXTRA_TIMESTAMP 0x5455
 
81
#define ZIP_SIGNATURE_EXTRA_UNIX 0x7855
 
82
#define ZIP_VERSION_EXTRACT 0x0014 /* ZIP version 2.0 is needed. */
 
83
#define ZIP_VERSION_BY 0x0314 /* Made by UNIX, using ZIP version 2.0. */
 
84
#define ZIP_FLAGS 0x08 /* Flagging bit 3 (count from 0) for using data descriptor. */
 
85
 
 
86
enum compression {
 
87
        COMPRESSION_STORE = 0
 
88
#ifdef HAVE_ZLIB_H
 
89
        ,
 
90
        COMPRESSION_DEFLATE = 8
 
91
#endif
 
92
};
 
93
 
 
94
static ssize_t archive_write_zip_data(struct archive_write *, const void *buff, size_t s);
 
95
static int archive_write_zip_finish(struct archive_write *);
 
96
static int archive_write_zip_destroy(struct archive_write *);
 
97
static int archive_write_zip_finish_entry(struct archive_write *);
 
98
static int archive_write_zip_header(struct archive_write *, struct archive_entry *);
 
99
static unsigned int dos_time(const time_t);
 
100
static size_t path_length(struct archive_entry *);
 
101
static int write_path(struct archive_entry *, struct archive_write *);
 
102
 
 
103
struct zip_local_file_header {
 
104
        char signature[4];
 
105
        char version[2];
 
106
        char flags[2];
 
107
        char compression[2];
 
108
        char timedate[4];
 
109
        char crc32[4];
 
110
        char compressed_size[4];
 
111
        char uncompressed_size[4];
 
112
        char filename_length[2];
 
113
        char extra_length[2];
 
114
};
 
115
 
 
116
struct zip_file_header {
 
117
        char signature[4];
 
118
        char version_by[2];
 
119
        char version_extract[2];
 
120
        char flags[2];
 
121
        char compression[2];
 
122
        char timedate[4];
 
123
        char crc32[4];
 
124
        char compressed_size[4];
 
125
        char uncompressed_size[4];
 
126
        char filename_length[2];
 
127
        char extra_length[2];
 
128
        char comment_length[2];
 
129
        char disk_number[2];
 
130
        char attributes_internal[2];
 
131
        char attributes_external[4];
 
132
        char offset[4];
 
133
};
 
134
 
 
135
struct zip_data_descriptor {
 
136
        char signature[4]; /* Not mandatory, but recommended by specification. */
 
137
        char crc32[4];
 
138
        char compressed_size[4];
 
139
        char uncompressed_size[4];
 
140
};
 
141
 
 
142
struct zip_extra_data_local {
 
143
        char time_id[2];
 
144
        char time_size[2];
 
145
        char time_flag[1];
 
146
        char mtime[4];
 
147
        char atime[4];
 
148
        char ctime[4];
 
149
        char unix_id[2];
 
150
        char unix_size[2];
 
151
        char unix_uid[2];
 
152
        char unix_gid[2];
 
153
};
 
154
 
 
155
struct zip_extra_data_central {
 
156
        char time_id[2];
 
157
        char time_size[2];
 
158
        char time_flag[1];
 
159
        char mtime[4];
 
160
        char unix_id[2];
 
161
        char unix_size[2];
 
162
};
 
163
 
 
164
struct zip_file_header_link {
 
165
        struct zip_file_header_link *next;
 
166
        struct archive_entry *entry;
 
167
        off_t offset;
 
168
        unsigned long crc32;
 
169
        off_t compressed_size;
 
170
        enum compression compression;
 
171
};
 
172
 
 
173
struct zip {
 
174
        struct zip_data_descriptor data_descriptor;
 
175
        struct zip_file_header_link *central_directory;
 
176
        struct zip_file_header_link *central_directory_end;
 
177
        int64_t offset;
 
178
        int64_t written_bytes;
 
179
        int64_t remaining_data_bytes;
 
180
        enum compression compression;
 
181
 
 
182
#ifdef HAVE_ZLIB_H
 
183
        z_stream stream;
 
184
        size_t len_buf;
 
185
        unsigned char *buf;
 
186
#endif
 
187
};
 
188
 
 
189
struct zip_central_directory_end {
 
190
        char signature[4];
 
191
        char disk[2];
 
192
        char start_disk[2];
 
193
        char entries_disk[2];
 
194
        char entries[2];
 
195
        char size[4];
 
196
        char offset[4];
 
197
        char comment_length[2];
 
198
};
 
199
 
 
200
static int
 
201
archive_write_zip_options(struct archive_write *a, const char *key,
 
202
    const char *value)
 
203
{
 
204
        struct zip *zip = a->format_data;
 
205
 
 
206
        if (strcmp(key, "compression") == 0) {
 
207
                if (strcmp(value, "deflate") == 0) {
 
208
#ifdef HAVE_ZLIB_H
 
209
                        zip->compression = COMPRESSION_DEFLATE;
 
210
#else
 
211
                        archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 
212
                            "deflate compression not supported");
 
213
                        return ARCHIVE_WARN;
 
214
#endif
 
215
                } else if (strcmp(value, "store") == 0)
 
216
                        zip->compression = COMPRESSION_STORE;
 
217
                else
 
218
                        return (ARCHIVE_WARN);
 
219
                return (ARCHIVE_OK);
 
220
        }
 
221
        return (ARCHIVE_WARN);
 
222
}
 
223
 
 
224
int
 
225
archive_write_set_format_zip(struct archive *_a)
 
226
{
 
227
        struct archive_write *a = (struct archive_write *)_a;
 
228
        struct zip *zip;
 
229
 
 
230
        /* If another format was already registered, unregister it. */
 
231
        if (a->format_destroy != NULL)
 
232
                (a->format_destroy)(a);
 
233
 
 
234
        zip = (struct zip *) calloc(1, sizeof(*zip));
 
235
        if (zip == NULL) {
 
236
                archive_set_error(&a->archive, ENOMEM, "Can't allocate zip data");
 
237
                return (ARCHIVE_FATAL);
 
238
        }
 
239
        zip->central_directory = NULL;
 
240
        zip->central_directory_end = NULL;
 
241
        zip->offset = 0;
 
242
        zip->written_bytes = 0;
 
243
        zip->remaining_data_bytes = 0;
 
244
 
 
245
#ifdef HAVE_ZLIB_H
 
246
        zip->compression = COMPRESSION_DEFLATE;
 
247
        zip->len_buf = 65536;
 
248
        zip->buf = malloc(zip->len_buf);
 
249
        if (zip->buf == NULL) {
 
250
                archive_set_error(&a->archive, ENOMEM, "Can't allocate compression buffer");
 
251
                return (ARCHIVE_FATAL);
 
252
        }
 
253
#else
 
254
        zip->compression = COMPRESSION_STORE;
 
255
#endif
 
256
 
 
257
        a->format_data = zip;
 
258
 
 
259
        a->pad_uncompressed = 0; /* Actually not needed for now, since no compression support yet. */
 
260
        a->format_name = "zip";
 
261
        a->format_options = archive_write_zip_options;
 
262
        a->format_write_header = archive_write_zip_header;
 
263
        a->format_write_data = archive_write_zip_data;
 
264
        a->format_finish_entry = archive_write_zip_finish_entry;
 
265
        a->format_finish = archive_write_zip_finish;
 
266
        a->format_destroy = archive_write_zip_destroy;
 
267
        a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
 
268
        a->archive.archive_format_name = "ZIP";
 
269
 
 
270
        archive_le32enc(&zip->data_descriptor.signature,
 
271
            ZIP_SIGNATURE_DATA_DESCRIPTOR);
 
272
 
 
273
        return (ARCHIVE_OK);
 
274
}
 
275
 
 
276
static int
 
277
archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
 
278
{
 
279
        struct zip *zip;
 
280
        struct zip_local_file_header h;
 
281
        struct zip_extra_data_local e;
 
282
        struct zip_data_descriptor *d;
 
283
        struct zip_file_header_link *l;
 
284
        int ret;
 
285
        int64_t size;
 
286
        mode_t type;
 
287
 
 
288
        /* Entries other than a regular file or a folder are skipped. */
 
289
        type = archive_entry_filetype(entry);
 
290
        if ((type != AE_IFREG) & (type != AE_IFDIR)) {
 
291
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Filetype not supported");
 
292
                return ARCHIVE_FAILED;
 
293
        };
 
294
 
 
295
        /* Directory entries should have a size of 0. */
 
296
        if (type == AE_IFDIR)
 
297
                archive_entry_set_size(entry, 0);
 
298
 
 
299
        zip = a->format_data;
 
300
        d = &zip->data_descriptor;
 
301
        size = archive_entry_size(entry);
 
302
        zip->remaining_data_bytes = size;
 
303
 
 
304
        /* Append archive entry to the central directory data. */
 
305
        l = (struct zip_file_header_link *) malloc(sizeof(*l));
 
306
        if (l == NULL) {
 
307
                archive_set_error(&a->archive, ENOMEM, "Can't allocate zip header data");
 
308
                return (ARCHIVE_FATAL);
 
309
        }
 
310
        l->entry = archive_entry_clone(entry);
 
311
        /* Initialize the CRC variable and potentially the local crc32(). */
 
312
        l->crc32 = crc32(0, NULL, 0);
 
313
        l->compression = zip->compression;
 
314
        l->compressed_size = 0;
 
315
        l->next = NULL;
 
316
        if (zip->central_directory == NULL) {
 
317
                zip->central_directory = l;
 
318
        } else {
 
319
                zip->central_directory_end->next = l;
 
320
        }
 
321
        zip->central_directory_end = l;
 
322
 
 
323
        /* Store the offset of this header for later use in central directory. */
 
324
        l->offset = zip->written_bytes;
 
325
 
 
326
        memset(&h, 0, sizeof(h));
 
327
        archive_le32enc(&h.signature, ZIP_SIGNATURE_LOCAL_FILE_HEADER);
 
328
        archive_le16enc(&h.version, ZIP_VERSION_EXTRACT);
 
329
        archive_le16enc(&h.flags, ZIP_FLAGS);
 
330
        archive_le16enc(&h.compression, zip->compression);
 
331
        archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(entry)));
 
332
        archive_le16enc(&h.filename_length, (uint16_t)path_length(entry));
 
333
 
 
334
        switch (zip->compression) {
 
335
        case COMPRESSION_STORE:
 
336
                /* Setting compressed and uncompressed sizes even when specification says
 
337
                 * to set to zero when using data descriptors. Otherwise the end of the
 
338
                 * data for an entry is rather difficult to find. */
 
339
                archive_le32enc(&h.compressed_size, size);
 
340
                archive_le32enc(&h.uncompressed_size, size);
 
341
                break;
 
342
#ifdef HAVE_ZLIB_H
 
343
        case COMPRESSION_DEFLATE:
 
344
                archive_le32enc(&h.uncompressed_size, size);
 
345
 
 
346
                zip->stream.zalloc = Z_NULL;
 
347
                zip->stream.zfree = Z_NULL;
 
348
                zip->stream.opaque = Z_NULL;
 
349
                zip->stream.next_out = zip->buf;
 
350
                zip->stream.avail_out = zip->len_buf;
 
351
                if (deflateInit2(&zip->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
 
352
                    -15, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
 
353
                        archive_set_error(&a->archive, ENOMEM, "Can't init deflate compressor");
 
354
                        return (ARCHIVE_FATAL);
 
355
                }
 
356
                break;
 
357
#endif
 
358
        }
 
359
 
 
360
        /* Formatting extra data. */
 
361
        archive_le16enc(&h.extra_length, sizeof(e));
 
362
        archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP);
 
363
        archive_le16enc(&e.time_size, sizeof(e.time_flag) +
 
364
            sizeof(e.mtime) + sizeof(e.atime) + sizeof(e.ctime));
 
365
        e.time_flag[0] = 0x07;
 
366
        archive_le32enc(&e.mtime, archive_entry_mtime(entry));
 
367
        archive_le32enc(&e.atime, archive_entry_atime(entry));
 
368
        archive_le32enc(&e.ctime, archive_entry_ctime(entry));
 
369
            
 
370
        archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_UNIX);
 
371
        archive_le16enc(&e.unix_size, sizeof(e.unix_uid) + sizeof(e.unix_gid));
 
372
        archive_le16enc(&e.unix_uid, archive_entry_uid(entry));
 
373
        archive_le16enc(&e.unix_gid, archive_entry_gid(entry));
 
374
 
 
375
        archive_le32enc(&d->uncompressed_size, size);
 
376
 
 
377
        ret = (a->compressor.write)(a, &h, sizeof(h));
 
378
        if (ret != ARCHIVE_OK)
 
379
                return (ARCHIVE_FATAL);
 
380
        zip->written_bytes += sizeof(h);
 
381
 
 
382
        ret = write_path(entry, a);
 
383
        if (ret <= ARCHIVE_OK)
 
384
                return (ARCHIVE_FATAL);
 
385
        zip->written_bytes += ret;
 
386
 
 
387
        ret = (a->compressor.write)(a, &e, sizeof(e));
 
388
        if (ret != ARCHIVE_OK)
 
389
                return (ARCHIVE_FATAL);
 
390
        zip->written_bytes += sizeof(e);
 
391
 
 
392
        return (ARCHIVE_OK);
 
393
}
 
394
 
 
395
static ssize_t
 
396
archive_write_zip_data(struct archive_write *a, const void *buff, size_t s)
 
397
{
 
398
        int ret;
 
399
        struct zip *zip = a->format_data;
 
400
        struct zip_file_header_link *l = zip->central_directory_end;
 
401
 
 
402
        if ((int64_t)s > zip->remaining_data_bytes)
 
403
                s = (size_t)zip->remaining_data_bytes;
 
404
 
 
405
        if (s == 0) return 0;
 
406
 
 
407
        switch (zip->compression) {
 
408
        case COMPRESSION_STORE:
 
409
                ret = (a->compressor.write)(a, buff, s);
 
410
                if (ret != ARCHIVE_OK) return (ret);
 
411
                zip->written_bytes += s;
 
412
                zip->remaining_data_bytes -= s;
 
413
                l->compressed_size += s;
 
414
                l->crc32 = crc32(l->crc32, buff, s);
 
415
                return (s);
 
416
#if HAVE_ZLIB_H
 
417
        case COMPRESSION_DEFLATE:
 
418
                zip->stream.next_in = (unsigned char*)(uintptr_t)buff;
 
419
                zip->stream.avail_in = s;
 
420
                do {
 
421
                        ret = deflate(&zip->stream, Z_NO_FLUSH);
 
422
                        if (ret == Z_STREAM_ERROR)
 
423
                                return (ARCHIVE_FATAL);
 
424
                        if (zip->stream.avail_out == 0) {
 
425
                                ret = (a->compressor.write)(a, zip->buf, zip->len_buf);
 
426
                                if (ret != ARCHIVE_OK)
 
427
                                        return (ret);
 
428
                                l->compressed_size += zip->len_buf;
 
429
                                zip->written_bytes += zip->len_buf;
 
430
                                zip->stream.next_out = zip->buf;
 
431
                                zip->stream.avail_out = zip->len_buf;
 
432
                        }
 
433
                } while (zip->stream.avail_in != 0);
 
434
                zip->remaining_data_bytes -= s;
 
435
                /* If we have it, use zlib's fast crc32() */
 
436
                l->crc32 = crc32(l->crc32, buff, s);
 
437
                return (s);
 
438
#endif
 
439
 
 
440
        default:
 
441
                archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
 
442
                    "Invalid ZIP compression type");
 
443
                return ARCHIVE_FATAL;
 
444
        }
 
445
}
 
446
 
 
447
static int
 
448
archive_write_zip_finish_entry(struct archive_write *a)
 
449
{
 
450
        /* Write the data descripter after file data has been written. */
 
451
        int ret;
 
452
        struct zip *zip = a->format_data;
 
453
        struct zip_data_descriptor *d = &zip->data_descriptor;
 
454
        struct zip_file_header_link *l = zip->central_directory_end;
 
455
#if HAVE_ZLIB_H
 
456
        size_t reminder;
 
457
#endif
 
458
 
 
459
        switch(zip->compression) {
 
460
        case COMPRESSION_STORE:
 
461
                break;
 
462
#if HAVE_ZLIB_H
 
463
        case COMPRESSION_DEFLATE:
 
464
                for (;;) {
 
465
                        ret = deflate(&zip->stream, Z_FINISH);
 
466
                        if (ret == Z_STREAM_ERROR)
 
467
                                return (ARCHIVE_FATAL);
 
468
                        reminder = zip->len_buf - zip->stream.avail_out;
 
469
                        ret = (a->compressor.write)(a, zip->buf, reminder);
 
470
                        if (ret != ARCHIVE_OK)
 
471
                                return (ret);
 
472
                        l->compressed_size += reminder;
 
473
                        zip->written_bytes += reminder;
 
474
                        zip->stream.next_out = zip->buf;
 
475
                        if (zip->stream.avail_out != 0)
 
476
                                break;
 
477
                        zip->stream.avail_out = zip->len_buf;
 
478
                }
 
479
                deflateEnd(&zip->stream);
 
480
                break;
 
481
#endif
 
482
        }
 
483
 
 
484
        archive_le32enc(&d->crc32, l->crc32);
 
485
        archive_le32enc(&d->compressed_size, l->compressed_size);
 
486
        ret = (a->compressor.write)(a, d, sizeof(*d));
 
487
        if (ret != ARCHIVE_OK)
 
488
                return (ARCHIVE_FATAL);
 
489
        zip->written_bytes += sizeof(*d);
 
490
        return (ARCHIVE_OK);
 
491
}
 
492
 
 
493
static int
 
494
archive_write_zip_finish(struct archive_write *a)
 
495
{
 
496
        struct zip *zip;
 
497
        struct zip_file_header_link *l;
 
498
        struct zip_file_header h;
 
499
        struct zip_central_directory_end end;
 
500
        struct zip_extra_data_central e;
 
501
        off_t offset_start, offset_end;
 
502
        int entries;
 
503
        int ret;
 
504
 
 
505
        zip = a->format_data;
 
506
        l = zip->central_directory;
 
507
 
 
508
        /*
 
509
         * Formatting central directory file header fields that are fixed for all entries.
 
510
         * Fields not used (and therefor 0) are:
 
511
         *
 
512
         *   - comment_length
 
513
         *   - disk_number
 
514
         *   - attributes_internal
 
515
         */
 
516
        memset(&h, 0, sizeof(h));
 
517
        archive_le32enc(&h.signature, ZIP_SIGNATURE_FILE_HEADER);
 
518
        archive_le16enc(&h.version_by, ZIP_VERSION_BY);
 
519
        archive_le16enc(&h.version_extract, ZIP_VERSION_EXTRACT);
 
520
        archive_le16enc(&h.flags, ZIP_FLAGS);
 
521
 
 
522
        entries = 0;
 
523
        offset_start = zip->written_bytes;
 
524
 
 
525
        /* Formatting individual header fields per entry and
 
526
         * writing each entry. */
 
527
        while (l != NULL) {
 
528
                archive_le16enc(&h.compression, l->compression);
 
529
                archive_le32enc(&h.timedate, dos_time(archive_entry_mtime(l->entry)));
 
530
                archive_le32enc(&h.crc32, l->crc32);
 
531
                archive_le32enc(&h.compressed_size, l->compressed_size);
 
532
                archive_le32enc(&h.uncompressed_size, archive_entry_size(l->entry));
 
533
                archive_le16enc(&h.filename_length, (uint16_t)path_length(l->entry));
 
534
                archive_le16enc(&h.extra_length, sizeof(e));
 
535
                archive_le16enc(&h.attributes_external[2], archive_entry_mode(l->entry));
 
536
                archive_le32enc(&h.offset, l->offset);
 
537
 
 
538
                /* Formatting extra data. */
 
539
                archive_le16enc(&e.time_id, ZIP_SIGNATURE_EXTRA_TIMESTAMP);
 
540
                archive_le16enc(&e.time_size, sizeof(e.mtime) + sizeof(e.time_flag));
 
541
                e.time_flag[0] = 0x07;
 
542
                archive_le32enc(&e.mtime, archive_entry_mtime(l->entry));
 
543
                archive_le16enc(&e.unix_id, ZIP_SIGNATURE_EXTRA_UNIX);
 
544
                archive_le16enc(&e.unix_size, 0x0000);
 
545
 
 
546
                ret = (a->compressor.write)(a, &h, sizeof(h));
 
547
                if (ret != ARCHIVE_OK)
 
548
                        return (ARCHIVE_FATAL);
 
549
                zip->written_bytes += sizeof(h);
 
550
 
 
551
                ret = write_path(l->entry, a);
 
552
                if (ret <= ARCHIVE_OK)
 
553
                        return (ARCHIVE_FATAL);
 
554
                zip->written_bytes += ret;
 
555
 
 
556
                ret = (a->compressor.write)(a, &e, sizeof(e));
 
557
                if (ret != ARCHIVE_OK)
 
558
                        return (ARCHIVE_FATAL);
 
559
                zip->written_bytes += sizeof(e);
 
560
 
 
561
                l = l->next;
 
562
                entries++;
 
563
        }
 
564
        offset_end = zip->written_bytes;
 
565
 
 
566
        /* Formatting end of central directory. */
 
567
        memset(&end, 0, sizeof(end));
 
568
        archive_le32enc(&end.signature, ZIP_SIGNATURE_CENTRAL_DIRECTORY_END);
 
569
        archive_le16enc(&end.entries_disk, entries);
 
570
        archive_le16enc(&end.entries, entries);
 
571
        archive_le32enc(&end.size, offset_end - offset_start);
 
572
        archive_le32enc(&end.offset, offset_start);
 
573
 
 
574
        /* Writing end of central directory. */
 
575
        ret = (a->compressor.write)(a, &end, sizeof(end));
 
576
        if (ret != ARCHIVE_OK)
 
577
                return (ARCHIVE_FATAL);
 
578
        zip->written_bytes += sizeof(end);
 
579
        return (ARCHIVE_OK);
 
580
}
 
581
 
 
582
static int
 
583
archive_write_zip_destroy(struct archive_write *a)
 
584
{
 
585
        struct zip *zip;
 
586
        struct zip_file_header_link *l;
 
587
 
 
588
        zip = a->format_data;
 
589
        while (zip->central_directory != NULL) {
 
590
           l = zip->central_directory;
 
591
           zip->central_directory = l->next;
 
592
           archive_entry_free(l->entry);
 
593
           free(l);
 
594
        }
 
595
#ifdef HAVE_ZLIB_H
 
596
        free(zip->buf);
 
597
#endif
 
598
        free(zip);
 
599
        a->format_data = NULL;
 
600
        return (ARCHIVE_OK);
 
601
}
 
602
 
 
603
/* Convert into MSDOS-style date/time. */
 
604
static unsigned int
 
605
dos_time(const time_t unix_time)
 
606
{
 
607
        struct tm *t;
 
608
        unsigned int dt;
 
609
 
 
610
        /* This will not preserve time when creating/extracting the archive
 
611
         * on two systems with different time zones. */
 
612
        t = localtime(&unix_time);
 
613
 
 
614
        dt = 0;
 
615
        dt += ((t->tm_year - 80) & 0x7f) << 9;
 
616
        dt += ((t->tm_mon + 1) & 0x0f) << 5;
 
617
        dt += (t->tm_mday & 0x1f);
 
618
        dt <<= 16;
 
619
        dt += (t->tm_hour & 0x1f) << 11;
 
620
        dt += (t->tm_min & 0x3f) << 5;
 
621
        dt += (t->tm_sec & 0x3e) >> 1; /* Only counting every 2 seconds. */
 
622
        return dt;
 
623
}
 
624
 
 
625
static size_t
 
626
path_length(struct archive_entry *entry)
 
627
{
 
628
        mode_t type;
 
629
        const char *path;
 
630
 
 
631
        type = archive_entry_filetype(entry);
 
632
        path = archive_entry_pathname(entry);
 
633
 
 
634
        if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) {
 
635
                return strlen(path) + 1;
 
636
        } else {
 
637
                return strlen(path);
 
638
        }
 
639
}
 
640
 
 
641
static int
 
642
write_path(struct archive_entry *entry, struct archive_write *archive)
 
643
{
 
644
        int ret;
 
645
        const char *path;
 
646
        mode_t type;
 
647
        size_t written_bytes;
 
648
 
 
649
        path = archive_entry_pathname(entry);
 
650
        type = archive_entry_filetype(entry);
 
651
        written_bytes = 0;
 
652
 
 
653
        ret = (archive->compressor.write)(archive, path, strlen(path));
 
654
        if (ret != ARCHIVE_OK)
 
655
                return (ARCHIVE_FATAL);
 
656
        written_bytes += strlen(path);
 
657
 
 
658
        /* Folders are recognized by a traling slash. */
 
659
        if ((type == AE_IFDIR) & (path[strlen(path) - 1] != '/')) {
 
660
                ret = (archive->compressor.write)(archive, "/", 1);
 
661
                if (ret != ARCHIVE_OK)
 
662
                        return (ARCHIVE_FATAL);
 
663
                written_bytes += 1;
 
664
        }
 
665
 
 
666
        return ((int)written_bytes);
 
667
}