Blame libarchive/archive_write_set_format_7zip.c

Packit Service 1d0348
/*-
Packit Service 1d0348
 * Copyright (c) 2011-2012 Michihiro NAKAJIMA
Packit Service 1d0348
 * All rights reserved.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Redistribution and use in source and binary forms, with or without
Packit Service 1d0348
 * modification, are permitted provided that the following conditions
Packit Service 1d0348
 * are met:
Packit Service 1d0348
 * 1. Redistributions of source code must retain the above copyright
Packit Service 1d0348
 *    notice, this list of conditions and the following disclaimer.
Packit Service 1d0348
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 1d0348
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 1d0348
 *    documentation and/or other materials provided with the distribution.
Packit Service 1d0348
 *
Packit Service 1d0348
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
Packit Service 1d0348
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit Service 1d0348
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit Service 1d0348
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service 1d0348
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit Service 1d0348
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 1d0348
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 1d0348
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 1d0348
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit Service 1d0348
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 1d0348
 */
Packit Service 1d0348
Packit Service 1d0348
#include "archive_platform.h"
Packit Service 1d0348
__FBSDID("$FreeBSD$");
Packit Service 1d0348
Packit Service 1d0348
#ifdef HAVE_ERRNO_H
Packit Service 1d0348
#include <errno.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
#include <stdlib.h>
Packit Service 1d0348
#ifdef HAVE_BZLIB_H
Packit Service 1d0348
#include <bzlib.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
#if HAVE_LZMA_H
Packit Service 1d0348
#include <lzma.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
#ifdef HAVE_ZLIB_H
Packit Service 1d0348
#include <zlib.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
#include "archive.h"
Packit Service 1d0348
#ifndef HAVE_ZLIB_H
Packit Service 1d0348
#include "archive_crc32.h"
Packit Service 1d0348
#endif
Packit Service 1d0348
#include "archive_endian.h"
Packit Service 1d0348
#include "archive_entry.h"
Packit Service 1d0348
#include "archive_entry_locale.h"
Packit Service 1d0348
#include "archive_ppmd7_private.h"
Packit Service 1d0348
#include "archive_private.h"
Packit Service 1d0348
#include "archive_rb.h"
Packit Service 1d0348
#include "archive_string.h"
Packit Service 1d0348
#include "archive_write_private.h"
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Codec ID
Packit Service 1d0348
 */
Packit Service 1d0348
#define _7Z_COPY	0
Packit Service 1d0348
#define _7Z_LZMA1	0x030101
Packit Service 1d0348
#define _7Z_LZMA2	0x21
Packit Service 1d0348
#define _7Z_DEFLATE	0x040108
Packit Service 1d0348
#define _7Z_BZIP2	0x040202
Packit Service 1d0348
#define _7Z_PPMD	0x030401
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * 7-Zip header property IDs.
Packit Service 1d0348
 */
