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