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