Packit Service 1d0348
#define kEnd			0x00
Packit Service 1d0348
#define kHeader			0x01
Packit Service 1d0348
#define kArchiveProperties	0x02
Packit Service 1d0348
#define kAdditionalStreamsInfo	0x03
Packit Service 1d0348
#define kMainStreamsInfo	0x04
Packit Service 1d0348
#define kFilesInfo		0x05
Packit Service 1d0348
#define kPackInfo		0x06
Packit Service 1d0348
#define kUnPackInfo		0x07
Packit Service 1d0348
#define kSubStreamsInfo		0x08
Packit Service 1d0348
#define kSize			0x09
Packit Service 1d0348
#define kCRC			0x0A
Packit Service 1d0348
#define kFolder			0x0B
Packit Service 1d0348
#define kCodersUnPackSize	0x0C
Packit Service 1d0348
#define kNumUnPackStream	0x0D
Packit Service 1d0348
#define kEmptyStream		0x0E
Packit Service 1d0348
#define kEmptyFile		0x0F
Packit Service 1d0348
#define kAnti			0x10
Packit Service 1d0348
#define kName			0x11
Packit Service 1d0348
#define kCTime			0x12
Packit Service 1d0348
#define kATime			0x13
Packit Service 1d0348
#define kMTime			0x14
Packit Service 1d0348
#define kAttributes		0x15
Packit Service 1d0348
#define kEncodedHeader		0x17
Packit Service 1d0348
Packit Service 1d0348
enum la_zaction {
Packit Service 1d0348
	ARCHIVE_Z_FINISH,
Packit Service 1d0348
	ARCHIVE_Z_RUN
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * A stream object of universal compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
struct la_zstream {
Packit Service 1d0348
	const uint8_t		*next_in;
Packit Service 1d0348
	size_t			 avail_in;
Packit Service 1d0348
	uint64_t		 total_in;
Packit Service 1d0348
Packit Service 1d0348
	uint8_t			*next_out;
Packit Service 1d0348
	size_t			 avail_out;
Packit Service 1d0348
	uint64_t		 total_out;
Packit Service 1d0348
Packit Service 1d0348
	uint32_t		 prop_size;
Packit Service 1d0348
	uint8_t			*props;
Packit Service 1d0348
Packit Service 1d0348
	int			 valid;
Packit Service 1d0348
	void			*real_stream;
Packit Service 1d0348
	int			 (*code) (struct archive *a,
Packit Service 1d0348
				    struct la_zstream *lastrm,
Packit Service 1d0348
				    enum la_zaction action);
Packit Service 1d0348
	int			 (*end)(struct archive *a,
Packit Service 1d0348
				    struct la_zstream *lastrm);
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
#define PPMD7_DEFAULT_ORDER	6
Packit Service 1d0348
#define PPMD7_DEFAULT_MEM_SIZE	(1 << 24)
Packit Service 1d0348
Packit Service 1d0348
struct ppmd_stream {
Packit Service 1d0348
	int			 stat;
Packit Service 1d0348
	CPpmd7			 ppmd7_context;
Packit Service 1d0348
	CPpmd7z_RangeEnc	 range_enc;
Packit Service 1d0348
	IByteOut		 byteout;
Packit Service 1d0348
	uint8_t			*buff;
Packit Service 1d0348
	uint8_t			*buff_ptr;
Packit Service 1d0348
	uint8_t			*buff_end;
Packit Service 1d0348
	size_t			 buff_bytes;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct coder {
Packit Service 1d0348
	unsigned		 codec;
Packit Service 1d0348
	size_t			 prop_size;
Packit Service 1d0348
	uint8_t			*props;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct file {
Packit Service 1d0348
	struct archive_rb_node	 rbnode;
Packit Service 1d0348
Packit Service 1d0348
	struct file		*next;
Packit Service 1d0348
	unsigned		 name_len;
Packit Service 1d0348
	uint8_t			*utf16name;/* UTF16-LE name. */
Packit Service 1d0348
	uint64_t		 size;
Packit Service 1d0348
	unsigned		 flg;
Packit Service 1d0348
#define MTIME_IS_SET	(1<<0)
Packit Service 1d0348
#define ATIME_IS_SET	(1<<1)
Packit Service 1d0348
#define CTIME_IS_SET	(1<<2)
Packit Service 1d0348
#define CRC32_IS_SET	(1<<3)
Packit Service 1d0348
#define HAS_STREAM	(1<<4)
Packit Service 1d0348
Packit Service 1d0348
	struct {
Packit Service 1d0348
		time_t		 time;
Packit Service 1d0348
		long		 time_ns;
Packit Service 1d0348
	}			 times[3];
Packit Service 1d0348
#define MTIME 0
Packit Service 1d0348
#define ATIME 1
Packit Service 1d0348
#define CTIME 2
Packit Service 1d0348
Packit Service 1d0348
	mode_t			 mode;
Packit Service 1d0348
	uint32_t		 crc32;
Packit Service 1d0348
Packit Service 1d0348
	int			 dir:1;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
struct _7zip {
Packit Service 1d0348
	int			 temp_fd;
Packit Service 1d0348
	uint64_t		 temp_offset;
Packit Service 1d0348
Packit Service 1d0348
	struct file		*cur_file;
Packit Service 1d0348
	size_t			 total_number_entry;
Packit Service 1d0348
	size_t			 total_number_nonempty_entry;
Packit Service 1d0348
	size_t			 total_number_empty_entry;
Packit Service 1d0348
	size_t			 total_number_dir_entry;
Packit Service 1d0348
	size_t			 total_bytes_entry_name;
Packit Service 1d0348
	size_t			 total_number_time_defined[3];
Packit Service 1d0348
	uint64_t		 total_bytes_compressed;
Packit Service 1d0348
	uint64_t		 total_bytes_uncompressed;
Packit Service 1d0348
	uint64_t		 entry_bytes_remaining;
Packit Service 1d0348
	uint32_t		 entry_crc32;
Packit Service 1d0348
	uint32_t		 precode_crc32;
Packit Service 1d0348
	uint32_t		 encoded_crc32;
Packit Service 1d0348
	int			 crc32flg;
Packit Service 1d0348
#define	PRECODE_CRC32	1
Packit Service 1d0348
#define	ENCODED_CRC32	2
Packit Service 1d0348
Packit Service 1d0348
	unsigned		 opt_compression;
Packit Service 1d0348
	int			 opt_compression_level;
Packit Service 1d0348
Packit Service 1d0348
	struct la_zstream	 stream;
Packit Service 1d0348
	struct coder		 coder;
Packit Service 1d0348
Packit Service 1d0348
	struct archive_string_conv *sconv;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Compressed data buffer.
Packit Service 1d0348
	 */
Packit Service 1d0348
	unsigned char		 wbuff[512 * 20 * 6];
Packit Service 1d0348
	size_t			 wbuff_remaining;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * The list of the file entries which has its contents is used to
Packit Service 1d0348
	 * manage struct file objects.
Packit Service 1d0348
	 * We use 'next' (a member of struct file) to chain.
Packit Service 1d0348
	 */
Packit Service 1d0348
	struct {
Packit Service 1d0348
		struct file	*first;
Packit Service 1d0348
		struct file	**last;
Packit Service 1d0348
	}			 file_list, empty_list;
Packit Service 1d0348
	struct archive_rb_tree	 rbtree;/* for empty files */
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
static int	_7z_options(struct archive_write *,
Packit Service 1d0348
		    const char *, const char *);
Packit Service 1d0348
static int	_7z_write_header(struct archive_write *,
Packit Service 1d0348
		    struct archive_entry *);
Packit Service 1d0348
static ssize_t	_7z_write_data(struct archive_write *,
Packit Service 1d0348
		    const void *, size_t);
Packit Service 1d0348
static int	_7z_finish_entry(struct archive_write *);
Packit Service 1d0348
static int	_7z_close(struct archive_write *);
Packit Service 1d0348
static int	_7z_free(struct archive_write *);
Packit Service 1d0348
static int	file_cmp_node(const struct archive_rb_node *,
Packit Service 1d0348
		    const struct archive_rb_node *);
Packit Service 1d0348
static int	file_cmp_key(const struct archive_rb_node *, const void *);
Packit Service 1d0348
static int	file_new(struct archive_write *a, struct archive_entry *,
Packit Service 1d0348
		    struct file **);
Packit Service 1d0348
static void	file_free(struct file *);
Packit Service 1d0348
static void	file_register(struct _7zip *, struct file *);
Packit Service 1d0348
static void	file_register_empty(struct _7zip *, struct file *);
Packit Service 1d0348
static void	file_init_register(struct _7zip *);
Packit Service 1d0348
static void	file_init_register_empty(struct _7zip *);
Packit Service 1d0348
static void	file_free_register(struct _7zip *);
Packit Service 1d0348
static ssize_t	compress_out(struct archive_write *, const void *, size_t ,
Packit Service 1d0348
		    enum la_zaction);
Packit Service 1d0348
static int	compression_init_encoder_copy(struct archive *,
Packit Service 1d0348
		    struct la_zstream *);
Packit Service 1d0348
static int	compression_code_copy(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end_copy(struct archive *, struct la_zstream *);
Packit Service 1d0348
static int	compression_init_encoder_deflate(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, int, int);
Packit Service 1d0348
#ifdef HAVE_ZLIB_H
Packit Service 1d0348
static int	compression_code_deflate(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end_deflate(struct archive *, struct la_zstream *);
Packit Service 1d0348
#endif
Packit Service 1d0348
static int	compression_init_encoder_bzip2(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, int);
Packit Service 1d0348
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
Packit Service 1d0348
static int	compression_code_bzip2(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end_bzip2(struct archive *, struct la_zstream *);
Packit Service 1d0348
#endif
Packit Service 1d0348
static int	compression_init_encoder_lzma1(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, int);
Packit Service 1d0348
static int	compression_init_encoder_lzma2(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, int);
Packit Service 1d0348
#if defined(HAVE_LZMA_H)
Packit Service 1d0348
static int	compression_code_lzma(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end_lzma(struct archive *, struct la_zstream *);
Packit Service 1d0348
#endif
Packit Service 1d0348
static int	compression_init_encoder_ppmd(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, unsigned, uint32_t);
Packit Service 1d0348
static int	compression_code_ppmd(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end_ppmd(struct archive *, struct la_zstream *);
Packit Service 1d0348
static int	_7z_compression_init_encoder(struct archive_write *, unsigned,
Packit Service 1d0348
		    int);
Packit Service 1d0348
static int	compression_code(struct archive *,
Packit Service 1d0348
		    struct la_zstream *, enum la_zaction);
Packit Service 1d0348
static int	compression_end(struct archive *,
Packit Service 1d0348
		    struct la_zstream *);
Packit Service 1d0348
static int	enc_uint64(struct archive_write *, uint64_t);
Packit Service 1d0348
static int	make_header(struct archive_write *, uint64_t, uint64_t,
Packit Service 1d0348
		    uint64_t, int, struct coder *);
Packit Service 1d0348
static int	make_streamsInfo(struct archive_write *, uint64_t, uint64_t,
Packit Service 1d0348
		    	uint64_t, int, struct coder *, int, uint32_t);
Packit Service 1d0348
Packit Service 1d0348
int
Packit Service 1d0348
archive_write_set_format_7zip(struct archive *_a)
Packit Service 1d0348
{
Packit Service 1d0348
	static const struct archive_rb_tree_ops rb_ops = {
Packit Service 1d0348
		file_cmp_node, file_cmp_key
Packit Service 1d0348
	};
Packit Service 1d0348
	struct archive_write *a = (struct archive_write *)_a;
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
Packit Service 1d0348
	archive_check_magic(_a, ARCHIVE_WRITE_MAGIC,
Packit Service 1d0348
	    ARCHIVE_STATE_NEW, "archive_write_set_format_7zip");
Packit Service 1d0348
Packit Service 1d0348
	/* If another format was already registered, unregister it. */
Packit Service 1d0348
	if (a->format_free != NULL)
Packit Service 1d0348
		(a->format_free)(a);
Packit Service 1d0348
Packit Service 1d0348
	zip = calloc(1, sizeof(*zip));
Packit Service 1d0348
	if (zip == NULL) {
Packit Service 1d0348
		archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
		    "Can't allocate 7-Zip data");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	zip->temp_fd = -1;
Packit Service 1d0348
	__archive_rb_tree_init(&(zip->rbtree), &rb_ops);
Packit Service 1d0348
	file_init_register(zip);
Packit Service 1d0348
	file_init_register_empty(zip);
Packit Service 1d0348
Packit Service 1d0348
	/* Set default compression type and its level. */
Packit Service 1d0348
#if HAVE_LZMA_H
Packit Service 1d0348
	zip->opt_compression = _7Z_LZMA1;
Packit Service 1d0348
#elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
Packit Service 1d0348
	zip->opt_compression = _7Z_BZIP2;
Packit Service 1d0348
#elif defined(HAVE_ZLIB_H)
Packit Service 1d0348
	zip->opt_compression = _7Z_DEFLATE;
Packit Service 1d0348
#else
Packit Service 1d0348
	zip->opt_compression = _7Z_COPY;
Packit Service 1d0348
#endif
Packit Service 1d0348
	zip->opt_compression_level = 6;
Packit Service 1d0348
Packit Service 1d0348
	a->format_data = zip;
Packit Service 1d0348
Packit Service 1d0348
	a->format_name = "7zip";
Packit Service 1d0348
	a->format_options = _7z_options;
Packit Service 1d0348
	a->format_write_header = _7z_write_header;
Packit Service 1d0348
	a->format_write_data = _7z_write_data;
Packit Service 1d0348
	a->format_finish_entry = _7z_finish_entry;
Packit Service 1d0348
	a->format_close = _7z_close;
Packit Service 1d0348
	a->format_free = _7z_free;
Packit Service 1d0348
	a->archive.archive_format = ARCHIVE_FORMAT_7ZIP;
Packit Service 1d0348
	a->archive.archive_format_name = "7zip";
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_options(struct archive_write *a, const char *key, const char *value)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
Packit Service 1d0348
	if (strcmp(key, "compression") == 0) {
Packit Service 1d0348
		const char *name = NULL;
Packit Service 1d0348
Packit Service 1d0348
		if (value == NULL || strcmp(value, "copy") == 0 ||
Packit Service 1d0348
		    strcmp(value, "COPY") == 0 ||
Packit Service 1d0348
		    strcmp(value, "store") == 0 ||
Packit Service 1d0348
		    strcmp(value, "STORE") == 0)
Packit Service 1d0348
			zip->opt_compression = _7Z_COPY;
Packit Service 1d0348
		else if (strcmp(value, "deflate") == 0 ||
Packit Service 1d0348
		    strcmp(value, "DEFLATE") == 0)
Packit Service 1d0348
#if HAVE_ZLIB_H
Packit Service 1d0348
			zip->opt_compression = _7Z_DEFLATE;
Packit Service 1d0348
#else
Packit Service 1d0348
			name = "deflate";
Packit Service 1d0348
#endif
Packit Service 1d0348
		else if (strcmp(value, "bzip2") == 0 ||
Packit Service 1d0348
		    strcmp(value, "BZIP2") == 0)
Packit Service 1d0348
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
Packit Service 1d0348
			zip->opt_compression = _7Z_BZIP2;
Packit Service 1d0348
#else
Packit Service 1d0348
			name = "bzip2";
Packit Service 1d0348
#endif
Packit Service 1d0348
		else if (strcmp(value, "lzma1") == 0 ||
Packit Service 1d0348
		    strcmp(value, "LZMA1") == 0)
Packit Service 1d0348
#if HAVE_LZMA_H
Packit Service 1d0348
			zip->opt_compression = _7Z_LZMA1;
Packit Service 1d0348
#else
Packit Service 1d0348
			name = "lzma1";
Packit Service 1d0348
#endif
Packit Service 1d0348
		else if (strcmp(value, "lzma2") == 0 ||
Packit Service 1d0348
		    strcmp(value, "LZMA2") == 0)
Packit Service 1d0348
#if HAVE_LZMA_H
Packit Service 1d0348
			zip->opt_compression = _7Z_LZMA2;
Packit Service 1d0348
#else
Packit Service 1d0348
			name = "lzma2";
Packit Service 1d0348
#endif
Packit Service 1d0348
		else if (strcmp(value, "ppmd") == 0 ||
Packit Service 1d0348
		    strcmp(value, "PPMD") == 0 ||
Packit Service 1d0348
		    strcmp(value, "PPMd") == 0)
Packit Service 1d0348
			zip->opt_compression = _7Z_PPMD;
Packit Service 1d0348
		else {
Packit Service 1d0348
			archive_set_error(&(a->archive),
Packit Service 1d0348
			    ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
			    "Unknown compression name: `%s'",
Packit Service 1d0348
			    value);
Packit Service 1d0348
			return (ARCHIVE_FAILED);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (name != NULL) {
Packit Service 1d0348
			archive_set_error(&(a->archive),
Packit Service 1d0348
			    ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
			    "`%s' compression not supported "
Packit Service 1d0348
			    "on this platform",
Packit Service 1d0348
			    name);
Packit Service 1d0348
			return (ARCHIVE_FAILED);
Packit Service 1d0348
		}
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (strcmp(key, "compression-level") == 0) {
Packit Service 1d0348
		if (value == NULL ||
Packit Service 1d0348
		    !(value[0] >= '0' && value[0] <= '9') ||
Packit Service 1d0348
		    value[1] != '\0') {
Packit Service 1d0348
			archive_set_error(&(a->archive),
Packit Service 1d0348
			    ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
			    "Illegal value `%s'",
Packit Service 1d0348
			    value);
Packit Service 1d0348
			return (ARCHIVE_FAILED);
Packit Service 1d0348
		}
Packit Service 1d0348
		zip->opt_compression_level = value[0] - '0';
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Note: The "warn" return is just to inform the options
Packit Service 1d0348
	 * supervisor that we didn't handle it.  It will generate
Packit Service 1d0348
	 * a suitable error if no one used this option. */
Packit Service 1d0348
	return (ARCHIVE_WARN);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_write_header(struct archive_write *a, struct archive_entry *entry)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	struct file *file;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	zip->cur_file = NULL;
Packit Service 1d0348
	zip->entry_bytes_remaining = 0;
Packit Service 1d0348
Packit Service 1d0348
	if (zip->sconv == NULL) {
Packit Service 1d0348
		zip->sconv = archive_string_conversion_to_charset(
Packit Service 1d0348
		    &a->archive, "UTF-16LE", 1);
Packit Service 1d0348
		if (zip->sconv == NULL)
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	r = file_new(a, entry, &file;;
Packit Service 1d0348
	if (r < ARCHIVE_WARN) {
Packit Service 1d0348
		file_free(file);
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (file->size == 0 && file->dir) {
Packit Service 1d0348
		if (!__archive_rb_tree_insert_node(&(zip->rbtree),
Packit Service 1d0348
		    (struct archive_rb_node *)file)) {
Packit Service 1d0348
			/* We have already had the same file. */
Packit Service 1d0348
			file_free(file);
Packit Service 1d0348
			return (ARCHIVE_OK);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	if (file->flg & MTIME_IS_SET)
Packit Service 1d0348
		zip->total_number_time_defined[MTIME]++;
Packit Service 1d0348
	if (file->flg & CTIME_IS_SET)
Packit Service 1d0348
		zip->total_number_time_defined[CTIME]++;
Packit Service 1d0348
	if (file->flg & ATIME_IS_SET)
Packit Service 1d0348
		zip->total_number_time_defined[ATIME]++;
Packit Service 1d0348
Packit Service 1d0348
	zip->total_number_entry++;
Packit Service 1d0348
	zip->total_bytes_entry_name += file->name_len + 2;
Packit Service 1d0348
	if (file->size == 0) {
Packit Service 1d0348
		/* Count up the number of empty files. */
Packit Service 1d0348
		zip->total_number_empty_entry++;
Packit Service 1d0348
		if (file->dir)
Packit Service 1d0348
			zip->total_number_dir_entry++;
Packit Service 1d0348
		else
Packit Service 1d0348
			file_register_empty(zip, file);
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Init compression.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) {
Packit Service 1d0348
		r = _7z_compression_init_encoder(a, zip->opt_compression,
Packit Service 1d0348
			zip->opt_compression_level);
Packit Service 1d0348
		if (r < 0) {
Packit Service 1d0348
			file_free(file);
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Register a non-empty file. */
Packit Service 1d0348
	file_register(zip, file);
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Set the current file to cur_file to read its contents.
Packit Service 1d0348
	 */
Packit Service 1d0348
	zip->cur_file = file;
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
	/* Save a offset of current file in temporary file. */
Packit Service 1d0348
	zip->entry_bytes_remaining = file->size;
Packit Service 1d0348
	zip->entry_crc32 = 0;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Store a symbolic link name as file contents.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if (archive_entry_filetype(entry) == AE_IFLNK) {
Packit Service 1d0348
		ssize_t bytes;
Packit Service 1d0348
		const void *p = (const void *)archive_entry_symlink(entry);
Packit Service 1d0348
		bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (bytes < 0)
Packit Service 1d0348
			return ((int)bytes);
Packit Service 1d0348
		zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes);
Packit Service 1d0348
		zip->entry_bytes_remaining -= bytes;
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Write data to a temporary file.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
write_to_temp(struct archive_write *a, const void *buff, size_t s)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	const unsigned char *p;
Packit Service 1d0348
	ssize_t ws;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Open a temporary file.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if (zip->temp_fd == -1) {
Packit Service 1d0348
		zip->temp_offset = 0;
Packit Service 1d0348
		zip->temp_fd = __archive_mktemp(NULL);
Packit Service 1d0348
		if (zip->temp_fd < 0) {
Packit Service 1d0348
			archive_set_error(&a->archive, errno,
Packit Service 1d0348
			    "Couldn't create temporary file");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	p = (const unsigned char *)buff;
Packit Service 1d0348
	while (s) {
Packit Service 1d0348
		ws = write(zip->temp_fd, p, s);
Packit Service 1d0348
		if (ws < 0) {
Packit Service 1d0348
			archive_set_error(&(a->archive), errno,
Packit Service 1d0348
			    "fwrite function failed");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
		s -= ws;
Packit Service 1d0348
		p += ws;
Packit Service 1d0348
		zip->temp_offset += ws;
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static ssize_t
Packit Service 1d0348
compress_out(struct archive_write *a, const void *buff, size_t s,
Packit Service 1d0348
    enum la_zaction run)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0)
Packit Service 1d0348
		return (0);
Packit Service 1d0348
Packit Service 1d0348
	if ((zip->crc32flg & PRECODE_CRC32) && s)
Packit Service 1d0348
		zip->precode_crc32 = crc32(zip->precode_crc32, buff,
Packit Service 1d0348
		    (unsigned)s);
Packit Service 1d0348
	zip->stream.next_in = (const unsigned char *)buff;
Packit Service 1d0348
	zip->stream.avail_in = s;
Packit Service 1d0348
	for (;;) {
Packit Service 1d0348
		/* Compress file data. */
Packit Service 1d0348
		r = compression_code(&(a->archive), &(zip->stream), run);
Packit Service 1d0348
		if (r != ARCHIVE_OK && r != ARCHIVE_EOF)
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		if (zip->stream.avail_out == 0) {
Packit Service 1d0348
			if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff))
Packit Service 1d0348
			    != ARCHIVE_OK)
Packit Service 1d0348
				return (ARCHIVE_FATAL);
Packit Service 1d0348
			zip->stream.next_out = zip->wbuff;
Packit Service 1d0348
			zip->stream.avail_out = sizeof(zip->wbuff);
Packit Service 1d0348
			if (zip->crc32flg & ENCODED_CRC32)
Packit Service 1d0348
				zip->encoded_crc32 = crc32(zip->encoded_crc32,
Packit Service 1d0348
				    zip->wbuff, sizeof(zip->wbuff));
Packit Service 1d0348
			if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF)
Packit Service 1d0348
				continue;
Packit Service 1d0348
		}
Packit Service 1d0348
		if (zip->stream.avail_in == 0)
Packit Service 1d0348
			break;
Packit Service 1d0348
	}
Packit Service 1d0348
	if (run == ARCHIVE_Z_FINISH) {
Packit Service 1d0348
		uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out;
Packit Service 1d0348
		if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK)
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		if ((zip->crc32flg & ENCODED_CRC32) && bytes)
Packit Service 1d0348
			zip->encoded_crc32 = crc32(zip->encoded_crc32,
Packit Service 1d0348
			    zip->wbuff, (unsigned)bytes);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	return (s);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static ssize_t
Packit Service 1d0348
_7z_write_data(struct archive_write *a, const void *buff, size_t s)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	ssize_t bytes;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
Packit Service 1d0348
	if (s > zip->entry_bytes_remaining)
Packit Service 1d0348
		s = (size_t)zip->entry_bytes_remaining;
Packit Service 1d0348
	if (s == 0 || zip->cur_file == NULL)
Packit Service 1d0348
		return (0);
Packit Service 1d0348
	bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN);
Packit Service 1d0348
	if (bytes < 0)
Packit Service 1d0348
		return (bytes);
Packit Service 1d0348
	zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes);
Packit Service 1d0348
	zip->entry_bytes_remaining -= bytes;
Packit Service 1d0348
	return (bytes);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_finish_entry(struct archive_write *a)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	size_t s;
Packit Service 1d0348
	ssize_t r;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	if (zip->cur_file == NULL)
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
Packit Service 1d0348
	while (zip->entry_bytes_remaining > 0) {
Packit Service 1d0348
		s = (size_t)zip->entry_bytes_remaining;
Packit Service 1d0348
		if (s > a->null_length)
Packit Service 1d0348
			s = a->null_length;
Packit Service 1d0348
		r = _7z_write_data(a, a->nulls, s);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return ((int)r);
Packit Service 1d0348
	}
Packit Service 1d0348
	zip->total_bytes_compressed += zip->stream.total_in;
Packit Service 1d0348
	zip->total_bytes_uncompressed += zip->stream.total_out;
Packit Service 1d0348
	zip->cur_file->crc32 = zip->entry_crc32;
Packit Service 1d0348
	zip->cur_file = NULL;
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
flush_wbuff(struct archive_write *a)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	int r;
Packit Service 1d0348
	size_t s;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	s = sizeof(zip->wbuff) - zip->wbuff_remaining;
Packit Service 1d0348
	r = __archive_write_output(a, zip->wbuff, s);
Packit Service 1d0348
	if (r != ARCHIVE_OK)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	zip->wbuff_remaining = sizeof(zip->wbuff);
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
copy_out(struct archive_write *a, uint64_t offset, uint64_t length)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	if (zip->temp_offset > 0 &&
Packit Service 1d0348
	    lseek(zip->temp_fd, offset, SEEK_SET) < 0) {
Packit Service 1d0348
		archive_set_error(&(a->archive), errno, "lseek failed");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	while (length) {
Packit Service 1d0348
		size_t rsize;
Packit Service 1d0348
		ssize_t rs;
Packit Service 1d0348
		unsigned char *wb;
Packit Service 1d0348
Packit Service 1d0348
		if (length > zip->wbuff_remaining)
Packit Service 1d0348
			rsize = zip->wbuff_remaining;
Packit Service 1d0348
		else
Packit Service 1d0348
			rsize = (size_t)length;
Packit Service 1d0348
		wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining);
Packit Service 1d0348
		rs = read(zip->temp_fd, wb, rsize);
Packit Service 1d0348
		if (rs < 0) {
Packit Service 1d0348
			archive_set_error(&(a->archive), errno,
Packit Service 1d0348
			    "Can't read temporary file(%jd)",
Packit Service 1d0348
			    (intmax_t)rs);
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (rs == 0) {
Packit Service 1d0348
			archive_set_error(&(a->archive), 0,
Packit Service 1d0348
			    "Truncated 7-Zip archive");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
		zip->wbuff_remaining -= rs;
Packit Service 1d0348
		length -= rs;
Packit Service 1d0348
		if (zip->wbuff_remaining == 0) {
Packit Service 1d0348
			r = flush_wbuff(a);
Packit Service 1d0348
			if (r != ARCHIVE_OK)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_close(struct archive_write *a)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	unsigned char *wb;
Packit Service 1d0348
	uint64_t header_offset, header_size, header_unpacksize;
Packit Service 1d0348
	uint64_t length;
Packit Service 1d0348
	uint32_t header_crc32;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
Packit Service 1d0348
	if (zip->total_number_entry > 0) {
Packit Service 1d0348
		struct archive_rb_node *n;
Packit Service 1d0348
		uint64_t data_offset, data_size, data_unpacksize;
Packit Service 1d0348
		unsigned header_compression;
Packit Service 1d0348
Packit Service 1d0348
		r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		data_offset = 0;
Packit Service 1d0348
		data_size = zip->stream.total_out;
Packit Service 1d0348
		data_unpacksize = zip->stream.total_in;
Packit Service 1d0348
		zip->coder.codec = zip->opt_compression;
Packit Service 1d0348
		zip->coder.prop_size = zip->stream.prop_size;
Packit Service 1d0348
		zip->coder.props = zip->stream.props;
Packit Service 1d0348
		zip->stream.prop_size = 0;
Packit Service 1d0348
		zip->stream.props = NULL;
Packit Service 1d0348
		zip->total_number_nonempty_entry =
Packit Service 1d0348
		    zip->total_number_entry - zip->total_number_empty_entry;
Packit Service 1d0348
Packit Service 1d0348
		/* Connect an empty file list. */
Packit Service 1d0348
		if (zip->empty_list.first != NULL) {
Packit Service 1d0348
			*zip->file_list.last = zip->empty_list.first;
Packit Service 1d0348
			zip->file_list.last = zip->empty_list.last;
Packit Service 1d0348
		}
Packit Service 1d0348
		/* Connect a directory file list. */
Packit Service 1d0348
		ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) {
Packit Service 1d0348
			file_register(zip, (struct file *)n);
Packit Service 1d0348
		}
Packit Service 1d0348
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for
Packit Service 1d0348
		 * the compression type for encoding the header.
Packit Service 1d0348
		 */
Packit Service 1d0348
#if HAVE_LZMA_H
Packit Service 1d0348
		header_compression = _7Z_LZMA1;
Packit Service 1d0348
		/* If the stored file is only one, do not encode the header.
Packit Service 1d0348
		 * This is the same way 7z command does. */
Packit Service 1d0348
		if (zip->total_number_entry == 1)
Packit Service 1d0348
			header_compression = _7Z_COPY;
Packit Service 1d0348
#else
Packit Service 1d0348
		header_compression = _7Z_COPY;
Packit Service 1d0348
#endif
Packit Service 1d0348
		r = _7z_compression_init_encoder(a, header_compression, 6);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		zip->crc32flg = PRECODE_CRC32;
Packit Service 1d0348
		zip->precode_crc32 = 0;
Packit Service 1d0348
		r = make_header(a, data_offset, data_size, data_unpacksize,
Packit Service 1d0348
			1, &(zip->coder));
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		header_offset = data_offset + data_size;
Packit Service 1d0348
		header_size = zip->stream.total_out;
Packit Service 1d0348
		header_crc32 = zip->precode_crc32;
Packit Service 1d0348
		header_unpacksize = zip->stream.total_in;
Packit Service 1d0348
Packit Service 1d0348
		if (header_compression != _7Z_COPY) {
Packit Service 1d0348
			/*
Packit Service 1d0348
			 * Encode the header in order to reduce the size
Packit Service 1d0348
			 * of the archive.
Packit Service 1d0348
			 */
Packit Service 1d0348
			free(zip->coder.props);
Packit Service 1d0348
			zip->coder.codec = header_compression;
Packit Service 1d0348
			zip->coder.prop_size = zip->stream.prop_size;
Packit Service 1d0348
			zip->coder.props = zip->stream.props;
Packit Service 1d0348
			zip->stream.prop_size = 0;
Packit Service 1d0348
			zip->stream.props = NULL;
Packit Service 1d0348
Packit Service 1d0348
			r = _7z_compression_init_encoder(a, _7Z_COPY, 0);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
			zip->crc32flg = ENCODED_CRC32;
Packit Service 1d0348
			zip->encoded_crc32 = 0;
Packit Service 1d0348
Packit Service 1d0348
			/*
Packit Service 1d0348
			 * Make EncodedHeader.
Packit Service 1d0348
			 */
Packit Service 1d0348
			r = enc_uint64(a, kEncodedHeader);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
			r = make_streamsInfo(a, header_offset, header_size,
Packit Service 1d0348
			      header_unpacksize, 1, &(zip->coder), 0,
Packit Service 1d0348
			      header_crc32);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
			r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
			header_offset = header_offset + header_size;
Packit Service 1d0348
			header_size = zip->stream.total_out;
Packit Service 1d0348
			header_crc32 = zip->encoded_crc32;
Packit Service 1d0348
		}
Packit Service 1d0348
		zip->crc32flg = 0;
Packit Service 1d0348
	} else {
Packit Service 1d0348
		header_offset = header_size = 0;
Packit Service 1d0348
		header_crc32 = 0;
Packit Service 1d0348
	}
Packit Service 1d0348
	
Packit Service 1d0348
	length = zip->temp_offset;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make the zip header on wbuff(write buffer).
Packit Service 1d0348
	 */
Packit Service 1d0348
	wb = zip->wbuff;
Packit Service 1d0348
	zip->wbuff_remaining = sizeof(zip->wbuff);
Packit Service 1d0348
	memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6);
Packit Service 1d0348
	wb[6] = 0;/* Major version. */
Packit Service 1d0348
	wb[7] = 3;/* Minor version. */
Packit Service 1d0348
	archive_le64enc(&wb[12], header_offset);/* Next Header Offset */
Packit Service 1d0348
	archive_le64enc(&wb[20], header_size);/* Next Header Size */
Packit Service 1d0348
	archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */
Packit Service 1d0348
	archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */
Packit Service 1d0348
	zip->wbuff_remaining -= 32;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Read all file contents and an encoded header from the temporary
Packit Service 1d0348
	 * file and write out it.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = copy_out(a, 0, length);
Packit Service 1d0348
	if (r != ARCHIVE_OK)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	r = flush_wbuff(a);
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Encode 64 bits value into 7-Zip's encoded UINT64 value.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
enc_uint64(struct archive_write *a, uint64_t val)
Packit Service 1d0348
{
Packit Service 1d0348
	unsigned mask = 0x80;
Packit Service 1d0348
	uint8_t numdata[9];
Packit Service 1d0348
	int i;
Packit Service 1d0348
Packit Service 1d0348
	numdata[0] = 0;
Packit Service 1d0348
	for (i = 1; i < (int)sizeof(numdata); i++) {
Packit Service 1d0348
		if (val < mask) {
Packit Service 1d0348
			numdata[0] |= (uint8_t)val;
Packit Service 1d0348
			break;
Packit Service 1d0348
		}
Packit Service 1d0348
		numdata[i] = (uint8_t)val;
Packit Service 1d0348
		val >>= 8;
Packit Service 1d0348
		numdata[0] |= mask;
Packit Service 1d0348
		mask >>= 1;
Packit Service 1d0348
	}
Packit Service 1d0348
	return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN));
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_substreamsInfo(struct archive_write *a, struct coder *coders)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	struct file *file;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make SubStreamsInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kSubStreamsInfo);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) {
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * Make NumUnPackStream.
Packit Service 1d0348
		 */
Packit Service 1d0348
		r = enc_uint64(a, kNumUnPackStream);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/* Write numUnpackStreams */
Packit Service 1d0348
		r = enc_uint64(a, zip->total_number_nonempty_entry);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * Make kSize.
Packit Service 1d0348
		 */
Packit Service 1d0348
		r = enc_uint64(a, kSize);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->next == NULL ||
Packit Service 1d0348
			    file->next->size == 0)
Packit Service 1d0348
				break;
Packit Service 1d0348
			r = enc_uint64(a, file->size);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make CRC.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kCRC);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
	/* All are defined */
Packit Service 1d0348
	r = enc_uint64(a, 1);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	file = zip->file_list.first;
Packit Service 1d0348
	for (;file != NULL; file = file->next) {
Packit Service 1d0348
		uint8_t crc[4];
Packit Service 1d0348
		if (file->size == 0)
Packit Service 1d0348
			break;
Packit Service 1d0348
		archive_le32enc(crc, file->crc32);
Packit Service 1d0348
		r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Write End. */
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size,
Packit Service 1d0348
    uint64_t unpack_size, int num_coder, struct coder *coders, int substrm,
Packit Service 1d0348
    uint32_t header_crc)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	uint8_t codec_buff[8];
Packit Service 1d0348
	int numFolders, fi;
Packit Service 1d0348
	int codec_size;
Packit Service 1d0348
	int i, r;
Packit Service 1d0348
Packit Service 1d0348
	if (coders->codec == _7Z_COPY)
Packit Service 1d0348
		numFolders = (int)zip->total_number_nonempty_entry;
Packit Service 1d0348
	else
Packit Service 1d0348
		numFolders = 1;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make PackInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kPackInfo);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write PackPos. */
Packit Service 1d0348
	r = enc_uint64(a, offset);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write NumPackStreams. */
Packit Service 1d0348
	r = enc_uint64(a, numFolders);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Make Size. */
Packit Service 1d0348
	r = enc_uint64(a, kSize);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	if (numFolders > 1) {
Packit Service 1d0348
		struct file *file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->size == 0)
Packit Service 1d0348
				break;
Packit Service 1d0348
			r = enc_uint64(a, file->size);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	} else {
Packit Service 1d0348
		/* Write size. */
Packit Service 1d0348
		r = enc_uint64(a, pack_size);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make UnPackInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kUnPackInfo);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make Folder.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kFolder);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write NumFolders. */
Packit Service 1d0348
	r = enc_uint64(a, numFolders);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write External. */
Packit Service 1d0348
	r = enc_uint64(a, 0);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	for (fi = 0; fi < numFolders; fi++) {
Packit Service 1d0348
		/* Write NumCoders. */
Packit Service 1d0348
		r = enc_uint64(a, num_coder);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		for (i = 0; i < num_coder; i++) {
Packit Service 1d0348
			unsigned codec_id = coders[i].codec;
Packit Service 1d0348
Packit Service 1d0348
			/* Write Codec flag. */
Packit Service 1d0348
			archive_be64enc(codec_buff, codec_id);
Packit Service 1d0348
			for (codec_size = 8; codec_size > 0; codec_size--) {
Packit Service 1d0348
				if (codec_buff[8 - codec_size])
Packit Service 1d0348
					break;
Packit Service 1d0348
			}
Packit Service 1d0348
			if (codec_size == 0)
Packit Service 1d0348
				codec_size = 1;
Packit Service 1d0348
			if (coders[i].prop_size)
Packit Service 1d0348
				r = enc_uint64(a, codec_size | 0x20);
Packit Service 1d0348
			else
Packit Service 1d0348
				r = enc_uint64(a, codec_size);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
Packit Service 1d0348
			/* Write Codec ID. */
Packit Service 1d0348
			codec_size &= 0x0f;
Packit Service 1d0348
			r = (int)compress_out(a, &codec_buff[8-codec_size],
Packit Service 1d0348
				codec_size, ARCHIVE_Z_RUN);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
Packit Service 1d0348
			if (coders[i].prop_size) {
Packit Service 1d0348
				/* Write Codec property size. */
Packit Service 1d0348
				r = enc_uint64(a, coders[i].prop_size);
Packit Service 1d0348
				if (r < 0)
Packit Service 1d0348
					return (r);
Packit Service 1d0348
Packit Service 1d0348
				/* Write Codec properties. */
Packit Service 1d0348
				r = (int)compress_out(a, coders[i].props,
Packit Service 1d0348
					coders[i].prop_size, ARCHIVE_Z_RUN);
Packit Service 1d0348
				if (r < 0)
Packit Service 1d0348
					return (r);
Packit Service 1d0348
			}
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make CodersUnPackSize.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kCodersUnPackSize);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	if (numFolders > 1) {
Packit Service 1d0348
		struct file *file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->size == 0)
Packit Service 1d0348
				break;
Packit Service 1d0348
			r = enc_uint64(a, file->size);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
Packit Service 1d0348
	} else {
Packit Service 1d0348
		/* Write UnPackSize. */
Packit Service 1d0348
		r = enc_uint64(a, unpack_size);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	if (!substrm) {
Packit Service 1d0348
		uint8_t crc[4];
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * Make CRC.
Packit Service 1d0348
		 */
Packit Service 1d0348
		r = enc_uint64(a, kCRC);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/* All are defined */
Packit Service 1d0348
		r = enc_uint64(a, 1);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		archive_le32enc(crc, header_crc);
Packit Service 1d0348
		r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Write End. */
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	if (substrm) {
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * Make SubStreamsInfo.
Packit Service 1d0348
		 */
Packit Service 1d0348
		r = make_substreamsInfo(a, coders);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
	/* Write End. */
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
Packit Service 1d0348
static uint64_t
Packit Service 1d0348
utcToFiletime(time_t t, long ns)
Packit Service 1d0348
{
Packit Service 1d0348
	uint64_t fileTime;
Packit Service 1d0348
Packit Service 1d0348
	fileTime = t;
Packit Service 1d0348
	fileTime *= 10000000;
Packit Service 1d0348
	fileTime += ns / 100;
Packit Service 1d0348
	fileTime += EPOC_TIME;
Packit Service 1d0348
	return (fileTime);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_time(struct archive_write *a, uint8_t type, unsigned flg, int ti)
Packit Service 1d0348
{
Packit Service 1d0348
	uint8_t filetime[8];
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	struct file *file;
Packit Service 1d0348
	int r;
Packit Service 1d0348
	uint8_t b, mask;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make Time Bools.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if (zip->total_number_time_defined[ti] == zip->total_number_entry) {
Packit Service 1d0348
		/* Write Time Type. */
Packit Service 1d0348
		r = enc_uint64(a, type);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		/* Write EmptyStream Size. */
Packit Service 1d0348
		r = enc_uint64(a, 2 + zip->total_number_entry * 8);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		/* All are defined. */
Packit Service 1d0348
		r = enc_uint64(a, 1);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	} else {
Packit Service 1d0348
		if (zip->total_number_time_defined[ti] == 0)
Packit Service 1d0348
			return (ARCHIVE_OK);
Packit Service 1d0348
Packit Service 1d0348
		/* Write Time Type. */
Packit Service 1d0348
		r = enc_uint64(a, type);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		/* Write EmptyStream Size. */
Packit Service 1d0348
		r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3)
Packit Service 1d0348
			+ zip->total_number_time_defined[ti] * 8);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/* All are not defined. */
Packit Service 1d0348
		r = enc_uint64(a, 0);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		b = 0;
Packit Service 1d0348
		mask = 0x80;
Packit Service 1d0348
		file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->flg & flg)
Packit Service 1d0348
				b |= mask;
Packit Service 1d0348
			mask >>= 1;
Packit Service 1d0348
			if (mask == 0) {
Packit Service 1d0348
				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
				if (r < 0)
Packit Service 1d0348
					return (r);
Packit Service 1d0348
				mask = 0x80;
Packit Service 1d0348
				b = 0;
Packit Service 1d0348
			}
Packit Service 1d0348
		}
Packit Service 1d0348
		if (mask != 0x80) {
Packit Service 1d0348
			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* External. */
Packit Service 1d0348
	r = enc_uint64(a, 0);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make Times.
Packit Service 1d0348
	 */
Packit Service 1d0348
	file = zip->file_list.first;
Packit Service 1d0348
	for (;file != NULL; file = file->next) {
Packit Service 1d0348
		if ((file->flg & flg) == 0)
Packit Service 1d0348
			continue;
Packit Service 1d0348
		archive_le64enc(filetime, utcToFiletime(file->times[ti].time,
Packit Service 1d0348
			file->times[ti].time_ns));
Packit Service 1d0348
		r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
make_header(struct archive_write *a, uint64_t offset, uint64_t pack_size,
Packit Service 1d0348
    uint64_t unpack_size, int codernum, struct coder *coders)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	struct file *file;
Packit Service 1d0348
	int r;
Packit Service 1d0348
	uint8_t b, mask;
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make FilesInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kHeader);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * If there are empty files only, do not write MainStreamInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if (zip->total_number_nonempty_entry) {
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * Make MainStreamInfo.
Packit Service 1d0348
		 */
Packit Service 1d0348
		r = enc_uint64(a, kMainStreamsInfo);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		r = make_streamsInfo(a, offset, pack_size, unpack_size,
Packit Service 1d0348
		      codernum, coders, 1, 0);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * Make FilesInfo.
Packit Service 1d0348
	 */
Packit Service 1d0348
	r = enc_uint64(a, kFilesInfo);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write numFiles. */
Packit Service 1d0348
	r = enc_uint64(a, zip->total_number_entry);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	if (zip->total_number_empty_entry > 0) {
Packit Service 1d0348
		/* Make EmptyStream. */
Packit Service 1d0348
		r = enc_uint64(a, kEmptyStream);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/* Write EmptyStream Size. */
Packit Service 1d0348
		r = enc_uint64(a, (zip->total_number_entry+7)>>3);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		b = 0;
Packit Service 1d0348
		mask = 0x80;
Packit Service 1d0348
		file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->size == 0)
Packit Service 1d0348
				b |= mask;
Packit Service 1d0348
			mask >>= 1;
Packit Service 1d0348
			if (mask == 0) {
Packit Service 1d0348
				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
				if (r < 0)
Packit Service 1d0348
					return (r);
Packit Service 1d0348
				mask = 0x80;
Packit Service 1d0348
				b = 0;
Packit Service 1d0348
			}
Packit Service 1d0348
		}
Packit Service 1d0348
		if (mask != 0x80) {
Packit Service 1d0348
			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	if (zip->total_number_empty_entry > zip->total_number_dir_entry) {
Packit Service 1d0348
		/* Make EmptyFile. */
Packit Service 1d0348
		r = enc_uint64(a, kEmptyFile);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		/* Write EmptyFile Size. */
Packit Service 1d0348
		r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
Packit Service 1d0348
		b = 0;
Packit Service 1d0348
		mask = 0x80;
Packit Service 1d0348
		file = zip->file_list.first;
Packit Service 1d0348
		for (;file != NULL; file = file->next) {
Packit Service 1d0348
			if (file->size)
Packit Service 1d0348
				continue;
Packit Service 1d0348
			if (!file->dir)
Packit Service 1d0348
				b |= mask;
Packit Service 1d0348
			mask >>= 1;
Packit Service 1d0348
			if (mask == 0) {
Packit Service 1d0348
				r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
				if (r < 0)
Packit Service 1d0348
					return (r);
Packit Service 1d0348
				mask = 0x80;
Packit Service 1d0348
				b = 0;
Packit Service 1d0348
			}
Packit Service 1d0348
		}
Packit Service 1d0348
		if (mask != 0x80) {
Packit Service 1d0348
			r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN);
Packit Service 1d0348
			if (r < 0)
Packit Service 1d0348
				return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Make Name. */
Packit Service 1d0348
	r = enc_uint64(a, kName);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write Name size. */
Packit Service 1d0348
	r = enc_uint64(a, zip->total_bytes_entry_name+1);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write dmy byte. */
Packit Service 1d0348
	r = enc_uint64(a, 0);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	file = zip->file_list.first;
Packit Service 1d0348
	for (;file != NULL; file = file->next) {
Packit Service 1d0348
		r = (int)compress_out(a, file->utf16name, file->name_len+2,
Packit Service 1d0348
			ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Make MTime. */
Packit Service 1d0348
	r = make_time(a, kMTime, MTIME_IS_SET, MTIME);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Make CTime. */
Packit Service 1d0348
	r = make_time(a, kCTime, CTIME_IS_SET, CTIME);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Make ATime. */
Packit Service 1d0348
	r = make_time(a, kATime, ATIME_IS_SET, ATIME);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Make Attributes. */
Packit Service 1d0348
	r = enc_uint64(a, kAttributes);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write Attributes size. */
Packit Service 1d0348
	r = enc_uint64(a, 2 + zip->total_number_entry * 4);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write "All Are Defined". */
Packit Service 1d0348
	r = enc_uint64(a, 1);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write dmy byte. */
Packit Service 1d0348
	r = enc_uint64(a, 0);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	file = zip->file_list.first;
Packit Service 1d0348
	for (;file != NULL; file = file->next) {
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * High 16bits is unix mode.
Packit Service 1d0348
		 * Low 16bits is Windows attributes.
Packit Service 1d0348
		 */
Packit Service 1d0348
		uint32_t encattr, attr;
Packit Service 1d0348
		if (file->dir)
Packit Service 1d0348
			attr = 0x8010;
Packit Service 1d0348
		else
Packit Service 1d0348
			attr = 0x8020;
Packit Service 1d0348
		if ((file->mode & 0222) == 0)
Packit Service 1d0348
			attr |= 1;/* Read Only. */
Packit Service 1d0348
		attr |= ((uint32_t)file->mode) << 16;
Packit Service 1d0348
		archive_le32enc(&encattr, attr);
Packit Service 1d0348
		r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN);
Packit Service 1d0348
		if (r < 0)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* Write End. */
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	/* Write End. */
Packit Service 1d0348
	r = enc_uint64(a, kEnd);
Packit Service 1d0348
	if (r < 0)
Packit Service 1d0348
		return (r);
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_free(struct archive_write *a)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
Packit Service 1d0348
	/* Close the temporary file. */
Packit Service 1d0348
	if (zip->temp_fd >= 0)
Packit Service 1d0348
		close(zip->temp_fd);
Packit Service 1d0348
Packit Service 1d0348
	file_free_register(zip);
Packit Service 1d0348
	compression_end(&(a->archive), &(zip->stream));
Packit Service 1d0348
	free(zip->coder.props);
Packit Service 1d0348
	free(zip);
Packit Service 1d0348
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
file_cmp_node(const struct archive_rb_node *n1,
Packit Service 1d0348
    const struct archive_rb_node *n2)
Packit Service 1d0348
{
Packit Service 1d0348
	const struct file *f1 = (const struct file *)n1;
Packit Service 1d0348
	const struct file *f2 = (const struct file *)n2;
Packit Service 1d0348
Packit Service 1d0348
	if (f1->name_len == f2->name_len)
Packit Service 1d0348
		return (memcmp(f1->utf16name, f2->utf16name, f1->name_len));
Packit Service 1d0348
	return (f1->name_len > f2->name_len)?1:-1;
Packit Service 1d0348
}
Packit Service 1d0348
        
Packit Service 1d0348
static int
Packit Service 1d0348
file_cmp_key(const struct archive_rb_node *n, const void *key)
Packit Service 1d0348
{
Packit Service 1d0348
	const struct file *f = (const struct file *)n;
Packit Service 1d0348
Packit Service 1d0348
	return (f->name_len - *(const char *)key);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
file_new(struct archive_write *a, struct archive_entry *entry,
Packit Service 1d0348
    struct file **newfile)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	struct file *file;
Packit Service 1d0348
	const char *u16;
Packit Service 1d0348
	size_t u16len;
Packit Service 1d0348
	int ret = ARCHIVE_OK;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	*newfile = NULL;
Packit Service 1d0348
Packit Service 1d0348
	file = calloc(1, sizeof(*file));
Packit Service 1d0348
	if (file == NULL) {
Packit Service 1d0348
		archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) {
Packit Service 1d0348
		if (errno == ENOMEM) {
Packit Service 1d0348
			free(file);
Packit Service 1d0348
			archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
			    "Can't allocate memory for UTF-16LE");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "A filename cannot be converted to UTF-16LE;"
Packit Service 1d0348
		    "You should disable making Joliet extension");
Packit Service 1d0348
		ret = ARCHIVE_WARN;
Packit Service 1d0348
	}
Packit Service 1d0348
	file->utf16name = malloc(u16len + 2);
Packit Service 1d0348
	if (file->utf16name == NULL) {
Packit Service 1d0348
		free(file);
Packit Service 1d0348
		archive_set_error(&a->archive, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for Name");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	memcpy(file->utf16name, u16, u16len);
Packit Service 1d0348
	file->utf16name[u16len+0] = 0;
Packit Service 1d0348
	file->utf16name[u16len+1] = 0;
Packit Service 1d0348
	file->name_len = (unsigned)u16len;
Packit Service 1d0348
	file->mode = archive_entry_mode(entry);
Packit Service 1d0348
	if (archive_entry_filetype(entry) == AE_IFREG)
Packit Service 1d0348
		file->size = archive_entry_size(entry);
Packit Service 1d0348
	else
Packit Service 1d0348
		archive_entry_set_size(entry, 0);
Packit Service 1d0348
	if (archive_entry_filetype(entry) == AE_IFDIR)
Packit Service 1d0348
		file->dir = 1;
Packit Service 1d0348
	else if (archive_entry_filetype(entry) == AE_IFLNK)
Packit Service 1d0348
		file->size = strlen(archive_entry_symlink(entry));
Packit Service 1d0348
	if (archive_entry_mtime_is_set(entry)) {
Packit Service 1d0348
		file->flg |= MTIME_IS_SET;
Packit Service 1d0348
		file->times[MTIME].time = archive_entry_mtime(entry);
Packit Service 1d0348
		file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (archive_entry_atime_is_set(entry)) {
Packit Service 1d0348
		file->flg |= ATIME_IS_SET;
Packit Service 1d0348
		file->times[ATIME].time = archive_entry_atime(entry);
Packit Service 1d0348
		file->times[ATIME].time_ns = archive_entry_atime_nsec(entry);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (archive_entry_ctime_is_set(entry)) {
Packit Service 1d0348
		file->flg |= CTIME_IS_SET;
Packit Service 1d0348
		file->times[CTIME].time = archive_entry_ctime(entry);
Packit Service 1d0348
		file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	*newfile = file;
Packit Service 1d0348
	return (ret);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_free(struct file *file)
Packit Service 1d0348
{
Packit Service 1d0348
	free(file->utf16name);
Packit Service 1d0348
	free(file);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_register(struct _7zip *zip, struct file *file)
Packit Service 1d0348
{
Packit Service 1d0348
	file->next = NULL;
Packit Service 1d0348
	*zip->file_list.last = file;
Packit Service 1d0348
	zip->file_list.last = &(file->next);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_init_register(struct _7zip *zip)
Packit Service 1d0348
{
Packit Service 1d0348
	zip->file_list.first = NULL;
Packit Service 1d0348
	zip->file_list.last = &(zip->file_list.first);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_free_register(struct _7zip *zip)
Packit Service 1d0348
{
Packit Service 1d0348
	struct file *file, *file_next;
Packit Service 1d0348
Packit Service 1d0348
	file = zip->file_list.first;
Packit Service 1d0348
	while (file != NULL) {
Packit Service 1d0348
		file_next = file->next;
Packit Service 1d0348
		file_free(file);
Packit Service 1d0348
		file = file_next;
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_register_empty(struct _7zip *zip, struct file *file)
Packit Service 1d0348
{
Packit Service 1d0348
	file->next = NULL;
Packit Service 1d0348
	*zip->empty_list.last = file;
Packit Service 1d0348
	zip->empty_list.last = &(file->next);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
file_init_register_empty(struct _7zip *zip)
Packit Service 1d0348
{
Packit Service 1d0348
	zip->empty_list.first = NULL;
Packit Service 1d0348
	zip->empty_list.last = &(zip->empty_list.first);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\
Packit Service 1d0348
	 !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H)
Packit Service 1d0348
static int
Packit Service 1d0348
compression_unsupported_encoder(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, const char *name)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
	    "%s compression not supported on this platform", name);
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	lastrm->real_stream = NULL;
Packit Service 1d0348
	return (ARCHIVE_FAILED);
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * _7_COPY compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	lastrm->valid = 1;
Packit Service 1d0348
	lastrm->code = compression_code_copy;
Packit Service 1d0348
	lastrm->end = compression_end_copy;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code_copy(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	size_t bytes;
Packit Service 1d0348
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
	if (lastrm->avail_out > lastrm->avail_in)
Packit Service 1d0348
		bytes = lastrm->avail_in;
Packit Service 1d0348
	else
Packit Service 1d0348
		bytes = lastrm->avail_out;
Packit Service 1d0348
	if (bytes) {
Packit Service 1d0348
		memcpy(lastrm->next_out, lastrm->next_in, bytes);
Packit Service 1d0348
		lastrm->next_in += bytes;
Packit Service 1d0348
		lastrm->avail_in -= bytes;
Packit Service 1d0348
		lastrm->total_in += bytes;
Packit Service 1d0348
		lastrm->next_out += bytes;
Packit Service 1d0348
		lastrm->avail_out -= bytes;
Packit Service 1d0348
		lastrm->total_out += bytes;
Packit Service 1d0348
	}
Packit Service 1d0348
	if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0)
Packit Service 1d0348
		return (ARCHIVE_EOF);
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end_copy(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * _7_DEFLATE compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
#ifdef HAVE_ZLIB_H
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_deflate(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level, int withheader)
Packit Service 1d0348
{
Packit Service 1d0348
	z_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	strm = calloc(1, sizeof(*strm));
Packit Service 1d0348
	if (strm == NULL) {
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for gzip stream");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	/* zlib.h is not const-correct, so we need this one bit
Packit Service 1d0348
	 * of ugly hackery to convert a const * pointer to
Packit Service 1d0348
	 * a non-const pointer. */
Packit Service 1d0348
	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
Packit Service 1d0348
	strm->avail_in = (uInt)lastrm->avail_in;
Packit Service 1d0348
	strm->total_in = (uLong)lastrm->total_in;
Packit Service 1d0348
	strm->next_out = lastrm->next_out;
Packit Service 1d0348
	strm->avail_out = (uInt)lastrm->avail_out;
Packit Service 1d0348
	strm->total_out = (uLong)lastrm->total_out;
Packit Service 1d0348
	if (deflateInit2(strm, level, Z_DEFLATED,
Packit Service 1d0348
	    (withheader)?15:-15,
Packit Service 1d0348
	    8, Z_DEFAULT_STRATEGY) != Z_OK) {
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Internal error initializing compression library");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	lastrm->real_stream = strm;
Packit Service 1d0348
	lastrm->valid = 1;
Packit Service 1d0348
	lastrm->code = compression_code_deflate;
Packit Service 1d0348
	lastrm->end = compression_end_deflate;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code_deflate(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	z_stream *strm;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	strm = (z_stream *)lastrm->real_stream;
Packit Service 1d0348
	/* zlib.h is not const-correct, so we need this one bit
Packit Service 1d0348
	 * of ugly hackery to convert a const * pointer to
Packit Service 1d0348
	 * a non-const pointer. */
Packit Service 1d0348
	strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in;
Packit Service 1d0348
	strm->avail_in = (uInt)lastrm->avail_in;
Packit Service 1d0348
	strm->total_in = (uLong)lastrm->total_in;
Packit Service 1d0348
	strm->next_out = lastrm->next_out;
Packit Service 1d0348
	strm->avail_out = (uInt)lastrm->avail_out;
Packit Service 1d0348
	strm->total_out = (uLong)lastrm->total_out;
Packit Service 1d0348
	r = deflate(strm,
Packit Service 1d0348
	    (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH);
Packit Service 1d0348
	lastrm->next_in = strm->next_in;
Packit Service 1d0348
	lastrm->avail_in = strm->avail_in;
Packit Service 1d0348
	lastrm->total_in = strm->total_in;
Packit Service 1d0348
	lastrm->next_out = strm->next_out;
Packit Service 1d0348
	lastrm->avail_out = strm->avail_out;
Packit Service 1d0348
	lastrm->total_out = strm->total_out;
Packit Service 1d0348
	switch (r) {
Packit Service 1d0348
	case Z_OK:
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
	case Z_STREAM_END:
Packit Service 1d0348
		return (ARCHIVE_EOF);
Packit Service 1d0348
	default:
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "GZip compression failed:"
Packit Service 1d0348
		    " deflate() call returned status %d", r);
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end_deflate(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	z_stream *strm;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	strm = (z_stream *)lastrm->real_stream;
Packit Service 1d0348
	r = deflateEnd(strm);
Packit Service 1d0348
	free(strm);
Packit Service 1d0348
	lastrm->real_stream = NULL;
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	if (r != Z_OK) {
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Failed to clean up compressor");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
#else
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_deflate(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level, int withheader)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	(void) level; /* UNUSED */
Packit Service 1d0348
	(void) withheader; /* UNUSED */
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	return (compression_unsupported_encoder(a, lastrm, "deflate"));
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * _7_BZIP2 compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR)
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_bzip2(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
	bz_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	strm = calloc(1, sizeof(*strm));
Packit Service 1d0348
	if (strm == NULL) {
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for bzip2 stream");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	/* bzlib.h is not const-correct, so we need this one bit
Packit Service 1d0348
	 * of ugly hackery to convert a const * pointer to
Packit Service 1d0348
	 * a non-const pointer. */
Packit Service 1d0348
	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
Packit Service 1d0348
	strm->avail_in = lastrm->avail_in;
Packit Service 1d0348
	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
Packit Service 1d0348
	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
Packit Service 1d0348
	strm->next_out = (char *)lastrm->next_out;
Packit Service 1d0348
	strm->avail_out = lastrm->avail_out;
Packit Service 1d0348
	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
Packit Service 1d0348
	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
Packit Service 1d0348
	if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) {
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Internal error initializing compression library");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	lastrm->real_stream = strm;
Packit Service 1d0348
	lastrm->valid = 1;
Packit Service 1d0348
	lastrm->code = compression_code_bzip2;
Packit Service 1d0348
	lastrm->end = compression_end_bzip2;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code_bzip2(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	bz_stream *strm;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	strm = (bz_stream *)lastrm->real_stream;
Packit Service 1d0348
	/* bzlib.h is not const-correct, so we need this one bit
Packit Service 1d0348
	 * of ugly hackery to convert a const * pointer to
Packit Service 1d0348
	 * a non-const pointer. */
Packit Service 1d0348
	strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in;
Packit Service 1d0348
	strm->avail_in = lastrm->avail_in;
Packit Service 1d0348
	strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff);
Packit Service 1d0348
	strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32);
Packit Service 1d0348
	strm->next_out = (char *)lastrm->next_out;
Packit Service 1d0348
	strm->avail_out = lastrm->avail_out;
Packit Service 1d0348
	strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff);
Packit Service 1d0348
	strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32);
Packit Service 1d0348
	r = BZ2_bzCompress(strm,
Packit Service 1d0348
	    (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN);
Packit Service 1d0348
	lastrm->next_in = (const unsigned char *)strm->next_in;
Packit Service 1d0348
	lastrm->avail_in = strm->avail_in;
Packit Service 1d0348
	lastrm->total_in =
Packit Service 1d0348
	    (((uint64_t)(uint32_t)strm->total_in_hi32) << 32)
Packit Service 1d0348
	    + (uint64_t)(uint32_t)strm->total_in_lo32;
Packit Service 1d0348
	lastrm->next_out = (unsigned char *)strm->next_out;
Packit Service 1d0348
	lastrm->avail_out = strm->avail_out;
Packit Service 1d0348
	lastrm->total_out =
Packit Service 1d0348
	    (((uint64_t)(uint32_t)strm->total_out_hi32) << 32)
Packit Service 1d0348
	    + (uint64_t)(uint32_t)strm->total_out_lo32;
Packit Service 1d0348
	switch (r) {
Packit Service 1d0348
	case BZ_RUN_OK:     /* Non-finishing */
Packit Service 1d0348
	case BZ_FINISH_OK:  /* Finishing: There's more work to do */
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
	case BZ_STREAM_END: /* Finishing: all done */
Packit Service 1d0348
		/* Only occurs in finishing case */
Packit Service 1d0348
		return (ARCHIVE_EOF);
Packit Service 1d0348
	default:
Packit Service 1d0348
		/* Any other return value indicates an error */
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Bzip2 compression failed:"
Packit Service 1d0348
		    " BZ2_bzCompress() call returned status %d", r);
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end_bzip2(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	bz_stream *strm;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	strm = (bz_stream *)lastrm->real_stream;
Packit Service 1d0348
	r = BZ2_bzCompressEnd(strm);
Packit Service 1d0348
	free(strm);
Packit Service 1d0348
	lastrm->real_stream = NULL;
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	if (r != BZ_OK) {
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Failed to clean up compressor");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
#else
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_bzip2(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	(void) level; /* UNUSED */
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	return (compression_unsupported_encoder(a, lastrm, "bzip2"));
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * _7_LZMA1, _7_LZMA2 compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
#if defined(HAVE_LZMA_H)
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_lzma(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level, uint64_t filter_id)
Packit Service 1d0348
{
Packit Service 1d0348
	static const lzma_stream lzma_init_data = LZMA_STREAM_INIT;
Packit Service 1d0348
	lzma_stream *strm;
Packit Service 1d0348
	lzma_filter *lzmafilters;
Packit Service 1d0348
	lzma_options_lzma lzma_opt;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2);
Packit Service 1d0348
	if (strm == NULL) {
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for lzma stream");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	lzmafilters = (lzma_filter *)(strm+1);
Packit Service 1d0348
	if (level > 6)
Packit Service 1d0348
		level = 6;
Packit Service 1d0348
	if (lzma_lzma_preset(&lzma_opt, level)) {
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Internal error initializing compression library");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	lzmafilters[0].id = filter_id;
Packit Service 1d0348
	lzmafilters[0].options = &lzma_opt;
Packit Service 1d0348
	lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
Packit Service 1d0348
Packit Service 1d0348
	r = lzma_properties_size(&(lastrm->prop_size), lzmafilters);
Packit Service 1d0348
	if (r != LZMA_OK) {
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "lzma_properties_size failed");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (lastrm->prop_size) {
Packit Service 1d0348
		lastrm->props = malloc(lastrm->prop_size);
Packit Service 1d0348
		if (lastrm->props == NULL) {
Packit Service 1d0348
			free(strm);
Packit Service 1d0348
			lastrm->real_stream = NULL;
Packit Service 1d0348
			archive_set_error(a, ENOMEM,
Packit Service 1d0348
			    "Cannot allocate memory");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
		r = lzma_properties_encode(lzmafilters,  lastrm->props);
Packit Service 1d0348
		if (r != LZMA_OK) {
Packit Service 1d0348
			free(strm);
Packit Service 1d0348
			lastrm->real_stream = NULL;
Packit Service 1d0348
			archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
			    "lzma_properties_encode failed");
Packit Service 1d0348
			return (ARCHIVE_FATAL);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	*strm = lzma_init_data;
Packit Service 1d0348
	r = lzma_raw_encoder(strm, lzmafilters);
Packit Service 1d0348
	switch (r) {
Packit Service 1d0348
	case LZMA_OK:
Packit Service 1d0348
		lastrm->real_stream = strm;
Packit Service 1d0348
		lastrm->valid = 1;
Packit Service 1d0348
		lastrm->code = compression_code_lzma;
Packit Service 1d0348
		lastrm->end = compression_end_lzma;
Packit Service 1d0348
		r = ARCHIVE_OK;
Packit Service 1d0348
		break;
Packit Service 1d0348
	case LZMA_MEM_ERROR:
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Internal error initializing compression library: "
Packit Service 1d0348
		    "Cannot allocate memory");
Packit Service 1d0348
		r =  ARCHIVE_FATAL;
Packit Service 1d0348
		break;
Packit Service 1d0348
        default:
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		lastrm->real_stream = NULL;
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "Internal error initializing compression library: "
Packit Service 1d0348
		    "It's a bug in liblzma");
Packit Service 1d0348
		r =  ARCHIVE_FATAL;
Packit Service 1d0348
		break;
Packit Service 1d0348
	}
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_lzma1(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
	return compression_init_encoder_lzma(a, lastrm, level,
Packit Service 1d0348
		    LZMA_FILTER_LZMA1);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_lzma2(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
	return compression_init_encoder_lzma(a, lastrm, level,
Packit Service 1d0348
		    LZMA_FILTER_LZMA2);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code_lzma(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	lzma_stream *strm;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	strm = (lzma_stream *)lastrm->real_stream;
Packit Service 1d0348
	strm->next_in = lastrm->next_in;
Packit Service 1d0348
	strm->avail_in = lastrm->avail_in;
Packit Service 1d0348
	strm->total_in = lastrm->total_in;
Packit Service 1d0348
	strm->next_out = lastrm->next_out;
Packit Service 1d0348
	strm->avail_out = lastrm->avail_out;
Packit Service 1d0348
	strm->total_out = lastrm->total_out;
Packit Service 1d0348
	r = lzma_code(strm,
Packit Service 1d0348
	    (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN);
Packit Service 1d0348
	lastrm->next_in = strm->next_in;
Packit Service 1d0348
	lastrm->avail_in = strm->avail_in;
Packit Service 1d0348
	lastrm->total_in = strm->total_in;
Packit Service 1d0348
	lastrm->next_out = strm->next_out;
Packit Service 1d0348
	lastrm->avail_out = strm->avail_out;
Packit Service 1d0348
	lastrm->total_out = strm->total_out;
Packit Service 1d0348
	switch (r) {
Packit Service 1d0348
	case LZMA_OK:
Packit Service 1d0348
		/* Non-finishing case */
Packit Service 1d0348
		return (ARCHIVE_OK);
Packit Service 1d0348
	case LZMA_STREAM_END:
Packit Service 1d0348
		/* This return can only occur in finishing case. */
Packit Service 1d0348
		return (ARCHIVE_EOF);
Packit Service 1d0348
	case LZMA_MEMLIMIT_ERROR:
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "lzma compression error:"
Packit Service 1d0348
		    " %ju MiB would have been needed",
Packit Service 1d0348
		    (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1)
Packit Service 1d0348
			/ (1024 * 1024)));
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	default:
Packit Service 1d0348
		/* Any other return value indicates an error */
Packit Service 1d0348
		archive_set_error(a, ARCHIVE_ERRNO_MISC,
Packit Service 1d0348
		    "lzma compression failed:"
Packit Service 1d0348
		    " lzma_code() call returned status %d", r);
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end_lzma(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	lzma_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
	strm = (lzma_stream *)lastrm->real_stream;
Packit Service 1d0348
	lzma_end(strm);
Packit Service 1d0348
	free(strm);
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	lastrm->real_stream = NULL;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
#else
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_lzma1(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	(void) level; /* UNUSED */
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	return (compression_unsupported_encoder(a, lastrm, "lzma"));
Packit Service 1d0348
}
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_lzma2(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, int level)
Packit Service 1d0348
{
Packit Service 1d0348
Packit Service 1d0348
	(void) level; /* UNUSED */
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	return (compression_unsupported_encoder(a, lastrm, "lzma"));
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * _7_PPMD compressor.
Packit Service 1d0348
 */
Packit Service 1d0348
static void
Packit Service 1d0348
ppmd_write(void *p, Byte b)
Packit Service 1d0348
{
Packit Service 1d0348
	struct archive_write *a = ((IByteOut *)p)->a;
Packit Service 1d0348
	struct _7zip *zip = (struct _7zip *)(a->format_data);
Packit Service 1d0348
	struct la_zstream *lastrm = &(zip->stream);
Packit Service 1d0348
	struct ppmd_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->avail_out) {
Packit Service 1d0348
		*lastrm->next_out++ = b;
Packit Service 1d0348
		lastrm->avail_out--;
Packit Service 1d0348
		lastrm->total_out++;
Packit Service 1d0348
		return;
Packit Service 1d0348
	}
Packit Service 1d0348
	strm = (struct ppmd_stream *)lastrm->real_stream;
Packit Service 1d0348
	if (strm->buff_ptr < strm->buff_end) {
Packit Service 1d0348
		*strm->buff_ptr++ = b;
Packit Service 1d0348
		strm->buff_bytes++;
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_init_encoder_ppmd(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize)
Packit Service 1d0348
{
Packit Service 1d0348
	struct ppmd_stream *strm;
Packit Service 1d0348
	uint8_t *props;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		compression_end(a, lastrm);
Packit Service 1d0348
	strm = calloc(1, sizeof(*strm));
Packit Service 1d0348
	if (strm == NULL) {
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for PPMd");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	strm->buff = malloc(32);
Packit Service 1d0348
	if (strm->buff == NULL) {
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Can't allocate memory for PPMd");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	strm->buff_ptr = strm->buff;
Packit Service 1d0348
	strm->buff_end = strm->buff + 32;
Packit Service 1d0348
Packit Service 1d0348
	props = malloc(1+4);
Packit Service 1d0348
	if (props == NULL) {
Packit Service 1d0348
		free(strm->buff);
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Coludn't allocate memory for PPMd");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	props[0] = maxOrder;
Packit Service 1d0348
	archive_le32enc(props+1, msize);
Packit Service 1d0348
	__archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context);
Packit Service 1d0348
	r = __archive_ppmd7_functions.Ppmd7_Alloc(
Packit Service 1d0348
		&strm->ppmd7_context, msize);
Packit Service 1d0348
	if (r == 0) {
Packit Service 1d0348
		free(strm->buff);
Packit Service 1d0348
		free(strm);
Packit Service 1d0348
		free(props);
Packit Service 1d0348
		archive_set_error(a, ENOMEM,
Packit Service 1d0348
		    "Coludn't allocate memory for PPMd");
Packit Service 1d0348
		return (ARCHIVE_FATAL);
Packit Service 1d0348
	}
Packit Service 1d0348
	__archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder);
Packit Service 1d0348
	strm->byteout.a = (struct archive_write *)a;
Packit Service 1d0348
	strm->byteout.Write = ppmd_write;
Packit Service 1d0348
	strm->range_enc.Stream = &(strm->byteout);
Packit Service 1d0348
	__archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc));
Packit Service 1d0348
	strm->stat = 0;
Packit Service 1d0348
Packit Service 1d0348
	lastrm->real_stream = strm;
Packit Service 1d0348
	lastrm->valid = 1;
Packit Service 1d0348
	lastrm->code = compression_code_ppmd;
Packit Service 1d0348
	lastrm->end = compression_end_ppmd;
Packit Service 1d0348
	lastrm->prop_size = 5;
Packit Service 1d0348
	lastrm->props = props;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code_ppmd(struct archive *a,
Packit Service 1d0348
    struct la_zstream *lastrm, enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	struct ppmd_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
Packit Service 1d0348
	strm = (struct ppmd_stream *)lastrm->real_stream;
Packit Service 1d0348
Packit Service 1d0348
	/* Copy encoded data if there are remaining bytes from previous call. */
Packit Service 1d0348
	if (strm->buff_bytes) {
Packit Service 1d0348
		uint8_t *p = strm->buff_ptr - strm->buff_bytes;
Packit Service 1d0348
		while (lastrm->avail_out && strm->buff_bytes) {
Packit Service 1d0348
			*lastrm->next_out++ = *p++;
Packit Service 1d0348
			lastrm->avail_out--;
Packit Service 1d0348
			lastrm->total_out++;
Packit Service 1d0348
			strm->buff_bytes--;
Packit Service 1d0348
		}
Packit Service 1d0348
		if (strm->buff_bytes)
Packit Service 1d0348
			return (ARCHIVE_OK);
Packit Service 1d0348
		if (strm->stat == 1)
Packit Service 1d0348
			return (ARCHIVE_EOF);
Packit Service 1d0348
		strm->buff_ptr = strm->buff;
Packit Service 1d0348
	}
Packit Service 1d0348
	while (lastrm->avail_in && lastrm->avail_out) {
Packit Service 1d0348
		__archive_ppmd7_functions.Ppmd7_EncodeSymbol(
Packit Service 1d0348
			&(strm->ppmd7_context), &(strm->range_enc),
Packit Service 1d0348
			*lastrm->next_in++);
Packit Service 1d0348
		lastrm->avail_in--;
Packit Service 1d0348
		lastrm->total_in++;
Packit Service 1d0348
	}
Packit Service 1d0348
	if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) {
Packit Service 1d0348
		__archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData(
Packit Service 1d0348
			&(strm->range_enc));
Packit Service 1d0348
		strm->stat = 1;
Packit Service 1d0348
		/* Return EOF if there are no remaining bytes. */
Packit Service 1d0348
		if (strm->buff_bytes == 0)
Packit Service 1d0348
			return (ARCHIVE_EOF);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end_ppmd(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	struct ppmd_stream *strm;
Packit Service 1d0348
Packit Service 1d0348
	(void)a; /* UNUSED */
Packit Service 1d0348
Packit Service 1d0348
	strm = (struct ppmd_stream *)lastrm->real_stream;
Packit Service 1d0348
	__archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context);
Packit Service 1d0348
	free(strm->buff);
Packit Service 1d0348
	free(strm);
Packit Service 1d0348
	lastrm->real_stream = NULL;
Packit Service 1d0348
	lastrm->valid = 0;
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Universal compressor initializer.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
_7z_compression_init_encoder(struct archive_write *a, unsigned compression,
Packit Service 1d0348
    int compression_level)
Packit Service 1d0348
{
Packit Service 1d0348
	struct _7zip *zip;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
	zip = (struct _7zip *)a->format_data;
Packit Service 1d0348
	switch (compression) {
Packit Service 1d0348
	case _7Z_DEFLATE:
Packit Service 1d0348
		r = compression_init_encoder_deflate(
Packit Service 1d0348
		    &(a->archive), &(zip->stream),
Packit Service 1d0348
		    compression_level, 0);
Packit Service 1d0348
		break;
Packit Service 1d0348
	case _7Z_BZIP2:
Packit Service 1d0348
		r = compression_init_encoder_bzip2(
Packit Service 1d0348
		    &(a->archive), &(zip->stream),
Packit Service 1d0348
		    compression_level);
Packit Service 1d0348
		break;
Packit Service 1d0348
	case _7Z_LZMA1:
Packit Service 1d0348
		r = compression_init_encoder_lzma1(
Packit Service 1d0348
		    &(a->archive), &(zip->stream),
Packit Service 1d0348
		    compression_level);
Packit Service 1d0348
		break;
Packit Service 1d0348
	case _7Z_LZMA2:
Packit Service 1d0348
		r = compression_init_encoder_lzma2(
Packit Service 1d0348
		    &(a->archive), &(zip->stream),
Packit Service 1d0348
		    compression_level);
Packit Service 1d0348
		break;
Packit Service 1d0348
	case _7Z_PPMD:
Packit Service 1d0348
		r = compression_init_encoder_ppmd(
Packit Service 1d0348
		    &(a->archive), &(zip->stream),
Packit Service 1d0348
		    PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE);
Packit Service 1d0348
		break;
Packit Service 1d0348
	case _7Z_COPY:
Packit Service 1d0348
	default:
Packit Service 1d0348
		r = compression_init_encoder_copy(
Packit Service 1d0348
		    &(a->archive), &(zip->stream));
Packit Service 1d0348
		break;
Packit Service 1d0348
	}
Packit Service 1d0348
	if (r == ARCHIVE_OK) {
Packit Service 1d0348
		zip->stream.total_in = 0;
Packit Service 1d0348
		zip->stream.next_out = zip->wbuff;
Packit Service 1d0348
		zip->stream.avail_out = sizeof(zip->wbuff);
Packit Service 1d0348
		zip->stream.total_out = 0;
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_code(struct archive *a, struct la_zstream *lastrm,
Packit Service 1d0348
    enum la_zaction action)
Packit Service 1d0348
{
Packit Service 1d0348
	if (lastrm->valid)
Packit Service 1d0348
		return (lastrm->code(a, lastrm, action));
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
compression_end(struct archive *a, struct la_zstream *lastrm)
Packit Service 1d0348
{
Packit Service 1d0348
	if (lastrm->valid) {
Packit Service 1d0348
		lastrm->prop_size = 0;
Packit Service 1d0348
		free(lastrm->props);
Packit Service 1d0348
		lastrm->props = NULL;
Packit Service 1d0348
		return (lastrm->end(a, lastrm));
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ARCHIVE_OK);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348