]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_write_set_format_7zip.c
MFC r299529,r299540,r299576,r299896:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / archive_write_set_format_7zip.c
1 /*-
2  * Copyright (c) 2011-2012 Michihiro NAKAJIMA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
28
29 #ifdef HAVE_ERRNO_H
30 #include <errno.h>
31 #endif
32 #include <stdlib.h>
33 #ifdef HAVE_BZLIB_H
34 #include <bzlib.h>
35 #endif
36 #if HAVE_LZMA_H
37 #include <lzma.h>
38 #endif
39 #ifdef HAVE_ZLIB_H
40 #include <zlib.h>
41 #endif
42
43 #include "archive.h"
44 #ifndef HAVE_ZLIB_H
45 #include "archive_crc32.h"
46 #endif
47 #include "archive_endian.h"
48 #include "archive_entry.h"
49 #include "archive_entry_locale.h"
50 #include "archive_ppmd7_private.h"
51 #include "archive_private.h"
52 #include "archive_rb.h"
53 #include "archive_string.h"
54 #include "archive_write_private.h"
55
56 /*
57  * Codec ID
58  */
59 #define _7Z_COPY        0
60 #define _7Z_LZMA1       0x030101
61 #define _7Z_LZMA2       0x21
62 #define _7Z_DEFLATE     0x040108
63 #define _7Z_BZIP2       0x040202
64 #define _7Z_PPMD        0x030401
65
66 /*
67  * 7-Zip header property IDs.
68  */
69 #define kEnd                    0x00
70 #define kHeader                 0x01
71 #define kArchiveProperties      0x02
72 #define kAdditionalStreamsInfo  0x03
73 #define kMainStreamsInfo        0x04
74 #define kFilesInfo              0x05
75 #define kPackInfo               0x06
76 #define kUnPackInfo             0x07
77 #define kSubStreamsInfo         0x08
78 #define kSize                   0x09
79 #define kCRC                    0x0A
80 #define kFolder                 0x0B
81 #define kCodersUnPackSize       0x0C
82 #define kNumUnPackStream        0x0D
83 #define kEmptyStream            0x0E
84 #define kEmptyFile              0x0F
85 #define kAnti                   0x10
86 #define kName                   0x11
87 #define kCTime                  0x12
88 #define kATime                  0x13
89 #define kMTime                  0x14
90 #define kAttributes             0x15
91 #define kEncodedHeader          0x17
92
93 enum la_zaction {
94         ARCHIVE_Z_FINISH,
95         ARCHIVE_Z_RUN
96 };
97
98 /*
99  * A stream object of universal compressor.
100  */
101 struct la_zstream {
102         const uint8_t           *next_in;
103         size_t                   avail_in;
104         uint64_t                 total_in;
105
106         uint8_t                 *next_out;
107         size_t                   avail_out;
108         uint64_t                 total_out;
109
110         uint32_t                 prop_size;
111         uint8_t                 *props;
112
113         int                      valid;
114         void                    *real_stream;
115         int                      (*code) (struct archive *a,
116                                     struct la_zstream *lastrm,
117                                     enum la_zaction action);
118         int                      (*end)(struct archive *a,
119                                     struct la_zstream *lastrm);
120 };
121
122 #define PPMD7_DEFAULT_ORDER     6
123 #define PPMD7_DEFAULT_MEM_SIZE  (1 << 24)
124
125 struct ppmd_stream {
126         int                      stat;
127         CPpmd7                   ppmd7_context;
128         CPpmd7z_RangeEnc         range_enc;
129         IByteOut                 byteout;
130         uint8_t                 *buff;
131         uint8_t                 *buff_ptr;
132         uint8_t                 *buff_end;
133         size_t                   buff_bytes;
134 };
135
136 struct coder {
137         unsigned                 codec;
138         size_t                   prop_size;
139         uint8_t                 *props;
140 };
141
142 struct file {
143         struct archive_rb_node   rbnode;
144
145         struct file             *next;
146         unsigned                 name_len;
147         uint8_t                 *utf16name;/* UTF16-LE name. */
148         uint64_t                 size;
149         unsigned                 flg;
150 #define MTIME_IS_SET    (1<<0)
151 #define ATIME_IS_SET    (1<<1)
152 #define CTIME_IS_SET    (1<<2)
153 #define CRC32_IS_SET    (1<<3)
154 #define HAS_STREAM      (1<<4)
155
156         struct {
157                 time_t           time;
158                 long             time_ns;
159         }                        times[3];
160 #define MTIME 0
161 #define ATIME 1
162 #define CTIME 2
163
164         mode_t                   mode;
165         uint32_t                 crc32;
166
167         int                      dir:1;
168 };
169
170 struct _7zip {
171         int                      temp_fd;
172         uint64_t                 temp_offset;
173
174         struct file             *cur_file;
175         size_t                   total_number_entry;
176         size_t                   total_number_nonempty_entry;
177         size_t                   total_number_empty_entry;
178         size_t                   total_number_dir_entry;
179         size_t                   total_bytes_entry_name;
180         size_t                   total_number_time_defined[3];
181         uint64_t                 total_bytes_compressed;
182         uint64_t                 total_bytes_uncompressed;
183         uint64_t                 entry_bytes_remaining;
184         uint32_t                 entry_crc32;
185         uint32_t                 precode_crc32;
186         uint32_t                 encoded_crc32;
187         int                      crc32flg;
188 #define PRECODE_CRC32   1
189 #define ENCODED_CRC32   2
190
191         unsigned                 opt_compression;
192         int                      opt_compression_level;
193
194         struct la_zstream        stream;
195         struct coder             coder;
196
197         struct archive_string_conv *sconv;
198
199         /*
200          * Compressed data buffer.
201          */
202         unsigned char            wbuff[512 * 20 * 6];
203         size_t                   wbuff_remaining;
204
205         /*
206          * The list of the file entries which has its contents is used to
207          * manage struct file objects.
208          * We use 'next' a menber of struct file to chain.
209          */
210         struct {
211                 struct file     *first;
212                 struct file     **last;
213         }                        file_list, empty_list;
214         struct archive_rb_tree   rbtree;/* for empty files */
215 };
216
217 static int      _7z_options(struct archive_write *,
218                     const char *, const char *);
219 static int      _7z_write_header(struct archive_write *,
220                     struct archive_entry *);
221 static ssize_t  _7z_write_data(struct archive_write *,
222                     const void *, size_t);
223 static int      _7z_finish_entry(struct archive_write *);
224 static int      _7z_close(struct archive_write *);
225 static int      _7z_free(struct archive_write *);
226 static int      file_cmp_node(const struct archive_rb_node *,
227                     const struct archive_rb_node *);
228 static int      file_cmp_key(const struct archive_rb_node *, const void *);
229 static int      file_new(struct archive_write *a, struct archive_entry *,
230                     struct file **);
231 static void     file_free(struct file *);
232 static void     file_register(struct _7zip *, struct file *);
233 static void     file_register_empty(struct _7zip *, struct file *);
234 static void     file_init_register(struct _7zip *);
235 static void     file_init_register_empty(struct _7zip *);
236 static void     file_free_register(struct _7zip *);
237 static ssize_t  compress_out(struct archive_write *, const void *, size_t ,
238                     enum la_zaction);
239 static int      compression_init_encoder_copy(struct archive *,
240                     struct la_zstream *);
241 static int      compression_code_copy(struct archive *,
242                     struct la_zstream *, enum la_zaction);
243 static int      compression_end_copy(struct archive *, struct la_zstream *);
244 static int      compression_init_encoder_deflate(struct archive *,
245                     struct la_zstream *, int, int);
246 #ifdef HAVE_ZLIB_H
247 static int      compression_code_deflate(struct archive *,
248                     struct la_zstream *, enum la_zaction);
249 static int      compression_end_deflate(struct archive *, struct la_zstream *);
250 #endif
251 static int      compression_init_encoder_bzip2(struct archive *,
252                     struct la_zstream *, int);
253 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
254 static int      compression_code_bzip2(struct archive *,
255                     struct la_zstream *, enum la_zaction);
256 static int      compression_end_bzip2(struct archive *, struct la_zstream *);
257 #endif
258 static int      compression_init_encoder_lzma1(struct archive *,
259                     struct la_zstream *, int);
260 static int      compression_init_encoder_lzma2(struct archive *,
261                     struct la_zstream *, int);
262 #if defined(HAVE_LZMA_H)
263 static int      compression_code_lzma(struct archive *,
264                     struct la_zstream *, enum la_zaction);
265 static int      compression_end_lzma(struct archive *, struct la_zstream *);
266 #endif
267 static int      compression_init_encoder_ppmd(struct archive *,
268                     struct la_zstream *, unsigned, uint32_t);
269 static int      compression_code_ppmd(struct archive *,
270                     struct la_zstream *, enum la_zaction);
271 static int      compression_end_ppmd(struct archive *, struct la_zstream *);
272 static int      _7z_compression_init_encoder(struct archive_write *, unsigned,
273                     int);
274 static int      compression_code(struct archive *,
275                     struct la_zstream *, enum la_zaction);
276 static int      compression_end(struct archive *,
277                     struct la_zstream *);
278 static int      enc_uint64(struct archive_write *, uint64_t);
279 static int      make_header(struct archive_write *, uint64_t, uint64_t,
280                     uint64_t, int, struct coder *);
281 static int      make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
282                         uint64_t, int, struct coder *, int, uint32_t);
283
284 int
285 archive_write_set_format_7zip(struct archive *_a)
286 {
287         static const struct archive_rb_tree_ops rb_ops = {
288                 file_cmp_node, file_cmp_key
289         };
290         struct archive_write *a = (struct archive_write *)_a;
291         struct _7zip *zip;
292
293         archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
294             ARCHIVE_STATE_NEW, "archive_write_set_format_7zip");
295
296         /* If another format was already registered, unregister it. */
297         if (a->format_free != NULL)
298                 (a->format_free)(a);
299
300         zip = calloc(1, sizeof(*zip));
301         if (zip == NULL) {
302                 archive_set_error(&a->archive, ENOMEM,
303                     "Can't allocate 7-Zip data");
304                 return (ARCHIVE_FATAL);
305         }
306         zip->temp_fd = -1;
307         __archive_rb_tree_init(&(zip->rbtree), &rb_ops);
308         file_init_register(zip);
309         file_init_register_empty(zip);
310
311         /* Set default compression type and its level. */
312 #if HAVE_LZMA_H
313         zip->opt_compression = _7Z_LZMA1;
314 #elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
315         zip->opt_compression = _7Z_BZIP2;
316 #elif defined(HAVE_ZLIB_H)
317         zip->opt_compression = _7Z_DEFLATE;
318 #else
319         zip->opt_compression = _7Z_COPY;
320 #endif
321         zip->opt_compression_level = 6;
322
323         a->format_data = zip;
324
325         a->format_name = "7zip";
326         a->format_options = _7z_options;
327         a->format_write_header = _7z_write_header;
328         a->format_write_data = _7z_write_data;
329         a->format_finish_entry = _7z_finish_entry;
330         a->format_close = _7z_close;
331         a->format_free = _7z_free;
332         a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
333         a->archive.archive_format_name = "7zip";
334
335         return (ARCHIVE_OK);
336 }
337
338 static int
339 _7z_options(struct archive_write *a, const char *key, const char *value)
340 {
341         struct _7zip *zip;
342
343         zip = (struct _7zip *)a->format_data;
344
345         if (strcmp(key, "compression") == 0) {
346                 const char *name = NULL;
347
348                 if (value == NULL || strcmp(value, "copy") == 0 ||
349                     strcmp(value, "COPY") == 0 ||
350                     strcmp(value, "store") == 0 ||
351                     strcmp(value, "STORE") == 0)
352                         zip->opt_compression = _7Z_COPY;
353                 else if (strcmp(value, "deflate") == 0 ||
354                     strcmp(value, "DEFLATE") == 0)
355 #if HAVE_ZLIB_H
356                         zip->opt_compression = _7Z_DEFLATE;
357 #else
358                         name = "deflate";
359 #endif
360                 else if (strcmp(value, "bzip2") == 0 ||
361                     strcmp(value, "BZIP2") == 0)
362 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
363                         zip->opt_compression = _7Z_BZIP2;
364 #else
365                         name = "bzip2";
366 #endif
367                 else if (strcmp(value, "lzma1") == 0 ||
368                     strcmp(value, "LZMA1") == 0)
369 #if HAVE_LZMA_H
370                         zip->opt_compression = _7Z_LZMA1;
371 #else
372                         name = "lzma1";
373 #endif
374                 else if (strcmp(value, "lzma2") == 0 ||
375                     strcmp(value, "LZMA2") == 0)
376 #if HAVE_LZMA_H
377                         zip->opt_compression = _7Z_LZMA2;
378 #else
379                         name = "lzma2";
380 #endif
381                 else if (strcmp(value, "ppmd") == 0 ||
382                     strcmp(value, "PPMD") == 0 ||
383                     strcmp(value, "PPMd") == 0)
384                         zip->opt_compression = _7Z_PPMD;
385                 else {
386                         archive_set_error(&(a->archive),
387                             ARCHIVE_ERRNO_MISC,
388                             "Unknown compression name: `%s'",
389                             value);
390                         return (ARCHIVE_FAILED);
391                 }
392                 if (name != NULL) {
393                         archive_set_error(&(a->archive),
394                             ARCHIVE_ERRNO_MISC,
395                             "`%s' compression not supported "
396                             "on this platform",
397                             name);
398                         return (ARCHIVE_FAILED);
399                 }
400                 return (ARCHIVE_OK);
401         }
402         if (strcmp(key, "compression-level") == 0) {
403                 if (value == NULL ||
404                     !(value[0] >= '0' && value[0] <= '9') ||
405                     value[1] != '\0') {
406                         archive_set_error(&(a->archive),
407                             ARCHIVE_ERRNO_MISC,
408                             "Illegal value `%s'",
409                             value);
410                         return (ARCHIVE_FAILED);
411                 }
412                 zip->opt_compression_level = value[0] - '0';
413                 return (ARCHIVE_OK);
414         }
415
416         /* Note: The "warn" return is just to inform the options
417          * supervisor that we didn't handle it.  It will generate
418          * a suitable error if no one used this option. */
419         return (ARCHIVE_WARN);
420 }
421
422 static int
423 _7z_write_header(struct archive_write *a, struct archive_entry *entry)
424 {
425         struct _7zip *zip;
426         struct file *file;
427         int r;
428
429         zip = (struct _7zip *)a->format_data;
430         zip->cur_file = NULL;
431         zip->entry_bytes_remaining = 0;
432
433         if (zip->sconv == NULL) {
434                 zip->sconv = archive_string_conversion_to_charset(
435                     &a->archive, "UTF-16LE", 1);
436                 if (zip->sconv == NULL)
437                         return (ARCHIVE_FATAL);
438         }
439
440         r = file_new(a, entry, &file);
441         if (r < ARCHIVE_WARN) {
442                 file_free(file);
443                 return (r);
444         }
445         if (file->size == 0 && file->dir) {
446                 if (!__archive_rb_tree_insert_node(&(zip->rbtree),
447                     (struct archive_rb_node *)file)) {
448                         /* We have already had the same file. */
449                         file_free(file);
450                         return (ARCHIVE_OK);
451                 }
452         }
453
454         if (file->flg & MTIME_IS_SET)
455                 zip->total_number_time_defined[MTIME]++;
456         if (file->flg & CTIME_IS_SET)
457                 zip->total_number_time_defined[CTIME]++;
458         if (file->flg & ATIME_IS_SET)
459                 zip->total_number_time_defined[ATIME]++;
460
461         zip->total_number_entry++;
462         zip->total_bytes_entry_name += file->name_len + 2;
463         if (file->size == 0) {
464                 /* Count up the number of empty files. */
465                 zip->total_number_empty_entry++;
466                 if (file->dir)
467                         zip->total_number_dir_entry++;
468                 else
469                         file_register_empty(zip, file);
470                 return (r);
471         }
472
473         /*
474          * Init compression.
475          */
476         if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
477                 r = _7z_compression_init_encoder(a, zip->opt_compression,
478                         zip->opt_compression_level);
479                 if (r < 0) {
480                         file_free(file);
481                         return (ARCHIVE_FATAL);
482                 }
483         }
484
485         /* Register a non-empty file. */
486         file_register(zip, file);
487
488         /*
489          * Set the current file to cur_file to read its contents.
490          */
491         zip->cur_file = file;
492
493
494         /* Save a offset of current file in temporary file. */
495         zip->entry_bytes_remaining = file->size;
496         zip->entry_crc32 = 0;
497
498         /*
499          * Store a symbolic link name as file contents.
500          */
501         if (archive_entry_filetype(entry) == AE_IFLNK) {
502                 ssize_t bytes;
503                 const void *p = (const void *)archive_entry_symlink(entry);
504                 bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
505                 if (bytes < 0)
506                         return ((int)bytes);
507                 zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
508                 zip->entry_bytes_remaining -= bytes;
509         }
510
511         return (r);
512 }
513
514 /*
515  * Write data to a temporary file.
516  */
517 static int
518 write_to_temp(struct archive_write *a, const void *buff, size_t s)
519 {
520         struct _7zip *zip;
521         const unsigned char *p;
522         ssize_t ws;
523
524         zip = (struct _7zip *)a->format_data;
525
526         /*
527          * Open a temporary file.
528          */
529         if (zip->temp_fd == -1) {
530                 zip->temp_offset = 0;
531                 zip->temp_fd = __archive_mktemp(NULL);
532                 if (zip->temp_fd < 0) {
533                         archive_set_error(&a->archive, errno,
534                             "Couldn't create temporary file");
535                         return (ARCHIVE_FATAL);
536                 }
537         }
538
539         p = (const unsigned char *)buff;
540         while (s) {
541                 ws = write(zip->temp_fd, p, s);
542                 if (ws < 0) {
543                         archive_set_error(&(a->archive), errno,
544                             "fwrite function failed");
545                         return (ARCHIVE_FATAL);
546                 }
547                 s -= ws;
548                 p += ws;
549                 zip->temp_offset += ws;
550         }
551         return (ARCHIVE_OK);
552 }
553
554 static ssize_t
555 compress_out(struct archive_write *a, const void *buff, size_t s,
556     enum la_zaction run)
557 {
558         struct _7zip *zip = (struct _7zip *)a->format_data;
559         int r;
560
561         if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
562                 return (0);
563
564         if ((zip->crc32flg & PRECODE_CRC32) && s)
565                 zip->precode_crc32 = crc32(zip->precode_crc32, buff,
566                     (unsigned)s);
567         zip->stream.next_in = (const unsigned char *)buff;
568         zip->stream.avail_in = s;
569         for (;;) {
570                 /* Compress file data. */
571                 r = compression_code(&(a->archive), &(zip->stream), run);
572                 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
573                         return (ARCHIVE_FATAL);
574                 if (zip->stream.avail_out == 0) {
575                         if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
576                             != ARCHIVE_OK)
577                                 return (ARCHIVE_FATAL);
578                         zip->stream.next_out = zip->wbuff;
579                         zip->stream.avail_out = sizeof(zip->wbuff);
580                         if (zip->crc32flg & ENCODED_CRC32)
581                                 zip->encoded_crc32 = crc32(zip->encoded_crc32,
582                                     zip->wbuff, sizeof(zip->wbuff));
583                         if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
584                                 continue;
585                 }
586                 if (zip->stream.avail_in == 0)
587                         break;
588         }
589         if (run == ARCHIVE_Z_FINISH) {
590                 uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
591                 if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
592                         return (ARCHIVE_FATAL);
593                 if ((zip->crc32flg & ENCODED_CRC32) && bytes)
594                         zip->encoded_crc32 = crc32(zip->encoded_crc32,
595                             zip->wbuff, (unsigned)bytes);
596         }
597
598         return (s);
599 }
600
601 static ssize_t
602 _7z_write_data(struct archive_write *a, const void *buff, size_t s)
603 {
604         struct _7zip *zip;
605         ssize_t bytes;
606
607         zip = (struct _7zip *)a->format_data;
608
609         if (s > zip->entry_bytes_remaining)
610                 s = (size_t)zip->entry_bytes_remaining;
611         if (s == 0 || zip->cur_file == NULL)
612                 return (0);
613         bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
614         if (bytes < 0)
615                 return (bytes);
616         zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
617         zip->entry_bytes_remaining -= bytes;
618         return (bytes);
619 }
620
621 static int
622 _7z_finish_entry(struct archive_write *a)
623 {
624         struct _7zip *zip;
625         size_t s;
626         ssize_t r;
627
628         zip = (struct _7zip *)a->format_data;
629         if (zip->cur_file == NULL)
630                 return (ARCHIVE_OK);
631
632         while (zip->entry_bytes_remaining > 0) {
633                 s = (size_t)zip->entry_bytes_remaining;
634                 if (s > a->null_length)
635                         s = a->null_length;
636                 r = _7z_write_data(a, a->nulls, s);
637                 if (r < 0)
638                         return ((int)r);
639         }
640         zip->total_bytes_compressed += zip->stream.total_in;
641         zip->total_bytes_uncompressed += zip->stream.total_out;
642         zip->cur_file->crc32 = zip->entry_crc32;
643         zip->cur_file = NULL;
644
645         return (ARCHIVE_OK);
646 }
647
648 static int
649 flush_wbuff(struct archive_write *a)
650 {
651         struct _7zip *zip;
652         int r;
653         size_t s;
654
655         zip = (struct _7zip *)a->format_data;
656         s = sizeof(zip->wbuff) - zip->wbuff_remaining;
657         r = __archive_write_output(a, zip->wbuff, s);
658         if (r != ARCHIVE_OK)
659                 return (r);
660         zip->wbuff_remaining = sizeof(zip->wbuff);
661         return (r);
662 }
663
664 static int
665 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
666 {
667         struct _7zip *zip;
668         int r;
669
670         zip = (struct _7zip *)a->format_data;
671         if (zip->temp_offset > 0 &&
672             lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
673                 archive_set_error(&(a->archive), errno, "lseek failed");
674                 return (ARCHIVE_FATAL);
675         }
676         while (length) {
677                 size_t rsize;
678                 ssize_t rs;
679                 unsigned char *wb;
680
681                 if (length > zip->wbuff_remaining)
682                         rsize = zip->wbuff_remaining;
683                 else
684                         rsize = (size_t)length;
685                 wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
686                 rs = read(zip->temp_fd, wb, rsize);
687                 if (rs < 0) {
688                         archive_set_error(&(a->archive), errno,
689                             "Can't read temporary file(%jd)",
690                             (intmax_t)rs);
691                         return (ARCHIVE_FATAL);
692                 }
693                 if (rs == 0) {
694                         archive_set_error(&(a->archive), 0,
695                             "Truncated 7-Zip archive");
696                         return (ARCHIVE_FATAL);
697                 }
698                 zip->wbuff_remaining -= rs;
699                 length -= rs;
700                 if (zip->wbuff_remaining == 0) {
701                         r = flush_wbuff(a);
702                         if (r != ARCHIVE_OK)
703                                 return (r);
704                 }
705         }
706         return (ARCHIVE_OK);
707 }
708
709 static int
710 _7z_close(struct archive_write *a)
711 {
712         struct _7zip *zip;
713         unsigned char *wb;
714         uint64_t header_offset, header_size, header_unpacksize;
715         uint64_t length;
716         uint32_t header_crc32;
717         int r;
718
719         zip = (struct _7zip *)a->format_data;
720
721         if (zip->total_number_entry > 0) {
722                 struct archive_rb_node *n;
723                 uint64_t data_offset, data_size, data_unpacksize;
724                 unsigned header_compression;
725
726                 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
727                 if (r < 0)
728                         return (r);
729                 data_offset = 0;
730                 data_size = zip->stream.total_out;
731                 data_unpacksize = zip->stream.total_in;
732                 zip->coder.codec = zip->opt_compression;
733                 zip->coder.prop_size = zip->stream.prop_size;
734                 zip->coder.props = zip->stream.props;
735                 zip->stream.prop_size = 0;
736                 zip->stream.props = NULL;
737                 zip->total_number_nonempty_entry =
738                     zip->total_number_entry - zip->total_number_empty_entry;
739
740                 /* Connect an empty file list. */
741                 if (zip->empty_list.first != NULL) {
742                         *zip->file_list.last = zip->empty_list.first;
743                         zip->file_list.last = zip->empty_list.last;
744                 }
745                 /* Connect a directory file list. */
746                 ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
747                         file_register(zip, (struct file *)n);
748                 }
749
750                 /*
751                  * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
752                  * the compression type for encoding the header.
753                  */
754 #if HAVE_LZMA_H
755                 header_compression = _7Z_LZMA1;
756                 /* If the stored file is only one, do not encode the header.
757                  * This is the same way 7z command does. */
758                 if (zip->total_number_entry == 1)
759                         header_compression = _7Z_COPY;
760 #else
761                 header_compression = _7Z_COPY;
762 #endif
763                 r = _7z_compression_init_encoder(a, header_compression, 6);
764                 if (r < 0)
765                         return (r);
766                 zip->crc32flg = PRECODE_CRC32;
767                 zip->precode_crc32 = 0;
768                 r = make_header(a, data_offset, data_size, data_unpacksize,
769                         1, &(zip->coder));
770                 if (r < 0)
771                         return (r);
772                 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
773                 if (r < 0)
774                         return (r);
775                 header_offset = data_offset + data_size;
776                 header_size = zip->stream.total_out;
777                 header_crc32 = zip->precode_crc32;
778                 header_unpacksize = zip->stream.total_in;
779
780                 if (header_compression != _7Z_COPY) {
781                         /*
782                          * Encode the header in order to reduce the size
783                          * of the archive.
784                          */
785                         free(zip->coder.props);
786                         zip->coder.codec = header_compression;
787                         zip->coder.prop_size = zip->stream.prop_size;
788                         zip->coder.props = zip->stream.props;
789                         zip->stream.prop_size = 0;
790                         zip->stream.props = NULL;
791
792                         r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
793                         if (r < 0)
794                                 return (r);
795                         zip->crc32flg = ENCODED_CRC32;
796                         zip->encoded_crc32 = 0;
797
798                         /*
799                          * Make EncodedHeader.
800                          */
801                         r = enc_uint64(a, kEncodedHeader);
802                         if (r < 0)
803                                 return (r);
804                         r = make_streamsInfo(a, header_offset, header_size,
805                               header_unpacksize, 1, &(zip->coder), 0,
806                               header_crc32);
807                         if (r < 0)
808                                 return (r);
809                         r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
810                         if (r < 0)
811                                 return (r);
812                         header_offset = header_offset + header_size;
813                         header_size = zip->stream.total_out;
814                         header_crc32 = zip->encoded_crc32;
815                 }
816                 zip->crc32flg = 0;
817         } else {
818                 header_offset = header_size = 0;
819                 header_crc32 = 0;
820         }
821         
822         length = zip->temp_offset;
823
824         /*
825          * Make the zip header on wbuff(write buffer).
826          */
827         wb = zip->wbuff;
828         zip->wbuff_remaining = sizeof(zip->wbuff);
829         memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
830         wb[6] = 0;/* Major version. */
831         wb[7] = 3;/* Minor version. */
832         archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
833         archive_le64enc(&wb[20], header_size);/* Next Header Size */
834         archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
835         archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
836         zip->wbuff_remaining -= 32;
837
838         /*
839          * Read all file contents and an encoded header from the temporary
840          * file and write out it.
841          */
842         r = copy_out(a, 0, length);
843         if (r != ARCHIVE_OK)
844                 return (r);
845         r = flush_wbuff(a);
846         return (r);
847 }
848
849 /*
850  * Encode 64 bits value into 7-Zip's encoded UINT64 value.
851  */
852 static int
853 enc_uint64(struct archive_write *a, uint64_t val)
854 {
855         unsigned mask = 0x80;
856         uint8_t numdata[9];
857         int i;
858
859         numdata[0] = 0;
860         for (i = 1; i < (int)sizeof(numdata); i++) {
861                 if (val < mask) {
862                         numdata[0] |= (uint8_t)val;
863                         break;
864                 }
865                 numdata[i] = (uint8_t)val;
866                 val >>= 8;
867                 numdata[0] |= mask;
868                 mask >>= 1;
869         }
870         return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
871 }
872
873 static int
874 make_substreamsInfo(struct archive_write *a, struct coder *coders)
875 {
876         struct _7zip *zip = (struct _7zip *)a->format_data;
877         struct file *file;
878         int r;
879
880         /*
881          * Make SubStreamsInfo.
882          */
883         r = enc_uint64(a, kSubStreamsInfo);
884         if (r < 0)
885                 return (r);
886
887         if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
888                 /*
889                  * Make NumUnPackStream.
890                  */
891                 r = enc_uint64(a, kNumUnPackStream);
892                 if (r < 0)
893                         return (r);
894
895                 /* Write numUnpackStreams */
896                 r = enc_uint64(a, zip->total_number_nonempty_entry);
897                 if (r < 0)
898                         return (r);
899
900                 /*
901                  * Make kSize.
902                  */
903                 r = enc_uint64(a, kSize);
904                 if (r < 0)
905                         return (r);
906                 file = zip->file_list.first;
907                 for (;file != NULL; file = file->next) {
908                         if (file->next == NULL ||
909                             file->next->size == 0)
910                                 break;
911                         r = enc_uint64(a, file->size);
912                         if (r < 0)
913                                 return (r);
914                 }
915         }
916
917         /*
918          * Make CRC.
919          */
920         r = enc_uint64(a, kCRC);
921         if (r < 0)
922                 return (r);
923
924
925         /* All are defined */
926         r = enc_uint64(a, 1);
927         if (r < 0)
928                 return (r);
929         file = zip->file_list.first;
930         for (;file != NULL; file = file->next) {
931                 uint8_t crc[4];
932                 if (file->size == 0)
933                         break;
934                 archive_le32enc(crc, file->crc32);
935                 r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
936                 if (r < 0)
937                         return (r);
938         }
939
940         /* Write End. */
941         r = enc_uint64(a, kEnd);
942         if (r < 0)
943                 return (r);
944         return (ARCHIVE_OK);
945 }
946
947 static int
948 make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
949     uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
950     uint32_t header_crc)
951 {
952         struct _7zip *zip = (struct _7zip *)a->format_data;
953         uint8_t codec_buff[8];
954         int numFolders, fi;
955         int codec_size;
956         int i, r;
957
958         if (coders->codec == _7Z_COPY)
959                 numFolders = (int)zip->total_number_nonempty_entry;
960         else
961                 numFolders = 1;
962
963         /*
964          * Make PackInfo.
965          */
966         r = enc_uint64(a, kPackInfo);
967         if (r < 0)
968                 return (r);
969
970         /* Write PackPos. */
971         r = enc_uint64(a, offset);
972         if (r < 0)
973                 return (r);
974
975         /* Write NumPackStreams. */
976         r = enc_uint64(a, numFolders);
977         if (r < 0)
978                 return (r);
979
980         /* Make Size. */
981         r = enc_uint64(a, kSize);
982         if (r < 0)
983                 return (r);
984
985         if (numFolders > 1) {
986                 struct file *file = zip->file_list.first;
987                 for (;file != NULL; file = file->next) {
988                         if (file->size == 0)
989                                 break;
990                         r = enc_uint64(a, file->size);
991                         if (r < 0)
992                                 return (r);
993                 }
994         } else {
995                 /* Write size. */
996                 r = enc_uint64(a, pack_size);
997                 if (r < 0)
998                         return (r);
999         }
1000
1001         r = enc_uint64(a, kEnd);
1002         if (r < 0)
1003                 return (r);
1004
1005         /*
1006          * Make UnPackInfo.
1007          */
1008         r = enc_uint64(a, kUnPackInfo);
1009         if (r < 0)
1010                 return (r);
1011
1012         /*
1013          * Make Folder.
1014          */
1015         r = enc_uint64(a, kFolder);
1016         if (r < 0)
1017                 return (r);
1018
1019         /* Write NumFolders. */
1020         r = enc_uint64(a, numFolders);
1021         if (r < 0)
1022                 return (r);
1023
1024         /* Write External. */
1025         r = enc_uint64(a, 0);
1026         if (r < 0)
1027                 return (r);
1028
1029         for (fi = 0; fi < numFolders; fi++) {
1030                 /* Write NumCoders. */
1031                 r = enc_uint64(a, num_coder);
1032                 if (r < 0)
1033                         return (r);
1034
1035                 for (i = 0; i < num_coder; i++) {
1036                         unsigned codec_id = coders[i].codec;
1037
1038                         /* Write Codec flag. */
1039                         archive_be64enc(codec_buff, codec_id);
1040                         for (codec_size = 8; codec_size > 0; codec_size--) {
1041                                 if (codec_buff[8 - codec_size])
1042                                         break;
1043                         }
1044                         if (codec_size == 0)
1045                                 codec_size = 1;
1046                         if (coders[i].prop_size)
1047                                 r = enc_uint64(a, codec_size | 0x20);
1048                         else
1049                                 r = enc_uint64(a, codec_size);
1050                         if (r < 0)
1051                                 return (r);
1052
1053                         /* Write Codec ID. */
1054                         codec_size &= 0x0f;
1055                         r = (int)compress_out(a, &codec_buff[8-codec_size],
1056                                 codec_size, ARCHIVE_Z_RUN);
1057                         if (r < 0)
1058                                 return (r);
1059
1060                         if (coders[i].prop_size) {
1061                                 /* Write Codec property size. */
1062                                 r = enc_uint64(a, coders[i].prop_size);
1063                                 if (r < 0)
1064                                         return (r);
1065
1066                                 /* Write Codec properties. */
1067                                 r = (int)compress_out(a, coders[i].props,
1068                                         coders[i].prop_size, ARCHIVE_Z_RUN);
1069                                 if (r < 0)
1070                                         return (r);
1071                         }
1072                 }
1073         }
1074
1075         /*
1076          * Make CodersUnPackSize.
1077          */
1078         r = enc_uint64(a, kCodersUnPackSize);
1079         if (r < 0)
1080                 return (r);
1081
1082         if (numFolders > 1) {
1083                 struct file *file = zip->file_list.first;
1084                 for (;file != NULL; file = file->next) {
1085                         if (file->size == 0)
1086                                 break;
1087                         r = enc_uint64(a, file->size);
1088                         if (r < 0)
1089                                 return (r);
1090                 }
1091
1092         } else {
1093                 /* Write UnPackSize. */
1094                 r = enc_uint64(a, unpack_size);
1095                 if (r < 0)
1096                         return (r);
1097         }
1098
1099         if (!substrm) {
1100                 uint8_t crc[4];
1101                 /*
1102                  * Make CRC.
1103                  */
1104                 r = enc_uint64(a, kCRC);
1105                 if (r < 0)
1106                         return (r);
1107
1108                 /* All are defined */
1109                 r = enc_uint64(a, 1);
1110                 if (r < 0)
1111                         return (r);
1112                 archive_le32enc(crc, header_crc);
1113                 r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
1114                 if (r < 0)
1115                         return (r);
1116         }
1117
1118         /* Write End. */
1119         r = enc_uint64(a, kEnd);
1120         if (r < 0)
1121                 return (r);
1122
1123         if (substrm) {
1124                 /*
1125                  * Make SubStreamsInfo.
1126                  */
1127                 r = make_substreamsInfo(a, coders);
1128                 if (r < 0)
1129                         return (r);
1130         }
1131
1132
1133         /* Write End. */
1134         r = enc_uint64(a, kEnd);
1135         if (r < 0)
1136                 return (r);
1137
1138         return (ARCHIVE_OK);
1139 }
1140
1141
1142 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1143 static uint64_t
1144 utcToFiletime(time_t t, long ns)
1145 {
1146         uint64_t fileTime;
1147
1148         fileTime = t;
1149         fileTime *= 10000000;
1150         fileTime += ns / 100;
1151         fileTime += EPOC_TIME;
1152         return (fileTime);
1153 }
1154
1155 static int
1156 make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
1157 {
1158         uint8_t filetime[8];
1159         struct _7zip *zip = (struct _7zip *)a->format_data;
1160         struct file *file;
1161         int r;
1162         uint8_t b, mask;
1163
1164         /*
1165          * Make Time Bools.
1166          */
1167         if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
1168                 /* Write Time Type. */
1169                 r = enc_uint64(a, type);
1170                 if (r < 0)
1171                         return (r);
1172                 /* Write EmptyStream Size. */
1173                 r = enc_uint64(a, 2 + zip->total_number_entry * 8);
1174                 if (r < 0)
1175                         return (r);
1176                 /* All are defined. */
1177                 r = enc_uint64(a, 1);
1178                 if (r < 0)
1179                         return (r);
1180         } else {
1181                 if (zip->total_number_time_defined[ti] == 0)
1182                         return (ARCHIVE_OK);
1183
1184                 /* Write Time Type. */
1185                 r = enc_uint64(a, type);
1186                 if (r < 0)
1187                         return (r);
1188                 /* Write EmptyStream Size. */
1189                 r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
1190                         + zip->total_number_time_defined[ti] * 8);
1191                 if (r < 0)
1192                         return (r);
1193
1194                 /* All are not defined. */
1195                 r = enc_uint64(a, 0);
1196                 if (r < 0)
1197                         return (r);
1198
1199                 b = 0;
1200                 mask = 0x80;
1201                 file = zip->file_list.first;
1202                 for (;file != NULL; file = file->next) {
1203                         if (file->flg & flg)
1204                                 b |= mask;
1205                         mask >>= 1;
1206                         if (mask == 0) {
1207                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1208                                 if (r < 0)
1209                                         return (r);
1210                                 mask = 0x80;
1211                                 b = 0;
1212                         }
1213                 }
1214                 if (mask != 0x80) {
1215                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1216                         if (r < 0)
1217                                 return (r);
1218                 }
1219         }
1220
1221         /* External. */
1222         r = enc_uint64(a, 0);
1223         if (r < 0)
1224                 return (r);
1225
1226
1227         /*
1228          * Make Times.
1229          */
1230         file = zip->file_list.first;
1231         for (;file != NULL; file = file->next) {
1232                 if ((file->flg & flg) == 0)
1233                         continue;
1234                 archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
1235                         file->times[ti].time_ns));
1236                 r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
1237                 if (r < 0)
1238                         return (r);
1239         }
1240
1241         return (ARCHIVE_OK);
1242 }
1243
1244 static int
1245 make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
1246     uint64_t unpack_size, int codernum, struct coder *coders)
1247 {
1248         struct _7zip *zip = (struct _7zip *)a->format_data;
1249         struct file *file;
1250         int r;
1251         uint8_t b, mask;
1252
1253         /*
1254          * Make FilesInfo.
1255          */
1256         r = enc_uint64(a, kHeader);
1257         if (r < 0)
1258                 return (r);
1259
1260         /*
1261          * If there are empty files only, do not write MainStreamInfo.
1262          */
1263         if (zip->total_number_nonempty_entry) {
1264                 /*
1265                  * Make MainStreamInfo.
1266                  */
1267                 r = enc_uint64(a, kMainStreamsInfo);
1268                 if (r < 0)
1269                         return (r);
1270                 r = make_streamsInfo(a, offset, pack_size, unpack_size,
1271                       codernum, coders, 1, 0);
1272                 if (r < 0)
1273                         return (r);
1274         }
1275
1276         /*
1277          * Make FilesInfo.
1278          */
1279         r = enc_uint64(a, kFilesInfo);
1280         if (r < 0)
1281                 return (r);
1282
1283         /* Write numFiles. */
1284         r = enc_uint64(a, zip->total_number_entry);
1285         if (r < 0)
1286                 return (r);
1287
1288         if (zip->total_number_empty_entry > 0) {
1289                 /* Make EmptyStream. */
1290                 r = enc_uint64(a, kEmptyStream);
1291                 if (r < 0)
1292                         return (r);
1293
1294                 /* Write EmptyStream Size. */
1295                 r = enc_uint64(a, (zip->total_number_entry+7)>>3);
1296                 if (r < 0)
1297                         return (r);
1298
1299                 b = 0;
1300                 mask = 0x80;
1301                 file = zip->file_list.first;
1302                 for (;file != NULL; file = file->next) {
1303                         if (file->size == 0)
1304                                 b |= mask;
1305                         mask >>= 1;
1306                         if (mask == 0) {
1307                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1308                                 if (r < 0)
1309                                         return (r);
1310                                 mask = 0x80;
1311                                 b = 0;
1312                         }
1313                 }
1314                 if (mask != 0x80) {
1315                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1316                         if (r < 0)
1317                                 return (r);
1318                 }
1319         }
1320
1321         if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
1322                 /* Make EmptyFile. */
1323                 r = enc_uint64(a, kEmptyFile);
1324                 if (r < 0)
1325                         return (r);
1326
1327                 /* Write EmptyFile Size. */
1328                 r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
1329                 if (r < 0)
1330                         return (r);
1331
1332                 b = 0;
1333                 mask = 0x80;
1334                 file = zip->file_list.first;
1335                 for (;file != NULL; file = file->next) {
1336                         if (file->size)
1337                                 continue;
1338                         if (!file->dir)
1339                                 b |= mask;
1340                         mask >>= 1;
1341                         if (mask == 0) {
1342                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1343                                 if (r < 0)
1344                                         return (r);
1345                                 mask = 0x80;
1346                                 b = 0;
1347                         }
1348                 }
1349                 if (mask != 0x80) {
1350                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1351                         if (r < 0)
1352                                 return (r);
1353                 }
1354         }
1355
1356         /* Make Name. */
1357         r = enc_uint64(a, kName);
1358         if (r < 0)
1359                 return (r);
1360
1361         /* Write Nume size. */
1362         r = enc_uint64(a, zip->total_bytes_entry_name+1);
1363         if (r < 0)
1364                 return (r);
1365
1366         /* Write dmy byte. */
1367         r = enc_uint64(a, 0);
1368         if (r < 0)
1369                 return (r);
1370
1371         file = zip->file_list.first;
1372         for (;file != NULL; file = file->next) {
1373                 r = (int)compress_out(a, file->utf16name, file->name_len+2,
1374                         ARCHIVE_Z_RUN);
1375                 if (r < 0)
1376                         return (r);
1377         }
1378
1379         /* Make MTime. */
1380         r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
1381         if (r < 0)
1382                 return (r);
1383
1384         /* Make CTime. */
1385         r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
1386         if (r < 0)
1387                 return (r);
1388
1389         /* Make ATime. */
1390         r = make_time(a, kATime, ATIME_IS_SET, ATIME);
1391         if (r < 0)
1392                 return (r);
1393
1394         /* Make Attributes. */
1395         r = enc_uint64(a, kAttributes);
1396         if (r < 0)
1397                 return (r);
1398
1399         /* Write Attributes size. */
1400         r = enc_uint64(a, 2 + zip->total_number_entry * 4);
1401         if (r < 0)
1402                 return (r);
1403
1404         /* Write "All Are Defined". */
1405         r = enc_uint64(a, 1);
1406         if (r < 0)
1407                 return (r);
1408
1409         /* Write dmy byte. */
1410         r = enc_uint64(a, 0);
1411         if (r < 0)
1412                 return (r);
1413
1414         file = zip->file_list.first;
1415         for (;file != NULL; file = file->next) {
1416                 /*
1417                  * High 16bits is unix mode.
1418                  * Low 16bits is Windows attributes.
1419                  */
1420                 uint32_t encattr, attr;
1421                 if (file->dir)
1422                         attr = 0x8010;
1423                 else
1424                         attr = 0x8020;
1425                 if ((file->mode & 0222) == 0)
1426                         attr |= 1;/* Read Only. */
1427                 attr |= ((uint32_t)file->mode) << 16;
1428                 archive_le32enc(&encattr, attr);
1429                 r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
1430                 if (r < 0)
1431                         return (r);
1432         }
1433
1434         /* Write End. */
1435         r = enc_uint64(a, kEnd);
1436         if (r < 0)
1437                 return (r);
1438
1439         /* Write End. */
1440         r = enc_uint64(a, kEnd);
1441         if (r < 0)
1442                 return (r);
1443
1444         return (ARCHIVE_OK);
1445 }
1446
1447
1448 static int
1449 _7z_free(struct archive_write *a)
1450 {
1451         struct _7zip *zip = (struct _7zip *)a->format_data;
1452
1453         /* Close the temporary file. */
1454         if (zip->temp_fd >= 0)
1455                 close(zip->temp_fd);
1456
1457         file_free_register(zip);
1458         compression_end(&(a->archive), &(zip->stream));
1459         free(zip->coder.props);
1460         free(zip);
1461
1462         return (ARCHIVE_OK);
1463 }
1464
1465 static int
1466 file_cmp_node(const struct archive_rb_node *n1,
1467     const struct archive_rb_node *n2)
1468 {
1469         const struct file *f1 = (const struct file *)n1;
1470         const struct file *f2 = (const struct file *)n2;
1471
1472         if (f1->name_len == f2->name_len)
1473                 return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
1474         return (f1->name_len > f2->name_len)?1:-1;
1475 }
1476         
1477 static int
1478 file_cmp_key(const struct archive_rb_node *n, const void *key)
1479 {
1480         const struct file *f = (const struct file *)n;
1481
1482         return (f->name_len - *(const char *)key);
1483 }
1484
1485 static int
1486 file_new(struct archive_write *a, struct archive_entry *entry,
1487     struct file **newfile)
1488 {
1489         struct _7zip *zip;
1490         struct file *file;
1491         const char *u16;
1492         size_t u16len;
1493         int ret = ARCHIVE_OK;
1494
1495         zip = (struct _7zip *)a->format_data;
1496         *newfile = NULL;
1497
1498         file = calloc(1, sizeof(*file));
1499         if (file == NULL) {
1500                 archive_set_error(&a->archive, ENOMEM,
1501                     "Can't allocate memory");
1502                 return (ARCHIVE_FATAL);
1503         }
1504
1505         if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
1506                 if (errno == ENOMEM) {
1507                         free(file);
1508                         archive_set_error(&a->archive, ENOMEM,
1509                             "Can't allocate memory for UTF-16LE");
1510                         return (ARCHIVE_FATAL);
1511                 }
1512                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1513                     "A filename cannot be converted to UTF-16LE;"
1514                     "You should disable making Joliet extension");
1515                 ret = ARCHIVE_WARN;
1516         }
1517         file->utf16name = malloc(u16len + 2);
1518         if (file->utf16name == NULL) {
1519                 free(file);
1520                 archive_set_error(&a->archive, ENOMEM,
1521                     "Can't allocate memory for Name");
1522                 return (ARCHIVE_FATAL);
1523         }
1524         memcpy(file->utf16name, u16, u16len);
1525         file->utf16name[u16len+0] = 0;
1526         file->utf16name[u16len+1] = 0;
1527         file->name_len = (unsigned)u16len;
1528         file->mode = archive_entry_mode(entry);
1529         if (archive_entry_filetype(entry) == AE_IFREG)
1530                 file->size = archive_entry_size(entry);
1531         else
1532                 archive_entry_set_size(entry, 0);
1533         if (archive_entry_filetype(entry) == AE_IFDIR)
1534                 file->dir = 1;
1535         else if (archive_entry_filetype(entry) == AE_IFLNK)
1536                 file->size = strlen(archive_entry_symlink(entry));
1537         if (archive_entry_mtime_is_set(entry)) {
1538                 file->flg |= MTIME_IS_SET;
1539                 file->times[MTIME].time = archive_entry_mtime(entry);
1540                 file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
1541         }
1542         if (archive_entry_atime_is_set(entry)) {
1543                 file->flg |= ATIME_IS_SET;
1544                 file->times[ATIME].time = archive_entry_atime(entry);
1545                 file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
1546         }
1547         if (archive_entry_ctime_is_set(entry)) {
1548                 file->flg |= CTIME_IS_SET;
1549                 file->times[CTIME].time = archive_entry_ctime(entry);
1550                 file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
1551         }
1552
1553         *newfile = file;
1554         return (ret);
1555 }
1556
1557 static void
1558 file_free(struct file *file)
1559 {
1560         free(file->utf16name);
1561         free(file);
1562 }
1563
1564 static void
1565 file_register(struct _7zip *zip, struct file *file)
1566 {
1567         file->next = NULL;
1568         *zip->file_list.last = file;
1569         zip->file_list.last = &(file->next);
1570 }
1571
1572 static void
1573 file_init_register(struct _7zip *zip)
1574 {
1575         zip->file_list.first = NULL;
1576         zip->file_list.last = &(zip->file_list.first);
1577 }
1578
1579 static void
1580 file_free_register(struct _7zip *zip)
1581 {
1582         struct file *file, *file_next;
1583
1584         file = zip->file_list.first;
1585         while (file != NULL) {
1586                 file_next = file->next;
1587                 file_free(file);
1588                 file = file_next;
1589         }
1590 }
1591
1592 static void
1593 file_register_empty(struct _7zip *zip, struct file *file)
1594 {
1595         file->next = NULL;
1596         *zip->empty_list.last = file;
1597         zip->empty_list.last = &(file->next);
1598 }
1599
1600 static void
1601 file_init_register_empty(struct _7zip *zip)
1602 {
1603         zip->empty_list.first = NULL;
1604         zip->empty_list.last = &(zip->empty_list.first);
1605 }
1606
1607 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
1608          !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
1609 static int
1610 compression_unsupported_encoder(struct archive *a,
1611     struct la_zstream *lastrm, const char *name)
1612 {
1613
1614         archive_set_error(a, ARCHIVE_ERRNO_MISC,
1615             "%s compression not supported on this platform", name);
1616         lastrm->valid = 0;
1617         lastrm->real_stream = NULL;
1618         return (ARCHIVE_FAILED);
1619 }
1620 #endif
1621
1622 /*
1623  * _7_COPY compressor.
1624  */
1625 static int
1626 compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
1627 {
1628
1629         if (lastrm->valid)
1630                 compression_end(a, lastrm);
1631         lastrm->valid = 1;
1632         lastrm->code = compression_code_copy;
1633         lastrm->end = compression_end_copy;
1634         return (ARCHIVE_OK);
1635 }
1636
1637 static int
1638 compression_code_copy(struct archive *a,
1639     struct la_zstream *lastrm, enum la_zaction action)
1640 {
1641         size_t bytes;
1642
1643         (void)a; /* UNUSED */
1644         if (lastrm->avail_out > lastrm->avail_in)
1645                 bytes = lastrm->avail_in;
1646         else
1647                 bytes = lastrm->avail_out;
1648         if (bytes) {
1649                 memcpy(lastrm->next_out, lastrm->next_in, bytes);
1650                 lastrm->next_in += bytes;
1651                 lastrm->avail_in -= bytes;
1652                 lastrm->total_in += bytes;
1653                 lastrm->next_out += bytes;
1654                 lastrm->avail_out -= bytes;
1655                 lastrm->total_out += bytes;
1656         }
1657         if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
1658                 return (ARCHIVE_EOF);
1659         return (ARCHIVE_OK);
1660 }
1661
1662 static int
1663 compression_end_copy(struct archive *a, struct la_zstream *lastrm)
1664 {
1665         (void)a; /* UNUSED */
1666         lastrm->valid = 0;
1667         return (ARCHIVE_OK);
1668 }
1669
1670 /*
1671  * _7_DEFLATE compressor.
1672  */
1673 #ifdef HAVE_ZLIB_H
1674 static int
1675 compression_init_encoder_deflate(struct archive *a,
1676     struct la_zstream *lastrm, int level, int withheader)
1677 {
1678         z_stream *strm;
1679
1680         if (lastrm->valid)
1681                 compression_end(a, lastrm);
1682         strm = calloc(1, sizeof(*strm));
1683         if (strm == NULL) {
1684                 archive_set_error(a, ENOMEM,
1685                     "Can't allocate memory for gzip stream");
1686                 return (ARCHIVE_FATAL);
1687         }
1688         /* zlib.h is not const-correct, so we need this one bit
1689          * of ugly hackery to convert a const * pointer to
1690          * a non-const pointer. */
1691         strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1692         strm->avail_in = (uInt)lastrm->avail_in;
1693         strm->total_in = (uLong)lastrm->total_in;
1694         strm->next_out = lastrm->next_out;
1695         strm->avail_out = (uInt)lastrm->avail_out;
1696         strm->total_out = (uLong)lastrm->total_out;
1697         if (deflateInit2(strm, level, Z_DEFLATED,
1698             (withheader)?15:-15,
1699             8, Z_DEFAULT_STRATEGY) != Z_OK) {
1700                 free(strm);
1701                 lastrm->real_stream = NULL;
1702                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1703                     "Internal error initializing compression library");
1704                 return (ARCHIVE_FATAL);
1705         }
1706         lastrm->real_stream = strm;
1707         lastrm->valid = 1;
1708         lastrm->code = compression_code_deflate;
1709         lastrm->end = compression_end_deflate;
1710         return (ARCHIVE_OK);
1711 }
1712
1713 static int
1714 compression_code_deflate(struct archive *a,
1715     struct la_zstream *lastrm, enum la_zaction action)
1716 {
1717         z_stream *strm;
1718         int r;
1719
1720         strm = (z_stream *)lastrm->real_stream;
1721         /* zlib.h is not const-correct, so we need this one bit
1722          * of ugly hackery to convert a const * pointer to
1723          * a non-const pointer. */
1724         strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1725         strm->avail_in = (uInt)lastrm->avail_in;
1726         strm->total_in = (uLong)lastrm->total_in;
1727         strm->next_out = lastrm->next_out;
1728         strm->avail_out = (uInt)lastrm->avail_out;
1729         strm->total_out = (uLong)lastrm->total_out;
1730         r = deflate(strm,
1731             (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
1732         lastrm->next_in = strm->next_in;
1733         lastrm->avail_in = strm->avail_in;
1734         lastrm->total_in = strm->total_in;
1735         lastrm->next_out = strm->next_out;
1736         lastrm->avail_out = strm->avail_out;
1737         lastrm->total_out = strm->total_out;
1738         switch (r) {
1739         case Z_OK:
1740                 return (ARCHIVE_OK);
1741         case Z_STREAM_END:
1742                 return (ARCHIVE_EOF);
1743         default:
1744                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1745                     "GZip compression failed:"
1746                     " deflate() call returned status %d", r);
1747                 return (ARCHIVE_FATAL);
1748         }
1749 }
1750
1751 static int
1752 compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
1753 {
1754         z_stream *strm;
1755         int r;
1756
1757         strm = (z_stream *)lastrm->real_stream;
1758         r = deflateEnd(strm);
1759         free(strm);
1760         lastrm->real_stream = NULL;
1761         lastrm->valid = 0;
1762         if (r != Z_OK) {
1763                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1764                     "Failed to clean up compressor");
1765                 return (ARCHIVE_FATAL);
1766         }
1767         return (ARCHIVE_OK);
1768 }
1769 #else
1770 static int
1771 compression_init_encoder_deflate(struct archive *a,
1772     struct la_zstream *lastrm, int level, int withheader)
1773 {
1774
1775         (void) level; /* UNUSED */
1776         (void) withheader; /* UNUSED */
1777         if (lastrm->valid)
1778                 compression_end(a, lastrm);
1779         return (compression_unsupported_encoder(a, lastrm, "deflate"));
1780 }
1781 #endif
1782
1783 /*
1784  * _7_BZIP2 compressor.
1785  */
1786 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
1787 static int
1788 compression_init_encoder_bzip2(struct archive *a,
1789     struct la_zstream *lastrm, int level)
1790 {
1791         bz_stream *strm;
1792
1793         if (lastrm->valid)
1794                 compression_end(a, lastrm);
1795         strm = calloc(1, sizeof(*strm));
1796         if (strm == NULL) {
1797                 archive_set_error(a, ENOMEM,
1798                     "Can't allocate memory for bzip2 stream");
1799                 return (ARCHIVE_FATAL);
1800         }
1801         /* bzlib.h is not const-correct, so we need this one bit
1802          * of ugly hackery to convert a const * pointer to
1803          * a non-const pointer. */
1804         strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1805         strm->avail_in = lastrm->avail_in;
1806         strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1807         strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1808         strm->next_out = (char *)lastrm->next_out;
1809         strm->avail_out = lastrm->avail_out;
1810         strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1811         strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1812         if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
1813                 free(strm);
1814                 lastrm->real_stream = NULL;
1815                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1816                     "Internal error initializing compression library");
1817                 return (ARCHIVE_FATAL);
1818         }
1819         lastrm->real_stream = strm;
1820         lastrm->valid = 1;
1821         lastrm->code = compression_code_bzip2;
1822         lastrm->end = compression_end_bzip2;
1823         return (ARCHIVE_OK);
1824 }
1825
1826 static int
1827 compression_code_bzip2(struct archive *a,
1828     struct la_zstream *lastrm, enum la_zaction action)
1829 {
1830         bz_stream *strm;
1831         int r;
1832
1833         strm = (bz_stream *)lastrm->real_stream;
1834         /* bzlib.h is not const-correct, so we need this one bit
1835          * of ugly hackery to convert a const * pointer to
1836          * a non-const pointer. */
1837         strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1838         strm->avail_in = lastrm->avail_in;
1839         strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1840         strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1841         strm->next_out = (char *)lastrm->next_out;
1842         strm->avail_out = lastrm->avail_out;
1843         strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1844         strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1845         r = BZ2_bzCompress(strm,
1846             (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
1847         lastrm->next_in = (const unsigned char *)strm->next_in;
1848         lastrm->avail_in = strm->avail_in;
1849         lastrm->total_in =
1850             (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
1851             + (uint64_t)(uint32_t)strm->total_in_lo32;
1852         lastrm->next_out = (unsigned char *)strm->next_out;
1853         lastrm->avail_out = strm->avail_out;
1854         lastrm->total_out =
1855             (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
1856             + (uint64_t)(uint32_t)strm->total_out_lo32;
1857         switch (r) {
1858         case BZ_RUN_OK:     /* Non-finishing */
1859         case BZ_FINISH_OK:  /* Finishing: There's more work to do */
1860                 return (ARCHIVE_OK);
1861         case BZ_STREAM_END: /* Finishing: all done */
1862                 /* Only occurs in finishing case */
1863                 return (ARCHIVE_EOF);
1864         default:
1865                 /* Any other return value indicates an error */
1866                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1867                     "Bzip2 compression failed:"
1868                     " BZ2_bzCompress() call returned status %d", r);
1869                 return (ARCHIVE_FATAL);
1870         }
1871 }
1872
1873 static int
1874 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
1875 {
1876         bz_stream *strm;
1877         int r;
1878
1879         strm = (bz_stream *)lastrm->real_stream;
1880         r = BZ2_bzCompressEnd(strm);
1881         free(strm);
1882         lastrm->real_stream = NULL;
1883         lastrm->valid = 0;
1884         if (r != BZ_OK) {
1885                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1886                     "Failed to clean up compressor");
1887                 return (ARCHIVE_FATAL);
1888         }
1889         return (ARCHIVE_OK);
1890 }
1891
1892 #else
1893 static int
1894 compression_init_encoder_bzip2(struct archive *a,
1895     struct la_zstream *lastrm, int level)
1896 {
1897
1898         (void) level; /* UNUSED */
1899         if (lastrm->valid)
1900                 compression_end(a, lastrm);
1901         return (compression_unsupported_encoder(a, lastrm, "bzip2"));
1902 }
1903 #endif
1904
1905 /*
1906  * _7_LZMA1, _7_LZMA2 compressor.
1907  */
1908 #if defined(HAVE_LZMA_H)
1909 static int
1910 compression_init_encoder_lzma(struct archive *a,
1911     struct la_zstream *lastrm, int level, uint64_t filter_id)
1912 {
1913         static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
1914         lzma_stream *strm;
1915         lzma_filter *lzmafilters;
1916         lzma_options_lzma lzma_opt;
1917         int r;
1918
1919         if (lastrm->valid)
1920                 compression_end(a, lastrm);
1921         strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
1922         if (strm == NULL) {
1923                 archive_set_error(a, ENOMEM,
1924                     "Can't allocate memory for lzma stream");
1925                 return (ARCHIVE_FATAL);
1926         }
1927         lzmafilters = (lzma_filter *)(strm+1);
1928         if (level > 6)
1929                 level = 6;
1930         if (lzma_lzma_preset(&lzma_opt, level)) {
1931                 free(strm);
1932                 lastrm->real_stream = NULL;
1933                 archive_set_error(a, ENOMEM,
1934                     "Internal error initializing compression library");
1935                 return (ARCHIVE_FATAL);
1936         }
1937         lzmafilters[0].id = filter_id;
1938         lzmafilters[0].options = &lzma_opt;
1939         lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
1940
1941         r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
1942         if (r != LZMA_OK) {
1943                 free(strm);
1944                 lastrm->real_stream = NULL;
1945                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1946                     "lzma_properties_size failed");
1947                 return (ARCHIVE_FATAL);
1948         }
1949         if (lastrm->prop_size) {
1950                 lastrm->props = malloc(lastrm->prop_size);
1951                 if (lastrm->props == NULL) {
1952                         free(strm);
1953                         lastrm->real_stream = NULL;
1954                         archive_set_error(a, ENOMEM,
1955                             "Cannot allocate memory");
1956                         return (ARCHIVE_FATAL);
1957                 }
1958                 r = lzma_properties_encode(lzmafilters,  lastrm->props);
1959                 if (r != LZMA_OK) {
1960                         free(strm);
1961                         lastrm->real_stream = NULL;
1962                         archive_set_error(a, ARCHIVE_ERRNO_MISC,
1963                             "lzma_properties_encode failed");
1964                         return (ARCHIVE_FATAL);
1965                 }
1966         }
1967
1968         *strm = lzma_init_data;
1969         r = lzma_raw_encoder(strm, lzmafilters);
1970         switch (r) {
1971         case LZMA_OK:
1972                 lastrm->real_stream = strm;
1973                 lastrm->valid = 1;
1974                 lastrm->code = compression_code_lzma;
1975                 lastrm->end = compression_end_lzma;
1976                 r = ARCHIVE_OK;
1977                 break;
1978         case LZMA_MEM_ERROR:
1979                 free(strm);
1980                 lastrm->real_stream = NULL;
1981                 archive_set_error(a, ENOMEM,
1982                     "Internal error initializing compression library: "
1983                     "Cannot allocate memory");
1984                 r =  ARCHIVE_FATAL;
1985                 break;
1986         default:
1987                 free(strm);
1988                 lastrm->real_stream = NULL;
1989                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1990                     "Internal error initializing compression library: "
1991                     "It's a bug in liblzma");
1992                 r =  ARCHIVE_FATAL;
1993                 break;
1994         }
1995         return (r);
1996 }
1997
1998 static int
1999 compression_init_encoder_lzma1(struct archive *a,
2000     struct la_zstream *lastrm, int level)
2001 {
2002         return compression_init_encoder_lzma(a, lastrm, level,
2003                     LZMA_FILTER_LZMA1);
2004 }
2005
2006 static int
2007 compression_init_encoder_lzma2(struct archive *a,
2008     struct la_zstream *lastrm, int level)
2009 {
2010         return compression_init_encoder_lzma(a, lastrm, level,
2011                     LZMA_FILTER_LZMA2);
2012 }
2013
2014 static int
2015 compression_code_lzma(struct archive *a,
2016     struct la_zstream *lastrm, enum la_zaction action)
2017 {
2018         lzma_stream *strm;
2019         int r;
2020
2021         strm = (lzma_stream *)lastrm->real_stream;
2022         strm->next_in = lastrm->next_in;
2023         strm->avail_in = lastrm->avail_in;
2024         strm->total_in = lastrm->total_in;
2025         strm->next_out = lastrm->next_out;
2026         strm->avail_out = lastrm->avail_out;
2027         strm->total_out = lastrm->total_out;
2028         r = lzma_code(strm,
2029             (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2030         lastrm->next_in = strm->next_in;
2031         lastrm->avail_in = strm->avail_in;
2032         lastrm->total_in = strm->total_in;
2033         lastrm->next_out = strm->next_out;
2034         lastrm->avail_out = strm->avail_out;
2035         lastrm->total_out = strm->total_out;
2036         switch (r) {
2037         case LZMA_OK:
2038                 /* Non-finishing case */
2039                 return (ARCHIVE_OK);
2040         case LZMA_STREAM_END:
2041                 /* This return can only occur in finishing case. */
2042                 return (ARCHIVE_EOF);
2043         case LZMA_MEMLIMIT_ERROR:
2044                 archive_set_error(a, ENOMEM,
2045                     "lzma compression error:"
2046                     " %ju MiB would have been needed",
2047                     (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2048                         / (1024 * 1024)));
2049                 return (ARCHIVE_FATAL);
2050         default:
2051                 /* Any other return value indicates an error */
2052                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2053                     "lzma compression failed:"
2054                     " lzma_code() call returned status %d", r);
2055                 return (ARCHIVE_FATAL);
2056         }
2057 }
2058
2059 static int
2060 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2061 {
2062         lzma_stream *strm;
2063
2064         (void)a; /* UNUSED */
2065         strm = (lzma_stream *)lastrm->real_stream;
2066         lzma_end(strm);
2067         free(strm);
2068         lastrm->valid = 0;
2069         lastrm->real_stream = NULL;
2070         return (ARCHIVE_OK);
2071 }
2072 #else
2073 static int
2074 compression_init_encoder_lzma1(struct archive *a,
2075     struct la_zstream *lastrm, int level)
2076 {
2077
2078         (void) level; /* UNUSED */
2079         if (lastrm->valid)
2080                 compression_end(a, lastrm);
2081         return (compression_unsupported_encoder(a, lastrm, "lzma"));
2082 }
2083 static int
2084 compression_init_encoder_lzma2(struct archive *a,
2085     struct la_zstream *lastrm, int level)
2086 {
2087
2088         (void) level; /* UNUSED */
2089         if (lastrm->valid)
2090                 compression_end(a, lastrm);
2091         return (compression_unsupported_encoder(a, lastrm, "lzma"));
2092 }
2093 #endif
2094
2095 /*
2096  * _7_PPMD compressor.
2097  */
2098 static void *
2099 ppmd_alloc(void *p, size_t size)
2100 {
2101         (void)p;
2102         return malloc(size);
2103 }
2104 static void
2105 ppmd_free(void *p, void *address)
2106 {
2107         (void)p;
2108         free(address);
2109 }
2110 static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
2111 static void
2112 ppmd_write(void *p, Byte b)
2113 {
2114         struct archive_write *a = ((IByteOut *)p)->a;
2115         struct _7zip *zip = (struct _7zip *)(a->format_data);
2116         struct la_zstream *lastrm = &(zip->stream);
2117         struct ppmd_stream *strm;
2118
2119         if (lastrm->avail_out) {
2120                 *lastrm->next_out++ = b;
2121                 lastrm->avail_out--;
2122                 lastrm->total_out++;
2123                 return;
2124         }
2125         strm = (struct ppmd_stream *)lastrm->real_stream;
2126         if (strm->buff_ptr < strm->buff_end) {
2127                 *strm->buff_ptr++ = b;
2128                 strm->buff_bytes++;
2129         }
2130 }
2131
2132 static int
2133 compression_init_encoder_ppmd(struct archive *a,
2134     struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
2135 {
2136         struct ppmd_stream *strm;
2137         uint8_t *props;
2138         int r;
2139
2140         if (lastrm->valid)
2141                 compression_end(a, lastrm);
2142         strm = calloc(1, sizeof(*strm));
2143         if (strm == NULL) {
2144                 archive_set_error(a, ENOMEM,
2145                     "Can't allocate memory for PPMd");
2146                 return (ARCHIVE_FATAL);
2147         }
2148         strm->buff = malloc(32);
2149         if (strm->buff == NULL) {
2150                 free(strm);
2151                 archive_set_error(a, ENOMEM,
2152                     "Can't allocate memory for PPMd");
2153                 return (ARCHIVE_FATAL);
2154         }
2155         strm->buff_ptr = strm->buff;
2156         strm->buff_end = strm->buff + 32;
2157
2158         props = malloc(1+4);
2159         if (props == NULL) {
2160                 free(strm->buff);
2161                 free(strm);
2162                 archive_set_error(a, ENOMEM,
2163                     "Coludn't allocate memory for PPMd");
2164                 return (ARCHIVE_FATAL);
2165         }
2166         props[0] = maxOrder;
2167         archive_le32enc(props+1, msize);
2168         __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
2169         r = __archive_ppmd7_functions.Ppmd7_Alloc(
2170                 &strm->ppmd7_context, msize, &g_szalloc);
2171         if (r == 0) {
2172                 free(strm->buff);
2173                 free(strm);
2174                 free(props);
2175                 archive_set_error(a, ENOMEM,
2176                     "Coludn't allocate memory for PPMd");
2177                 return (ARCHIVE_FATAL);
2178         }
2179         __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder);
2180         strm->byteout.a = (struct archive_write *)a;
2181         strm->byteout.Write = ppmd_write;
2182         strm->range_enc.Stream = &(strm->byteout);
2183         __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc));
2184         strm->stat = 0;
2185
2186         lastrm->real_stream = strm;
2187         lastrm->valid = 1;
2188         lastrm->code = compression_code_ppmd;
2189         lastrm->end = compression_end_ppmd;
2190         lastrm->prop_size = 5;
2191         lastrm->props = props;
2192         return (ARCHIVE_OK);
2193 }
2194
2195 static int
2196 compression_code_ppmd(struct archive *a,
2197     struct la_zstream *lastrm, enum la_zaction action)
2198 {
2199         struct ppmd_stream *strm;
2200
2201         (void)a; /* UNUSED */
2202
2203         strm = (struct ppmd_stream *)lastrm->real_stream;
2204
2205         /* Copy encoded data if there are remaining bytes from previous call. */
2206         if (strm->buff_bytes) {
2207                 uint8_t *p = strm->buff_ptr - strm->buff_bytes;
2208                 while (lastrm->avail_out && strm->buff_bytes) {
2209                         *lastrm->next_out++ = *p++;
2210                         lastrm->avail_out--;
2211                         lastrm->total_out++;
2212                         strm->buff_bytes--;
2213                 }
2214                 if (strm->buff_bytes)
2215                         return (ARCHIVE_OK);
2216                 if (strm->stat == 1)
2217                         return (ARCHIVE_EOF);
2218                 strm->buff_ptr = strm->buff;
2219         }
2220         while (lastrm->avail_in && lastrm->avail_out) {
2221                 __archive_ppmd7_functions.Ppmd7_EncodeSymbol(
2222                         &(strm->ppmd7_context), &(strm->range_enc),
2223                         *lastrm->next_in++);
2224                 lastrm->avail_in--;
2225                 lastrm->total_in++;
2226         }
2227         if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
2228                 __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
2229                         &(strm->range_enc));
2230                 strm->stat = 1;
2231                 /* Return EOF if there are no remaining bytes. */
2232                 if (strm->buff_bytes == 0)
2233                         return (ARCHIVE_EOF);
2234         }
2235         return (ARCHIVE_OK);
2236 }
2237
2238 static int
2239 compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
2240 {
2241         struct ppmd_stream *strm;
2242
2243         (void)a; /* UNUSED */
2244
2245         strm = (struct ppmd_stream *)lastrm->real_stream;
2246         __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
2247         free(strm->buff);
2248         free(strm);
2249         lastrm->real_stream = NULL;
2250         lastrm->valid = 0;
2251         return (ARCHIVE_OK);
2252 }
2253
2254 /*
2255  * Universal compressor initializer.
2256  */
2257 static int
2258 _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
2259     int compression_level)
2260 {
2261         struct _7zip *zip;
2262         int r;
2263
2264         zip = (struct _7zip *)a->format_data;
2265         switch (compression) {
2266         case _7Z_DEFLATE:
2267                 r = compression_init_encoder_deflate(
2268                     &(a->archive), &(zip->stream),
2269                     compression_level, 0);
2270                 break;
2271         case _7Z_BZIP2:
2272                 r = compression_init_encoder_bzip2(
2273                     &(a->archive), &(zip->stream),
2274                     compression_level);
2275                 break;
2276         case _7Z_LZMA1:
2277                 r = compression_init_encoder_lzma1(
2278                     &(a->archive), &(zip->stream),
2279                     compression_level);
2280                 break;
2281         case _7Z_LZMA2:
2282                 r = compression_init_encoder_lzma2(
2283                     &(a->archive), &(zip->stream),
2284                     compression_level);
2285                 break;
2286         case _7Z_PPMD:
2287                 r = compression_init_encoder_ppmd(
2288                     &(a->archive), &(zip->stream),
2289                     PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
2290                 break;
2291         case _7Z_COPY:
2292         default:
2293                 r = compression_init_encoder_copy(
2294                     &(a->archive), &(zip->stream));
2295                 break;
2296         }
2297         if (r == ARCHIVE_OK) {
2298                 zip->stream.total_in = 0;
2299                 zip->stream.next_out = zip->wbuff;
2300                 zip->stream.avail_out = sizeof(zip->wbuff);
2301                 zip->stream.total_out = 0;
2302         }
2303
2304         return (r);
2305 }
2306
2307 static int
2308 compression_code(struct archive *a, struct la_zstream *lastrm,
2309     enum la_zaction action)
2310 {
2311         if (lastrm->valid)
2312                 return (lastrm->code(a, lastrm, action));
2313         return (ARCHIVE_OK);
2314 }
2315
2316 static int
2317 compression_end(struct archive *a, struct la_zstream *lastrm)
2318 {
2319         if (lastrm->valid) {
2320                 lastrm->prop_size = 0;
2321                 free(lastrm->props);
2322                 lastrm->props = NULL;
2323                 return (lastrm->end(a, lastrm));
2324         }
2325         return (ARCHIVE_OK);
2326 }
2327
2328