]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_write_set_format_7zip.c
MFC r345497:
[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 member 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                 if (file != NULL)
443                         file_free(file);
444                 return (r);
445         }
446         if (file->size == 0 && file->dir) {
447                 if (!__archive_rb_tree_insert_node(&(zip->rbtree),
448                     (struct archive_rb_node *)file)) {
449                         /* We have already had the same file. */
450                         file_free(file);
451                         return (ARCHIVE_OK);
452                 }
453         }
454
455         if (file->flg & MTIME_IS_SET)
456                 zip->total_number_time_defined[MTIME]++;
457         if (file->flg & CTIME_IS_SET)
458                 zip->total_number_time_defined[CTIME]++;
459         if (file->flg & ATIME_IS_SET)
460                 zip->total_number_time_defined[ATIME]++;
461
462         zip->total_number_entry++;
463         zip->total_bytes_entry_name += file->name_len + 2;
464         if (file->size == 0) {
465                 /* Count up the number of empty files. */
466                 zip->total_number_empty_entry++;
467                 if (file->dir)
468                         zip->total_number_dir_entry++;
469                 else
470                         file_register_empty(zip, file);
471                 return (r);
472         }
473
474         /*
475          * Init compression.
476          */
477         if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
478                 r = _7z_compression_init_encoder(a, zip->opt_compression,
479                         zip->opt_compression_level);
480                 if (r < 0) {
481                         file_free(file);
482                         return (ARCHIVE_FATAL);
483                 }
484         }
485
486         /* Register a non-empty file. */
487         file_register(zip, file);
488
489         /*
490          * Set the current file to cur_file to read its contents.
491          */
492         zip->cur_file = file;
493
494
495         /* Save a offset of current file in temporary file. */
496         zip->entry_bytes_remaining = file->size;
497         zip->entry_crc32 = 0;
498
499         /*
500          * Store a symbolic link name as file contents.
501          */
502         if (archive_entry_filetype(entry) == AE_IFLNK) {
503                 ssize_t bytes;
504                 const void *p = (const void *)archive_entry_symlink(entry);
505                 bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
506                 if (bytes < 0)
507                         return ((int)bytes);
508                 zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
509                 zip->entry_bytes_remaining -= bytes;
510         }
511
512         return (r);
513 }
514
515 /*
516  * Write data to a temporary file.
517  */
518 static int
519 write_to_temp(struct archive_write *a, const void *buff, size_t s)
520 {
521         struct _7zip *zip;
522         const unsigned char *p;
523         ssize_t ws;
524
525         zip = (struct _7zip *)a->format_data;
526
527         /*
528          * Open a temporary file.
529          */
530         if (zip->temp_fd == -1) {
531                 zip->temp_offset = 0;
532                 zip->temp_fd = __archive_mktemp(NULL);
533                 if (zip->temp_fd < 0) {
534                         archive_set_error(&a->archive, errno,
535                             "Couldn't create temporary file");
536                         return (ARCHIVE_FATAL);
537                 }
538         }
539
540         p = (const unsigned char *)buff;
541         while (s) {
542                 ws = write(zip->temp_fd, p, s);
543                 if (ws < 0) {
544                         archive_set_error(&(a->archive), errno,
545                             "fwrite function failed");
546                         return (ARCHIVE_FATAL);
547                 }
548                 s -= ws;
549                 p += ws;
550                 zip->temp_offset += ws;
551         }
552         return (ARCHIVE_OK);
553 }
554
555 static ssize_t
556 compress_out(struct archive_write *a, const void *buff, size_t s,
557     enum la_zaction run)
558 {
559         struct _7zip *zip = (struct _7zip *)a->format_data;
560         int r;
561
562         if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
563                 return (0);
564
565         if ((zip->crc32flg & PRECODE_CRC32) && s)
566                 zip->precode_crc32 = crc32(zip->precode_crc32, buff,
567                     (unsigned)s);
568         zip->stream.next_in = (const unsigned char *)buff;
569         zip->stream.avail_in = s;
570         for (;;) {
571                 /* Compress file data. */
572                 r = compression_code(&(a->archive), &(zip->stream), run);
573                 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
574                         return (ARCHIVE_FATAL);
575                 if (zip->stream.avail_out == 0) {
576                         if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
577                             != ARCHIVE_OK)
578                                 return (ARCHIVE_FATAL);
579                         zip->stream.next_out = zip->wbuff;
580                         zip->stream.avail_out = sizeof(zip->wbuff);
581                         if (zip->crc32flg & ENCODED_CRC32)
582                                 zip->encoded_crc32 = crc32(zip->encoded_crc32,
583                                     zip->wbuff, sizeof(zip->wbuff));
584                         if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
585                                 continue;
586                 }
587                 if (zip->stream.avail_in == 0)
588                         break;
589         }
590         if (run == ARCHIVE_Z_FINISH) {
591                 uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
592                 if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
593                         return (ARCHIVE_FATAL);
594                 if ((zip->crc32flg & ENCODED_CRC32) && bytes)
595                         zip->encoded_crc32 = crc32(zip->encoded_crc32,
596                             zip->wbuff, (unsigned)bytes);
597         }
598
599         return (s);
600 }
601
602 static ssize_t
603 _7z_write_data(struct archive_write *a, const void *buff, size_t s)
604 {
605         struct _7zip *zip;
606         ssize_t bytes;
607
608         zip = (struct _7zip *)a->format_data;
609
610         if (s > zip->entry_bytes_remaining)
611                 s = (size_t)zip->entry_bytes_remaining;
612         if (s == 0 || zip->cur_file == NULL)
613                 return (0);
614         bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
615         if (bytes < 0)
616                 return (bytes);
617         zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
618         zip->entry_bytes_remaining -= bytes;
619         return (bytes);
620 }
621
622 static int
623 _7z_finish_entry(struct archive_write *a)
624 {
625         struct _7zip *zip;
626         size_t s;
627         ssize_t r;
628
629         zip = (struct _7zip *)a->format_data;
630         if (zip->cur_file == NULL)
631                 return (ARCHIVE_OK);
632
633         while (zip->entry_bytes_remaining > 0) {
634                 s = (size_t)zip->entry_bytes_remaining;
635                 if (s > a->null_length)
636                         s = a->null_length;
637                 r = _7z_write_data(a, a->nulls, s);
638                 if (r < 0)
639                         return ((int)r);
640         }
641         zip->total_bytes_compressed += zip->stream.total_in;
642         zip->total_bytes_uncompressed += zip->stream.total_out;
643         zip->cur_file->crc32 = zip->entry_crc32;
644         zip->cur_file = NULL;
645
646         return (ARCHIVE_OK);
647 }
648
649 static int
650 flush_wbuff(struct archive_write *a)
651 {
652         struct _7zip *zip;
653         int r;
654         size_t s;
655
656         zip = (struct _7zip *)a->format_data;
657         s = sizeof(zip->wbuff) - zip->wbuff_remaining;
658         r = __archive_write_output(a, zip->wbuff, s);
659         if (r != ARCHIVE_OK)
660                 return (r);
661         zip->wbuff_remaining = sizeof(zip->wbuff);
662         return (r);
663 }
664
665 static int
666 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
667 {
668         struct _7zip *zip;
669         int r;
670
671         zip = (struct _7zip *)a->format_data;
672         if (zip->temp_offset > 0 &&
673             lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
674                 archive_set_error(&(a->archive), errno, "lseek failed");
675                 return (ARCHIVE_FATAL);
676         }
677         while (length) {
678                 size_t rsize;
679                 ssize_t rs;
680                 unsigned char *wb;
681
682                 if (length > zip->wbuff_remaining)
683                         rsize = zip->wbuff_remaining;
684                 else
685                         rsize = (size_t)length;
686                 wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
687                 rs = read(zip->temp_fd, wb, rsize);
688                 if (rs < 0) {
689                         archive_set_error(&(a->archive), errno,
690                             "Can't read temporary file(%jd)",
691                             (intmax_t)rs);
692                         return (ARCHIVE_FATAL);
693                 }
694                 if (rs == 0) {
695                         archive_set_error(&(a->archive), 0,
696                             "Truncated 7-Zip archive");
697                         return (ARCHIVE_FATAL);
698                 }
699                 zip->wbuff_remaining -= rs;
700                 length -= rs;
701                 if (zip->wbuff_remaining == 0) {
702                         r = flush_wbuff(a);
703                         if (r != ARCHIVE_OK)
704                                 return (r);
705                 }
706         }
707         return (ARCHIVE_OK);
708 }
709
710 static int
711 _7z_close(struct archive_write *a)
712 {
713         struct _7zip *zip;
714         unsigned char *wb;
715         uint64_t header_offset, header_size, header_unpacksize;
716         uint64_t length;
717         uint32_t header_crc32;
718         int r;
719
720         zip = (struct _7zip *)a->format_data;
721
722         if (zip->total_number_entry > 0) {
723                 struct archive_rb_node *n;
724                 uint64_t data_offset, data_size, data_unpacksize;
725                 unsigned header_compression;
726
727                 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
728                 if (r < 0)
729                         return (r);
730                 data_offset = 0;
731                 data_size = zip->stream.total_out;
732                 data_unpacksize = zip->stream.total_in;
733                 zip->coder.codec = zip->opt_compression;
734                 zip->coder.prop_size = zip->stream.prop_size;
735                 zip->coder.props = zip->stream.props;
736                 zip->stream.prop_size = 0;
737                 zip->stream.props = NULL;
738                 zip->total_number_nonempty_entry =
739                     zip->total_number_entry - zip->total_number_empty_entry;
740
741                 /* Connect an empty file list. */
742                 if (zip->empty_list.first != NULL) {
743                         *zip->file_list.last = zip->empty_list.first;
744                         zip->file_list.last = zip->empty_list.last;
745                 }
746                 /* Connect a directory file list. */
747                 ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
748                         file_register(zip, (struct file *)n);
749                 }
750
751                 /*
752                  * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
753                  * the compression type for encoding the header.
754                  */
755 #if HAVE_LZMA_H
756                 header_compression = _7Z_LZMA1;
757                 /* If the stored file is only one, do not encode the header.
758                  * This is the same way 7z command does. */
759                 if (zip->total_number_entry == 1)
760                         header_compression = _7Z_COPY;
761 #else
762                 header_compression = _7Z_COPY;
763 #endif
764                 r = _7z_compression_init_encoder(a, header_compression, 6);
765                 if (r < 0)
766                         return (r);
767                 zip->crc32flg = PRECODE_CRC32;
768                 zip->precode_crc32 = 0;
769                 r = make_header(a, data_offset, data_size, data_unpacksize,
770                         1, &(zip->coder));
771                 if (r < 0)
772                         return (r);
773                 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
774                 if (r < 0)
775                         return (r);
776                 header_offset = data_offset + data_size;
777                 header_size = zip->stream.total_out;
778                 header_crc32 = zip->precode_crc32;
779                 header_unpacksize = zip->stream.total_in;
780
781                 if (header_compression != _7Z_COPY) {
782                         /*
783                          * Encode the header in order to reduce the size
784                          * of the archive.
785                          */
786                         free(zip->coder.props);
787                         zip->coder.codec = header_compression;
788                         zip->coder.prop_size = zip->stream.prop_size;
789                         zip->coder.props = zip->stream.props;
790                         zip->stream.prop_size = 0;
791                         zip->stream.props = NULL;
792
793                         r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
794                         if (r < 0)
795                                 return (r);
796                         zip->crc32flg = ENCODED_CRC32;
797                         zip->encoded_crc32 = 0;
798
799                         /*
800                          * Make EncodedHeader.
801                          */
802                         r = enc_uint64(a, kEncodedHeader);
803                         if (r < 0)
804                                 return (r);
805                         r = make_streamsInfo(a, header_offset, header_size,
806                               header_unpacksize, 1, &(zip->coder), 0,
807                               header_crc32);
808                         if (r < 0)
809                                 return (r);
810                         r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
811                         if (r < 0)
812                                 return (r);
813                         header_offset = header_offset + header_size;
814                         header_size = zip->stream.total_out;
815                         header_crc32 = zip->encoded_crc32;
816                 }
817                 zip->crc32flg = 0;
818         } else {
819                 header_offset = header_size = 0;
820                 header_crc32 = 0;
821         }
822         
823         length = zip->temp_offset;
824
825         /*
826          * Make the zip header on wbuff(write buffer).
827          */
828         wb = zip->wbuff;
829         zip->wbuff_remaining = sizeof(zip->wbuff);
830         memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
831         wb[6] = 0;/* Major version. */
832         wb[7] = 3;/* Minor version. */
833         archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
834         archive_le64enc(&wb[20], header_size);/* Next Header Size */
835         archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
836         archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
837         zip->wbuff_remaining -= 32;
838
839         /*
840          * Read all file contents and an encoded header from the temporary
841          * file and write out it.
842          */
843         r = copy_out(a, 0, length);
844         if (r != ARCHIVE_OK)
845                 return (r);
846         r = flush_wbuff(a);
847         return (r);
848 }
849
850 /*
851  * Encode 64 bits value into 7-Zip's encoded UINT64 value.
852  */
853 static int
854 enc_uint64(struct archive_write *a, uint64_t val)
855 {
856         unsigned mask = 0x80;
857         uint8_t numdata[9];
858         int i;
859
860         numdata[0] = 0;
861         for (i = 1; i < (int)sizeof(numdata); i++) {
862                 if (val < mask) {
863                         numdata[0] |= (uint8_t)val;
864                         break;
865                 }
866                 numdata[i] = (uint8_t)val;
867                 val >>= 8;
868                 numdata[0] |= mask;
869                 mask >>= 1;
870         }
871         return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
872 }
873
874 static int
875 make_substreamsInfo(struct archive_write *a, struct coder *coders)
876 {
877         struct _7zip *zip = (struct _7zip *)a->format_data;
878         struct file *file;
879         int r;
880
881         /*
882          * Make SubStreamsInfo.
883          */
884         r = enc_uint64(a, kSubStreamsInfo);
885         if (r < 0)
886                 return (r);
887
888         if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
889                 /*
890                  * Make NumUnPackStream.
891                  */
892                 r = enc_uint64(a, kNumUnPackStream);
893                 if (r < 0)
894                         return (r);
895
896                 /* Write numUnpackStreams */
897                 r = enc_uint64(a, zip->total_number_nonempty_entry);
898                 if (r < 0)
899                         return (r);
900
901                 /*
902                  * Make kSize.
903                  */
904                 r = enc_uint64(a, kSize);
905                 if (r < 0)
906                         return (r);
907                 file = zip->file_list.first;
908                 for (;file != NULL; file = file->next) {
909                         if (file->next == NULL ||
910                             file->next->size == 0)
911                                 break;
912                         r = enc_uint64(a, file->size);
913                         if (r < 0)
914                                 return (r);
915                 }
916         }
917
918         /*
919          * Make CRC.
920          */
921         r = enc_uint64(a, kCRC);
922         if (r < 0)
923                 return (r);
924
925
926         /* All are defined */
927         r = enc_uint64(a, 1);
928         if (r < 0)
929                 return (r);
930         file = zip->file_list.first;
931         for (;file != NULL; file = file->next) {
932                 uint8_t crc[4];
933                 if (file->size == 0)
934                         break;
935                 archive_le32enc(crc, file->crc32);
936                 r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
937                 if (r < 0)
938                         return (r);
939         }
940
941         /* Write End. */
942         r = enc_uint64(a, kEnd);
943         if (r < 0)
944                 return (r);
945         return (ARCHIVE_OK);
946 }
947
948 static int
949 make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
950     uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
951     uint32_t header_crc)
952 {
953         struct _7zip *zip = (struct _7zip *)a->format_data;
954         uint8_t codec_buff[8];
955         int numFolders, fi;
956         int codec_size;
957         int i, r;
958
959         if (coders->codec == _7Z_COPY)
960                 numFolders = (int)zip->total_number_nonempty_entry;
961         else
962                 numFolders = 1;
963
964         /*
965          * Make PackInfo.
966          */
967         r = enc_uint64(a, kPackInfo);
968         if (r < 0)
969                 return (r);
970
971         /* Write PackPos. */
972         r = enc_uint64(a, offset);
973         if (r < 0)
974                 return (r);
975
976         /* Write NumPackStreams. */
977         r = enc_uint64(a, numFolders);
978         if (r < 0)
979                 return (r);
980
981         /* Make Size. */
982         r = enc_uint64(a, kSize);
983         if (r < 0)
984                 return (r);
985
986         if (numFolders > 1) {
987                 struct file *file = zip->file_list.first;
988                 for (;file != NULL; file = file->next) {
989                         if (file->size == 0)
990                                 break;
991                         r = enc_uint64(a, file->size);
992                         if (r < 0)
993                                 return (r);
994                 }
995         } else {
996                 /* Write size. */
997                 r = enc_uint64(a, pack_size);
998                 if (r < 0)
999                         return (r);
1000         }
1001
1002         r = enc_uint64(a, kEnd);
1003         if (r < 0)
1004                 return (r);
1005
1006         /*
1007          * Make UnPackInfo.
1008          */
1009         r = enc_uint64(a, kUnPackInfo);
1010         if (r < 0)
1011                 return (r);
1012
1013         /*
1014          * Make Folder.
1015          */
1016         r = enc_uint64(a, kFolder);
1017         if (r < 0)
1018                 return (r);
1019
1020         /* Write NumFolders. */
1021         r = enc_uint64(a, numFolders);
1022         if (r < 0)
1023                 return (r);
1024
1025         /* Write External. */
1026         r = enc_uint64(a, 0);
1027         if (r < 0)
1028                 return (r);
1029
1030         for (fi = 0; fi < numFolders; fi++) {
1031                 /* Write NumCoders. */
1032                 r = enc_uint64(a, num_coder);
1033                 if (r < 0)
1034                         return (r);
1035
1036                 for (i = 0; i < num_coder; i++) {
1037                         unsigned codec_id = coders[i].codec;
1038
1039                         /* Write Codec flag. */
1040                         archive_be64enc(codec_buff, codec_id);
1041                         for (codec_size = 8; codec_size > 0; codec_size--) {
1042                                 if (codec_buff[8 - codec_size])
1043                                         break;
1044                         }
1045                         if (codec_size == 0)
1046                                 codec_size = 1;
1047                         if (coders[i].prop_size)
1048                                 r = enc_uint64(a, codec_size | 0x20);
1049                         else
1050                                 r = enc_uint64(a, codec_size);
1051                         if (r < 0)
1052                                 return (r);
1053
1054                         /* Write Codec ID. */
1055                         codec_size &= 0x0f;
1056                         r = (int)compress_out(a, &codec_buff[8-codec_size],
1057                                 codec_size, ARCHIVE_Z_RUN);
1058                         if (r < 0)
1059                                 return (r);
1060
1061                         if (coders[i].prop_size) {
1062                                 /* Write Codec property size. */
1063                                 r = enc_uint64(a, coders[i].prop_size);
1064                                 if (r < 0)
1065                                         return (r);
1066
1067                                 /* Write Codec properties. */
1068                                 r = (int)compress_out(a, coders[i].props,
1069                                         coders[i].prop_size, ARCHIVE_Z_RUN);
1070                                 if (r < 0)
1071                                         return (r);
1072                         }
1073                 }
1074         }
1075
1076         /*
1077          * Make CodersUnPackSize.
1078          */
1079         r = enc_uint64(a, kCodersUnPackSize);
1080         if (r < 0)
1081                 return (r);
1082
1083         if (numFolders > 1) {
1084                 struct file *file = zip->file_list.first;
1085                 for (;file != NULL; file = file->next) {
1086                         if (file->size == 0)
1087                                 break;
1088                         r = enc_uint64(a, file->size);
1089                         if (r < 0)
1090                                 return (r);
1091                 }
1092
1093         } else {
1094                 /* Write UnPackSize. */
1095                 r = enc_uint64(a, unpack_size);
1096                 if (r < 0)
1097                         return (r);
1098         }
1099
1100         if (!substrm) {
1101                 uint8_t crc[4];
1102                 /*
1103                  * Make CRC.
1104                  */
1105                 r = enc_uint64(a, kCRC);
1106                 if (r < 0)
1107                         return (r);
1108
1109                 /* All are defined */
1110                 r = enc_uint64(a, 1);
1111                 if (r < 0)
1112                         return (r);
1113                 archive_le32enc(crc, header_crc);
1114                 r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
1115                 if (r < 0)
1116                         return (r);
1117         }
1118
1119         /* Write End. */
1120         r = enc_uint64(a, kEnd);
1121         if (r < 0)
1122                 return (r);
1123
1124         if (substrm) {
1125                 /*
1126                  * Make SubStreamsInfo.
1127                  */
1128                 r = make_substreamsInfo(a, coders);
1129                 if (r < 0)
1130                         return (r);
1131         }
1132
1133
1134         /* Write End. */
1135         r = enc_uint64(a, kEnd);
1136         if (r < 0)
1137                 return (r);
1138
1139         return (ARCHIVE_OK);
1140 }
1141
1142
1143 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1144 static uint64_t
1145 utcToFiletime(time_t t, long ns)
1146 {
1147         uint64_t fileTime;
1148
1149         fileTime = t;
1150         fileTime *= 10000000;
1151         fileTime += ns / 100;
1152         fileTime += EPOC_TIME;
1153         return (fileTime);
1154 }
1155
1156 static int
1157 make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
1158 {
1159         uint8_t filetime[8];
1160         struct _7zip *zip = (struct _7zip *)a->format_data;
1161         struct file *file;
1162         int r;
1163         uint8_t b, mask;
1164
1165         /*
1166          * Make Time Bools.
1167          */
1168         if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
1169                 /* Write Time Type. */
1170                 r = enc_uint64(a, type);
1171                 if (r < 0)
1172                         return (r);
1173                 /* Write EmptyStream Size. */
1174                 r = enc_uint64(a, 2 + zip->total_number_entry * 8);
1175                 if (r < 0)
1176                         return (r);
1177                 /* All are defined. */
1178                 r = enc_uint64(a, 1);
1179                 if (r < 0)
1180                         return (r);
1181         } else {
1182                 if (zip->total_number_time_defined[ti] == 0)
1183                         return (ARCHIVE_OK);
1184
1185                 /* Write Time Type. */
1186                 r = enc_uint64(a, type);
1187                 if (r < 0)
1188                         return (r);
1189                 /* Write EmptyStream Size. */
1190                 r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
1191                         + zip->total_number_time_defined[ti] * 8);
1192                 if (r < 0)
1193                         return (r);
1194
1195                 /* All are not defined. */
1196                 r = enc_uint64(a, 0);
1197                 if (r < 0)
1198                         return (r);
1199
1200                 b = 0;
1201                 mask = 0x80;
1202                 file = zip->file_list.first;
1203                 for (;file != NULL; file = file->next) {
1204                         if (file->flg & flg)
1205                                 b |= mask;
1206                         mask >>= 1;
1207                         if (mask == 0) {
1208                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1209                                 if (r < 0)
1210                                         return (r);
1211                                 mask = 0x80;
1212                                 b = 0;
1213                         }
1214                 }
1215                 if (mask != 0x80) {
1216                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1217                         if (r < 0)
1218                                 return (r);
1219                 }
1220         }
1221
1222         /* External. */
1223         r = enc_uint64(a, 0);
1224         if (r < 0)
1225                 return (r);
1226
1227
1228         /*
1229          * Make Times.
1230          */
1231         file = zip->file_list.first;
1232         for (;file != NULL; file = file->next) {
1233                 if ((file->flg & flg) == 0)
1234                         continue;
1235                 archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
1236                         file->times[ti].time_ns));
1237                 r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
1238                 if (r < 0)
1239                         return (r);
1240         }
1241
1242         return (ARCHIVE_OK);
1243 }
1244
1245 static int
1246 make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
1247     uint64_t unpack_size, int codernum, struct coder *coders)
1248 {
1249         struct _7zip *zip = (struct _7zip *)a->format_data;
1250         struct file *file;
1251         int r;
1252         uint8_t b, mask;
1253
1254         /*
1255          * Make FilesInfo.
1256          */
1257         r = enc_uint64(a, kHeader);
1258         if (r < 0)
1259                 return (r);
1260
1261         /*
1262          * If there are empty files only, do not write MainStreamInfo.
1263          */
1264         if (zip->total_number_nonempty_entry) {
1265                 /*
1266                  * Make MainStreamInfo.
1267                  */
1268                 r = enc_uint64(a, kMainStreamsInfo);
1269                 if (r < 0)
1270                         return (r);
1271                 r = make_streamsInfo(a, offset, pack_size, unpack_size,
1272                       codernum, coders, 1, 0);
1273                 if (r < 0)
1274                         return (r);
1275         }
1276
1277         /*
1278          * Make FilesInfo.
1279          */
1280         r = enc_uint64(a, kFilesInfo);
1281         if (r < 0)
1282                 return (r);
1283
1284         /* Write numFiles. */
1285         r = enc_uint64(a, zip->total_number_entry);
1286         if (r < 0)
1287                 return (r);
1288
1289         if (zip->total_number_empty_entry > 0) {
1290                 /* Make EmptyStream. */
1291                 r = enc_uint64(a, kEmptyStream);
1292                 if (r < 0)
1293                         return (r);
1294
1295                 /* Write EmptyStream Size. */
1296                 r = enc_uint64(a, (zip->total_number_entry+7)>>3);
1297                 if (r < 0)
1298                         return (r);
1299
1300                 b = 0;
1301                 mask = 0x80;
1302                 file = zip->file_list.first;
1303                 for (;file != NULL; file = file->next) {
1304                         if (file->size == 0)
1305                                 b |= mask;
1306                         mask >>= 1;
1307                         if (mask == 0) {
1308                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1309                                 if (r < 0)
1310                                         return (r);
1311                                 mask = 0x80;
1312                                 b = 0;
1313                         }
1314                 }
1315                 if (mask != 0x80) {
1316                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1317                         if (r < 0)
1318                                 return (r);
1319                 }
1320         }
1321
1322         if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
1323                 /* Make EmptyFile. */
1324                 r = enc_uint64(a, kEmptyFile);
1325                 if (r < 0)
1326                         return (r);
1327
1328                 /* Write EmptyFile Size. */
1329                 r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
1330                 if (r < 0)
1331                         return (r);
1332
1333                 b = 0;
1334                 mask = 0x80;
1335                 file = zip->file_list.first;
1336                 for (;file != NULL; file = file->next) {
1337                         if (file->size)
1338                                 continue;
1339                         if (!file->dir)
1340                                 b |= mask;
1341                         mask >>= 1;
1342                         if (mask == 0) {
1343                                 r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1344                                 if (r < 0)
1345                                         return (r);
1346                                 mask = 0x80;
1347                                 b = 0;
1348                         }
1349                 }
1350                 if (mask != 0x80) {
1351                         r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1352                         if (r < 0)
1353                                 return (r);
1354                 }
1355         }
1356
1357         /* Make Name. */
1358         r = enc_uint64(a, kName);
1359         if (r < 0)
1360                 return (r);
1361
1362         /* Write Name size. */
1363         r = enc_uint64(a, zip->total_bytes_entry_name+1);
1364         if (r < 0)
1365                 return (r);
1366
1367         /* Write dmy byte. */
1368         r = enc_uint64(a, 0);
1369         if (r < 0)
1370                 return (r);
1371
1372         file = zip->file_list.first;
1373         for (;file != NULL; file = file->next) {
1374                 r = (int)compress_out(a, file->utf16name, file->name_len+2,
1375                         ARCHIVE_Z_RUN);
1376                 if (r < 0)
1377                         return (r);
1378         }
1379
1380         /* Make MTime. */
1381         r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
1382         if (r < 0)
1383                 return (r);
1384
1385         /* Make CTime. */
1386         r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
1387         if (r < 0)
1388                 return (r);
1389
1390         /* Make ATime. */
1391         r = make_time(a, kATime, ATIME_IS_SET, ATIME);
1392         if (r < 0)
1393                 return (r);
1394
1395         /* Make Attributes. */
1396         r = enc_uint64(a, kAttributes);
1397         if (r < 0)
1398                 return (r);
1399
1400         /* Write Attributes size. */
1401         r = enc_uint64(a, 2 + zip->total_number_entry * 4);
1402         if (r < 0)
1403                 return (r);
1404
1405         /* Write "All Are Defined". */
1406         r = enc_uint64(a, 1);
1407         if (r < 0)
1408                 return (r);
1409
1410         /* Write dmy byte. */
1411         r = enc_uint64(a, 0);
1412         if (r < 0)
1413                 return (r);
1414
1415         file = zip->file_list.first;
1416         for (;file != NULL; file = file->next) {
1417                 /*
1418                  * High 16bits is unix mode.
1419                  * Low 16bits is Windows attributes.
1420                  */
1421                 uint32_t encattr, attr;
1422                 if (file->dir)
1423                         attr = 0x8010;
1424                 else
1425                         attr = 0x8020;
1426                 if ((file->mode & 0222) == 0)
1427                         attr |= 1;/* Read Only. */
1428                 attr |= ((uint32_t)file->mode) << 16;
1429                 archive_le32enc(&encattr, attr);
1430                 r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
1431                 if (r < 0)
1432                         return (r);
1433         }
1434
1435         /* Write End. */
1436         r = enc_uint64(a, kEnd);
1437         if (r < 0)
1438                 return (r);
1439
1440         /* Write End. */
1441         r = enc_uint64(a, kEnd);
1442         if (r < 0)
1443                 return (r);
1444
1445         return (ARCHIVE_OK);
1446 }
1447
1448
1449 static int
1450 _7z_free(struct archive_write *a)
1451 {
1452         struct _7zip *zip = (struct _7zip *)a->format_data;
1453
1454         /* Close the temporary file. */
1455         if (zip->temp_fd >= 0)
1456                 close(zip->temp_fd);
1457
1458         file_free_register(zip);
1459         compression_end(&(a->archive), &(zip->stream));
1460         free(zip->coder.props);
1461         free(zip);
1462
1463         return (ARCHIVE_OK);
1464 }
1465
1466 static int
1467 file_cmp_node(const struct archive_rb_node *n1,
1468     const struct archive_rb_node *n2)
1469 {
1470         const struct file *f1 = (const struct file *)n1;
1471         const struct file *f2 = (const struct file *)n2;
1472
1473         if (f1->name_len == f2->name_len)
1474                 return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
1475         return (f1->name_len > f2->name_len)?1:-1;
1476 }
1477         
1478 static int
1479 file_cmp_key(const struct archive_rb_node *n, const void *key)
1480 {
1481         const struct file *f = (const struct file *)n;
1482
1483         return (f->name_len - *(const char *)key);
1484 }
1485
1486 static int
1487 file_new(struct archive_write *a, struct archive_entry *entry,
1488     struct file **newfile)
1489 {
1490         struct _7zip *zip;
1491         struct file *file;
1492         const char *u16;
1493         size_t u16len;
1494         int ret = ARCHIVE_OK;
1495
1496         zip = (struct _7zip *)a->format_data;
1497         *newfile = NULL;
1498
1499         file = calloc(1, sizeof(*file));
1500         if (file == NULL) {
1501                 archive_set_error(&a->archive, ENOMEM,
1502                     "Can't allocate memory");
1503                 return (ARCHIVE_FATAL);
1504         }
1505
1506         if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
1507                 if (errno == ENOMEM) {
1508                         free(file);
1509                         archive_set_error(&a->archive, ENOMEM,
1510                             "Can't allocate memory for UTF-16LE");
1511                         return (ARCHIVE_FATAL);
1512                 }
1513                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1514                     "A filename cannot be converted to UTF-16LE;"
1515                     "You should disable making Joliet extension");
1516                 ret = ARCHIVE_WARN;
1517         }
1518         file->utf16name = malloc(u16len + 2);
1519         if (file->utf16name == NULL) {
1520                 free(file);
1521                 archive_set_error(&a->archive, ENOMEM,
1522                     "Can't allocate memory for Name");
1523                 return (ARCHIVE_FATAL);
1524         }
1525         memcpy(file->utf16name, u16, u16len);
1526         file->utf16name[u16len+0] = 0;
1527         file->utf16name[u16len+1] = 0;
1528         file->name_len = (unsigned)u16len;
1529         file->mode = archive_entry_mode(entry);
1530         if (archive_entry_filetype(entry) == AE_IFREG)
1531                 file->size = archive_entry_size(entry);
1532         else
1533                 archive_entry_set_size(entry, 0);
1534         if (archive_entry_filetype(entry) == AE_IFDIR)
1535                 file->dir = 1;
1536         else if (archive_entry_filetype(entry) == AE_IFLNK)
1537                 file->size = strlen(archive_entry_symlink(entry));
1538         if (archive_entry_mtime_is_set(entry)) {
1539                 file->flg |= MTIME_IS_SET;
1540                 file->times[MTIME].time = archive_entry_mtime(entry);
1541                 file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
1542         }
1543         if (archive_entry_atime_is_set(entry)) {
1544                 file->flg |= ATIME_IS_SET;
1545                 file->times[ATIME].time = archive_entry_atime(entry);
1546                 file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
1547         }
1548         if (archive_entry_ctime_is_set(entry)) {
1549                 file->flg |= CTIME_IS_SET;
1550                 file->times[CTIME].time = archive_entry_ctime(entry);
1551                 file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
1552         }
1553
1554         *newfile = file;
1555         return (ret);
1556 }
1557
1558 static void
1559 file_free(struct file *file)
1560 {
1561         free(file->utf16name);
1562         free(file);
1563 }
1564
1565 static void
1566 file_register(struct _7zip *zip, struct file *file)
1567 {
1568         file->next = NULL;
1569         *zip->file_list.last = file;
1570         zip->file_list.last = &(file->next);
1571 }
1572
1573 static void
1574 file_init_register(struct _7zip *zip)
1575 {
1576         zip->file_list.first = NULL;
1577         zip->file_list.last = &(zip->file_list.first);
1578 }
1579
1580 static void
1581 file_free_register(struct _7zip *zip)
1582 {
1583         struct file *file, *file_next;
1584
1585         file = zip->file_list.first;
1586         while (file != NULL) {
1587                 file_next = file->next;
1588                 file_free(file);
1589                 file = file_next;
1590         }
1591 }
1592
1593 static void
1594 file_register_empty(struct _7zip *zip, struct file *file)
1595 {
1596         file->next = NULL;
1597         *zip->empty_list.last = file;
1598         zip->empty_list.last = &(file->next);
1599 }
1600
1601 static void
1602 file_init_register_empty(struct _7zip *zip)
1603 {
1604         zip->empty_list.first = NULL;
1605         zip->empty_list.last = &(zip->empty_list.first);
1606 }
1607
1608 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
1609          !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
1610 static int
1611 compression_unsupported_encoder(struct archive *a,
1612     struct la_zstream *lastrm, const char *name)
1613 {
1614
1615         archive_set_error(a, ARCHIVE_ERRNO_MISC,
1616             "%s compression not supported on this platform", name);
1617         lastrm->valid = 0;
1618         lastrm->real_stream = NULL;
1619         return (ARCHIVE_FAILED);
1620 }
1621 #endif
1622
1623 /*
1624  * _7_COPY compressor.
1625  */
1626 static int
1627 compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
1628 {
1629
1630         if (lastrm->valid)
1631                 compression_end(a, lastrm);
1632         lastrm->valid = 1;
1633         lastrm->code = compression_code_copy;
1634         lastrm->end = compression_end_copy;
1635         return (ARCHIVE_OK);
1636 }
1637
1638 static int
1639 compression_code_copy(struct archive *a,
1640     struct la_zstream *lastrm, enum la_zaction action)
1641 {
1642         size_t bytes;
1643
1644         (void)a; /* UNUSED */
1645         if (lastrm->avail_out > lastrm->avail_in)
1646                 bytes = lastrm->avail_in;
1647         else
1648                 bytes = lastrm->avail_out;
1649         if (bytes) {
1650                 memcpy(lastrm->next_out, lastrm->next_in, bytes);
1651                 lastrm->next_in += bytes;
1652                 lastrm->avail_in -= bytes;
1653                 lastrm->total_in += bytes;
1654                 lastrm->next_out += bytes;
1655                 lastrm->avail_out -= bytes;
1656                 lastrm->total_out += bytes;
1657         }
1658         if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
1659                 return (ARCHIVE_EOF);
1660         return (ARCHIVE_OK);
1661 }
1662
1663 static int
1664 compression_end_copy(struct archive *a, struct la_zstream *lastrm)
1665 {
1666         (void)a; /* UNUSED */
1667         lastrm->valid = 0;
1668         return (ARCHIVE_OK);
1669 }
1670
1671 /*
1672  * _7_DEFLATE compressor.
1673  */
1674 #ifdef HAVE_ZLIB_H
1675 static int
1676 compression_init_encoder_deflate(struct archive *a,
1677     struct la_zstream *lastrm, int level, int withheader)
1678 {
1679         z_stream *strm;
1680
1681         if (lastrm->valid)
1682                 compression_end(a, lastrm);
1683         strm = calloc(1, sizeof(*strm));
1684         if (strm == NULL) {
1685                 archive_set_error(a, ENOMEM,
1686                     "Can't allocate memory for gzip stream");
1687                 return (ARCHIVE_FATAL);
1688         }
1689         /* zlib.h is not const-correct, so we need this one bit
1690          * of ugly hackery to convert a const * pointer to
1691          * a non-const pointer. */
1692         strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1693         strm->avail_in = (uInt)lastrm->avail_in;
1694         strm->total_in = (uLong)lastrm->total_in;
1695         strm->next_out = lastrm->next_out;
1696         strm->avail_out = (uInt)lastrm->avail_out;
1697         strm->total_out = (uLong)lastrm->total_out;
1698         if (deflateInit2(strm, level, Z_DEFLATED,
1699             (withheader)?15:-15,
1700             8, Z_DEFAULT_STRATEGY) != Z_OK) {
1701                 free(strm);
1702                 lastrm->real_stream = NULL;
1703                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1704                     "Internal error initializing compression library");
1705                 return (ARCHIVE_FATAL);
1706         }
1707         lastrm->real_stream = strm;
1708         lastrm->valid = 1;
1709         lastrm->code = compression_code_deflate;
1710         lastrm->end = compression_end_deflate;
1711         return (ARCHIVE_OK);
1712 }
1713
1714 static int
1715 compression_code_deflate(struct archive *a,
1716     struct la_zstream *lastrm, enum la_zaction action)
1717 {
1718         z_stream *strm;
1719         int r;
1720
1721         strm = (z_stream *)lastrm->real_stream;
1722         /* zlib.h is not const-correct, so we need this one bit
1723          * of ugly hackery to convert a const * pointer to
1724          * a non-const pointer. */
1725         strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1726         strm->avail_in = (uInt)lastrm->avail_in;
1727         strm->total_in = (uLong)lastrm->total_in;
1728         strm->next_out = lastrm->next_out;
1729         strm->avail_out = (uInt)lastrm->avail_out;
1730         strm->total_out = (uLong)lastrm->total_out;
1731         r = deflate(strm,
1732             (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
1733         lastrm->next_in = strm->next_in;
1734         lastrm->avail_in = strm->avail_in;
1735         lastrm->total_in = strm->total_in;
1736         lastrm->next_out = strm->next_out;
1737         lastrm->avail_out = strm->avail_out;
1738         lastrm->total_out = strm->total_out;
1739         switch (r) {
1740         case Z_OK:
1741                 return (ARCHIVE_OK);
1742         case Z_STREAM_END:
1743                 return (ARCHIVE_EOF);
1744         default:
1745                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1746                     "GZip compression failed:"
1747                     " deflate() call returned status %d", r);
1748                 return (ARCHIVE_FATAL);
1749         }
1750 }
1751
1752 static int
1753 compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
1754 {
1755         z_stream *strm;
1756         int r;
1757
1758         strm = (z_stream *)lastrm->real_stream;
1759         r = deflateEnd(strm);
1760         free(strm);
1761         lastrm->real_stream = NULL;
1762         lastrm->valid = 0;
1763         if (r != Z_OK) {
1764                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1765                     "Failed to clean up compressor");
1766                 return (ARCHIVE_FATAL);
1767         }
1768         return (ARCHIVE_OK);
1769 }
1770 #else
1771 static int
1772 compression_init_encoder_deflate(struct archive *a,
1773     struct la_zstream *lastrm, int level, int withheader)
1774 {
1775
1776         (void) level; /* UNUSED */
1777         (void) withheader; /* UNUSED */
1778         if (lastrm->valid)
1779                 compression_end(a, lastrm);
1780         return (compression_unsupported_encoder(a, lastrm, "deflate"));
1781 }
1782 #endif
1783
1784 /*
1785  * _7_BZIP2 compressor.
1786  */
1787 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
1788 static int
1789 compression_init_encoder_bzip2(struct archive *a,
1790     struct la_zstream *lastrm, int level)
1791 {
1792         bz_stream *strm;
1793
1794         if (lastrm->valid)
1795                 compression_end(a, lastrm);
1796         strm = calloc(1, sizeof(*strm));
1797         if (strm == NULL) {
1798                 archive_set_error(a, ENOMEM,
1799                     "Can't allocate memory for bzip2 stream");
1800                 return (ARCHIVE_FATAL);
1801         }
1802         /* bzlib.h is not const-correct, so we need this one bit
1803          * of ugly hackery to convert a const * pointer to
1804          * a non-const pointer. */
1805         strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1806         strm->avail_in = lastrm->avail_in;
1807         strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1808         strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1809         strm->next_out = (char *)lastrm->next_out;
1810         strm->avail_out = lastrm->avail_out;
1811         strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1812         strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1813         if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
1814                 free(strm);
1815                 lastrm->real_stream = NULL;
1816                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1817                     "Internal error initializing compression library");
1818                 return (ARCHIVE_FATAL);
1819         }
1820         lastrm->real_stream = strm;
1821         lastrm->valid = 1;
1822         lastrm->code = compression_code_bzip2;
1823         lastrm->end = compression_end_bzip2;
1824         return (ARCHIVE_OK);
1825 }
1826
1827 static int
1828 compression_code_bzip2(struct archive *a,
1829     struct la_zstream *lastrm, enum la_zaction action)
1830 {
1831         bz_stream *strm;
1832         int r;
1833
1834         strm = (bz_stream *)lastrm->real_stream;
1835         /* bzlib.h is not const-correct, so we need this one bit
1836          * of ugly hackery to convert a const * pointer to
1837          * a non-const pointer. */
1838         strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1839         strm->avail_in = lastrm->avail_in;
1840         strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1841         strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1842         strm->next_out = (char *)lastrm->next_out;
1843         strm->avail_out = lastrm->avail_out;
1844         strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1845         strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1846         r = BZ2_bzCompress(strm,
1847             (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
1848         lastrm->next_in = (const unsigned char *)strm->next_in;
1849         lastrm->avail_in = strm->avail_in;
1850         lastrm->total_in =
1851             (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
1852             + (uint64_t)(uint32_t)strm->total_in_lo32;
1853         lastrm->next_out = (unsigned char *)strm->next_out;
1854         lastrm->avail_out = strm->avail_out;
1855         lastrm->total_out =
1856             (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
1857             + (uint64_t)(uint32_t)strm->total_out_lo32;
1858         switch (r) {
1859         case BZ_RUN_OK:     /* Non-finishing */
1860         case BZ_FINISH_OK:  /* Finishing: There's more work to do */
1861                 return (ARCHIVE_OK);
1862         case BZ_STREAM_END: /* Finishing: all done */
1863                 /* Only occurs in finishing case */
1864                 return (ARCHIVE_EOF);
1865         default:
1866                 /* Any other return value indicates an error */
1867                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1868                     "Bzip2 compression failed:"
1869                     " BZ2_bzCompress() call returned status %d", r);
1870                 return (ARCHIVE_FATAL);
1871         }
1872 }
1873
1874 static int
1875 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
1876 {
1877         bz_stream *strm;
1878         int r;
1879
1880         strm = (bz_stream *)lastrm->real_stream;
1881         r = BZ2_bzCompressEnd(strm);
1882         free(strm);
1883         lastrm->real_stream = NULL;
1884         lastrm->valid = 0;
1885         if (r != BZ_OK) {
1886                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1887                     "Failed to clean up compressor");
1888                 return (ARCHIVE_FATAL);
1889         }
1890         return (ARCHIVE_OK);
1891 }
1892
1893 #else
1894 static int
1895 compression_init_encoder_bzip2(struct archive *a,
1896     struct la_zstream *lastrm, int level)
1897 {
1898
1899         (void) level; /* UNUSED */
1900         if (lastrm->valid)
1901                 compression_end(a, lastrm);
1902         return (compression_unsupported_encoder(a, lastrm, "bzip2"));
1903 }
1904 #endif
1905
1906 /*
1907  * _7_LZMA1, _7_LZMA2 compressor.
1908  */
1909 #if defined(HAVE_LZMA_H)
1910 static int
1911 compression_init_encoder_lzma(struct archive *a,
1912     struct la_zstream *lastrm, int level, uint64_t filter_id)
1913 {
1914         static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
1915         lzma_stream *strm;
1916         lzma_filter *lzmafilters;
1917         lzma_options_lzma lzma_opt;
1918         int r;
1919
1920         if (lastrm->valid)
1921                 compression_end(a, lastrm);
1922         strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
1923         if (strm == NULL) {
1924                 archive_set_error(a, ENOMEM,
1925                     "Can't allocate memory for lzma stream");
1926                 return (ARCHIVE_FATAL);
1927         }
1928         lzmafilters = (lzma_filter *)(strm+1);
1929         if (level > 6)
1930                 level = 6;
1931         if (lzma_lzma_preset(&lzma_opt, level)) {
1932                 free(strm);
1933                 lastrm->real_stream = NULL;
1934                 archive_set_error(a, ENOMEM,
1935                     "Internal error initializing compression library");
1936                 return (ARCHIVE_FATAL);
1937         }
1938         lzmafilters[0].id = filter_id;
1939         lzmafilters[0].options = &lzma_opt;
1940         lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
1941
1942         r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
1943         if (r != LZMA_OK) {
1944                 free(strm);
1945                 lastrm->real_stream = NULL;
1946                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1947                     "lzma_properties_size failed");
1948                 return (ARCHIVE_FATAL);
1949         }
1950         if (lastrm->prop_size) {
1951                 lastrm->props = malloc(lastrm->prop_size);
1952                 if (lastrm->props == NULL) {
1953                         free(strm);
1954                         lastrm->real_stream = NULL;
1955                         archive_set_error(a, ENOMEM,
1956                             "Cannot allocate memory");
1957                         return (ARCHIVE_FATAL);
1958                 }
1959                 r = lzma_properties_encode(lzmafilters,  lastrm->props);
1960                 if (r != LZMA_OK) {
1961                         free(strm);
1962                         lastrm->real_stream = NULL;
1963                         archive_set_error(a, ARCHIVE_ERRNO_MISC,
1964                             "lzma_properties_encode failed");
1965                         return (ARCHIVE_FATAL);
1966                 }
1967         }
1968
1969         *strm = lzma_init_data;
1970         r = lzma_raw_encoder(strm, lzmafilters);
1971         switch (r) {
1972         case LZMA_OK:
1973                 lastrm->real_stream = strm;
1974                 lastrm->valid = 1;
1975                 lastrm->code = compression_code_lzma;
1976                 lastrm->end = compression_end_lzma;
1977                 r = ARCHIVE_OK;
1978                 break;
1979         case LZMA_MEM_ERROR:
1980                 free(strm);
1981                 lastrm->real_stream = NULL;
1982                 archive_set_error(a, ENOMEM,
1983                     "Internal error initializing compression library: "
1984                     "Cannot allocate memory");
1985                 r =  ARCHIVE_FATAL;
1986                 break;
1987         default:
1988                 free(strm);
1989                 lastrm->real_stream = NULL;
1990                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1991                     "Internal error initializing compression library: "
1992                     "It's a bug in liblzma");
1993                 r =  ARCHIVE_FATAL;
1994                 break;
1995         }
1996         return (r);
1997 }
1998
1999 static int
2000 compression_init_encoder_lzma1(struct archive *a,
2001     struct la_zstream *lastrm, int level)
2002 {
2003         return compression_init_encoder_lzma(a, lastrm, level,
2004                     LZMA_FILTER_LZMA1);
2005 }
2006
2007 static int
2008 compression_init_encoder_lzma2(struct archive *a,
2009     struct la_zstream *lastrm, int level)
2010 {
2011         return compression_init_encoder_lzma(a, lastrm, level,
2012                     LZMA_FILTER_LZMA2);
2013 }
2014
2015 static int
2016 compression_code_lzma(struct archive *a,
2017     struct la_zstream *lastrm, enum la_zaction action)
2018 {
2019         lzma_stream *strm;
2020         int r;
2021
2022         strm = (lzma_stream *)lastrm->real_stream;
2023         strm->next_in = lastrm->next_in;
2024         strm->avail_in = lastrm->avail_in;
2025         strm->total_in = lastrm->total_in;
2026         strm->next_out = lastrm->next_out;
2027         strm->avail_out = lastrm->avail_out;
2028         strm->total_out = lastrm->total_out;
2029         r = lzma_code(strm,
2030             (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2031         lastrm->next_in = strm->next_in;
2032         lastrm->avail_in = strm->avail_in;
2033         lastrm->total_in = strm->total_in;
2034         lastrm->next_out = strm->next_out;
2035         lastrm->avail_out = strm->avail_out;
2036         lastrm->total_out = strm->total_out;
2037         switch (r) {
2038         case LZMA_OK:
2039                 /* Non-finishing case */
2040                 return (ARCHIVE_OK);
2041         case LZMA_STREAM_END:
2042                 /* This return can only occur in finishing case. */
2043                 return (ARCHIVE_EOF);
2044         case LZMA_MEMLIMIT_ERROR:
2045                 archive_set_error(a, ENOMEM,
2046                     "lzma compression error:"
2047                     " %ju MiB would have been needed",
2048                     (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2049                         / (1024 * 1024)));
2050                 return (ARCHIVE_FATAL);
2051         default:
2052                 /* Any other return value indicates an error */
2053                 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2054                     "lzma compression failed:"
2055                     " lzma_code() call returned status %d", r);
2056                 return (ARCHIVE_FATAL);
2057         }
2058 }
2059
2060 static int
2061 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2062 {
2063         lzma_stream *strm;
2064
2065         (void)a; /* UNUSED */
2066         strm = (lzma_stream *)lastrm->real_stream;
2067         lzma_end(strm);
2068         free(strm);
2069         lastrm->valid = 0;
2070         lastrm->real_stream = NULL;
2071         return (ARCHIVE_OK);
2072 }
2073 #else
2074 static int
2075 compression_init_encoder_lzma1(struct archive *a,
2076     struct la_zstream *lastrm, int level)
2077 {
2078
2079         (void) level; /* UNUSED */
2080         if (lastrm->valid)
2081                 compression_end(a, lastrm);
2082         return (compression_unsupported_encoder(a, lastrm, "lzma"));
2083 }
2084 static int
2085 compression_init_encoder_lzma2(struct archive *a,
2086     struct la_zstream *lastrm, int level)
2087 {
2088
2089         (void) level; /* UNUSED */
2090         if (lastrm->valid)
2091                 compression_end(a, lastrm);
2092         return (compression_unsupported_encoder(a, lastrm, "lzma"));
2093 }
2094 #endif
2095
2096 /*
2097  * _7_PPMD compressor.
2098  */
2099 static void
2100 ppmd_write(void *p, Byte b)
2101 {
2102         struct archive_write *a = ((IByteOut *)p)->a;
2103         struct _7zip *zip = (struct _7zip *)(a->format_data);
2104         struct la_zstream *lastrm = &(zip->stream);
2105         struct ppmd_stream *strm;
2106
2107         if (lastrm->avail_out) {
2108                 *lastrm->next_out++ = b;
2109                 lastrm->avail_out--;
2110                 lastrm->total_out++;
2111                 return;
2112         }
2113         strm = (struct ppmd_stream *)lastrm->real_stream;
2114         if (strm->buff_ptr < strm->buff_end) {
2115                 *strm->buff_ptr++ = b;
2116                 strm->buff_bytes++;
2117         }
2118 }
2119
2120 static int
2121 compression_init_encoder_ppmd(struct archive *a,
2122     struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
2123 {
2124         struct ppmd_stream *strm;
2125         uint8_t *props;
2126         int r;
2127
2128         if (lastrm->valid)
2129                 compression_end(a, lastrm);
2130         strm = calloc(1, sizeof(*strm));
2131         if (strm == NULL) {
2132                 archive_set_error(a, ENOMEM,
2133                     "Can't allocate memory for PPMd");
2134                 return (ARCHIVE_FATAL);
2135         }
2136         strm->buff = malloc(32);
2137         if (strm->buff == NULL) {
2138                 free(strm);
2139                 archive_set_error(a, ENOMEM,
2140                     "Can't allocate memory for PPMd");
2141                 return (ARCHIVE_FATAL);
2142         }
2143         strm->buff_ptr = strm->buff;
2144         strm->buff_end = strm->buff + 32;
2145
2146         props = malloc(1+4);
2147         if (props == NULL) {
2148                 free(strm->buff);
2149                 free(strm);
2150                 archive_set_error(a, ENOMEM,
2151                     "Coludn't allocate memory for PPMd");
2152                 return (ARCHIVE_FATAL);
2153         }
2154         props[0] = maxOrder;
2155         archive_le32enc(props+1, msize);
2156         __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
2157         r = __archive_ppmd7_functions.Ppmd7_Alloc(
2158                 &strm->ppmd7_context, msize);
2159         if (r == 0) {
2160                 free(strm->buff);
2161                 free(strm);
2162                 free(props);
2163                 archive_set_error(a, ENOMEM,
2164                     "Coludn't allocate memory for PPMd");
2165                 return (ARCHIVE_FATAL);
2166         }
2167         __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder);
2168         strm->byteout.a = (struct archive_write *)a;
2169         strm->byteout.Write = ppmd_write;
2170         strm->range_enc.Stream = &(strm->byteout);
2171         __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc));
2172         strm->stat = 0;
2173
2174         lastrm->real_stream = strm;
2175         lastrm->valid = 1;
2176         lastrm->code = compression_code_ppmd;
2177         lastrm->end = compression_end_ppmd;
2178         lastrm->prop_size = 5;
2179         lastrm->props = props;
2180         return (ARCHIVE_OK);
2181 }
2182
2183 static int
2184 compression_code_ppmd(struct archive *a,
2185     struct la_zstream *lastrm, enum la_zaction action)
2186 {
2187         struct ppmd_stream *strm;
2188
2189         (void)a; /* UNUSED */
2190
2191         strm = (struct ppmd_stream *)lastrm->real_stream;
2192
2193         /* Copy encoded data if there are remaining bytes from previous call. */
2194         if (strm->buff_bytes) {
2195                 uint8_t *p = strm->buff_ptr - strm->buff_bytes;
2196                 while (lastrm->avail_out && strm->buff_bytes) {
2197                         *lastrm->next_out++ = *p++;
2198                         lastrm->avail_out--;
2199                         lastrm->total_out++;
2200                         strm->buff_bytes--;
2201                 }
2202                 if (strm->buff_bytes)
2203                         return (ARCHIVE_OK);
2204                 if (strm->stat == 1)
2205                         return (ARCHIVE_EOF);
2206                 strm->buff_ptr = strm->buff;
2207         }
2208         while (lastrm->avail_in && lastrm->avail_out) {
2209                 __archive_ppmd7_functions.Ppmd7_EncodeSymbol(
2210                         &(strm->ppmd7_context), &(strm->range_enc),
2211                         *lastrm->next_in++);
2212                 lastrm->avail_in--;
2213                 lastrm->total_in++;
2214         }
2215         if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
2216                 __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
2217                         &(strm->range_enc));
2218                 strm->stat = 1;
2219                 /* Return EOF if there are no remaining bytes. */
2220                 if (strm->buff_bytes == 0)
2221                         return (ARCHIVE_EOF);
2222         }
2223         return (ARCHIVE_OK);
2224 }
2225
2226 static int
2227 compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
2228 {
2229         struct ppmd_stream *strm;
2230
2231         (void)a; /* UNUSED */
2232
2233         strm = (struct ppmd_stream *)lastrm->real_stream;
2234         __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
2235         free(strm->buff);
2236         free(strm);
2237         lastrm->real_stream = NULL;
2238         lastrm->valid = 0;
2239         return (ARCHIVE_OK);
2240 }
2241
2242 /*
2243  * Universal compressor initializer.
2244  */
2245 static int
2246 _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
2247     int compression_level)
2248 {
2249         struct _7zip *zip;
2250         int r;
2251
2252         zip = (struct _7zip *)a->format_data;
2253         switch (compression) {
2254         case _7Z_DEFLATE:
2255                 r = compression_init_encoder_deflate(
2256                     &(a->archive), &(zip->stream),
2257                     compression_level, 0);
2258                 break;
2259         case _7Z_BZIP2:
2260                 r = compression_init_encoder_bzip2(
2261                     &(a->archive), &(zip->stream),
2262                     compression_level);
2263                 break;
2264         case _7Z_LZMA1:
2265                 r = compression_init_encoder_lzma1(
2266                     &(a->archive), &(zip->stream),
2267                     compression_level);
2268                 break;
2269         case _7Z_LZMA2:
2270                 r = compression_init_encoder_lzma2(
2271                     &(a->archive), &(zip->stream),
2272                     compression_level);
2273                 break;
2274         case _7Z_PPMD:
2275                 r = compression_init_encoder_ppmd(
2276                     &(a->archive), &(zip->stream),
2277                     PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
2278                 break;
2279         case _7Z_COPY:
2280         default:
2281                 r = compression_init_encoder_copy(
2282                     &(a->archive), &(zip->stream));
2283                 break;
2284         }
2285         if (r == ARCHIVE_OK) {
2286                 zip->stream.total_in = 0;
2287                 zip->stream.next_out = zip->wbuff;
2288                 zip->stream.avail_out = sizeof(zip->wbuff);
2289                 zip->stream.total_out = 0;
2290         }
2291
2292         return (r);
2293 }
2294
2295 static int
2296 compression_code(struct archive *a, struct la_zstream *lastrm,
2297     enum la_zaction action)
2298 {
2299         if (lastrm->valid)
2300                 return (lastrm->code(a, lastrm, action));
2301         return (ARCHIVE_OK);
2302 }
2303
2304 static int
2305 compression_end(struct archive *a, struct la_zstream *lastrm)
2306 {
2307         if (lastrm->valid) {
2308                 lastrm->prop_size = 0;
2309                 free(lastrm->props);
2310                 lastrm->props = NULL;
2311                 return (lastrm->end(a, lastrm));
2312         }
2313         return (ARCHIVE_OK);
2314 }
2315
2316