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 "Unknown 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 "Illegal 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
) {
445 if (file
->size
== 0 && file
->dir
) {
446 if (!__archive_rb_tree_insert_node(&(zip
->rbtree
),
447 (struct archive_rb_node
*)file
)) {
448 /* We have already had the same file. */
454 if (file
->flg
& MTIME_IS_SET
)
455 zip
->total_number_time_defined
[MTIME
]++;
456 if (file
->flg
& CTIME_IS_SET
)
457 zip
->total_number_time_defined
[CTIME
]++;
458 if (file
->flg
& ATIME_IS_SET
)
459 zip
->total_number_time_defined
[ATIME
]++;
461 zip
->total_number_entry
++;
462 zip
->total_bytes_entry_name
+= file
->name_len
+ 2;
463 if (file
->size
== 0) {
464 /* Count up the number of empty files. */
465 zip
->total_number_empty_entry
++;
467 zip
->total_number_dir_entry
++;
469 file_register_empty(zip
, file
);
476 if ((zip
->total_number_entry
- zip
->total_number_empty_entry
) == 1) {
477 r
= _7z_compression_init_encoder(a
, zip
->opt_compression
,
478 zip
->opt_compression_level
);
481 return (ARCHIVE_FATAL
);
485 /* Register a non-empty file. */
486 file_register(zip
, file
);
489 * Set the current file to cur_file to read its contents.
491 zip
->cur_file
= file
;
494 /* Save a offset of current file in temporary file. */
495 zip
->entry_bytes_remaining
= file
->size
;
496 zip
->entry_crc32
= 0;
499 * Store a symbolic link name as file contents.
501 if (archive_entry_filetype(entry
) == AE_IFLNK
) {
503 const void *p
= (const void *)archive_entry_symlink(entry
);
504 bytes
= compress_out(a
, p
, (size_t)file
->size
, ARCHIVE_Z_RUN
);
507 zip
->entry_crc32
= crc32(zip
->entry_crc32
, p
, (unsigned)bytes
);
508 zip
->entry_bytes_remaining
-= bytes
;
515 * Write data to a temporary file.
518 write_to_temp(struct archive_write
*a
, const void *buff
, size_t s
)
521 const unsigned char *p
;
524 zip
= (struct _7zip
*)a
->format_data
;
527 * Open a temporary file.
529 if (zip
->temp_fd
== -1) {
530 zip
->temp_offset
= 0;
531 zip
->temp_fd
= __archive_mktemp(NULL
);
532 if (zip
->temp_fd
< 0) {
533 archive_set_error(&a
->archive
, errno
,
534 "Couldn't create temporary file");
535 return (ARCHIVE_FATAL
);
539 p
= (const unsigned char *)buff
;
541 ws
= write(zip
->temp_fd
, p
, s
);
543 archive_set_error(&(a
->archive
), errno
,
544 "fwrite function failed");
545 return (ARCHIVE_FATAL
);
549 zip
->temp_offset
+= ws
;
555 compress_out(struct archive_write
*a
, const void *buff
, size_t s
,
558 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
561 if (run
== ARCHIVE_Z_FINISH
&& zip
->stream
.total_in
== 0 && s
== 0)
564 if ((zip
->crc32flg
& PRECODE_CRC32
) && s
)
565 zip
->precode_crc32
= crc32(zip
->precode_crc32
, buff
,
567 zip
->stream
.next_in
= (const unsigned char *)buff
;
568 zip
->stream
.avail_in
= s
;
570 /* Compress file data. */
571 r
= compression_code(&(a
->archive
), &(zip
->stream
), run
);
572 if (r
!= ARCHIVE_OK
&& r
!= ARCHIVE_EOF
)
573 return (ARCHIVE_FATAL
);
574 if (zip
->stream
.avail_out
== 0) {
575 if (write_to_temp(a
, zip
->wbuff
, sizeof(zip
->wbuff
))
577 return (ARCHIVE_FATAL
);
578 zip
->stream
.next_out
= zip
->wbuff
;
579 zip
->stream
.avail_out
= sizeof(zip
->wbuff
);
580 if (zip
->crc32flg
& ENCODED_CRC32
)
581 zip
->encoded_crc32
= crc32(zip
->encoded_crc32
,
582 zip
->wbuff
, sizeof(zip
->wbuff
));
583 if (run
== ARCHIVE_Z_FINISH
&& r
!= ARCHIVE_EOF
)
586 if (zip
->stream
.avail_in
== 0)
589 if (run
== ARCHIVE_Z_FINISH
) {
590 uint64_t bytes
= sizeof(zip
->wbuff
) - zip
->stream
.avail_out
;
591 if (write_to_temp(a
, zip
->wbuff
, (size_t)bytes
) != ARCHIVE_OK
)
592 return (ARCHIVE_FATAL
);
593 if ((zip
->crc32flg
& ENCODED_CRC32
) && bytes
)
594 zip
->encoded_crc32
= crc32(zip
->encoded_crc32
,
595 zip
->wbuff
, (unsigned)bytes
);
602 _7z_write_data(struct archive_write
*a
, const void *buff
, size_t s
)
607 zip
= (struct _7zip
*)a
->format_data
;
609 if (s
> zip
->entry_bytes_remaining
)
610 s
= (size_t)zip
->entry_bytes_remaining
;
611 if (s
== 0 || zip
->cur_file
== NULL
)
613 bytes
= compress_out(a
, buff
, s
, ARCHIVE_Z_RUN
);
616 zip
->entry_crc32
= crc32(zip
->entry_crc32
, buff
, (unsigned)bytes
);
617 zip
->entry_bytes_remaining
-= bytes
;
622 _7z_finish_entry(struct archive_write
*a
)
628 zip
= (struct _7zip
*)a
->format_data
;
629 if (zip
->cur_file
== NULL
)
632 while (zip
->entry_bytes_remaining
> 0) {
633 s
= (size_t)zip
->entry_bytes_remaining
;
634 if (s
> a
->null_length
)
636 r
= _7z_write_data(a
, a
->nulls
, s
);
640 zip
->total_bytes_compressed
+= zip
->stream
.total_in
;
641 zip
->total_bytes_uncompressed
+= zip
->stream
.total_out
;
642 zip
->cur_file
->crc32
= zip
->entry_crc32
;
643 zip
->cur_file
= NULL
;
649 flush_wbuff(struct archive_write
*a
)
655 zip
= (struct _7zip
*)a
->format_data
;
656 s
= sizeof(zip
->wbuff
) - zip
->wbuff_remaining
;
657 r
= __archive_write_output(a
, zip
->wbuff
, s
);
660 zip
->wbuff_remaining
= sizeof(zip
->wbuff
);
665 copy_out(struct archive_write
*a
, uint64_t offset
, uint64_t length
)
670 zip
= (struct _7zip
*)a
->format_data
;
671 if (zip
->temp_offset
> 0 &&
672 lseek(zip
->temp_fd
, offset
, SEEK_SET
) < 0) {
673 archive_set_error(&(a
->archive
), errno
, "lseek failed");
674 return (ARCHIVE_FATAL
);
681 if (length
> zip
->wbuff_remaining
)
682 rsize
= zip
->wbuff_remaining
;
684 rsize
= (size_t)length
;
685 wb
= zip
->wbuff
+ (sizeof(zip
->wbuff
) - zip
->wbuff_remaining
);
686 rs
= read(zip
->temp_fd
, wb
, rsize
);
688 archive_set_error(&(a
->archive
), errno
,
689 "Can't read temporary file(%jd)",
691 return (ARCHIVE_FATAL
);
694 archive_set_error(&(a
->archive
), 0,
695 "Truncated 7-Zip archive");
696 return (ARCHIVE_FATAL
);
698 zip
->wbuff_remaining
-= rs
;
700 if (zip
->wbuff_remaining
== 0) {
710 _7z_close(struct archive_write
*a
)
714 uint64_t header_offset
, header_size
, header_unpacksize
;
716 uint32_t header_crc32
;
719 zip
= (struct _7zip
*)a
->format_data
;
721 if (zip
->total_number_entry
> 0) {
722 struct archive_rb_node
*n
;
723 uint64_t data_offset
, data_size
, data_unpacksize
;
724 unsigned header_compression
;
726 r
= (int)compress_out(a
, NULL
, 0, ARCHIVE_Z_FINISH
);
730 data_size
= zip
->stream
.total_out
;
731 data_unpacksize
= zip
->stream
.total_in
;
732 zip
->coder
.codec
= zip
->opt_compression
;
733 zip
->coder
.prop_size
= zip
->stream
.prop_size
;
734 zip
->coder
.props
= zip
->stream
.props
;
735 zip
->stream
.prop_size
= 0;
736 zip
->stream
.props
= NULL
;
737 zip
->total_number_nonempty_entry
=
738 zip
->total_number_entry
- zip
->total_number_empty_entry
;
740 /* Connect an empty file list. */
741 if (zip
->empty_list
.first
!= NULL
) {
742 *zip
->file_list
.last
= zip
->empty_list
.first
;
743 zip
->file_list
.last
= zip
->empty_list
.last
;
745 /* Connect a directory file list. */
746 ARCHIVE_RB_TREE_FOREACH(n
, &(zip
->rbtree
)) {
747 file_register(zip
, (struct file
*)n
);
751 * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
752 * the compression type for encoding the header.
755 header_compression
= _7Z_LZMA1
;
756 /* If the stored file is only one, do not encode the header.
757 * This is the same way 7z command does. */
758 if (zip
->total_number_entry
== 1)
759 header_compression
= _7Z_COPY
;
761 header_compression
= _7Z_COPY
;
763 r
= _7z_compression_init_encoder(a
, header_compression
, 6);
766 zip
->crc32flg
= PRECODE_CRC32
;
767 zip
->precode_crc32
= 0;
768 r
= make_header(a
, data_offset
, data_size
, data_unpacksize
,
772 r
= (int)compress_out(a
, NULL
, 0, ARCHIVE_Z_FINISH
);
775 header_offset
= data_offset
+ data_size
;
776 header_size
= zip
->stream
.total_out
;
777 header_crc32
= zip
->precode_crc32
;
778 header_unpacksize
= zip
->stream
.total_in
;
780 if (header_compression
!= _7Z_COPY
) {
782 * Encode the header in order to reduce the size
785 free(zip
->coder
.props
);
786 zip
->coder
.codec
= header_compression
;
787 zip
->coder
.prop_size
= zip
->stream
.prop_size
;
788 zip
->coder
.props
= zip
->stream
.props
;
789 zip
->stream
.prop_size
= 0;
790 zip
->stream
.props
= NULL
;
792 r
= _7z_compression_init_encoder(a
, _7Z_COPY
, 0);
795 zip
->crc32flg
= ENCODED_CRC32
;
796 zip
->encoded_crc32
= 0;
799 * Make EncodedHeader.
801 r
= enc_uint64(a
, kEncodedHeader
);
804 r
= make_streamsInfo(a
, header_offset
, header_size
,
805 header_unpacksize
, 1, &(zip
->coder
), 0,
809 r
= (int)compress_out(a
, NULL
, 0, ARCHIVE_Z_FINISH
);
812 header_offset
= header_offset
+ header_size
;
813 header_size
= zip
->stream
.total_out
;
814 header_crc32
= zip
->encoded_crc32
;
818 header_offset
= header_size
= 0;
822 length
= zip
->temp_offset
;
825 * Make the zip header on wbuff(write buffer).
828 zip
->wbuff_remaining
= sizeof(zip
->wbuff
);
829 memcpy(&wb
[0], "7z\xBC\xAF\x27\x1C", 6);
830 wb
[6] = 0;/* Major version. */
831 wb
[7] = 3;/* Minor version. */
832 archive_le64enc(&wb
[12], header_offset
);/* Next Header Offset */
833 archive_le64enc(&wb
[20], header_size
);/* Next Header Size */
834 archive_le32enc(&wb
[28], header_crc32
);/* Next Header CRC */
835 archive_le32enc(&wb
[8], crc32(0, &wb
[12], 20));/* Start Header CRC */
836 zip
->wbuff_remaining
-= 32;
839 * Read all file contents and an encoded header from the temporary
840 * file and write out it.
842 r
= copy_out(a
, 0, length
);
850 * Encode 64 bits value into 7-Zip's encoded UINT64 value.
853 enc_uint64(struct archive_write
*a
, uint64_t val
)
855 unsigned mask
= 0x80;
860 for (i
= 1; i
< (int)sizeof(numdata
); i
++) {
862 numdata
[0] |= (uint8_t)val
;
865 numdata
[i
] = (uint8_t)val
;
870 return ((int)compress_out(a
, numdata
, i
, ARCHIVE_Z_RUN
));
874 make_substreamsInfo(struct archive_write
*a
, struct coder
*coders
)
876 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
881 * Make SubStreamsInfo.
883 r
= enc_uint64(a
, kSubStreamsInfo
);
887 if (zip
->total_number_nonempty_entry
> 1 && coders
->codec
!= _7Z_COPY
) {
889 * Make NumUnPackStream.
891 r
= enc_uint64(a
, kNumUnPackStream
);
895 /* Write numUnpackStreams */
896 r
= enc_uint64(a
, zip
->total_number_nonempty_entry
);
903 r
= enc_uint64(a
, kSize
);
906 file
= zip
->file_list
.first
;
907 for (;file
!= NULL
; file
= file
->next
) {
908 if (file
->next
== NULL
||
909 file
->next
->size
== 0)
911 r
= enc_uint64(a
, file
->size
);
920 r
= enc_uint64(a
, kCRC
);
925 /* All are defined */
926 r
= enc_uint64(a
, 1);
929 file
= zip
->file_list
.first
;
930 for (;file
!= NULL
; file
= file
->next
) {
934 archive_le32enc(crc
, file
->crc32
);
935 r
= (int)compress_out(a
, crc
, 4, ARCHIVE_Z_RUN
);
941 r
= enc_uint64(a
, kEnd
);
948 make_streamsInfo(struct archive_write
*a
, uint64_t offset
, uint64_t pack_size
,
949 uint64_t unpack_size
, int num_coder
, struct coder
*coders
, int substrm
,
952 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
953 uint8_t codec_buff
[8];
958 if (coders
->codec
== _7Z_COPY
)
959 numFolders
= (int)zip
->total_number_nonempty_entry
;
966 r
= enc_uint64(a
, kPackInfo
);
971 r
= enc_uint64(a
, offset
);
975 /* Write NumPackStreams. */
976 r
= enc_uint64(a
, numFolders
);
981 r
= enc_uint64(a
, kSize
);
985 if (numFolders
> 1) {
986 struct file
*file
= zip
->file_list
.first
;
987 for (;file
!= NULL
; file
= file
->next
) {
990 r
= enc_uint64(a
, file
->size
);
996 r
= enc_uint64(a
, pack_size
);
1001 r
= enc_uint64(a
, kEnd
);
1008 r
= enc_uint64(a
, kUnPackInfo
);
1015 r
= enc_uint64(a
, kFolder
);
1019 /* Write NumFolders. */
1020 r
= enc_uint64(a
, numFolders
);
1024 /* Write External. */
1025 r
= enc_uint64(a
, 0);
1029 for (fi
= 0; fi
< numFolders
; fi
++) {
1030 /* Write NumCoders. */
1031 r
= enc_uint64(a
, num_coder
);
1035 for (i
= 0; i
< num_coder
; i
++) {
1036 unsigned codec_id
= coders
[i
].codec
;
1038 /* Write Codec flag. */
1039 archive_be64enc(codec_buff
, codec_id
);
1040 for (codec_size
= 8; codec_size
> 0; codec_size
--) {
1041 if (codec_buff
[8 - codec_size
])
1044 if (codec_size
== 0)
1046 if (coders
[i
].prop_size
)
1047 r
= enc_uint64(a
, codec_size
| 0x20);
1049 r
= enc_uint64(a
, codec_size
);
1053 /* Write Codec ID. */
1055 r
= (int)compress_out(a
, &codec_buff
[8-codec_size
],
1056 codec_size
, ARCHIVE_Z_RUN
);
1060 if (coders
[i
].prop_size
) {
1061 /* Write Codec property size. */
1062 r
= enc_uint64(a
, coders
[i
].prop_size
);
1066 /* Write Codec properties. */
1067 r
= (int)compress_out(a
, coders
[i
].props
,
1068 coders
[i
].prop_size
, ARCHIVE_Z_RUN
);
1076 * Make CodersUnPackSize.
1078 r
= enc_uint64(a
, kCodersUnPackSize
);
1082 if (numFolders
> 1) {
1083 struct file
*file
= zip
->file_list
.first
;
1084 for (;file
!= NULL
; file
= file
->next
) {
1085 if (file
->size
== 0)
1087 r
= enc_uint64(a
, file
->size
);
1093 /* Write UnPackSize. */
1094 r
= enc_uint64(a
, unpack_size
);
1104 r
= enc_uint64(a
, kCRC
);
1108 /* All are defined */
1109 r
= enc_uint64(a
, 1);
1112 archive_le32enc(crc
, header_crc
);
1113 r
= (int)compress_out(a
, crc
, 4, ARCHIVE_Z_RUN
);
1119 r
= enc_uint64(a
, kEnd
);
1125 * Make SubStreamsInfo.
1127 r
= make_substreamsInfo(a
, coders
);
1134 r
= enc_uint64(a
, kEnd
);
1138 return (ARCHIVE_OK
);
1142 #define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
1144 utcToFiletime(time_t t
, long ns
)
1149 fileTime
*= 10000000;
1150 fileTime
+= ns
/ 100;
1151 fileTime
+= EPOC_TIME
;
1156 make_time(struct archive_write
*a
, uint8_t type
, unsigned flg
, int ti
)
1158 uint8_t filetime
[8];
1159 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
1167 if (zip
->total_number_time_defined
[ti
] == zip
->total_number_entry
) {
1168 /* Write Time Type. */
1169 r
= enc_uint64(a
, type
);
1172 /* Write EmptyStream Size. */
1173 r
= enc_uint64(a
, 2 + zip
->total_number_entry
* 8);
1176 /* All are defined. */
1177 r
= enc_uint64(a
, 1);
1181 if (zip
->total_number_time_defined
[ti
] == 0)
1182 return (ARCHIVE_OK
);
1184 /* Write Time Type. */
1185 r
= enc_uint64(a
, type
);
1188 /* Write EmptyStream Size. */
1189 r
= enc_uint64(a
, 2 + ((zip
->total_number_entry
+ 7) >> 3)
1190 + zip
->total_number_time_defined
[ti
] * 8);
1194 /* All are not defined. */
1195 r
= enc_uint64(a
, 0);
1201 file
= zip
->file_list
.first
;
1202 for (;file
!= NULL
; file
= file
->next
) {
1203 if (file
->flg
& flg
)
1207 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1215 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1222 r
= enc_uint64(a
, 0);
1230 file
= zip
->file_list
.first
;
1231 for (;file
!= NULL
; file
= file
->next
) {
1232 if ((file
->flg
& flg
) == 0)
1234 archive_le64enc(filetime
, utcToFiletime(file
->times
[ti
].time
,
1235 file
->times
[ti
].time_ns
));
1236 r
= (int)compress_out(a
, filetime
, 8, ARCHIVE_Z_RUN
);
1241 return (ARCHIVE_OK
);
1245 make_header(struct archive_write
*a
, uint64_t offset
, uint64_t pack_size
,
1246 uint64_t unpack_size
, int codernum
, struct coder
*coders
)
1248 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
1256 r
= enc_uint64(a
, kHeader
);
1261 * If there are empty files only, do not write MainStreamInfo.
1263 if (zip
->total_number_nonempty_entry
) {
1265 * Make MainStreamInfo.
1267 r
= enc_uint64(a
, kMainStreamsInfo
);
1270 r
= make_streamsInfo(a
, offset
, pack_size
, unpack_size
,
1271 codernum
, coders
, 1, 0);
1279 r
= enc_uint64(a
, kFilesInfo
);
1283 /* Write numFiles. */
1284 r
= enc_uint64(a
, zip
->total_number_entry
);
1288 if (zip
->total_number_empty_entry
> 0) {
1289 /* Make EmptyStream. */
1290 r
= enc_uint64(a
, kEmptyStream
);
1294 /* Write EmptyStream Size. */
1295 r
= enc_uint64(a
, (zip
->total_number_entry
+7)>>3);
1301 file
= zip
->file_list
.first
;
1302 for (;file
!= NULL
; file
= file
->next
) {
1303 if (file
->size
== 0)
1307 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1315 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1321 if (zip
->total_number_empty_entry
> zip
->total_number_dir_entry
) {
1322 /* Make EmptyFile. */
1323 r
= enc_uint64(a
, kEmptyFile
);
1327 /* Write EmptyFile Size. */
1328 r
= enc_uint64(a
, (zip
->total_number_empty_entry
+ 7) >> 3);
1334 file
= zip
->file_list
.first
;
1335 for (;file
!= NULL
; file
= file
->next
) {
1342 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1350 r
= (int)compress_out(a
, &b
, 1, ARCHIVE_Z_RUN
);
1357 r
= enc_uint64(a
, kName
);
1361 /* Write Nume size. */
1362 r
= enc_uint64(a
, zip
->total_bytes_entry_name
+1);
1366 /* Write dmy byte. */
1367 r
= enc_uint64(a
, 0);
1371 file
= zip
->file_list
.first
;
1372 for (;file
!= NULL
; file
= file
->next
) {
1373 r
= (int)compress_out(a
, file
->utf16name
, file
->name_len
+2,
1380 r
= make_time(a
, kMTime
, MTIME_IS_SET
, MTIME
);
1385 r
= make_time(a
, kCTime
, CTIME_IS_SET
, CTIME
);
1390 r
= make_time(a
, kATime
, ATIME_IS_SET
, ATIME
);
1394 /* Make Attributes. */
1395 r
= enc_uint64(a
, kAttributes
);
1399 /* Write Attributes size. */
1400 r
= enc_uint64(a
, 2 + zip
->total_number_entry
* 4);
1404 /* Write "All Are Defined". */
1405 r
= enc_uint64(a
, 1);
1409 /* Write dmy byte. */
1410 r
= enc_uint64(a
, 0);
1414 file
= zip
->file_list
.first
;
1415 for (;file
!= NULL
; file
= file
->next
) {
1417 * High 16bits is unix mode.
1418 * Low 16bits is Windows attributes.
1420 uint32_t encattr
, attr
;
1425 if ((file
->mode
& 0222) == 0)
1426 attr
|= 1;/* Read Only. */
1427 attr
|= ((uint32_t)file
->mode
) << 16;
1428 archive_le32enc(&encattr
, attr
);
1429 r
= (int)compress_out(a
, &encattr
, 4, ARCHIVE_Z_RUN
);
1435 r
= enc_uint64(a
, kEnd
);
1440 r
= enc_uint64(a
, kEnd
);
1444 return (ARCHIVE_OK
);
1449 _7z_free(struct archive_write
*a
)
1451 struct _7zip
*zip
= (struct _7zip
*)a
->format_data
;
1453 /* Close the temporary file. */
1454 if (zip
->temp_fd
>= 0)
1455 close(zip
->temp_fd
);
1457 file_free_register(zip
);
1458 compression_end(&(a
->archive
), &(zip
->stream
));
1459 free(zip
->coder
.props
);
1462 return (ARCHIVE_OK
);
1466 file_cmp_node(const struct archive_rb_node
*n1
,
1467 const struct archive_rb_node
*n2
)
1469 const struct file
*f1
= (const struct file
*)n1
;
1470 const struct file
*f2
= (const struct file
*)n2
;
1472 if (f1
->name_len
== f2
->name_len
)
1473 return (memcmp(f1
->utf16name
, f2
->utf16name
, f1
->name_len
));
1474 return (f1
->name_len
> f2
->name_len
)?1:-1;
1478 file_cmp_key(const struct archive_rb_node
*n
, const void *key
)
1480 const struct file
*f
= (const struct file
*)n
;
1482 return (f
->name_len
- *(const char *)key
);
1486 file_new(struct archive_write
*a
, struct archive_entry
*entry
,
1487 struct file
**newfile
)
1493 int ret
= ARCHIVE_OK
;
1495 zip
= (struct _7zip
*)a
->format_data
;
1498 file
= calloc(1, sizeof(*file
));
1500 archive_set_error(&a
->archive
, ENOMEM
,
1501 "Can't allocate memory");
1502 return (ARCHIVE_FATAL
);
1505 if (0 > archive_entry_pathname_l(entry
, &u16
, &u16len
, zip
->sconv
)) {
1506 if (errno
== ENOMEM
) {
1508 archive_set_error(&a
->archive
, ENOMEM
,
1509 "Can't allocate memory for UTF-16LE");
1510 return (ARCHIVE_FATAL
);
1512 archive_set_error(&a
->archive
, ARCHIVE_ERRNO_MISC
,
1513 "A filename cannot be converted to UTF-16LE;"
1514 "You should disable making Joliet extension");
1517 file
->utf16name
= malloc(u16len
+ 2);
1518 if (file
->utf16name
== NULL
) {
1520 archive_set_error(&a
->archive
, ENOMEM
,
1521 "Can't allocate memory for Name");
1522 return (ARCHIVE_FATAL
);
1524 memcpy(file
->utf16name
, u16
, u16len
);
1525 file
->utf16name
[u16len
+0] = 0;
1526 file
->utf16name
[u16len
+1] = 0;
1527 file
->name_len
= (unsigned)u16len
;
1528 file
->mode
= archive_entry_mode(entry
);
1529 if (archive_entry_filetype(entry
) == AE_IFREG
)
1530 file
->size
= archive_entry_size(entry
);
1532 archive_entry_set_size(entry
, 0);
1533 if (archive_entry_filetype(entry
) == AE_IFDIR
)
1535 else if (archive_entry_filetype(entry
) == AE_IFLNK
)
1536 file
->size
= strlen(archive_entry_symlink(entry
));
1537 if (archive_entry_mtime_is_set(entry
)) {
1538 file
->flg
|= MTIME_IS_SET
;
1539 file
->times
[MTIME
].time
= archive_entry_mtime(entry
);
1540 file
->times
[MTIME
].time_ns
= archive_entry_mtime_nsec(entry
);
1542 if (archive_entry_atime_is_set(entry
)) {
1543 file
->flg
|= ATIME_IS_SET
;
1544 file
->times
[ATIME
].time
= archive_entry_atime(entry
);
1545 file
->times
[ATIME
].time_ns
= archive_entry_atime_nsec(entry
);
1547 if (archive_entry_ctime_is_set(entry
)) {
1548 file
->flg
|= CTIME_IS_SET
;
1549 file
->times
[CTIME
].time
= archive_entry_ctime(entry
);
1550 file
->times
[CTIME
].time_ns
= archive_entry_ctime_nsec(entry
);
1558 file_free(struct file
*file
)
1560 free(file
->utf16name
);
1565 file_register(struct _7zip
*zip
, struct file
*file
)
1568 *zip
->file_list
.last
= file
;
1569 zip
->file_list
.last
= &(file
->next
);
1573 file_init_register(struct _7zip
*zip
)
1575 zip
->file_list
.first
= NULL
;
1576 zip
->file_list
.last
= &(zip
->file_list
.first
);
1580 file_free_register(struct _7zip
*zip
)
1582 struct file
*file
, *file_next
;
1584 file
= zip
->file_list
.first
;
1585 while (file
!= NULL
) {
1586 file_next
= file
->next
;
1593 file_register_empty(struct _7zip
*zip
, struct file
*file
)
1596 *zip
->empty_list
.last
= file
;
1597 zip
->empty_list
.last
= &(file
->next
);
1601 file_init_register_empty(struct _7zip
*zip
)
1603 zip
->empty_list
.first
= NULL
;
1604 zip
->empty_list
.last
= &(zip
->empty_list
.first
);
1607 #if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
1608 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
1610 compression_unsupported_encoder(struct archive
*a
,
1611 struct la_zstream
*lastrm
, const char *name
)
1614 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1615 "%s compression not supported on this platform", name
);
1617 lastrm
->real_stream
= NULL
;
1618 return (ARCHIVE_FAILED
);
1623 * _7_COPY compressor.
1626 compression_init_encoder_copy(struct archive
*a
, struct la_zstream
*lastrm
)
1630 compression_end(a
, lastrm
);
1632 lastrm
->code
= compression_code_copy
;
1633 lastrm
->end
= compression_end_copy
;
1634 return (ARCHIVE_OK
);
1638 compression_code_copy(struct archive
*a
,
1639 struct la_zstream
*lastrm
, enum la_zaction action
)
1643 (void)a
; /* UNUSED */
1644 if (lastrm
->avail_out
> lastrm
->avail_in
)
1645 bytes
= lastrm
->avail_in
;
1647 bytes
= lastrm
->avail_out
;
1649 memcpy(lastrm
->next_out
, lastrm
->next_in
, bytes
);
1650 lastrm
->next_in
+= bytes
;
1651 lastrm
->avail_in
-= bytes
;
1652 lastrm
->total_in
+= bytes
;
1653 lastrm
->next_out
+= bytes
;
1654 lastrm
->avail_out
-= bytes
;
1655 lastrm
->total_out
+= bytes
;
1657 if (action
== ARCHIVE_Z_FINISH
&& lastrm
->avail_in
== 0)
1658 return (ARCHIVE_EOF
);
1659 return (ARCHIVE_OK
);
1663 compression_end_copy(struct archive
*a
, struct la_zstream
*lastrm
)
1665 (void)a
; /* UNUSED */
1667 return (ARCHIVE_OK
);
1671 * _7_DEFLATE compressor.
1675 compression_init_encoder_deflate(struct archive
*a
,
1676 struct la_zstream
*lastrm
, int level
, int withheader
)
1681 compression_end(a
, lastrm
);
1682 strm
= calloc(1, sizeof(*strm
));
1684 archive_set_error(a
, ENOMEM
,
1685 "Can't allocate memory for gzip stream");
1686 return (ARCHIVE_FATAL
);
1688 /* zlib.h is not const-correct, so we need this one bit
1689 * of ugly hackery to convert a const * pointer to
1690 * a non-const pointer. */
1691 strm
->next_in
= (Bytef
*)(uintptr_t)(const void *)lastrm
->next_in
;
1692 strm
->avail_in
= (uInt
)lastrm
->avail_in
;
1693 strm
->total_in
= (uLong
)lastrm
->total_in
;
1694 strm
->next_out
= lastrm
->next_out
;
1695 strm
->avail_out
= (uInt
)lastrm
->avail_out
;
1696 strm
->total_out
= (uLong
)lastrm
->total_out
;
1697 if (deflateInit2(strm
, level
, Z_DEFLATED
,
1698 (withheader
)?15:-15,
1699 8, Z_DEFAULT_STRATEGY
) != Z_OK
) {
1701 lastrm
->real_stream
= NULL
;
1702 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1703 "Internal error initializing compression library");
1704 return (ARCHIVE_FATAL
);
1706 lastrm
->real_stream
= strm
;
1708 lastrm
->code
= compression_code_deflate
;
1709 lastrm
->end
= compression_end_deflate
;
1710 return (ARCHIVE_OK
);
1714 compression_code_deflate(struct archive
*a
,
1715 struct la_zstream
*lastrm
, enum la_zaction action
)
1720 strm
= (z_stream
*)lastrm
->real_stream
;
1721 /* zlib.h is not const-correct, so we need this one bit
1722 * of ugly hackery to convert a const * pointer to
1723 * a non-const pointer. */
1724 strm
->next_in
= (Bytef
*)(uintptr_t)(const void *)lastrm
->next_in
;
1725 strm
->avail_in
= (uInt
)lastrm
->avail_in
;
1726 strm
->total_in
= (uLong
)lastrm
->total_in
;
1727 strm
->next_out
= lastrm
->next_out
;
1728 strm
->avail_out
= (uInt
)lastrm
->avail_out
;
1729 strm
->total_out
= (uLong
)lastrm
->total_out
;
1731 (action
== ARCHIVE_Z_FINISH
)? Z_FINISH
: Z_NO_FLUSH
);
1732 lastrm
->next_in
= strm
->next_in
;
1733 lastrm
->avail_in
= strm
->avail_in
;
1734 lastrm
->total_in
= strm
->total_in
;
1735 lastrm
->next_out
= strm
->next_out
;
1736 lastrm
->avail_out
= strm
->avail_out
;
1737 lastrm
->total_out
= strm
->total_out
;
1740 return (ARCHIVE_OK
);
1742 return (ARCHIVE_EOF
);
1744 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1745 "GZip compression failed:"
1746 " deflate() call returned status %d", r
);
1747 return (ARCHIVE_FATAL
);
1752 compression_end_deflate(struct archive
*a
, struct la_zstream
*lastrm
)
1757 strm
= (z_stream
*)lastrm
->real_stream
;
1758 r
= deflateEnd(strm
);
1760 lastrm
->real_stream
= NULL
;
1763 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1764 "Failed to clean up compressor");
1765 return (ARCHIVE_FATAL
);
1767 return (ARCHIVE_OK
);
1771 compression_init_encoder_deflate(struct archive
*a
,
1772 struct la_zstream
*lastrm
, int level
, int withheader
)
1775 (void) level
; /* UNUSED */
1776 (void) withheader
; /* UNUSED */
1778 compression_end(a
, lastrm
);
1779 return (compression_unsupported_encoder(a
, lastrm
, "deflate"));
1784 * _7_BZIP2 compressor.
1786 #if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
1788 compression_init_encoder_bzip2(struct archive
*a
,
1789 struct la_zstream
*lastrm
, int level
)
1794 compression_end(a
, lastrm
);
1795 strm
= calloc(1, sizeof(*strm
));
1797 archive_set_error(a
, ENOMEM
,
1798 "Can't allocate memory for bzip2 stream");
1799 return (ARCHIVE_FATAL
);
1801 /* bzlib.h is not const-correct, so we need this one bit
1802 * of ugly hackery to convert a const * pointer to
1803 * a non-const pointer. */
1804 strm
->next_in
= (char *)(uintptr_t)(const void *)lastrm
->next_in
;
1805 strm
->avail_in
= lastrm
->avail_in
;
1806 strm
->total_in_lo32
= (uint32_t)(lastrm
->total_in
& 0xffffffff);
1807 strm
->total_in_hi32
= (uint32_t)(lastrm
->total_in
>> 32);
1808 strm
->next_out
= (char *)lastrm
->next_out
;
1809 strm
->avail_out
= lastrm
->avail_out
;
1810 strm
->total_out_lo32
= (uint32_t)(lastrm
->total_out
& 0xffffffff);
1811 strm
->total_out_hi32
= (uint32_t)(lastrm
->total_out
>> 32);
1812 if (BZ2_bzCompressInit(strm
, level
, 0, 30) != BZ_OK
) {
1814 lastrm
->real_stream
= NULL
;
1815 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1816 "Internal error initializing compression library");
1817 return (ARCHIVE_FATAL
);
1819 lastrm
->real_stream
= strm
;
1821 lastrm
->code
= compression_code_bzip2
;
1822 lastrm
->end
= compression_end_bzip2
;
1823 return (ARCHIVE_OK
);
1827 compression_code_bzip2(struct archive
*a
,
1828 struct la_zstream
*lastrm
, enum la_zaction action
)
1833 strm
= (bz_stream
*)lastrm
->real_stream
;
1834 /* bzlib.h is not const-correct, so we need this one bit
1835 * of ugly hackery to convert a const * pointer to
1836 * a non-const pointer. */
1837 strm
->next_in
= (char *)(uintptr_t)(const void *)lastrm
->next_in
;
1838 strm
->avail_in
= lastrm
->avail_in
;
1839 strm
->total_in_lo32
= (uint32_t)(lastrm
->total_in
& 0xffffffff);
1840 strm
->total_in_hi32
= (uint32_t)(lastrm
->total_in
>> 32);
1841 strm
->next_out
= (char *)lastrm
->next_out
;
1842 strm
->avail_out
= lastrm
->avail_out
;
1843 strm
->total_out_lo32
= (uint32_t)(lastrm
->total_out
& 0xffffffff);
1844 strm
->total_out_hi32
= (uint32_t)(lastrm
->total_out
>> 32);
1845 r
= BZ2_bzCompress(strm
,
1846 (action
== ARCHIVE_Z_FINISH
)? BZ_FINISH
: BZ_RUN
);
1847 lastrm
->next_in
= (const unsigned char *)strm
->next_in
;
1848 lastrm
->avail_in
= strm
->avail_in
;
1850 (((uint64_t)(uint32_t)strm
->total_in_hi32
) << 32)
1851 + (uint64_t)(uint32_t)strm
->total_in_lo32
;
1852 lastrm
->next_out
= (unsigned char *)strm
->next_out
;
1853 lastrm
->avail_out
= strm
->avail_out
;
1855 (((uint64_t)(uint32_t)strm
->total_out_hi32
) << 32)
1856 + (uint64_t)(uint32_t)strm
->total_out_lo32
;
1858 case BZ_RUN_OK
: /* Non-finishing */
1859 case BZ_FINISH_OK
: /* Finishing: There's more work to do */
1860 return (ARCHIVE_OK
);
1861 case BZ_STREAM_END
: /* Finishing: all done */
1862 /* Only occurs in finishing case */
1863 return (ARCHIVE_EOF
);
1865 /* Any other return value indicates an error */
1866 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1867 "Bzip2 compression failed:"
1868 " BZ2_bzCompress() call returned status %d", r
);
1869 return (ARCHIVE_FATAL
);
1874 compression_end_bzip2(struct archive
*a
, struct la_zstream
*lastrm
)
1879 strm
= (bz_stream
*)lastrm
->real_stream
;
1880 r
= BZ2_bzCompressEnd(strm
);
1882 lastrm
->real_stream
= NULL
;
1885 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1886 "Failed to clean up compressor");
1887 return (ARCHIVE_FATAL
);
1889 return (ARCHIVE_OK
);
1894 compression_init_encoder_bzip2(struct archive
*a
,
1895 struct la_zstream
*lastrm
, int level
)
1898 (void) level
; /* UNUSED */
1900 compression_end(a
, lastrm
);
1901 return (compression_unsupported_encoder(a
, lastrm
, "bzip2"));
1906 * _7_LZMA1, _7_LZMA2 compressor.
1908 #if defined(HAVE_LZMA_H)
1910 compression_init_encoder_lzma(struct archive
*a
,
1911 struct la_zstream
*lastrm
, int level
, uint64_t filter_id
)
1913 static const lzma_stream lzma_init_data
= LZMA_STREAM_INIT
;
1915 lzma_filter
*lzmafilters
;
1916 lzma_options_lzma lzma_opt
;
1920 compression_end(a
, lastrm
);
1921 strm
= calloc(1, sizeof(*strm
) + sizeof(*lzmafilters
) * 2);
1923 archive_set_error(a
, ENOMEM
,
1924 "Can't allocate memory for lzma stream");
1925 return (ARCHIVE_FATAL
);
1927 lzmafilters
= (lzma_filter
*)(strm
+1);
1930 if (lzma_lzma_preset(&lzma_opt
, level
)) {
1932 lastrm
->real_stream
= NULL
;
1933 archive_set_error(a
, ENOMEM
,
1934 "Internal error initializing compression library");
1935 return (ARCHIVE_FATAL
);
1937 lzmafilters
[0].id
= filter_id
;
1938 lzmafilters
[0].options
= &lzma_opt
;
1939 lzmafilters
[1].id
= LZMA_VLI_UNKNOWN
;/* Terminate */
1941 r
= lzma_properties_size(&(lastrm
->prop_size
), lzmafilters
);
1944 lastrm
->real_stream
= NULL
;
1945 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1946 "lzma_properties_size failed");
1947 return (ARCHIVE_FATAL
);
1949 if (lastrm
->prop_size
) {
1950 lastrm
->props
= malloc(lastrm
->prop_size
);
1951 if (lastrm
->props
== NULL
) {
1953 lastrm
->real_stream
= NULL
;
1954 archive_set_error(a
, ENOMEM
,
1955 "Cannot allocate memory");
1956 return (ARCHIVE_FATAL
);
1958 r
= lzma_properties_encode(lzmafilters
, lastrm
->props
);
1961 lastrm
->real_stream
= NULL
;
1962 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1963 "lzma_properties_encode failed");
1964 return (ARCHIVE_FATAL
);
1968 *strm
= lzma_init_data
;
1969 r
= lzma_raw_encoder(strm
, lzmafilters
);
1972 lastrm
->real_stream
= strm
;
1974 lastrm
->code
= compression_code_lzma
;
1975 lastrm
->end
= compression_end_lzma
;
1978 case LZMA_MEM_ERROR
:
1980 lastrm
->real_stream
= NULL
;
1981 archive_set_error(a
, ENOMEM
,
1982 "Internal error initializing compression library: "
1983 "Cannot allocate memory");
1988 lastrm
->real_stream
= NULL
;
1989 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
1990 "Internal error initializing compression library: "
1991 "It's a bug in liblzma");
1999 compression_init_encoder_lzma1(struct archive
*a
,
2000 struct la_zstream
*lastrm
, int level
)
2002 return compression_init_encoder_lzma(a
, lastrm
, level
,
2007 compression_init_encoder_lzma2(struct archive
*a
,
2008 struct la_zstream
*lastrm
, int level
)
2010 return compression_init_encoder_lzma(a
, lastrm
, level
,
2015 compression_code_lzma(struct archive
*a
,
2016 struct la_zstream
*lastrm
, enum la_zaction action
)
2021 strm
= (lzma_stream
*)lastrm
->real_stream
;
2022 strm
->next_in
= lastrm
->next_in
;
2023 strm
->avail_in
= lastrm
->avail_in
;
2024 strm
->total_in
= lastrm
->total_in
;
2025 strm
->next_out
= lastrm
->next_out
;
2026 strm
->avail_out
= lastrm
->avail_out
;
2027 strm
->total_out
= lastrm
->total_out
;
2029 (action
== ARCHIVE_Z_FINISH
)? LZMA_FINISH
: LZMA_RUN
);
2030 lastrm
->next_in
= strm
->next_in
;
2031 lastrm
->avail_in
= strm
->avail_in
;
2032 lastrm
->total_in
= strm
->total_in
;
2033 lastrm
->next_out
= strm
->next_out
;
2034 lastrm
->avail_out
= strm
->avail_out
;
2035 lastrm
->total_out
= strm
->total_out
;
2038 /* Non-finishing case */
2039 return (ARCHIVE_OK
);
2040 case LZMA_STREAM_END
:
2041 /* This return can only occur in finishing case. */
2042 return (ARCHIVE_EOF
);
2043 case LZMA_MEMLIMIT_ERROR
:
2044 archive_set_error(a
, ENOMEM
,
2045 "lzma compression error:"
2046 " %ju MiB would have been needed",
2047 (uintmax_t)((lzma_memusage(strm
) + 1024 * 1024 -1)
2049 return (ARCHIVE_FATAL
);
2051 /* Any other return value indicates an error */
2052 archive_set_error(a
, ARCHIVE_ERRNO_MISC
,
2053 "lzma compression failed:"
2054 " lzma_code() call returned status %d", r
);
2055 return (ARCHIVE_FATAL
);
2060 compression_end_lzma(struct archive
*a
, struct la_zstream
*lastrm
)
2064 (void)a
; /* UNUSED */
2065 strm
= (lzma_stream
*)lastrm
->real_stream
;
2069 lastrm
->real_stream
= NULL
;
2070 return (ARCHIVE_OK
);
2074 compression_init_encoder_lzma1(struct archive
*a
,
2075 struct la_zstream
*lastrm
, int level
)
2078 (void) level
; /* UNUSED */
2080 compression_end(a
, lastrm
);
2081 return (compression_unsupported_encoder(a
, lastrm
, "lzma"));
2084 compression_init_encoder_lzma2(struct archive
*a
,
2085 struct la_zstream
*lastrm
, int level
)
2088 (void) level
; /* UNUSED */
2090 compression_end(a
, lastrm
);
2091 return (compression_unsupported_encoder(a
, lastrm
, "lzma"));
2096 * _7_PPMD compressor.
2099 ppmd_alloc(void *p
, size_t size
)
2102 return malloc(size
);
2105 ppmd_free(void *p
, void *address
)
2110 static ISzAlloc g_szalloc
= { ppmd_alloc
, ppmd_free
};
2112 ppmd_write(void *p
, Byte b
)
2114 struct archive_write
*a
= ((IByteOut
*)p
)->a
;
2115 struct _7zip
*zip
= (struct _7zip
*)(a
->format_data
);
2116 struct la_zstream
*lastrm
= &(zip
->stream
);
2117 struct ppmd_stream
*strm
;
2119 if (lastrm
->avail_out
) {
2120 *lastrm
->next_out
++ = b
;
2121 lastrm
->avail_out
--;
2122 lastrm
->total_out
++;
2125 strm
= (struct ppmd_stream
*)lastrm
->real_stream
;
2126 if (strm
->buff_ptr
< strm
->buff_end
) {
2127 *strm
->buff_ptr
++ = b
;
2133 compression_init_encoder_ppmd(struct archive
*a
,
2134 struct la_zstream
*lastrm
, unsigned maxOrder
, uint32_t msize
)
2136 struct ppmd_stream
*strm
;
2141 compression_end(a
, lastrm
);
2142 strm
= calloc(1, sizeof(*strm
));
2144 archive_set_error(a
, ENOMEM
,
2145 "Can't allocate memory for PPMd");
2146 return (ARCHIVE_FATAL
);
2148 strm
->buff
= malloc(32);
2149 if (strm
->buff
== NULL
) {
2151 archive_set_error(a
, ENOMEM
,
2152 "Can't allocate memory for PPMd");
2153 return (ARCHIVE_FATAL
);
2155 strm
->buff_ptr
= strm
->buff
;
2156 strm
->buff_end
= strm
->buff
+ 32;
2158 props
= malloc(1+4);
2159 if (props
== NULL
) {
2162 archive_set_error(a
, ENOMEM
,
2163 "Coludn't allocate memory for PPMd");
2164 return (ARCHIVE_FATAL
);
2166 props
[0] = maxOrder
;
2167 archive_le32enc(props
+1, msize
);
2168 __archive_ppmd7_functions
.Ppmd7_Construct(&strm
->ppmd7_context
);
2169 r
= __archive_ppmd7_functions
.Ppmd7_Alloc(
2170 &strm
->ppmd7_context
, msize
, &g_szalloc
);
2175 archive_set_error(a
, ENOMEM
,
2176 "Coludn't allocate memory for PPMd");
2177 return (ARCHIVE_FATAL
);
2179 __archive_ppmd7_functions
.Ppmd7_Init(&(strm
->ppmd7_context
), maxOrder
);
2180 strm
->byteout
.a
= (struct archive_write
*)a
;
2181 strm
->byteout
.Write
= ppmd_write
;
2182 strm
->range_enc
.Stream
= &(strm
->byteout
);
2183 __archive_ppmd7_functions
.Ppmd7z_RangeEnc_Init(&(strm
->range_enc
));
2186 lastrm
->real_stream
= strm
;
2188 lastrm
->code
= compression_code_ppmd
;
2189 lastrm
->end
= compression_end_ppmd
;
2190 lastrm
->prop_size
= 5;
2191 lastrm
->props
= props
;
2192 return (ARCHIVE_OK
);
2196 compression_code_ppmd(struct archive
*a
,
2197 struct la_zstream
*lastrm
, enum la_zaction action
)
2199 struct ppmd_stream
*strm
;
2201 (void)a
; /* UNUSED */
2203 strm
= (struct ppmd_stream
*)lastrm
->real_stream
;
2205 /* Copy encoded data if there are remaining bytes from previous call. */
2206 if (strm
->buff_bytes
) {
2207 uint8_t *p
= strm
->buff_ptr
- strm
->buff_bytes
;
2208 while (lastrm
->avail_out
&& strm
->buff_bytes
) {
2209 *lastrm
->next_out
++ = *p
++;
2210 lastrm
->avail_out
--;
2211 lastrm
->total_out
++;
2214 if (strm
->buff_bytes
)
2215 return (ARCHIVE_OK
);
2216 if (strm
->stat
== 1)
2217 return (ARCHIVE_EOF
);
2218 strm
->buff_ptr
= strm
->buff
;
2220 while (lastrm
->avail_in
&& lastrm
->avail_out
) {
2221 __archive_ppmd7_functions
.Ppmd7_EncodeSymbol(
2222 &(strm
->ppmd7_context
), &(strm
->range_enc
),
2223 *lastrm
->next_in
++);
2227 if (lastrm
->avail_in
== 0 && action
== ARCHIVE_Z_FINISH
) {
2228 __archive_ppmd7_functions
.Ppmd7z_RangeEnc_FlushData(
2229 &(strm
->range_enc
));
2231 /* Return EOF if there are no remaining bytes. */
2232 if (strm
->buff_bytes
== 0)
2233 return (ARCHIVE_EOF
);
2235 return (ARCHIVE_OK
);
2239 compression_end_ppmd(struct archive
*a
, struct la_zstream
*lastrm
)
2241 struct ppmd_stream
*strm
;
2243 (void)a
; /* UNUSED */
2245 strm
= (struct ppmd_stream
*)lastrm
->real_stream
;
2246 __archive_ppmd7_functions
.Ppmd7_Free(&strm
->ppmd7_context
, &g_szalloc
);
2249 lastrm
->real_stream
= NULL
;
2251 return (ARCHIVE_OK
);
2255 * Universal compressor initializer.
2258 _7z_compression_init_encoder(struct archive_write
*a
, unsigned compression
,
2259 int compression_level
)
2264 zip
= (struct _7zip
*)a
->format_data
;
2265 switch (compression
) {
2267 r
= compression_init_encoder_deflate(
2268 &(a
->archive
), &(zip
->stream
),
2269 compression_level
, 0);
2272 r
= compression_init_encoder_bzip2(
2273 &(a
->archive
), &(zip
->stream
),
2277 r
= compression_init_encoder_lzma1(
2278 &(a
->archive
), &(zip
->stream
),
2282 r
= compression_init_encoder_lzma2(
2283 &(a
->archive
), &(zip
->stream
),
2287 r
= compression_init_encoder_ppmd(
2288 &(a
->archive
), &(zip
->stream
),
2289 PPMD7_DEFAULT_ORDER
, PPMD7_DEFAULT_MEM_SIZE
);
2293 r
= compression_init_encoder_copy(
2294 &(a
->archive
), &(zip
->stream
));
2297 if (r
== ARCHIVE_OK
) {
2298 zip
->stream
.total_in
= 0;
2299 zip
->stream
.next_out
= zip
->wbuff
;
2300 zip
->stream
.avail_out
= sizeof(zip
->wbuff
);
2301 zip
->stream
.total_out
= 0;
2308 compression_code(struct archive
*a
, struct la_zstream
*lastrm
,
2309 enum la_zaction action
)
2312 return (lastrm
->code(a
, lastrm
, action
));
2313 return (ARCHIVE_OK
);
2317 compression_end(struct archive
*a
, struct la_zstream
*lastrm
)
2319 if (lastrm
->valid
) {
2320 lastrm
->prop_size
= 0;
2321 free(lastrm
->props
);
2322 lastrm
->props
= NULL
;
2323 return (lastrm
->end(a
, lastrm
));
2325 return (ARCHIVE_OK
);