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