2 * Copyright (c) 2011-2012 Michihiro NAKAJIMA
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 #include "archive_platform.h"
27 __FBSDID("$FreeBSD$");
45 #include "archive_crc32.h"
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"
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
67 * 7-Zip header property IDs.
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
81 #define kCodersUnPackSize 0x0C
82 #define kNumUnPackStream 0x0D
83 #define kEmptyStream 0x0E
84 #define kEmptyFile 0x0F
90 #define kAttributes 0x15
91 #define kEncodedHeader 0x17
99 * A stream object of universal compressor.
102 const uint8_t *next_in;
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);
122 #define PPMD7_DEFAULT_ORDER 6
123 #define PPMD7_DEFAULT_MEM_SIZE (1 << 24)
127 CPpmd7 ppmd7_context;
128 CPpmd7z_RangeEnc range_enc;
143 struct archive_rb_node rbnode;
147 uint8_t *utf16name;/* UTF16-LE name. */
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)
172 uint64_t temp_offset;
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;
188 #define PRECODE_CRC32 1
189 #define ENCODED_CRC32 2
191 unsigned opt_compression;
192 int opt_compression_level;
194 struct la_zstream stream;
197 struct archive_string_conv *sconv;
200 * Compressed data buffer.
202 unsigned char wbuff[512 * 20 * 6];
203 size_t wbuff_remaining;
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.
213 } file_list, empty_list;
214 struct archive_rb_tree rbtree;/* for empty files */
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 *,
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 ,
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);
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 *);
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 *);
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 *);
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,
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);
285 archive_write_set_format_7zip(struct archive *_a)
287 static const struct archive_rb_tree_ops rb_ops = {
288 file_cmp_node, file_cmp_key
290 struct archive_write *a = (struct archive_write *)_a;
293 archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
294 ARCHIVE_STATE_NEW, "archive_write_set_format_7zip");
296 /* If another format was already registered, unregister it. */
297 if (a->format_free != NULL)
300 zip = calloc(1, sizeof(*zip));
302 archive_set_error(&a->archive, ENOMEM,
303 "Can't allocate 7-Zip data");
304 return (ARCHIVE_FATAL);
307 __archive_rb_tree_init(&(zip->rbtree), &rb_ops);
308 file_init_register(zip);
309 file_init_register_empty(zip);
311 /* Set default compression type and its level. */
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;
319 zip->opt_compression = _7Z_COPY;
321 zip->opt_compression_level = 6;
323 a->format_data = zip;
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";
339 _7z_options(struct archive_write *a, const char *key, const char *value)
343 zip = (struct _7zip *)a->format_data;
345 if (strcmp(key, "compression") == 0) {
346 const char *name = NULL;
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)
356 zip->opt_compression = _7Z_DEFLATE;
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;
367 else if (strcmp(value, "lzma1") == 0 ||
368 strcmp(value, "LZMA1") == 0)
370 zip->opt_compression = _7Z_LZMA1;
374 else if (strcmp(value, "lzma2") == 0 ||
375 strcmp(value, "LZMA2") == 0)
377 zip->opt_compression = _7Z_LZMA2;
381 else if (strcmp(value, "ppmd") == 0 ||
382 strcmp(value, "PPMD") == 0 ||
383 strcmp(value, "PPMd") == 0)
384 zip->opt_compression = _7Z_PPMD;
386 archive_set_error(&(a->archive),
388 "Unkonwn compression name: `%s'",
390 return (ARCHIVE_FAILED);
393 archive_set_error(&(a->archive),
395 "`%s' compression not supported "
398 return (ARCHIVE_FAILED);
402 if (strcmp(key, "compression-level") == 0) {
404 !(value[0] >= '0' && value[0] <= '9') ||
406 archive_set_error(&(a->archive),
408 "Illeagal value `%s'",
410 return (ARCHIVE_FAILED);
412 zip->opt_compression_level = value[0] - '0';
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);
423 _7z_write_header(struct archive_write *a, struct archive_entry *entry)
429 zip = (struct _7zip *)a->format_data;
430 zip->cur_file = NULL;
431 zip->entry_bytes_remaining = 0;
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);
440 r = file_new(a, entry, &file);
441 if (r < ARCHIVE_WARN) {
446 if (file->flg & MTIME_IS_SET)
447 zip->total_number_time_defined[MTIME]++;
448 if (file->flg & CTIME_IS_SET)
449 zip->total_number_time_defined[CTIME]++;
450 if (file->flg & ATIME_IS_SET)
451 zip->total_number_time_defined[ATIME]++;
453 if (file->size == 0 && file->dir) {
454 if (!__archive_rb_tree_insert_node(&(zip->rbtree),
455 (struct archive_rb_node *)file))
458 zip->total_number_entry++;
459 zip->total_bytes_entry_name += file->name_len + 2;
460 if (file->size == 0) {
461 /* Count up the number of empty files. */
462 zip->total_number_empty_entry++;
464 zip->total_number_dir_entry++;
466 file_register_empty(zip, file);
473 if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
474 r = _7z_compression_init_encoder(a, zip->opt_compression,
475 zip->opt_compression_level);
478 return (ARCHIVE_FATAL);
482 /* Register a non-empty file. */
483 file_register(zip, file);
486 * Set the current file to cur_file to read its contents.
488 zip->cur_file = file;
491 /* Save a offset of current file in temporary file. */
492 zip->entry_bytes_remaining = file->size;
493 zip->entry_crc32 = 0;
496 * Store a symbolic link name as file contents.
498 if (archive_entry_filetype(entry) == AE_IFLNK) {
500 const void *p = (const void *)archive_entry_symlink(entry);
501 bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
504 zip->entry_crc32 = crc32(zip->entry_crc32, p, bytes);
505 zip->entry_bytes_remaining -= bytes;
512 * Write data to a temporary file.
515 write_to_temp(struct archive_write *a, const void *buff, size_t s)
518 const unsigned char *p;
521 zip = (struct _7zip *)a->format_data;
524 * Open a temporary file.
526 if (zip->temp_fd == -1) {
527 zip->temp_offset = 0;
528 zip->temp_fd = __archive_mktemp(NULL);
529 if (zip->temp_fd < 0) {
530 archive_set_error(&a->archive, errno,
531 "Couldn't create temporary file");
532 return (ARCHIVE_FATAL);
536 p = (const unsigned char *)buff;
538 ws = write(zip->temp_fd, p, s);
540 archive_set_error(&(a->archive), errno,
541 "fwrite function failed");
542 return (ARCHIVE_FATAL);
546 zip->temp_offset += ws;
552 compress_out(struct archive_write *a, const void *buff, size_t s,
555 struct _7zip *zip = (struct _7zip *)a->format_data;
558 if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
561 if ((zip->crc32flg & PRECODE_CRC32) && s)
562 zip->precode_crc32 = crc32(zip->precode_crc32, buff, s);
563 zip->stream.next_in = (const unsigned char *)buff;
564 zip->stream.avail_in = s;
566 /* Compress file data. */
567 r = compression_code(&(a->archive), &(zip->stream), run);
568 if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
569 return (ARCHIVE_FATAL);
570 if (zip->stream.avail_out == 0) {
571 if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
573 return (ARCHIVE_FATAL);
574 zip->stream.next_out = zip->wbuff;
575 zip->stream.avail_out = sizeof(zip->wbuff);
576 if (zip->crc32flg & ENCODED_CRC32)
577 zip->encoded_crc32 = crc32(zip->encoded_crc32,
578 zip->wbuff, sizeof(zip->wbuff));
580 } while (zip->stream.avail_in);
581 if (run == ARCHIVE_Z_FINISH) {
582 uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
583 if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
584 return (ARCHIVE_FATAL);
585 if ((zip->crc32flg & ENCODED_CRC32) && bytes)
586 zip->encoded_crc32 = crc32(zip->encoded_crc32,
587 zip->wbuff, (unsigned)bytes);
594 _7z_write_data(struct archive_write *a, const void *buff, size_t s)
599 zip = (struct _7zip *)a->format_data;
601 if (s > zip->entry_bytes_remaining)
602 s = (size_t)zip->entry_bytes_remaining;
603 if (s == 0 || zip->cur_file == NULL)
605 bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
608 zip->entry_crc32 = crc32(zip->entry_crc32, buff, bytes);
609 zip->entry_bytes_remaining -= bytes;
614 _7z_finish_entry(struct archive_write *a)
620 zip = (struct _7zip *)a->format_data;
621 if (zip->cur_file == NULL)
624 while (zip->entry_bytes_remaining > 0) {
625 s = (size_t)zip->entry_bytes_remaining;
626 if (s > a->null_length)
628 r = _7z_write_data(a, a->nulls, s);
632 zip->total_bytes_compressed += zip->stream.total_in;
633 zip->total_bytes_uncompressed += zip->stream.total_out;
634 zip->cur_file->crc32 = zip->entry_crc32;
635 zip->cur_file = NULL;
641 flush_wbuff(struct archive_write *a)
647 zip = (struct _7zip *)a->format_data;
648 s = sizeof(zip->wbuff) - zip->wbuff_remaining;
649 r = __archive_write_output(a, zip->wbuff, s);
652 zip->wbuff_remaining = sizeof(zip->wbuff);
657 copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
662 zip = (struct _7zip *)a->format_data;
663 if (zip->temp_offset > 0 &&
664 lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
665 archive_set_error(&(a->archive), errno, "lseek failed");
666 return (ARCHIVE_FATAL);
673 if (length > zip->wbuff_remaining)
674 rsize = zip->wbuff_remaining;
676 rsize = (size_t)length;
677 wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
678 rs = read(zip->temp_fd, wb, rsize);
680 archive_set_error(&(a->archive), errno,
681 "Can't read temporary file(%jd)",
683 return (ARCHIVE_FATAL);
686 archive_set_error(&(a->archive), 0,
687 "Truncated 7-Zip archive");
688 return (ARCHIVE_FATAL);
690 zip->wbuff_remaining -= rs;
692 if (zip->wbuff_remaining == 0) {
702 _7z_close(struct archive_write *a)
706 uint64_t header_offset, header_size, header_unpacksize;
708 uint32_t header_crc32;
711 zip = (struct _7zip *)a->format_data;
713 if (zip->total_number_entry > 0) {
714 struct archive_rb_node *n;
715 uint64_t data_offset, data_size, data_unpacksize;
716 unsigned header_compression;
718 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
722 data_size = zip->stream.total_out;
723 data_unpacksize = zip->stream.total_in;
724 zip->coder.codec = zip->opt_compression;
725 zip->coder.prop_size = zip->stream.prop_size;
726 zip->coder.props = zip->stream.props;
727 zip->stream.prop_size = 0;
728 zip->stream.props = NULL;
729 zip->total_number_nonempty_entry =
730 zip->total_number_entry - zip->total_number_empty_entry;
732 /* Connect an empty file list. */
733 if (zip->empty_list.first != NULL) {
734 *zip->file_list.last = zip->empty_list.first;
735 zip->file_list.last = zip->empty_list.last;
737 /* Connect a directory file list. */
738 ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
739 file_register(zip, (struct file *)n);
743 * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
744 * the compression type for encoding the header.
747 header_compression = _7Z_LZMA1;
748 /* If the stored file is only one, do not encode the header.
749 * This is the same way 7z command does. */
750 if (zip->total_number_entry == 1)
751 header_compression = _7Z_COPY;
753 header_compression = _7Z_COPY;
755 r = _7z_compression_init_encoder(a, header_compression, 6);
758 zip->crc32flg = PRECODE_CRC32;
759 zip->precode_crc32 = 0;
760 r = make_header(a, data_offset, data_size, data_unpacksize,
764 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
767 header_offset = data_offset + data_size;
768 header_size = zip->stream.total_out;
769 header_crc32 = zip->precode_crc32;
770 header_unpacksize = zip->stream.total_in;
772 if (header_compression != _7Z_COPY) {
774 * Encode the header in order to reduce the size
777 free(zip->coder.props);
778 zip->coder.codec = header_compression;
779 zip->coder.prop_size = zip->stream.prop_size;
780 zip->coder.props = zip->stream.props;
781 zip->stream.prop_size = 0;
782 zip->stream.props = NULL;
784 r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
787 zip->crc32flg = ENCODED_CRC32;
788 zip->encoded_crc32 = 0;
791 * Make EncodedHeader.
793 r = enc_uint64(a, kEncodedHeader);
796 r = make_streamsInfo(a, header_offset, header_size,
797 header_unpacksize, 1, &(zip->coder), 0,
801 r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
804 header_offset = header_offset + header_size;
805 header_size = zip->stream.total_out;
806 header_crc32 = zip->encoded_crc32;
810 header_offset = header_size = 0;
814 length = zip->temp_offset;
817 * Make the zip header on wbuff(write buffer).
820 zip->wbuff_remaining = sizeof(zip->wbuff);
821 memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
822 wb[6] = 0;/* Major version. */
823 wb[7] = 3;/* Minor version. */
824 archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
825 archive_le64enc(&wb[20], header_size);/* Next Header Size */
826 archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
827 archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
828 zip->wbuff_remaining -= 32;
831 * Read all file contents and an encoded header from the temporary
832 * file and write out it.
834 r = copy_out(a, 0, length);
842 * Encode 64 bits value into 7-Zip's encoded UINT64 value.
845 enc_uint64(struct archive_write *a, uint64_t val)
847 unsigned mask = 0x80;
852 for (i = 1; i < (int)sizeof(numdata); i++) {
854 numdata[0] |= (uint8_t)val;
857 numdata[i] = (uint8_t)val;
862 return (compress_out(a, numdata, i, ARCHIVE_Z_RUN));
866 make_substreamsInfo(struct archive_write *a, struct coder *coders)
868 struct _7zip *zip = (struct _7zip *)a->format_data;
873 * Make SubStreamsInfo.
875 r = enc_uint64(a, kSubStreamsInfo);
879 if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
881 * Make NumUnPackStream.
883 r = enc_uint64(a, kNumUnPackStream);
887 /* Write numUnpackStreams */
888 r = enc_uint64(a, zip->total_number_nonempty_entry);
895 r = enc_uint64(a, kSize);
898 file = zip->file_list.first;
899 for (;file != NULL; file = file->next) {
900 if (file->next == NULL ||
901 file->next->size == 0)
903 r = enc_uint64(a, file->size);
912 r = enc_uint64(a, kCRC);
917 /* All are defined */
918 r = enc_uint64(a, 1);
921 file = zip->file_list.first;
922 for (;file != NULL; file = file->next) {
926 archive_le32enc(crc, file->crc32);
927 r = compress_out(a, crc, 4, ARCHIVE_Z_RUN);
933 r = enc_uint64(a, kEnd);
940 make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
941 uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
944 struct _7zip *zip = (struct _7zip *)a->format_data;
945 uint8_t codec_buff[8];
950 if (coders->codec == _7Z_COPY)
951 numFolders = zip->total_number_nonempty_entry;
958 r = enc_uint64(a, kPackInfo);
963 r = enc_uint64(a, offset);
967 /* Write NumPackStreams. */
968 r = enc_uint64(a, numFolders);
973 r = enc_uint64(a, kSize);
977 if (numFolders > 1) {
978 struct file *file = zip->file_list.first;
979 for (;file != NULL; file = file->next) {
982 r = enc_uint64(a, file->size);
988 r = enc_uint64(a, pack_size);
993 r = enc_uint64(a, kEnd);
1000 r = enc_uint64(a, kUnPackInfo);
1007 r = enc_uint64(a, kFolder);
1011 /* Write NumFolders. */
1012 r = enc_uint64(a, numFolders);
1016 /* Write External. */
1017 r = enc_uint64(a, 0);
1021 for (fi = 0; fi < numFolders; fi++) {
1022 /* Write NumCoders. */
1023 r = enc_uint64(a, num_coder);
1027 for (i = 0; i < num_coder; i++) {
1028 unsigned codec_id = coders[i].codec;
1030 /* Write Codec flag. */
1031 archive_be64enc(codec_buff, codec_id);
1032 for (codec_size = 8; codec_size > 0; codec_size--) {
1033 if (codec_buff[8 - codec_size])
1036 if (codec_size == 0)
1038 if (coders[i].prop_size)
1039 r = enc_uint64(a, codec_size | 0x20);
1041 r = enc_uint64(a, codec_size);
1045 /* Write Codec ID. */
1047 r = compress_out(a, &codec_buff[8-codec_size],
1048 codec_size, ARCHIVE_Z_RUN);
1052 if (coders[i].prop_size) {
1053 /* Write Codec property size. */
1054 r = enc_uint64(a, coders[i].prop_size);
1058 /* Write Codec properties. */
1059 r = compress_out(a, coders[i].props,
1060 coders[i].prop_size, ARCHIVE_Z_RUN);
1068 * Make CodersUnPackSize.
1070 r = enc_uint64(a, kCodersUnPackSize);
1074 if (numFolders > 1) {
1075 struct file *file = zip->file_list.first;
1076 for (;file != NULL; file = file->next) {
1077 if (file->size == 0)
1079 r = enc_uint64(a, file->size);
1085 /* Write UnPackSize. */
1086 r = enc_uint64(a, unpack_size);
1096 r = enc_uint64(a, kCRC);
1100 /* All are defined */
1101 r = enc_uint64(a, 1);
1104 archive_le32enc(crc, header_crc);
1105 r = compress_out(a, crc, 4, ARCHIVE_Z_RUN);
1111 r = enc_uint64(a, kEnd);
1117 * Make SubStreamsInfo.
1119 r = make_substreamsInfo(a, coders);
1126 r = enc_uint64(a, kEnd);
1130 return (ARCHIVE_OK);
1134 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1136 utcToFiletime(time_t t, long ns)
1141 fileTime *= 10000000;
1142 fileTime += ns / 100;
1143 fileTime += EPOC_TIME;
1148 make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
1150 uint8_t filetime[8];
1151 struct _7zip *zip = (struct _7zip *)a->format_data;
1159 if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
1160 /* Write Time Type. */
1161 r = enc_uint64(a, type);
1164 /* Write EmptyStream Size. */
1165 r = enc_uint64(a, 2 + zip->total_number_entry * 8);
1168 /* All are defined. */
1169 r = enc_uint64(a, 1);
1173 if (zip->total_number_time_defined[ti] == 0)
1174 return (ARCHIVE_OK);
1176 /* Write Time Type. */
1177 r = enc_uint64(a, type);
1180 /* Write EmptyStream Size. */
1181 r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
1182 + zip->total_number_time_defined[ti] * 8);
1186 /* All are not defined. */
1187 r = enc_uint64(a, 0);
1193 file = zip->file_list.first;
1194 for (;file != NULL; file = file->next) {
1195 if (file->flg & flg)
1199 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1207 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1214 r = enc_uint64(a, 0);
1222 file = zip->file_list.first;
1223 for (;file != NULL; file = file->next) {
1224 if ((file->flg & flg) == 0)
1226 archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
1227 file->times[ti].time_ns));
1228 r = compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
1233 return (ARCHIVE_OK);
1237 make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
1238 uint64_t unpack_size, int codernum, struct coder *coders)
1240 struct _7zip *zip = (struct _7zip *)a->format_data;
1248 r = enc_uint64(a, kHeader);
1253 * If there are empty files only, do not write MainStreamInfo.
1255 if (zip->total_number_nonempty_entry) {
1257 * Make MainStreamInfo.
1259 r = enc_uint64(a, kMainStreamsInfo);
1262 r = make_streamsInfo(a, offset, pack_size, unpack_size,
1263 codernum, coders, 1, 0);
1271 r = enc_uint64(a, kFilesInfo);
1275 /* Write numFiles. */
1276 r = enc_uint64(a, zip->total_number_entry);
1280 if (zip->total_number_empty_entry > 0) {
1281 /* Make EmptyStream. */
1282 r = enc_uint64(a, kEmptyStream);
1286 /* Write EmptyStream Size. */
1287 r = enc_uint64(a, (zip->total_number_entry+7)>>3);
1293 file = zip->file_list.first;
1294 for (;file != NULL; file = file->next) {
1295 if (file->size == 0)
1299 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1307 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1313 if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
1314 /* Make EmptyFile. */
1315 r = enc_uint64(a, kEmptyFile);
1319 /* Write EmptyFile Size. */
1320 r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
1326 file = zip->file_list.first;
1327 for (;file != NULL; file = file->next) {
1334 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1342 r = compress_out(a, &b, 1, ARCHIVE_Z_RUN);
1349 r = enc_uint64(a, kName);
1353 /* Write Nume size. */
1354 r = enc_uint64(a, zip->total_bytes_entry_name+1);
1358 /* Write dmy byte. */
1359 r = enc_uint64(a, 0);
1363 file = zip->file_list.first;
1364 for (;file != NULL; file = file->next) {
1365 r = compress_out(a, file->utf16name, file->name_len+2,
1372 r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
1377 r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
1382 r = make_time(a, kATime, ATIME_IS_SET, ATIME);
1386 /* Make Attributes. */
1387 r = enc_uint64(a, kAttributes);
1391 /* Write Attributes size. */
1392 r = enc_uint64(a, 2 + zip->total_number_entry * 4);
1396 /* Write "All Are Defined". */
1397 r = enc_uint64(a, 1);
1401 /* Write dmy byte. */
1402 r = enc_uint64(a, 0);
1406 file = zip->file_list.first;
1407 for (;file != NULL; file = file->next) {
1409 * High 16bits is unix mode.
1410 * Low 16bits is Windows attributes.
1412 uint32_t encattr, attr;
1417 if ((file->mode & 0222) == 0)
1418 attr |= 1;/* Read Only. */
1419 attr |= ((uint32_t)file->mode) << 16;
1420 archive_le32enc(&encattr, attr);
1421 r = compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
1427 r = enc_uint64(a, kEnd);
1432 r = enc_uint64(a, kEnd);
1436 return (ARCHIVE_OK);
1441 _7z_free(struct archive_write *a)
1443 struct _7zip *zip = (struct _7zip *)a->format_data;
1445 file_free_register(zip);
1446 compression_end(&(a->archive), &(zip->stream));
1447 free(zip->coder.props);
1450 return (ARCHIVE_OK);
1454 file_cmp_node(const struct archive_rb_node *n1,
1455 const struct archive_rb_node *n2)
1457 const struct file *f1 = (const struct file *)n1;
1458 const struct file *f2 = (const struct file *)n2;
1460 if (f1->name_len == f2->name_len)
1461 return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
1462 return (f1->name_len > f2->name_len)?1:-1;
1466 file_cmp_key(const struct archive_rb_node *n, const void *key)
1468 const struct file *f = (const struct file *)n;
1470 return (f->name_len - *(const char *)key);
1474 file_new(struct archive_write *a, struct archive_entry *entry,
1475 struct file **newfile)
1481 int ret = ARCHIVE_OK;
1483 zip = (struct _7zip *)a->format_data;
1486 file = calloc(1, sizeof(*file));
1488 archive_set_error(&a->archive, ENOMEM,
1489 "Can't allocate memory");
1490 return (ARCHIVE_FATAL);
1493 if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
1494 if (errno == ENOMEM) {
1496 archive_set_error(&a->archive, ENOMEM,
1497 "Can't allocate memory for UTF-16LE");
1498 return (ARCHIVE_FATAL);
1500 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1501 "A filename cannot be converted to UTF-16LE;"
1502 "You should disable making Joliet extension");
1505 file->utf16name = malloc(u16len + 2);
1506 if (file->utf16name == NULL) {
1508 archive_set_error(&a->archive, ENOMEM,
1509 "Can't allocate memory for Name");
1510 return (ARCHIVE_FATAL);
1512 memcpy(file->utf16name, u16, u16len);
1513 file->utf16name[u16len+0] = 0;
1514 file->utf16name[u16len+1] = 0;
1515 file->name_len = u16len;
1516 file->mode = archive_entry_mode(entry);
1517 if (archive_entry_filetype(entry) == AE_IFREG)
1518 file->size = archive_entry_size(entry);
1520 archive_entry_set_size(entry, 0);
1521 if (archive_entry_filetype(entry) == AE_IFDIR)
1523 else if (archive_entry_filetype(entry) == AE_IFLNK)
1524 file->size = strlen(archive_entry_symlink(entry));
1525 if (archive_entry_mtime_is_set(entry)) {
1526 file->flg |= MTIME_IS_SET;
1527 file->times[MTIME].time = archive_entry_mtime(entry);
1528 file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
1530 if (archive_entry_atime_is_set(entry)) {
1531 file->flg |= ATIME_IS_SET;
1532 file->times[ATIME].time = archive_entry_atime(entry);
1533 file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
1535 if (archive_entry_ctime_is_set(entry)) {
1536 file->flg |= CTIME_IS_SET;
1537 file->times[CTIME].time = archive_entry_ctime(entry);
1538 file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
1546 file_free(struct file *file)
1548 free(file->utf16name);
1553 file_register(struct _7zip *zip, struct file *file)
1556 *zip->file_list.last = file;
1557 zip->file_list.last = &(file->next);
1561 file_init_register(struct _7zip *zip)
1563 zip->file_list.first = NULL;
1564 zip->file_list.last = &(zip->file_list.first);
1568 file_free_register(struct _7zip *zip)
1570 struct file *file, *file_next;
1572 file = zip->file_list.first;
1573 while (file != NULL) {
1574 file_next = file->next;
1581 file_register_empty(struct _7zip *zip, struct file *file)
1584 *zip->empty_list.last = file;
1585 zip->empty_list.last = &(file->next);
1589 file_init_register_empty(struct _7zip *zip)
1591 zip->empty_list.first = NULL;
1592 zip->empty_list.last = &(zip->empty_list.first);
1595 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
1596 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
1598 compression_unsupported_encoder(struct archive *a,
1599 struct la_zstream *lastrm, const char *name)
1602 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1603 "%s compression not supported on this platform", name);
1605 lastrm->real_stream = NULL;
1606 return (ARCHIVE_FAILED);
1611 * _7_COPY compressor.
1614 compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
1618 compression_end(a, lastrm);
1620 lastrm->code = compression_code_copy;
1621 lastrm->end = compression_end_copy;
1622 return (ARCHIVE_OK);
1626 compression_code_copy(struct archive *a,
1627 struct la_zstream *lastrm, enum la_zaction action)
1631 (void)a; /* UNUSED */
1632 if (lastrm->avail_out > lastrm->avail_in)
1633 bytes = lastrm->avail_in;
1635 bytes = lastrm->avail_out;
1637 memcpy(lastrm->next_out, lastrm->next_in, bytes);
1638 lastrm->next_in += bytes;
1639 lastrm->avail_in -= bytes;
1640 lastrm->total_in += bytes;
1641 lastrm->next_out += bytes;
1642 lastrm->avail_out -= bytes;
1643 lastrm->total_out += bytes;
1645 if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
1646 return (ARCHIVE_EOF);
1647 return (ARCHIVE_OK);
1651 compression_end_copy(struct archive *a, struct la_zstream *lastrm)
1653 (void)a; /* UNUSED */
1655 return (ARCHIVE_OK);
1659 * _7_DEFLATE compressor.
1663 compression_init_encoder_deflate(struct archive *a,
1664 struct la_zstream *lastrm, int level, int withheader)
1669 compression_end(a, lastrm);
1670 strm = calloc(1, sizeof(*strm));
1672 archive_set_error(a, ENOMEM,
1673 "Can't allocate memory for gzip stream");
1674 return (ARCHIVE_FATAL);
1676 /* zlib.h is not const-correct, so we need this one bit
1677 * of ugly hackery to convert a const * pointer to
1678 * a non-const pointer. */
1679 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1680 strm->avail_in = lastrm->avail_in;
1681 strm->total_in = (uLong)lastrm->total_in;
1682 strm->next_out = lastrm->next_out;
1683 strm->avail_out = lastrm->avail_out;
1684 strm->total_out = (uLong)lastrm->total_out;
1685 if (deflateInit2(strm, level, Z_DEFLATED,
1686 (withheader)?15:-15,
1687 8, Z_DEFAULT_STRATEGY) != Z_OK) {
1689 lastrm->real_stream = NULL;
1690 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1691 "Internal error initializing compression library");
1692 return (ARCHIVE_FATAL);
1694 lastrm->real_stream = strm;
1696 lastrm->code = compression_code_deflate;
1697 lastrm->end = compression_end_deflate;
1698 return (ARCHIVE_OK);
1702 compression_code_deflate(struct archive *a,
1703 struct la_zstream *lastrm, enum la_zaction action)
1708 strm = (z_stream *)lastrm->real_stream;
1709 /* zlib.h is not const-correct, so we need this one bit
1710 * of ugly hackery to convert a const * pointer to
1711 * a non-const pointer. */
1712 strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
1713 strm->avail_in = lastrm->avail_in;
1714 strm->total_in = (uLong)lastrm->total_in;
1715 strm->next_out = lastrm->next_out;
1716 strm->avail_out = lastrm->avail_out;
1717 strm->total_out = (uLong)lastrm->total_out;
1719 (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
1720 lastrm->next_in = strm->next_in;
1721 lastrm->avail_in = strm->avail_in;
1722 lastrm->total_in = strm->total_in;
1723 lastrm->next_out = strm->next_out;
1724 lastrm->avail_out = strm->avail_out;
1725 lastrm->total_out = strm->total_out;
1728 return (ARCHIVE_OK);
1730 return (ARCHIVE_EOF);
1732 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1733 "GZip compression failed:"
1734 " deflate() call returned status %d", r);
1735 return (ARCHIVE_FATAL);
1740 compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
1745 strm = (z_stream *)lastrm->real_stream;
1746 r = deflateEnd(strm);
1748 lastrm->real_stream = NULL;
1751 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1752 "Failed to clean up compressor");
1753 return (ARCHIVE_FATAL);
1755 return (ARCHIVE_OK);
1759 compression_init_encoder_deflate(struct archive *a,
1760 struct la_zstream *lastrm, int level, int withheader)
1763 (void) level; /* UNUSED */
1764 (void) withheader; /* UNUSED */
1766 compression_end(a, lastrm);
1767 return (compression_unsupported_encoder(a, lastrm, "deflate"));
1772 * _7_BZIP2 compressor.
1774 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
1776 compression_init_encoder_bzip2(struct archive *a,
1777 struct la_zstream *lastrm, int level)
1782 compression_end(a, lastrm);
1783 strm = calloc(1, sizeof(*strm));
1785 archive_set_error(a, ENOMEM,
1786 "Can't allocate memory for bzip2 stream");
1787 return (ARCHIVE_FATAL);
1789 /* bzlib.h is not const-correct, so we need this one bit
1790 * of ugly hackery to convert a const * pointer to
1791 * a non-const pointer. */
1792 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1793 strm->avail_in = lastrm->avail_in;
1794 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1795 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1796 strm->next_out = (char *)lastrm->next_out;
1797 strm->avail_out = lastrm->avail_out;
1798 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1799 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1800 if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
1802 lastrm->real_stream = NULL;
1803 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1804 "Internal error initializing compression library");
1805 return (ARCHIVE_FATAL);
1807 lastrm->real_stream = strm;
1809 lastrm->code = compression_code_bzip2;
1810 lastrm->end = compression_end_bzip2;
1811 return (ARCHIVE_OK);
1815 compression_code_bzip2(struct archive *a,
1816 struct la_zstream *lastrm, enum la_zaction action)
1821 strm = (bz_stream *)lastrm->real_stream;
1822 /* bzlib.h is not const-correct, so we need this one bit
1823 * of ugly hackery to convert a const * pointer to
1824 * a non-const pointer. */
1825 strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
1826 strm->avail_in = lastrm->avail_in;
1827 strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
1828 strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
1829 strm->next_out = (char *)lastrm->next_out;
1830 strm->avail_out = lastrm->avail_out;
1831 strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
1832 strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
1833 r = BZ2_bzCompress(strm,
1834 (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
1835 lastrm->next_in = (const unsigned char *)strm->next_in;
1836 lastrm->avail_in = strm->avail_in;
1838 (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
1839 + (uint64_t)(uint32_t)strm->total_in_lo32;
1840 lastrm->next_out = (unsigned char *)strm->next_out;
1841 lastrm->avail_out = strm->avail_out;
1843 (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
1844 + (uint64_t)(uint32_t)strm->total_out_lo32;
1846 case BZ_RUN_OK: /* Non-finishing */
1847 case BZ_FINISH_OK: /* Finishing: There's more work to do */
1848 return (ARCHIVE_OK);
1849 case BZ_STREAM_END: /* Finishing: all done */
1850 /* Only occurs in finishing case */
1851 return (ARCHIVE_EOF);
1853 /* Any other return value indicates an error */
1854 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1855 "Bzip2 compression failed:"
1856 " BZ2_bzCompress() call returned status %d", r);
1857 return (ARCHIVE_FATAL);
1862 compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
1867 strm = (bz_stream *)lastrm->real_stream;
1868 r = BZ2_bzCompressEnd(strm);
1870 lastrm->real_stream = NULL;
1873 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1874 "Failed to clean up compressor");
1875 return (ARCHIVE_FATAL);
1877 return (ARCHIVE_OK);
1882 compression_init_encoder_bzip2(struct archive *a,
1883 struct la_zstream *lastrm, int level)
1886 (void) level; /* UNUSED */
1888 compression_end(a, lastrm);
1889 return (compression_unsupported_encoder(a, lastrm, "bzip2"));
1894 * _7_LZMA1, _7_LZMA2 compressor.
1896 #if defined(HAVE_LZMA_H)
1898 compression_init_encoder_lzma(struct archive *a,
1899 struct la_zstream *lastrm, int level, uint64_t filter_id)
1901 static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
1903 lzma_filter *lzmafilters;
1904 lzma_options_lzma lzma_opt;
1908 compression_end(a, lastrm);
1909 strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
1911 archive_set_error(a, ENOMEM,
1912 "Can't allocate memory for lzma stream");
1913 return (ARCHIVE_FATAL);
1915 lzmafilters = (lzma_filter *)(strm+1);
1918 if (lzma_lzma_preset(&lzma_opt, level)) {
1920 lastrm->real_stream = NULL;
1921 archive_set_error(a, ENOMEM,
1922 "Internal error initializing compression library");
1923 return (ARCHIVE_FATAL);
1925 lzmafilters[0].id = filter_id;
1926 lzmafilters[0].options = &lzma_opt;
1927 lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
1929 r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
1932 lastrm->real_stream = NULL;
1933 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1934 "lzma_properties_size failed");
1935 return (ARCHIVE_FATAL);
1937 if (lastrm->prop_size) {
1938 lastrm->props = malloc(lastrm->prop_size);
1939 if (lastrm->props == NULL) {
1941 lastrm->real_stream = NULL;
1942 archive_set_error(a, ENOMEM,
1943 "Cannot allocate memory");
1944 return (ARCHIVE_FATAL);
1946 r = lzma_properties_encode(lzmafilters, lastrm->props);
1949 lastrm->real_stream = NULL;
1950 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1951 "lzma_properties_encode failed");
1952 return (ARCHIVE_FATAL);
1956 *strm = lzma_init_data;
1957 r = lzma_raw_encoder(strm, lzmafilters);
1960 lastrm->real_stream = strm;
1962 lastrm->code = compression_code_lzma;
1963 lastrm->end = compression_end_lzma;
1966 case LZMA_MEM_ERROR:
1968 lastrm->real_stream = NULL;
1969 archive_set_error(a, ENOMEM,
1970 "Internal error initializing compression library: "
1971 "Cannot allocate memory");
1976 lastrm->real_stream = NULL;
1977 archive_set_error(a, ARCHIVE_ERRNO_MISC,
1978 "Internal error initializing compression library: "
1979 "It's a bug in liblzma");
1987 compression_init_encoder_lzma1(struct archive *a,
1988 struct la_zstream *lastrm, int level)
1990 return compression_init_encoder_lzma(a, lastrm, level,
1995 compression_init_encoder_lzma2(struct archive *a,
1996 struct la_zstream *lastrm, int level)
1998 return compression_init_encoder_lzma(a, lastrm, level,
2003 compression_code_lzma(struct archive *a,
2004 struct la_zstream *lastrm, enum la_zaction action)
2009 strm = (lzma_stream *)lastrm->real_stream;
2010 strm->next_in = lastrm->next_in;
2011 strm->avail_in = lastrm->avail_in;
2012 strm->total_in = lastrm->total_in;
2013 strm->next_out = lastrm->next_out;
2014 strm->avail_out = lastrm->avail_out;
2015 strm->total_out = lastrm->total_out;
2017 (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
2018 lastrm->next_in = strm->next_in;
2019 lastrm->avail_in = strm->avail_in;
2020 lastrm->total_in = strm->total_in;
2021 lastrm->next_out = strm->next_out;
2022 lastrm->avail_out = strm->avail_out;
2023 lastrm->total_out = strm->total_out;
2026 /* Non-finishing case */
2027 return (ARCHIVE_OK);
2028 case LZMA_STREAM_END:
2029 /* This return can only occur in finishing case. */
2030 return (ARCHIVE_EOF);
2031 case LZMA_MEMLIMIT_ERROR:
2032 archive_set_error(a, ENOMEM,
2033 "lzma compression error:"
2034 " %ju MiB would have been needed",
2035 (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
2037 return (ARCHIVE_FATAL);
2039 /* Any other return value indicates an error */
2040 archive_set_error(a, ARCHIVE_ERRNO_MISC,
2041 "lzma compression failed:"
2042 " lzma_code() call returned status %d", r);
2043 return (ARCHIVE_FATAL);
2048 compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
2052 (void)a; /* UNUSED */
2053 strm = (lzma_stream *)lastrm->real_stream;
2057 lastrm->real_stream = NULL;
2058 return (ARCHIVE_OK);
2062 compression_init_encoder_lzma1(struct archive *a,
2063 struct la_zstream *lastrm, int level)
2066 (void) level; /* UNUSED */
2068 compression_end(a, lastrm);
2069 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2072 compression_init_encoder_lzma2(struct archive *a,
2073 struct la_zstream *lastrm, int level)
2076 (void) level; /* UNUSED */
2078 compression_end(a, lastrm);
2079 return (compression_unsupported_encoder(a, lastrm, "lzma"));
2084 * _7_PPMD compressor.
2087 ppmd_alloc(void *p, size_t size)
2090 return malloc(size);
2093 ppmd_free(void *p, void *address)
2098 static ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free };
2100 ppmd_write(void *p, Byte b)
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;
2107 if (lastrm->avail_out) {
2108 *lastrm->next_out++ = b;
2109 lastrm->avail_out--;
2110 lastrm->total_out++;
2113 strm = (struct ppmd_stream *)lastrm->real_stream;
2114 if (strm->buff_ptr < strm->buff_end) {
2115 *strm->buff_ptr++ = b;
2121 compression_init_encoder_ppmd(struct archive *a,
2122 struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
2124 struct ppmd_stream *strm;
2129 compression_end(a, lastrm);
2130 strm = calloc(1, sizeof(*strm));
2132 archive_set_error(a, ENOMEM,
2133 "Can't allocate memory for PPMd");
2134 return (ARCHIVE_FATAL);
2136 strm->buff = malloc(32);
2137 if (strm->buff == NULL) {
2139 archive_set_error(a, ENOMEM,
2140 "Can't allocate memory for PPMd");
2141 return (ARCHIVE_FATAL);
2143 strm->buff_ptr = strm->buff;
2144 strm->buff_end = strm->buff + 32;
2146 props = malloc(1+4);
2147 if (props == NULL) {
2150 archive_set_error(a, ENOMEM,
2151 "Coludn't allocate memory for PPMd");
2152 return (ARCHIVE_FATAL);
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, &g_szalloc);
2163 archive_set_error(a, ENOMEM,
2164 "Coludn't allocate memory for PPMd");
2165 return (ARCHIVE_FATAL);
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));
2174 lastrm->real_stream = strm;
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);
2184 compression_code_ppmd(struct archive *a,
2185 struct la_zstream *lastrm, enum la_zaction action)
2187 struct ppmd_stream *strm;
2189 (void)a; /* UNUSED */
2191 strm = (struct ppmd_stream *)lastrm->real_stream;
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++;
2202 if (strm->buff_bytes)
2203 return (ARCHIVE_OK);
2204 if (strm->stat == 1)
2205 return (ARCHIVE_EOF);
2206 strm->buff_ptr = strm->buff;
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++);
2215 if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
2216 __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
2217 &(strm->range_enc));
2219 /* Return EOF if there are no remaining bytes. */
2220 if (strm->buff_bytes == 0)
2221 return (ARCHIVE_EOF);
2223 return (ARCHIVE_OK);
2227 compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
2229 struct ppmd_stream *strm;
2231 (void)a; /* UNUSED */
2233 strm = (struct ppmd_stream *)lastrm->real_stream;
2234 __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc);
2237 lastrm->real_stream = NULL;
2239 return (ARCHIVE_OK);
2243 * Universal compressor initializer.
2246 _7z_compression_init_encoder(struct archive_write *a, unsigned compression,
2247 int compression_level)
2252 zip = (struct _7zip *)a->format_data;
2253 switch (compression) {
2255 r = compression_init_encoder_deflate(
2256 &(a->archive), &(zip->stream),
2257 compression_level, 0);
2260 r = compression_init_encoder_bzip2(
2261 &(a->archive), &(zip->stream),
2265 r = compression_init_encoder_lzma1(
2266 &(a->archive), &(zip->stream),
2270 r = compression_init_encoder_lzma2(
2271 &(a->archive), &(zip->stream),
2275 r = compression_init_encoder_ppmd(
2276 &(a->archive), &(zip->stream),
2277 PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
2281 r = compression_init_encoder_copy(
2282 &(a->archive), &(zip->stream));
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;
2296 compression_code(struct archive *a, struct la_zstream *lastrm,
2297 enum la_zaction action)
2300 return (lastrm->code(a, lastrm, action));
2301 return (ARCHIVE_OK);
2305 compression_end(struct archive *a, struct la_zstream *lastrm)
2307 if (lastrm->valid) {
2308 lastrm->prop_size = 0;
2309 free(lastrm->props);
2310 lastrm->props = NULL;
2311 return (lastrm->end(a, lastrm));
2313 return (ARCHIVE_OK);