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