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