1231200Smm/*- 2231200Smm * Copyright (c) 2011-2012 Michihiro NAKAJIMA 3231200Smm * All rights reserved. 4231200Smm * 5231200Smm * Redistribution and use in source and binary forms, with or without 6231200Smm * modification, are permitted provided that the following conditions 7231200Smm * are met: 8231200Smm * 1. Redistributions of source code must retain the above copyright 9231200Smm * notice, this list of conditions and the following disclaimer. 10231200Smm * 2. Redistributions in binary form must reproduce the above copyright 11231200Smm * notice, this list of conditions and the following disclaimer in the 12231200Smm * documentation and/or other materials provided with the distribution. 13231200Smm * 14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24231200Smm */ 25231200Smm 26231200Smm#include "archive_platform.h" 27231200Smm__FBSDID("$FreeBSD$"); 28231200Smm 29231200Smm#ifdef HAVE_ERRNO_H 30231200Smm#include <errno.h> 31231200Smm#endif 32231200Smm#include <stdlib.h> 33231200Smm#ifdef HAVE_BZLIB_H 34231200Smm#include <bzlib.h> 35231200Smm#endif 36231200Smm#if HAVE_LZMA_H 37231200Smm#include <lzma.h> 38231200Smm#endif 39231200Smm#ifdef HAVE_ZLIB_H 40231200Smm#include <zlib.h> 41231200Smm#endif 42231200Smm 43231200Smm#include "archive.h" 44231200Smm#ifndef HAVE_ZLIB_H 45231200Smm#include "archive_crc32.h" 46231200Smm#endif 47231200Smm#include "archive_endian.h" 48231200Smm#include "archive_entry.h" 49231200Smm#include "archive_entry_locale.h" 50231200Smm#include "archive_ppmd7_private.h" 51231200Smm#include "archive_private.h" 52231200Smm#include "archive_rb.h" 53231200Smm#include "archive_string.h" 54231200Smm#include "archive_write_private.h" 55358088Smm#include "archive_write_set_format_private.h" 56231200Smm 57231200Smm/* 58231200Smm * Codec ID 59231200Smm */ 60231200Smm#define _7Z_COPY 0 61231200Smm#define _7Z_LZMA1 0x030101 62231200Smm#define _7Z_LZMA2 0x21 63231200Smm#define _7Z_DEFLATE 0x040108 64231200Smm#define _7Z_BZIP2 0x040202 65231200Smm#define _7Z_PPMD 0x030401 66231200Smm 67231200Smm/* 68231200Smm * 7-Zip header property IDs. 69231200Smm */ 70231200Smm#define kEnd 0x00 71231200Smm#define kHeader 0x01 72231200Smm#define kArchiveProperties 0x02 73231200Smm#define kAdditionalStreamsInfo 0x03 74231200Smm#define kMainStreamsInfo 0x04 75231200Smm#define kFilesInfo 0x05 76231200Smm#define kPackInfo 0x06 77231200Smm#define kUnPackInfo 0x07 78231200Smm#define kSubStreamsInfo 0x08 79231200Smm#define kSize 0x09 80231200Smm#define kCRC 0x0A 81231200Smm#define kFolder 0x0B 82231200Smm#define kCodersUnPackSize 0x0C 83231200Smm#define kNumUnPackStream 0x0D 84231200Smm#define kEmptyStream 0x0E 85231200Smm#define kEmptyFile 0x0F 86231200Smm#define kAnti 0x10 87231200Smm#define kName 0x11 88231200Smm#define kCTime 0x12 89231200Smm#define kATime 0x13 90231200Smm#define kMTime 0x14 91231200Smm#define kAttributes 0x15 92231200Smm#define kEncodedHeader 0x17 93231200Smm 94231200Smmenum la_zaction { 95231200Smm ARCHIVE_Z_FINISH, 96231200Smm ARCHIVE_Z_RUN 97231200Smm}; 98231200Smm 99231200Smm/* 100231200Smm * A stream object of universal compressor. 101231200Smm */ 102231200Smmstruct la_zstream { 103231200Smm const uint8_t *next_in; 104231200Smm size_t avail_in; 105231200Smm uint64_t total_in; 106231200Smm 107231200Smm uint8_t *next_out; 108231200Smm size_t avail_out; 109231200Smm uint64_t total_out; 110231200Smm 111231200Smm uint32_t prop_size; 112231200Smm uint8_t *props; 113231200Smm 114231200Smm int valid; 115231200Smm void *real_stream; 116231200Smm int (*code) (struct archive *a, 117231200Smm struct la_zstream *lastrm, 118231200Smm enum la_zaction action); 119231200Smm int (*end)(struct archive *a, 120231200Smm struct la_zstream *lastrm); 121231200Smm}; 122231200Smm 123231200Smm#define PPMD7_DEFAULT_ORDER 6 124231200Smm#define PPMD7_DEFAULT_MEM_SIZE (1 << 24) 125231200Smm 126231200Smmstruct ppmd_stream { 127231200Smm int stat; 128231200Smm CPpmd7 ppmd7_context; 129231200Smm CPpmd7z_RangeEnc range_enc; 130231200Smm IByteOut byteout; 131231200Smm uint8_t *buff; 132231200Smm uint8_t *buff_ptr; 133231200Smm uint8_t *buff_end; 134231200Smm size_t buff_bytes; 135231200Smm}; 136231200Smm 137231200Smmstruct coder { 138231200Smm unsigned codec; 139231200Smm size_t prop_size; 140231200Smm uint8_t *props; 141231200Smm}; 142231200Smm 143231200Smmstruct file { 144231200Smm struct archive_rb_node rbnode; 145231200Smm 146231200Smm struct file *next; 147231200Smm unsigned name_len; 148231200Smm uint8_t *utf16name;/* UTF16-LE name. */ 149231200Smm uint64_t size; 150231200Smm unsigned flg; 151231200Smm#define MTIME_IS_SET (1<<0) 152231200Smm#define ATIME_IS_SET (1<<1) 153231200Smm#define CTIME_IS_SET (1<<2) 154231200Smm#define CRC32_IS_SET (1<<3) 155231200Smm#define HAS_STREAM (1<<4) 156231200Smm 157231200Smm struct { 158231200Smm time_t time; 159231200Smm long time_ns; 160231200Smm } times[3]; 161231200Smm#define MTIME 0 162231200Smm#define ATIME 1 163231200Smm#define CTIME 2 164231200Smm 165231200Smm mode_t mode; 166231200Smm uint32_t crc32; 167231200Smm 168358088Smm signed int dir:1; 169231200Smm}; 170231200Smm 171231200Smmstruct _7zip { 172231200Smm int temp_fd; 173231200Smm uint64_t temp_offset; 174231200Smm 175231200Smm struct file *cur_file; 176231200Smm size_t total_number_entry; 177231200Smm size_t total_number_nonempty_entry; 178231200Smm size_t total_number_empty_entry; 179231200Smm size_t total_number_dir_entry; 180231200Smm size_t total_bytes_entry_name; 181231200Smm size_t total_number_time_defined[3]; 182231200Smm uint64_t total_bytes_compressed; 183231200Smm uint64_t total_bytes_uncompressed; 184231200Smm uint64_t entry_bytes_remaining; 185231200Smm uint32_t entry_crc32; 186231200Smm uint32_t precode_crc32; 187231200Smm uint32_t encoded_crc32; 188231200Smm int crc32flg; 189231200Smm#define PRECODE_CRC32 1 190231200Smm#define ENCODED_CRC32 2 191231200Smm 192231200Smm unsigned opt_compression; 193231200Smm int opt_compression_level; 194231200Smm 195231200Smm struct la_zstream stream; 196231200Smm struct coder coder; 197231200Smm 198231200Smm struct archive_string_conv *sconv; 199231200Smm 200231200Smm /* 201231200Smm * Compressed data buffer. 202231200Smm */ 203238856Smm unsigned char wbuff[512 * 20 * 6]; 204231200Smm size_t wbuff_remaining; 205231200Smm 206231200Smm /* 207231200Smm * The list of the file entries which has its contents is used to 208231200Smm * manage struct file objects. 209311041Smm * We use 'next' (a member of struct file) to chain. 210231200Smm */ 211231200Smm struct { 212231200Smm struct file *first; 213231200Smm struct file **last; 214231200Smm } file_list, empty_list; 215231200Smm struct archive_rb_tree rbtree;/* for empty files */ 216231200Smm}; 217231200Smm 218231200Smmstatic int _7z_options(struct archive_write *, 219231200Smm const char *, const char *); 220231200Smmstatic int _7z_write_header(struct archive_write *, 221231200Smm struct archive_entry *); 222231200Smmstatic ssize_t _7z_write_data(struct archive_write *, 223231200Smm const void *, size_t); 224231200Smmstatic int _7z_finish_entry(struct archive_write *); 225231200Smmstatic int _7z_close(struct archive_write *); 226231200Smmstatic int _7z_free(struct archive_write *); 227231200Smmstatic int file_cmp_node(const struct archive_rb_node *, 228231200Smm const struct archive_rb_node *); 229231200Smmstatic int file_cmp_key(const struct archive_rb_node *, const void *); 230231200Smmstatic int file_new(struct archive_write *a, struct archive_entry *, 231231200Smm struct file **); 232231200Smmstatic void file_free(struct file *); 233231200Smmstatic void file_register(struct _7zip *, struct file *); 234231200Smmstatic void file_register_empty(struct _7zip *, struct file *); 235231200Smmstatic void file_init_register(struct _7zip *); 236231200Smmstatic void file_init_register_empty(struct _7zip *); 237231200Smmstatic void file_free_register(struct _7zip *); 238231200Smmstatic ssize_t compress_out(struct archive_write *, const void *, size_t , 239231200Smm enum la_zaction); 240231200Smmstatic int compression_init_encoder_copy(struct archive *, 241231200Smm struct la_zstream *); 242231200Smmstatic int compression_code_copy(struct archive *, 243231200Smm struct la_zstream *, enum la_zaction); 244231200Smmstatic int compression_end_copy(struct archive *, struct la_zstream *); 245231200Smmstatic int compression_init_encoder_deflate(struct archive *, 246231200Smm struct la_zstream *, int, int); 247231200Smm#ifdef HAVE_ZLIB_H 248231200Smmstatic int compression_code_deflate(struct archive *, 249231200Smm struct la_zstream *, enum la_zaction); 250231200Smmstatic int compression_end_deflate(struct archive *, struct la_zstream *); 251231200Smm#endif 252231200Smmstatic int compression_init_encoder_bzip2(struct archive *, 253231200Smm struct la_zstream *, int); 254231200Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 255231200Smmstatic int compression_code_bzip2(struct archive *, 256231200Smm struct la_zstream *, enum la_zaction); 257231200Smmstatic int compression_end_bzip2(struct archive *, struct la_zstream *); 258231200Smm#endif 259231200Smmstatic int compression_init_encoder_lzma1(struct archive *, 260231200Smm struct la_zstream *, int); 261231200Smmstatic int compression_init_encoder_lzma2(struct archive *, 262231200Smm struct la_zstream *, int); 263231200Smm#if defined(HAVE_LZMA_H) 264231200Smmstatic int compression_code_lzma(struct archive *, 265231200Smm struct la_zstream *, enum la_zaction); 266231200Smmstatic int compression_end_lzma(struct archive *, struct la_zstream *); 267231200Smm#endif 268231200Smmstatic int compression_init_encoder_ppmd(struct archive *, 269231200Smm struct la_zstream *, unsigned, uint32_t); 270231200Smmstatic int compression_code_ppmd(struct archive *, 271231200Smm struct la_zstream *, enum la_zaction); 272231200Smmstatic int compression_end_ppmd(struct archive *, struct la_zstream *); 273231200Smmstatic int _7z_compression_init_encoder(struct archive_write *, unsigned, 274231200Smm int); 275231200Smmstatic int compression_code(struct archive *, 276231200Smm struct la_zstream *, enum la_zaction); 277231200Smmstatic int compression_end(struct archive *, 278231200Smm struct la_zstream *); 279231200Smmstatic int enc_uint64(struct archive_write *, uint64_t); 280231200Smmstatic int make_header(struct archive_write *, uint64_t, uint64_t, 281231200Smm uint64_t, int, struct coder *); 282231200Smmstatic int make_streamsInfo(struct archive_write *, uint64_t, uint64_t, 283231200Smm uint64_t, int, struct coder *, int, uint32_t); 284231200Smm 285231200Smmint 286231200Smmarchive_write_set_format_7zip(struct archive *_a) 287231200Smm{ 288231200Smm static const struct archive_rb_tree_ops rb_ops = { 289231200Smm file_cmp_node, file_cmp_key 290231200Smm }; 291231200Smm struct archive_write *a = (struct archive_write *)_a; 292231200Smm struct _7zip *zip; 293231200Smm 294231200Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 295231200Smm ARCHIVE_STATE_NEW, "archive_write_set_format_7zip"); 296231200Smm 297231200Smm /* If another format was already registered, unregister it. */ 298231200Smm if (a->format_free != NULL) 299231200Smm (a->format_free)(a); 300231200Smm 301231200Smm zip = calloc(1, sizeof(*zip)); 302231200Smm if (zip == NULL) { 303231200Smm archive_set_error(&a->archive, ENOMEM, 304231200Smm "Can't allocate 7-Zip data"); 305231200Smm return (ARCHIVE_FATAL); 306231200Smm } 307231200Smm zip->temp_fd = -1; 308231200Smm __archive_rb_tree_init(&(zip->rbtree), &rb_ops); 309231200Smm file_init_register(zip); 310231200Smm file_init_register_empty(zip); 311231200Smm 312231200Smm /* Set default compression type and its level. */ 313231200Smm#if HAVE_LZMA_H 314231200Smm zip->opt_compression = _7Z_LZMA1; 315231200Smm#elif defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 316231200Smm zip->opt_compression = _7Z_BZIP2; 317231200Smm#elif defined(HAVE_ZLIB_H) 318231200Smm zip->opt_compression = _7Z_DEFLATE; 319231200Smm#else 320231200Smm zip->opt_compression = _7Z_COPY; 321231200Smm#endif 322231200Smm zip->opt_compression_level = 6; 323231200Smm 324231200Smm a->format_data = zip; 325231200Smm 326231200Smm a->format_name = "7zip"; 327231200Smm a->format_options = _7z_options; 328231200Smm a->format_write_header = _7z_write_header; 329231200Smm a->format_write_data = _7z_write_data; 330231200Smm a->format_finish_entry = _7z_finish_entry; 331231200Smm a->format_close = _7z_close; 332231200Smm a->format_free = _7z_free; 333231200Smm a->archive.archive_format = ARCHIVE_FORMAT_7ZIP; 334231200Smm a->archive.archive_format_name = "7zip"; 335231200Smm 336231200Smm return (ARCHIVE_OK); 337231200Smm} 338231200Smm 339231200Smmstatic int 340231200Smm_7z_options(struct archive_write *a, const char *key, const char *value) 341231200Smm{ 342231200Smm struct _7zip *zip; 343231200Smm 344231200Smm zip = (struct _7zip *)a->format_data; 345231200Smm 346231200Smm if (strcmp(key, "compression") == 0) { 347231200Smm const char *name = NULL; 348231200Smm 349231200Smm if (value == NULL || strcmp(value, "copy") == 0 || 350231200Smm strcmp(value, "COPY") == 0 || 351231200Smm strcmp(value, "store") == 0 || 352231200Smm strcmp(value, "STORE") == 0) 353231200Smm zip->opt_compression = _7Z_COPY; 354231200Smm else if (strcmp(value, "deflate") == 0 || 355231200Smm strcmp(value, "DEFLATE") == 0) 356231200Smm#if HAVE_ZLIB_H 357231200Smm zip->opt_compression = _7Z_DEFLATE; 358231200Smm#else 359231200Smm name = "deflate"; 360231200Smm#endif 361231200Smm else if (strcmp(value, "bzip2") == 0 || 362231200Smm strcmp(value, "BZIP2") == 0) 363231200Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 364231200Smm zip->opt_compression = _7Z_BZIP2; 365231200Smm#else 366231200Smm name = "bzip2"; 367231200Smm#endif 368231200Smm else if (strcmp(value, "lzma1") == 0 || 369231200Smm strcmp(value, "LZMA1") == 0) 370231200Smm#if HAVE_LZMA_H 371231200Smm zip->opt_compression = _7Z_LZMA1; 372231200Smm#else 373231200Smm name = "lzma1"; 374231200Smm#endif 375231200Smm else if (strcmp(value, "lzma2") == 0 || 376231200Smm strcmp(value, "LZMA2") == 0) 377231200Smm#if HAVE_LZMA_H 378231200Smm zip->opt_compression = _7Z_LZMA2; 379231200Smm#else 380231200Smm name = "lzma2"; 381231200Smm#endif 382231200Smm else if (strcmp(value, "ppmd") == 0 || 383231200Smm strcmp(value, "PPMD") == 0 || 384231200Smm strcmp(value, "PPMd") == 0) 385231200Smm zip->opt_compression = _7Z_PPMD; 386231200Smm else { 387231200Smm archive_set_error(&(a->archive), 388231200Smm ARCHIVE_ERRNO_MISC, 389248616Smm "Unknown compression name: `%s'", 390231200Smm value); 391231200Smm return (ARCHIVE_FAILED); 392231200Smm } 393231200Smm if (name != NULL) { 394231200Smm archive_set_error(&(a->archive), 395231200Smm ARCHIVE_ERRNO_MISC, 396231200Smm "`%s' compression not supported " 397231200Smm "on this platform", 398231200Smm name); 399231200Smm return (ARCHIVE_FAILED); 400231200Smm } 401231200Smm return (ARCHIVE_OK); 402231200Smm } 403231200Smm if (strcmp(key, "compression-level") == 0) { 404231200Smm if (value == NULL || 405231200Smm !(value[0] >= '0' && value[0] <= '9') || 406231200Smm value[1] != '\0') { 407231200Smm archive_set_error(&(a->archive), 408231200Smm ARCHIVE_ERRNO_MISC, 409248616Smm "Illegal value `%s'", 410231200Smm value); 411231200Smm return (ARCHIVE_FAILED); 412231200Smm } 413231200Smm zip->opt_compression_level = value[0] - '0'; 414231200Smm return (ARCHIVE_OK); 415231200Smm } 416231200Smm 417232153Smm /* Note: The "warn" return is just to inform the options 418232153Smm * supervisor that we didn't handle it. It will generate 419232153Smm * a suitable error if no one used this option. */ 420232153Smm return (ARCHIVE_WARN); 421231200Smm} 422231200Smm 423231200Smmstatic int 424231200Smm_7z_write_header(struct archive_write *a, struct archive_entry *entry) 425231200Smm{ 426231200Smm struct _7zip *zip; 427231200Smm struct file *file; 428231200Smm int r; 429231200Smm 430231200Smm zip = (struct _7zip *)a->format_data; 431231200Smm zip->cur_file = NULL; 432231200Smm zip->entry_bytes_remaining = 0; 433231200Smm 434231200Smm if (zip->sconv == NULL) { 435231200Smm zip->sconv = archive_string_conversion_to_charset( 436231200Smm &a->archive, "UTF-16LE", 1); 437231200Smm if (zip->sconv == NULL) 438231200Smm return (ARCHIVE_FATAL); 439231200Smm } 440231200Smm 441231200Smm r = file_new(a, entry, &file); 442231200Smm if (r < ARCHIVE_WARN) { 443346104Smm if (file != NULL) 444346104Smm file_free(file); 445231200Smm return (r); 446231200Smm } 447248616Smm if (file->size == 0 && file->dir) { 448248616Smm if (!__archive_rb_tree_insert_node(&(zip->rbtree), 449248616Smm (struct archive_rb_node *)file)) { 450248616Smm /* We have already had the same file. */ 451248616Smm file_free(file); 452248616Smm return (ARCHIVE_OK); 453248616Smm } 454248616Smm } 455231200Smm 456231200Smm if (file->flg & MTIME_IS_SET) 457231200Smm zip->total_number_time_defined[MTIME]++; 458231200Smm if (file->flg & CTIME_IS_SET) 459231200Smm zip->total_number_time_defined[CTIME]++; 460231200Smm if (file->flg & ATIME_IS_SET) 461231200Smm zip->total_number_time_defined[ATIME]++; 462231200Smm 463231200Smm zip->total_number_entry++; 464231200Smm zip->total_bytes_entry_name += file->name_len + 2; 465231200Smm if (file->size == 0) { 466231200Smm /* Count up the number of empty files. */ 467231200Smm zip->total_number_empty_entry++; 468231200Smm if (file->dir) 469231200Smm zip->total_number_dir_entry++; 470231200Smm else 471231200Smm file_register_empty(zip, file); 472231200Smm return (r); 473231200Smm } 474231200Smm 475231200Smm /* 476231200Smm * Init compression. 477231200Smm */ 478231200Smm if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) { 479231200Smm r = _7z_compression_init_encoder(a, zip->opt_compression, 480231200Smm zip->opt_compression_level); 481231200Smm if (r < 0) { 482231200Smm file_free(file); 483231200Smm return (ARCHIVE_FATAL); 484231200Smm } 485231200Smm } 486231200Smm 487231200Smm /* Register a non-empty file. */ 488231200Smm file_register(zip, file); 489231200Smm 490231200Smm /* 491231200Smm * Set the current file to cur_file to read its contents. 492231200Smm */ 493231200Smm zip->cur_file = file; 494231200Smm 495231200Smm 496231200Smm /* Save a offset of current file in temporary file. */ 497231200Smm zip->entry_bytes_remaining = file->size; 498231200Smm zip->entry_crc32 = 0; 499231200Smm 500231200Smm /* 501231200Smm * Store a symbolic link name as file contents. 502231200Smm */ 503231200Smm if (archive_entry_filetype(entry) == AE_IFLNK) { 504231200Smm ssize_t bytes; 505231200Smm const void *p = (const void *)archive_entry_symlink(entry); 506238856Smm bytes = compress_out(a, p, (size_t)file->size, ARCHIVE_Z_RUN); 507231200Smm if (bytes < 0) 508231200Smm return ((int)bytes); 509248616Smm zip->entry_crc32 = crc32(zip->entry_crc32, p, (unsigned)bytes); 510231200Smm zip->entry_bytes_remaining -= bytes; 511231200Smm } 512231200Smm 513231200Smm return (r); 514231200Smm} 515231200Smm 516231200Smm/* 517231200Smm * Write data to a temporary file. 518231200Smm */ 519231200Smmstatic int 520231200Smmwrite_to_temp(struct archive_write *a, const void *buff, size_t s) 521231200Smm{ 522231200Smm struct _7zip *zip; 523232153Smm const unsigned char *p; 524231200Smm ssize_t ws; 525231200Smm 526231200Smm zip = (struct _7zip *)a->format_data; 527231200Smm 528231200Smm /* 529231200Smm * Open a temporary file. 530231200Smm */ 531231200Smm if (zip->temp_fd == -1) { 532231200Smm zip->temp_offset = 0; 533231200Smm zip->temp_fd = __archive_mktemp(NULL); 534231200Smm if (zip->temp_fd < 0) { 535231200Smm archive_set_error(&a->archive, errno, 536231200Smm "Couldn't create temporary file"); 537231200Smm return (ARCHIVE_FATAL); 538231200Smm } 539231200Smm } 540231200Smm 541232153Smm p = (const unsigned char *)buff; 542231200Smm while (s) { 543231200Smm ws = write(zip->temp_fd, p, s); 544231200Smm if (ws < 0) { 545231200Smm archive_set_error(&(a->archive), errno, 546231200Smm "fwrite function failed"); 547231200Smm return (ARCHIVE_FATAL); 548231200Smm } 549231200Smm s -= ws; 550231200Smm p += ws; 551231200Smm zip->temp_offset += ws; 552231200Smm } 553231200Smm return (ARCHIVE_OK); 554231200Smm} 555231200Smm 556231200Smmstatic ssize_t 557231200Smmcompress_out(struct archive_write *a, const void *buff, size_t s, 558231200Smm enum la_zaction run) 559231200Smm{ 560231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 561231200Smm int r; 562231200Smm 563231200Smm if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0) 564231200Smm return (0); 565231200Smm 566231200Smm if ((zip->crc32flg & PRECODE_CRC32) && s) 567248616Smm zip->precode_crc32 = crc32(zip->precode_crc32, buff, 568248616Smm (unsigned)s); 569231200Smm zip->stream.next_in = (const unsigned char *)buff; 570231200Smm zip->stream.avail_in = s; 571248616Smm for (;;) { 572231200Smm /* Compress file data. */ 573231200Smm r = compression_code(&(a->archive), &(zip->stream), run); 574231200Smm if (r != ARCHIVE_OK && r != ARCHIVE_EOF) 575231200Smm return (ARCHIVE_FATAL); 576231200Smm if (zip->stream.avail_out == 0) { 577231200Smm if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff)) 578231200Smm != ARCHIVE_OK) 579231200Smm return (ARCHIVE_FATAL); 580231200Smm zip->stream.next_out = zip->wbuff; 581231200Smm zip->stream.avail_out = sizeof(zip->wbuff); 582231200Smm if (zip->crc32flg & ENCODED_CRC32) 583231200Smm zip->encoded_crc32 = crc32(zip->encoded_crc32, 584231200Smm zip->wbuff, sizeof(zip->wbuff)); 585248616Smm if (run == ARCHIVE_Z_FINISH && r != ARCHIVE_EOF) 586248616Smm continue; 587231200Smm } 588248616Smm if (zip->stream.avail_in == 0) 589248616Smm break; 590248616Smm } 591231200Smm if (run == ARCHIVE_Z_FINISH) { 592231200Smm uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out; 593238856Smm if (write_to_temp(a, zip->wbuff, (size_t)bytes) != ARCHIVE_OK) 594231200Smm return (ARCHIVE_FATAL); 595231200Smm if ((zip->crc32flg & ENCODED_CRC32) && bytes) 596231200Smm zip->encoded_crc32 = crc32(zip->encoded_crc32, 597238856Smm zip->wbuff, (unsigned)bytes); 598231200Smm } 599231200Smm 600231200Smm return (s); 601231200Smm} 602231200Smm 603231200Smmstatic ssize_t 604231200Smm_7z_write_data(struct archive_write *a, const void *buff, size_t s) 605231200Smm{ 606231200Smm struct _7zip *zip; 607231200Smm ssize_t bytes; 608231200Smm 609231200Smm zip = (struct _7zip *)a->format_data; 610231200Smm 611231200Smm if (s > zip->entry_bytes_remaining) 612238856Smm s = (size_t)zip->entry_bytes_remaining; 613231200Smm if (s == 0 || zip->cur_file == NULL) 614231200Smm return (0); 615231200Smm bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN); 616231200Smm if (bytes < 0) 617231200Smm return (bytes); 618248616Smm zip->entry_crc32 = crc32(zip->entry_crc32, buff, (unsigned)bytes); 619231200Smm zip->entry_bytes_remaining -= bytes; 620231200Smm return (bytes); 621231200Smm} 622231200Smm 623231200Smmstatic int 624231200Smm_7z_finish_entry(struct archive_write *a) 625231200Smm{ 626231200Smm struct _7zip *zip; 627231200Smm size_t s; 628231200Smm ssize_t r; 629231200Smm 630231200Smm zip = (struct _7zip *)a->format_data; 631231200Smm if (zip->cur_file == NULL) 632231200Smm return (ARCHIVE_OK); 633231200Smm 634231200Smm while (zip->entry_bytes_remaining > 0) { 635238856Smm s = (size_t)zip->entry_bytes_remaining; 636231200Smm if (s > a->null_length) 637231200Smm s = a->null_length; 638231200Smm r = _7z_write_data(a, a->nulls, s); 639231200Smm if (r < 0) 640248616Smm return ((int)r); 641231200Smm } 642231200Smm zip->total_bytes_compressed += zip->stream.total_in; 643231200Smm zip->total_bytes_uncompressed += zip->stream.total_out; 644231200Smm zip->cur_file->crc32 = zip->entry_crc32; 645231200Smm zip->cur_file = NULL; 646231200Smm 647231200Smm return (ARCHIVE_OK); 648231200Smm} 649231200Smm 650231200Smmstatic int 651231200Smmflush_wbuff(struct archive_write *a) 652231200Smm{ 653231200Smm struct _7zip *zip; 654231200Smm int r; 655231200Smm size_t s; 656231200Smm 657231200Smm zip = (struct _7zip *)a->format_data; 658231200Smm s = sizeof(zip->wbuff) - zip->wbuff_remaining; 659231200Smm r = __archive_write_output(a, zip->wbuff, s); 660231200Smm if (r != ARCHIVE_OK) 661231200Smm return (r); 662231200Smm zip->wbuff_remaining = sizeof(zip->wbuff); 663231200Smm return (r); 664231200Smm} 665231200Smm 666231200Smmstatic int 667231200Smmcopy_out(struct archive_write *a, uint64_t offset, uint64_t length) 668231200Smm{ 669231200Smm struct _7zip *zip; 670231200Smm int r; 671231200Smm 672231200Smm zip = (struct _7zip *)a->format_data; 673231200Smm if (zip->temp_offset > 0 && 674231200Smm lseek(zip->temp_fd, offset, SEEK_SET) < 0) { 675231200Smm archive_set_error(&(a->archive), errno, "lseek failed"); 676231200Smm return (ARCHIVE_FATAL); 677231200Smm } 678231200Smm while (length) { 679231200Smm size_t rsize; 680231200Smm ssize_t rs; 681231200Smm unsigned char *wb; 682231200Smm 683231200Smm if (length > zip->wbuff_remaining) 684231200Smm rsize = zip->wbuff_remaining; 685231200Smm else 686231200Smm rsize = (size_t)length; 687231200Smm wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining); 688231200Smm rs = read(zip->temp_fd, wb, rsize); 689231200Smm if (rs < 0) { 690231200Smm archive_set_error(&(a->archive), errno, 691231200Smm "Can't read temporary file(%jd)", 692231200Smm (intmax_t)rs); 693231200Smm return (ARCHIVE_FATAL); 694231200Smm } 695231200Smm if (rs == 0) { 696231200Smm archive_set_error(&(a->archive), 0, 697231200Smm "Truncated 7-Zip archive"); 698231200Smm return (ARCHIVE_FATAL); 699231200Smm } 700231200Smm zip->wbuff_remaining -= rs; 701231200Smm length -= rs; 702231200Smm if (zip->wbuff_remaining == 0) { 703231200Smm r = flush_wbuff(a); 704231200Smm if (r != ARCHIVE_OK) 705231200Smm return (r); 706231200Smm } 707231200Smm } 708231200Smm return (ARCHIVE_OK); 709231200Smm} 710231200Smm 711231200Smmstatic int 712231200Smm_7z_close(struct archive_write *a) 713231200Smm{ 714231200Smm struct _7zip *zip; 715231200Smm unsigned char *wb; 716231200Smm uint64_t header_offset, header_size, header_unpacksize; 717231200Smm uint64_t length; 718231200Smm uint32_t header_crc32; 719231200Smm int r; 720231200Smm 721231200Smm zip = (struct _7zip *)a->format_data; 722231200Smm 723231200Smm if (zip->total_number_entry > 0) { 724231200Smm struct archive_rb_node *n; 725231200Smm uint64_t data_offset, data_size, data_unpacksize; 726231200Smm unsigned header_compression; 727231200Smm 728231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 729231200Smm if (r < 0) 730231200Smm return (r); 731231200Smm data_offset = 0; 732231200Smm data_size = zip->stream.total_out; 733231200Smm data_unpacksize = zip->stream.total_in; 734231200Smm zip->coder.codec = zip->opt_compression; 735231200Smm zip->coder.prop_size = zip->stream.prop_size; 736231200Smm zip->coder.props = zip->stream.props; 737231200Smm zip->stream.prop_size = 0; 738231200Smm zip->stream.props = NULL; 739231200Smm zip->total_number_nonempty_entry = 740231200Smm zip->total_number_entry - zip->total_number_empty_entry; 741231200Smm 742231200Smm /* Connect an empty file list. */ 743231200Smm if (zip->empty_list.first != NULL) { 744231200Smm *zip->file_list.last = zip->empty_list.first; 745231200Smm zip->file_list.last = zip->empty_list.last; 746231200Smm } 747231200Smm /* Connect a directory file list. */ 748231200Smm ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { 749231200Smm file_register(zip, (struct file *)n); 750231200Smm } 751231200Smm 752231200Smm /* 753231200Smm * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for 754231200Smm * the compression type for encoding the header. 755231200Smm */ 756231200Smm#if HAVE_LZMA_H 757231200Smm header_compression = _7Z_LZMA1; 758370535Sgit2svn if(zip->opt_compression == _7Z_LZMA2 || 759370535Sgit2svn zip->opt_compression == _7Z_COPY) 760370535Sgit2svn header_compression = zip->opt_compression; 761370535Sgit2svn 762231200Smm /* If the stored file is only one, do not encode the header. 763231200Smm * This is the same way 7z command does. */ 764231200Smm if (zip->total_number_entry == 1) 765231200Smm header_compression = _7Z_COPY; 766231200Smm#else 767231200Smm header_compression = _7Z_COPY; 768231200Smm#endif 769370535Sgit2svn r = _7z_compression_init_encoder(a, header_compression, 770370535Sgit2svn zip->opt_compression_level); 771231200Smm if (r < 0) 772231200Smm return (r); 773231200Smm zip->crc32flg = PRECODE_CRC32; 774231200Smm zip->precode_crc32 = 0; 775231200Smm r = make_header(a, data_offset, data_size, data_unpacksize, 776231200Smm 1, &(zip->coder)); 777231200Smm if (r < 0) 778231200Smm return (r); 779231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 780231200Smm if (r < 0) 781231200Smm return (r); 782231200Smm header_offset = data_offset + data_size; 783231200Smm header_size = zip->stream.total_out; 784231200Smm header_crc32 = zip->precode_crc32; 785231200Smm header_unpacksize = zip->stream.total_in; 786231200Smm 787231200Smm if (header_compression != _7Z_COPY) { 788231200Smm /* 789231200Smm * Encode the header in order to reduce the size 790231200Smm * of the archive. 791231200Smm */ 792231200Smm free(zip->coder.props); 793231200Smm zip->coder.codec = header_compression; 794231200Smm zip->coder.prop_size = zip->stream.prop_size; 795231200Smm zip->coder.props = zip->stream.props; 796231200Smm zip->stream.prop_size = 0; 797231200Smm zip->stream.props = NULL; 798231200Smm 799231200Smm r = _7z_compression_init_encoder(a, _7Z_COPY, 0); 800231200Smm if (r < 0) 801231200Smm return (r); 802231200Smm zip->crc32flg = ENCODED_CRC32; 803231200Smm zip->encoded_crc32 = 0; 804231200Smm 805231200Smm /* 806231200Smm * Make EncodedHeader. 807231200Smm */ 808231200Smm r = enc_uint64(a, kEncodedHeader); 809231200Smm if (r < 0) 810231200Smm return (r); 811231200Smm r = make_streamsInfo(a, header_offset, header_size, 812231200Smm header_unpacksize, 1, &(zip->coder), 0, 813231200Smm header_crc32); 814231200Smm if (r < 0) 815231200Smm return (r); 816231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 817231200Smm if (r < 0) 818231200Smm return (r); 819231200Smm header_offset = header_offset + header_size; 820231200Smm header_size = zip->stream.total_out; 821231200Smm header_crc32 = zip->encoded_crc32; 822231200Smm } 823231200Smm zip->crc32flg = 0; 824231200Smm } else { 825231200Smm header_offset = header_size = 0; 826231200Smm header_crc32 = 0; 827231200Smm } 828231200Smm 829231200Smm length = zip->temp_offset; 830231200Smm 831231200Smm /* 832231200Smm * Make the zip header on wbuff(write buffer). 833231200Smm */ 834231200Smm wb = zip->wbuff; 835231200Smm zip->wbuff_remaining = sizeof(zip->wbuff); 836231200Smm memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6); 837231200Smm wb[6] = 0;/* Major version. */ 838231200Smm wb[7] = 3;/* Minor version. */ 839231200Smm archive_le64enc(&wb[12], header_offset);/* Next Header Offset */ 840231200Smm archive_le64enc(&wb[20], header_size);/* Next Header Size */ 841231200Smm archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */ 842231200Smm archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */ 843231200Smm zip->wbuff_remaining -= 32; 844231200Smm 845231200Smm /* 846231200Smm * Read all file contents and an encoded header from the temporary 847231200Smm * file and write out it. 848231200Smm */ 849231200Smm r = copy_out(a, 0, length); 850231200Smm if (r != ARCHIVE_OK) 851231200Smm return (r); 852231200Smm r = flush_wbuff(a); 853231200Smm return (r); 854231200Smm} 855231200Smm 856231200Smm/* 857231200Smm * Encode 64 bits value into 7-Zip's encoded UINT64 value. 858231200Smm */ 859231200Smmstatic int 860231200Smmenc_uint64(struct archive_write *a, uint64_t val) 861231200Smm{ 862231200Smm unsigned mask = 0x80; 863231200Smm uint8_t numdata[9]; 864231200Smm int i; 865231200Smm 866231200Smm numdata[0] = 0; 867232153Smm for (i = 1; i < (int)sizeof(numdata); i++) { 868231200Smm if (val < mask) { 869231200Smm numdata[0] |= (uint8_t)val; 870231200Smm break; 871231200Smm } 872231200Smm numdata[i] = (uint8_t)val; 873231200Smm val >>= 8; 874231200Smm numdata[0] |= mask; 875231200Smm mask >>= 1; 876231200Smm } 877248616Smm return ((int)compress_out(a, numdata, i, ARCHIVE_Z_RUN)); 878231200Smm} 879231200Smm 880231200Smmstatic int 881231200Smmmake_substreamsInfo(struct archive_write *a, struct coder *coders) 882231200Smm{ 883231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 884231200Smm struct file *file; 885231200Smm int r; 886231200Smm 887231200Smm /* 888231200Smm * Make SubStreamsInfo. 889231200Smm */ 890231200Smm r = enc_uint64(a, kSubStreamsInfo); 891231200Smm if (r < 0) 892231200Smm return (r); 893231200Smm 894231200Smm if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) { 895231200Smm /* 896231200Smm * Make NumUnPackStream. 897231200Smm */ 898231200Smm r = enc_uint64(a, kNumUnPackStream); 899231200Smm if (r < 0) 900231200Smm return (r); 901231200Smm 902231200Smm /* Write numUnpackStreams */ 903231200Smm r = enc_uint64(a, zip->total_number_nonempty_entry); 904231200Smm if (r < 0) 905231200Smm return (r); 906231200Smm 907231200Smm /* 908231200Smm * Make kSize. 909231200Smm */ 910231200Smm r = enc_uint64(a, kSize); 911231200Smm if (r < 0) 912231200Smm return (r); 913231200Smm file = zip->file_list.first; 914231200Smm for (;file != NULL; file = file->next) { 915231200Smm if (file->next == NULL || 916231200Smm file->next->size == 0) 917231200Smm break; 918231200Smm r = enc_uint64(a, file->size); 919231200Smm if (r < 0) 920231200Smm return (r); 921231200Smm } 922231200Smm } 923231200Smm 924231200Smm /* 925231200Smm * Make CRC. 926231200Smm */ 927231200Smm r = enc_uint64(a, kCRC); 928231200Smm if (r < 0) 929231200Smm return (r); 930231200Smm 931231200Smm 932231200Smm /* All are defined */ 933231200Smm r = enc_uint64(a, 1); 934231200Smm if (r < 0) 935231200Smm return (r); 936231200Smm file = zip->file_list.first; 937231200Smm for (;file != NULL; file = file->next) { 938231200Smm uint8_t crc[4]; 939231200Smm if (file->size == 0) 940231200Smm break; 941231200Smm archive_le32enc(crc, file->crc32); 942248616Smm r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); 943231200Smm if (r < 0) 944231200Smm return (r); 945231200Smm } 946231200Smm 947231200Smm /* Write End. */ 948231200Smm r = enc_uint64(a, kEnd); 949231200Smm if (r < 0) 950231200Smm return (r); 951231200Smm return (ARCHIVE_OK); 952231200Smm} 953231200Smm 954231200Smmstatic int 955231200Smmmake_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, 956231200Smm uint64_t unpack_size, int num_coder, struct coder *coders, int substrm, 957231200Smm uint32_t header_crc) 958231200Smm{ 959231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 960231200Smm uint8_t codec_buff[8]; 961231200Smm int numFolders, fi; 962231200Smm int codec_size; 963231200Smm int i, r; 964231200Smm 965231200Smm if (coders->codec == _7Z_COPY) 966248616Smm numFolders = (int)zip->total_number_nonempty_entry; 967231200Smm else 968231200Smm numFolders = 1; 969231200Smm 970231200Smm /* 971231200Smm * Make PackInfo. 972231200Smm */ 973231200Smm r = enc_uint64(a, kPackInfo); 974231200Smm if (r < 0) 975231200Smm return (r); 976231200Smm 977231200Smm /* Write PackPos. */ 978231200Smm r = enc_uint64(a, offset); 979231200Smm if (r < 0) 980231200Smm return (r); 981231200Smm 982231200Smm /* Write NumPackStreams. */ 983231200Smm r = enc_uint64(a, numFolders); 984231200Smm if (r < 0) 985231200Smm return (r); 986231200Smm 987231200Smm /* Make Size. */ 988231200Smm r = enc_uint64(a, kSize); 989231200Smm if (r < 0) 990231200Smm return (r); 991231200Smm 992231200Smm if (numFolders > 1) { 993231200Smm struct file *file = zip->file_list.first; 994231200Smm for (;file != NULL; file = file->next) { 995231200Smm if (file->size == 0) 996231200Smm break; 997231200Smm r = enc_uint64(a, file->size); 998231200Smm if (r < 0) 999231200Smm return (r); 1000231200Smm } 1001231200Smm } else { 1002231200Smm /* Write size. */ 1003231200Smm r = enc_uint64(a, pack_size); 1004231200Smm if (r < 0) 1005231200Smm return (r); 1006231200Smm } 1007231200Smm 1008231200Smm r = enc_uint64(a, kEnd); 1009231200Smm if (r < 0) 1010231200Smm return (r); 1011231200Smm 1012231200Smm /* 1013231200Smm * Make UnPackInfo. 1014231200Smm */ 1015231200Smm r = enc_uint64(a, kUnPackInfo); 1016231200Smm if (r < 0) 1017231200Smm return (r); 1018231200Smm 1019231200Smm /* 1020231200Smm * Make Folder. 1021231200Smm */ 1022231200Smm r = enc_uint64(a, kFolder); 1023231200Smm if (r < 0) 1024231200Smm return (r); 1025231200Smm 1026231200Smm /* Write NumFolders. */ 1027231200Smm r = enc_uint64(a, numFolders); 1028231200Smm if (r < 0) 1029231200Smm return (r); 1030231200Smm 1031231200Smm /* Write External. */ 1032231200Smm r = enc_uint64(a, 0); 1033231200Smm if (r < 0) 1034231200Smm return (r); 1035231200Smm 1036231200Smm for (fi = 0; fi < numFolders; fi++) { 1037231200Smm /* Write NumCoders. */ 1038231200Smm r = enc_uint64(a, num_coder); 1039231200Smm if (r < 0) 1040231200Smm return (r); 1041231200Smm 1042231200Smm for (i = 0; i < num_coder; i++) { 1043231200Smm unsigned codec_id = coders[i].codec; 1044231200Smm 1045231200Smm /* Write Codec flag. */ 1046231200Smm archive_be64enc(codec_buff, codec_id); 1047231200Smm for (codec_size = 8; codec_size > 0; codec_size--) { 1048231200Smm if (codec_buff[8 - codec_size]) 1049231200Smm break; 1050231200Smm } 1051231200Smm if (codec_size == 0) 1052231200Smm codec_size = 1; 1053231200Smm if (coders[i].prop_size) 1054231200Smm r = enc_uint64(a, codec_size | 0x20); 1055231200Smm else 1056231200Smm r = enc_uint64(a, codec_size); 1057231200Smm if (r < 0) 1058231200Smm return (r); 1059231200Smm 1060231200Smm /* Write Codec ID. */ 1061231200Smm codec_size &= 0x0f; 1062248616Smm r = (int)compress_out(a, &codec_buff[8-codec_size], 1063231200Smm codec_size, ARCHIVE_Z_RUN); 1064231200Smm if (r < 0) 1065231200Smm return (r); 1066231200Smm 1067231200Smm if (coders[i].prop_size) { 1068231200Smm /* Write Codec property size. */ 1069231200Smm r = enc_uint64(a, coders[i].prop_size); 1070231200Smm if (r < 0) 1071231200Smm return (r); 1072231200Smm 1073231200Smm /* Write Codec properties. */ 1074248616Smm r = (int)compress_out(a, coders[i].props, 1075231200Smm coders[i].prop_size, ARCHIVE_Z_RUN); 1076231200Smm if (r < 0) 1077231200Smm return (r); 1078231200Smm } 1079231200Smm } 1080231200Smm } 1081231200Smm 1082231200Smm /* 1083231200Smm * Make CodersUnPackSize. 1084231200Smm */ 1085231200Smm r = enc_uint64(a, kCodersUnPackSize); 1086231200Smm if (r < 0) 1087231200Smm return (r); 1088231200Smm 1089231200Smm if (numFolders > 1) { 1090231200Smm struct file *file = zip->file_list.first; 1091231200Smm for (;file != NULL; file = file->next) { 1092231200Smm if (file->size == 0) 1093231200Smm break; 1094231200Smm r = enc_uint64(a, file->size); 1095231200Smm if (r < 0) 1096231200Smm return (r); 1097231200Smm } 1098231200Smm 1099231200Smm } else { 1100231200Smm /* Write UnPackSize. */ 1101231200Smm r = enc_uint64(a, unpack_size); 1102231200Smm if (r < 0) 1103231200Smm return (r); 1104231200Smm } 1105231200Smm 1106231200Smm if (!substrm) { 1107231200Smm uint8_t crc[4]; 1108231200Smm /* 1109231200Smm * Make CRC. 1110231200Smm */ 1111231200Smm r = enc_uint64(a, kCRC); 1112231200Smm if (r < 0) 1113231200Smm return (r); 1114231200Smm 1115231200Smm /* All are defined */ 1116231200Smm r = enc_uint64(a, 1); 1117231200Smm if (r < 0) 1118231200Smm return (r); 1119231200Smm archive_le32enc(crc, header_crc); 1120248616Smm r = (int)compress_out(a, crc, 4, ARCHIVE_Z_RUN); 1121231200Smm if (r < 0) 1122231200Smm return (r); 1123231200Smm } 1124231200Smm 1125231200Smm /* Write End. */ 1126231200Smm r = enc_uint64(a, kEnd); 1127231200Smm if (r < 0) 1128231200Smm return (r); 1129231200Smm 1130231200Smm if (substrm) { 1131231200Smm /* 1132231200Smm * Make SubStreamsInfo. 1133231200Smm */ 1134231200Smm r = make_substreamsInfo(a, coders); 1135231200Smm if (r < 0) 1136231200Smm return (r); 1137231200Smm } 1138231200Smm 1139231200Smm 1140231200Smm /* Write End. */ 1141231200Smm r = enc_uint64(a, kEnd); 1142231200Smm if (r < 0) 1143231200Smm return (r); 1144231200Smm 1145231200Smm return (ARCHIVE_OK); 1146231200Smm} 1147231200Smm 1148231200Smm 1149231200Smm#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) 1150231200Smmstatic uint64_t 1151232153SmmutcToFiletime(time_t t, long ns) 1152231200Smm{ 1153231200Smm uint64_t fileTime; 1154231200Smm 1155232153Smm fileTime = t; 1156231200Smm fileTime *= 10000000; 1157231200Smm fileTime += ns / 100; 1158231200Smm fileTime += EPOC_TIME; 1159231200Smm return (fileTime); 1160231200Smm} 1161231200Smm 1162231200Smmstatic int 1163231200Smmmake_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) 1164231200Smm{ 1165231200Smm uint8_t filetime[8]; 1166231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1167231200Smm struct file *file; 1168231200Smm int r; 1169238856Smm uint8_t b, mask; 1170231200Smm 1171231200Smm /* 1172231200Smm * Make Time Bools. 1173231200Smm */ 1174231200Smm if (zip->total_number_time_defined[ti] == zip->total_number_entry) { 1175231200Smm /* Write Time Type. */ 1176231200Smm r = enc_uint64(a, type); 1177231200Smm if (r < 0) 1178231200Smm return (r); 1179231200Smm /* Write EmptyStream Size. */ 1180231200Smm r = enc_uint64(a, 2 + zip->total_number_entry * 8); 1181231200Smm if (r < 0) 1182231200Smm return (r); 1183231200Smm /* All are defined. */ 1184231200Smm r = enc_uint64(a, 1); 1185231200Smm if (r < 0) 1186231200Smm return (r); 1187231200Smm } else { 1188231200Smm if (zip->total_number_time_defined[ti] == 0) 1189231200Smm return (ARCHIVE_OK); 1190231200Smm 1191231200Smm /* Write Time Type. */ 1192231200Smm r = enc_uint64(a, type); 1193231200Smm if (r < 0) 1194231200Smm return (r); 1195231200Smm /* Write EmptyStream Size. */ 1196231200Smm r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3) 1197231200Smm + zip->total_number_time_defined[ti] * 8); 1198231200Smm if (r < 0) 1199231200Smm return (r); 1200231200Smm 1201231200Smm /* All are not defined. */ 1202231200Smm r = enc_uint64(a, 0); 1203231200Smm if (r < 0) 1204231200Smm return (r); 1205231200Smm 1206238856Smm b = 0; 1207231200Smm mask = 0x80; 1208231200Smm file = zip->file_list.first; 1209231200Smm for (;file != NULL; file = file->next) { 1210231200Smm if (file->flg & flg) 1211238856Smm b |= mask; 1212231200Smm mask >>= 1; 1213231200Smm if (mask == 0) { 1214248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1215231200Smm if (r < 0) 1216231200Smm return (r); 1217231200Smm mask = 0x80; 1218238856Smm b = 0; 1219231200Smm } 1220231200Smm } 1221231200Smm if (mask != 0x80) { 1222248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1223231200Smm if (r < 0) 1224231200Smm return (r); 1225231200Smm } 1226231200Smm } 1227231200Smm 1228231200Smm /* External. */ 1229231200Smm r = enc_uint64(a, 0); 1230231200Smm if (r < 0) 1231231200Smm return (r); 1232231200Smm 1233231200Smm 1234231200Smm /* 1235231200Smm * Make Times. 1236231200Smm */ 1237231200Smm file = zip->file_list.first; 1238231200Smm for (;file != NULL; file = file->next) { 1239231200Smm if ((file->flg & flg) == 0) 1240231200Smm continue; 1241231200Smm archive_le64enc(filetime, utcToFiletime(file->times[ti].time, 1242231200Smm file->times[ti].time_ns)); 1243248616Smm r = (int)compress_out(a, filetime, 8, ARCHIVE_Z_RUN); 1244231200Smm if (r < 0) 1245231200Smm return (r); 1246231200Smm } 1247231200Smm 1248231200Smm return (ARCHIVE_OK); 1249231200Smm} 1250231200Smm 1251231200Smmstatic int 1252231200Smmmake_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, 1253231200Smm uint64_t unpack_size, int codernum, struct coder *coders) 1254231200Smm{ 1255231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1256231200Smm struct file *file; 1257231200Smm int r; 1258238856Smm uint8_t b, mask; 1259231200Smm 1260231200Smm /* 1261231200Smm * Make FilesInfo. 1262231200Smm */ 1263231200Smm r = enc_uint64(a, kHeader); 1264231200Smm if (r < 0) 1265231200Smm return (r); 1266231200Smm 1267231200Smm /* 1268231200Smm * If there are empty files only, do not write MainStreamInfo. 1269231200Smm */ 1270231200Smm if (zip->total_number_nonempty_entry) { 1271231200Smm /* 1272231200Smm * Make MainStreamInfo. 1273231200Smm */ 1274231200Smm r = enc_uint64(a, kMainStreamsInfo); 1275231200Smm if (r < 0) 1276231200Smm return (r); 1277231200Smm r = make_streamsInfo(a, offset, pack_size, unpack_size, 1278231200Smm codernum, coders, 1, 0); 1279231200Smm if (r < 0) 1280231200Smm return (r); 1281231200Smm } 1282231200Smm 1283231200Smm /* 1284231200Smm * Make FilesInfo. 1285231200Smm */ 1286231200Smm r = enc_uint64(a, kFilesInfo); 1287231200Smm if (r < 0) 1288231200Smm return (r); 1289231200Smm 1290231200Smm /* Write numFiles. */ 1291231200Smm r = enc_uint64(a, zip->total_number_entry); 1292231200Smm if (r < 0) 1293231200Smm return (r); 1294231200Smm 1295231200Smm if (zip->total_number_empty_entry > 0) { 1296231200Smm /* Make EmptyStream. */ 1297231200Smm r = enc_uint64(a, kEmptyStream); 1298231200Smm if (r < 0) 1299231200Smm return (r); 1300231200Smm 1301231200Smm /* Write EmptyStream Size. */ 1302231200Smm r = enc_uint64(a, (zip->total_number_entry+7)>>3); 1303231200Smm if (r < 0) 1304231200Smm return (r); 1305231200Smm 1306238856Smm b = 0; 1307231200Smm mask = 0x80; 1308231200Smm file = zip->file_list.first; 1309231200Smm for (;file != NULL; file = file->next) { 1310231200Smm if (file->size == 0) 1311238856Smm b |= mask; 1312231200Smm mask >>= 1; 1313231200Smm if (mask == 0) { 1314248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1315231200Smm if (r < 0) 1316231200Smm return (r); 1317231200Smm mask = 0x80; 1318238856Smm b = 0; 1319231200Smm } 1320231200Smm } 1321231200Smm if (mask != 0x80) { 1322248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1323231200Smm if (r < 0) 1324231200Smm return (r); 1325231200Smm } 1326231200Smm } 1327231200Smm 1328231200Smm if (zip->total_number_empty_entry > zip->total_number_dir_entry) { 1329231200Smm /* Make EmptyFile. */ 1330231200Smm r = enc_uint64(a, kEmptyFile); 1331231200Smm if (r < 0) 1332231200Smm return (r); 1333231200Smm 1334231200Smm /* Write EmptyFile Size. */ 1335231200Smm r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3); 1336231200Smm if (r < 0) 1337231200Smm return (r); 1338231200Smm 1339238856Smm b = 0; 1340231200Smm mask = 0x80; 1341231200Smm file = zip->file_list.first; 1342231200Smm for (;file != NULL; file = file->next) { 1343231200Smm if (file->size) 1344231200Smm continue; 1345231200Smm if (!file->dir) 1346238856Smm b |= mask; 1347231200Smm mask >>= 1; 1348231200Smm if (mask == 0) { 1349248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1350231200Smm if (r < 0) 1351231200Smm return (r); 1352231200Smm mask = 0x80; 1353238856Smm b = 0; 1354231200Smm } 1355231200Smm } 1356231200Smm if (mask != 0x80) { 1357248616Smm r = (int)compress_out(a, &b, 1, ARCHIVE_Z_RUN); 1358231200Smm if (r < 0) 1359231200Smm return (r); 1360231200Smm } 1361231200Smm } 1362231200Smm 1363231200Smm /* Make Name. */ 1364231200Smm r = enc_uint64(a, kName); 1365231200Smm if (r < 0) 1366231200Smm return (r); 1367231200Smm 1368313570Smm /* Write Name size. */ 1369231200Smm r = enc_uint64(a, zip->total_bytes_entry_name+1); 1370231200Smm if (r < 0) 1371231200Smm return (r); 1372231200Smm 1373231200Smm /* Write dmy byte. */ 1374231200Smm r = enc_uint64(a, 0); 1375231200Smm if (r < 0) 1376231200Smm return (r); 1377231200Smm 1378231200Smm file = zip->file_list.first; 1379231200Smm for (;file != NULL; file = file->next) { 1380248616Smm r = (int)compress_out(a, file->utf16name, file->name_len+2, 1381231200Smm ARCHIVE_Z_RUN); 1382231200Smm if (r < 0) 1383231200Smm return (r); 1384231200Smm } 1385231200Smm 1386231200Smm /* Make MTime. */ 1387231200Smm r = make_time(a, kMTime, MTIME_IS_SET, MTIME); 1388231200Smm if (r < 0) 1389231200Smm return (r); 1390231200Smm 1391231200Smm /* Make CTime. */ 1392231200Smm r = make_time(a, kCTime, CTIME_IS_SET, CTIME); 1393231200Smm if (r < 0) 1394231200Smm return (r); 1395231200Smm 1396231200Smm /* Make ATime. */ 1397231200Smm r = make_time(a, kATime, ATIME_IS_SET, ATIME); 1398231200Smm if (r < 0) 1399231200Smm return (r); 1400231200Smm 1401231200Smm /* Make Attributes. */ 1402231200Smm r = enc_uint64(a, kAttributes); 1403231200Smm if (r < 0) 1404231200Smm return (r); 1405231200Smm 1406231200Smm /* Write Attributes size. */ 1407231200Smm r = enc_uint64(a, 2 + zip->total_number_entry * 4); 1408231200Smm if (r < 0) 1409231200Smm return (r); 1410231200Smm 1411231200Smm /* Write "All Are Defined". */ 1412231200Smm r = enc_uint64(a, 1); 1413231200Smm if (r < 0) 1414231200Smm return (r); 1415231200Smm 1416231200Smm /* Write dmy byte. */ 1417231200Smm r = enc_uint64(a, 0); 1418231200Smm if (r < 0) 1419231200Smm return (r); 1420231200Smm 1421231200Smm file = zip->file_list.first; 1422231200Smm for (;file != NULL; file = file->next) { 1423231200Smm /* 1424231200Smm * High 16bits is unix mode. 1425231200Smm * Low 16bits is Windows attributes. 1426231200Smm */ 1427231200Smm uint32_t encattr, attr; 1428231200Smm if (file->dir) 1429231200Smm attr = 0x8010; 1430231200Smm else 1431231200Smm attr = 0x8020; 1432231200Smm if ((file->mode & 0222) == 0) 1433231200Smm attr |= 1;/* Read Only. */ 1434231200Smm attr |= ((uint32_t)file->mode) << 16; 1435231200Smm archive_le32enc(&encattr, attr); 1436248616Smm r = (int)compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); 1437231200Smm if (r < 0) 1438231200Smm return (r); 1439231200Smm } 1440231200Smm 1441231200Smm /* Write End. */ 1442231200Smm r = enc_uint64(a, kEnd); 1443231200Smm if (r < 0) 1444231200Smm return (r); 1445231200Smm 1446231200Smm /* Write End. */ 1447231200Smm r = enc_uint64(a, kEnd); 1448231200Smm if (r < 0) 1449231200Smm return (r); 1450231200Smm 1451231200Smm return (ARCHIVE_OK); 1452231200Smm} 1453231200Smm 1454231200Smm 1455231200Smmstatic int 1456231200Smm_7z_free(struct archive_write *a) 1457231200Smm{ 1458231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1459231200Smm 1460299529Smm /* Close the temporary file. */ 1461299529Smm if (zip->temp_fd >= 0) 1462299529Smm close(zip->temp_fd); 1463299529Smm 1464231200Smm file_free_register(zip); 1465231200Smm compression_end(&(a->archive), &(zip->stream)); 1466231200Smm free(zip->coder.props); 1467231200Smm free(zip); 1468231200Smm 1469231200Smm return (ARCHIVE_OK); 1470231200Smm} 1471231200Smm 1472231200Smmstatic int 1473231200Smmfile_cmp_node(const struct archive_rb_node *n1, 1474231200Smm const struct archive_rb_node *n2) 1475231200Smm{ 1476232153Smm const struct file *f1 = (const struct file *)n1; 1477232153Smm const struct file *f2 = (const struct file *)n2; 1478231200Smm 1479231200Smm if (f1->name_len == f2->name_len) 1480231200Smm return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); 1481231200Smm return (f1->name_len > f2->name_len)?1:-1; 1482231200Smm} 1483231200Smm 1484231200Smmstatic int 1485231200Smmfile_cmp_key(const struct archive_rb_node *n, const void *key) 1486231200Smm{ 1487232153Smm const struct file *f = (const struct file *)n; 1488231200Smm 1489231200Smm return (f->name_len - *(const char *)key); 1490231200Smm} 1491231200Smm 1492231200Smmstatic int 1493231200Smmfile_new(struct archive_write *a, struct archive_entry *entry, 1494231200Smm struct file **newfile) 1495231200Smm{ 1496231200Smm struct _7zip *zip; 1497231200Smm struct file *file; 1498231200Smm const char *u16; 1499231200Smm size_t u16len; 1500231200Smm int ret = ARCHIVE_OK; 1501231200Smm 1502231200Smm zip = (struct _7zip *)a->format_data; 1503231200Smm *newfile = NULL; 1504231200Smm 1505231200Smm file = calloc(1, sizeof(*file)); 1506231200Smm if (file == NULL) { 1507231200Smm archive_set_error(&a->archive, ENOMEM, 1508231200Smm "Can't allocate memory"); 1509231200Smm return (ARCHIVE_FATAL); 1510231200Smm } 1511231200Smm 1512231200Smm if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { 1513231200Smm if (errno == ENOMEM) { 1514238856Smm free(file); 1515231200Smm archive_set_error(&a->archive, ENOMEM, 1516231200Smm "Can't allocate memory for UTF-16LE"); 1517231200Smm return (ARCHIVE_FATAL); 1518231200Smm } 1519231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1520231200Smm "A filename cannot be converted to UTF-16LE;" 1521231200Smm "You should disable making Joliet extension"); 1522231200Smm ret = ARCHIVE_WARN; 1523231200Smm } 1524231200Smm file->utf16name = malloc(u16len + 2); 1525231200Smm if (file->utf16name == NULL) { 1526238856Smm free(file); 1527231200Smm archive_set_error(&a->archive, ENOMEM, 1528231200Smm "Can't allocate memory for Name"); 1529231200Smm return (ARCHIVE_FATAL); 1530231200Smm } 1531231200Smm memcpy(file->utf16name, u16, u16len); 1532231200Smm file->utf16name[u16len+0] = 0; 1533231200Smm file->utf16name[u16len+1] = 0; 1534248616Smm file->name_len = (unsigned)u16len; 1535231200Smm file->mode = archive_entry_mode(entry); 1536231200Smm if (archive_entry_filetype(entry) == AE_IFREG) 1537231200Smm file->size = archive_entry_size(entry); 1538231200Smm else 1539231200Smm archive_entry_set_size(entry, 0); 1540231200Smm if (archive_entry_filetype(entry) == AE_IFDIR) 1541231200Smm file->dir = 1; 1542231200Smm else if (archive_entry_filetype(entry) == AE_IFLNK) 1543231200Smm file->size = strlen(archive_entry_symlink(entry)); 1544231200Smm if (archive_entry_mtime_is_set(entry)) { 1545231200Smm file->flg |= MTIME_IS_SET; 1546231200Smm file->times[MTIME].time = archive_entry_mtime(entry); 1547231200Smm file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry); 1548231200Smm } 1549231200Smm if (archive_entry_atime_is_set(entry)) { 1550231200Smm file->flg |= ATIME_IS_SET; 1551231200Smm file->times[ATIME].time = archive_entry_atime(entry); 1552231200Smm file->times[ATIME].time_ns = archive_entry_atime_nsec(entry); 1553231200Smm } 1554231200Smm if (archive_entry_ctime_is_set(entry)) { 1555231200Smm file->flg |= CTIME_IS_SET; 1556231200Smm file->times[CTIME].time = archive_entry_ctime(entry); 1557231200Smm file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry); 1558231200Smm } 1559231200Smm 1560231200Smm *newfile = file; 1561231200Smm return (ret); 1562231200Smm} 1563231200Smm 1564231200Smmstatic void 1565231200Smmfile_free(struct file *file) 1566231200Smm{ 1567231200Smm free(file->utf16name); 1568231200Smm free(file); 1569231200Smm} 1570231200Smm 1571231200Smmstatic void 1572231200Smmfile_register(struct _7zip *zip, struct file *file) 1573231200Smm{ 1574231200Smm file->next = NULL; 1575231200Smm *zip->file_list.last = file; 1576231200Smm zip->file_list.last = &(file->next); 1577231200Smm} 1578231200Smm 1579231200Smmstatic void 1580231200Smmfile_init_register(struct _7zip *zip) 1581231200Smm{ 1582231200Smm zip->file_list.first = NULL; 1583231200Smm zip->file_list.last = &(zip->file_list.first); 1584231200Smm} 1585231200Smm 1586231200Smmstatic void 1587231200Smmfile_free_register(struct _7zip *zip) 1588231200Smm{ 1589231200Smm struct file *file, *file_next; 1590231200Smm 1591231200Smm file = zip->file_list.first; 1592231200Smm while (file != NULL) { 1593231200Smm file_next = file->next; 1594231200Smm file_free(file); 1595231200Smm file = file_next; 1596231200Smm } 1597231200Smm} 1598231200Smm 1599231200Smmstatic void 1600231200Smmfile_register_empty(struct _7zip *zip, struct file *file) 1601231200Smm{ 1602231200Smm file->next = NULL; 1603231200Smm *zip->empty_list.last = file; 1604231200Smm zip->empty_list.last = &(file->next); 1605231200Smm} 1606231200Smm 1607231200Smmstatic void 1608231200Smmfile_init_register_empty(struct _7zip *zip) 1609231200Smm{ 1610231200Smm zip->empty_list.first = NULL; 1611231200Smm zip->empty_list.last = &(zip->empty_list.first); 1612231200Smm} 1613231200Smm 1614232153Smm#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ 1615232153Smm !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) 1616231200Smmstatic int 1617231200Smmcompression_unsupported_encoder(struct archive *a, 1618231200Smm struct la_zstream *lastrm, const char *name) 1619231200Smm{ 1620231200Smm 1621231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1622231200Smm "%s compression not supported on this platform", name); 1623231200Smm lastrm->valid = 0; 1624231200Smm lastrm->real_stream = NULL; 1625231200Smm return (ARCHIVE_FAILED); 1626231200Smm} 1627231200Smm#endif 1628231200Smm 1629231200Smm/* 1630231200Smm * _7_COPY compressor. 1631231200Smm */ 1632231200Smmstatic int 1633231200Smmcompression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) 1634231200Smm{ 1635231200Smm 1636231200Smm if (lastrm->valid) 1637231200Smm compression_end(a, lastrm); 1638231200Smm lastrm->valid = 1; 1639231200Smm lastrm->code = compression_code_copy; 1640231200Smm lastrm->end = compression_end_copy; 1641231200Smm return (ARCHIVE_OK); 1642231200Smm} 1643231200Smm 1644231200Smmstatic int 1645231200Smmcompression_code_copy(struct archive *a, 1646231200Smm struct la_zstream *lastrm, enum la_zaction action) 1647231200Smm{ 1648231200Smm size_t bytes; 1649231200Smm 1650231200Smm (void)a; /* UNUSED */ 1651231200Smm if (lastrm->avail_out > lastrm->avail_in) 1652231200Smm bytes = lastrm->avail_in; 1653231200Smm else 1654231200Smm bytes = lastrm->avail_out; 1655231200Smm if (bytes) { 1656231200Smm memcpy(lastrm->next_out, lastrm->next_in, bytes); 1657231200Smm lastrm->next_in += bytes; 1658231200Smm lastrm->avail_in -= bytes; 1659231200Smm lastrm->total_in += bytes; 1660231200Smm lastrm->next_out += bytes; 1661231200Smm lastrm->avail_out -= bytes; 1662231200Smm lastrm->total_out += bytes; 1663231200Smm } 1664231200Smm if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0) 1665231200Smm return (ARCHIVE_EOF); 1666231200Smm return (ARCHIVE_OK); 1667231200Smm} 1668231200Smm 1669231200Smmstatic int 1670231200Smmcompression_end_copy(struct archive *a, struct la_zstream *lastrm) 1671231200Smm{ 1672231200Smm (void)a; /* UNUSED */ 1673231200Smm lastrm->valid = 0; 1674231200Smm return (ARCHIVE_OK); 1675231200Smm} 1676231200Smm 1677231200Smm/* 1678231200Smm * _7_DEFLATE compressor. 1679231200Smm */ 1680231200Smm#ifdef HAVE_ZLIB_H 1681231200Smmstatic int 1682231200Smmcompression_init_encoder_deflate(struct archive *a, 1683231200Smm struct la_zstream *lastrm, int level, int withheader) 1684231200Smm{ 1685231200Smm z_stream *strm; 1686231200Smm 1687231200Smm if (lastrm->valid) 1688231200Smm compression_end(a, lastrm); 1689231200Smm strm = calloc(1, sizeof(*strm)); 1690231200Smm if (strm == NULL) { 1691231200Smm archive_set_error(a, ENOMEM, 1692231200Smm "Can't allocate memory for gzip stream"); 1693231200Smm return (ARCHIVE_FATAL); 1694231200Smm } 1695231200Smm /* zlib.h is not const-correct, so we need this one bit 1696231200Smm * of ugly hackery to convert a const * pointer to 1697231200Smm * a non-const pointer. */ 1698231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1699248616Smm strm->avail_in = (uInt)lastrm->avail_in; 1700238856Smm strm->total_in = (uLong)lastrm->total_in; 1701231200Smm strm->next_out = lastrm->next_out; 1702248616Smm strm->avail_out = (uInt)lastrm->avail_out; 1703238856Smm strm->total_out = (uLong)lastrm->total_out; 1704231200Smm if (deflateInit2(strm, level, Z_DEFLATED, 1705231200Smm (withheader)?15:-15, 1706231200Smm 8, Z_DEFAULT_STRATEGY) != Z_OK) { 1707231200Smm free(strm); 1708231200Smm lastrm->real_stream = NULL; 1709231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1710231200Smm "Internal error initializing compression library"); 1711231200Smm return (ARCHIVE_FATAL); 1712231200Smm } 1713231200Smm lastrm->real_stream = strm; 1714231200Smm lastrm->valid = 1; 1715231200Smm lastrm->code = compression_code_deflate; 1716231200Smm lastrm->end = compression_end_deflate; 1717231200Smm return (ARCHIVE_OK); 1718231200Smm} 1719231200Smm 1720231200Smmstatic int 1721231200Smmcompression_code_deflate(struct archive *a, 1722231200Smm struct la_zstream *lastrm, enum la_zaction action) 1723231200Smm{ 1724231200Smm z_stream *strm; 1725231200Smm int r; 1726231200Smm 1727231200Smm strm = (z_stream *)lastrm->real_stream; 1728231200Smm /* zlib.h is not const-correct, so we need this one bit 1729231200Smm * of ugly hackery to convert a const * pointer to 1730231200Smm * a non-const pointer. */ 1731231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1732248616Smm strm->avail_in = (uInt)lastrm->avail_in; 1733238856Smm strm->total_in = (uLong)lastrm->total_in; 1734231200Smm strm->next_out = lastrm->next_out; 1735248616Smm strm->avail_out = (uInt)lastrm->avail_out; 1736238856Smm strm->total_out = (uLong)lastrm->total_out; 1737231200Smm r = deflate(strm, 1738231200Smm (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); 1739231200Smm lastrm->next_in = strm->next_in; 1740231200Smm lastrm->avail_in = strm->avail_in; 1741231200Smm lastrm->total_in = strm->total_in; 1742231200Smm lastrm->next_out = strm->next_out; 1743231200Smm lastrm->avail_out = strm->avail_out; 1744231200Smm lastrm->total_out = strm->total_out; 1745231200Smm switch (r) { 1746231200Smm case Z_OK: 1747231200Smm return (ARCHIVE_OK); 1748231200Smm case Z_STREAM_END: 1749231200Smm return (ARCHIVE_EOF); 1750231200Smm default: 1751231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1752231200Smm "GZip compression failed:" 1753231200Smm " deflate() call returned status %d", r); 1754231200Smm return (ARCHIVE_FATAL); 1755231200Smm } 1756231200Smm} 1757231200Smm 1758231200Smmstatic int 1759231200Smmcompression_end_deflate(struct archive *a, struct la_zstream *lastrm) 1760231200Smm{ 1761231200Smm z_stream *strm; 1762231200Smm int r; 1763231200Smm 1764231200Smm strm = (z_stream *)lastrm->real_stream; 1765231200Smm r = deflateEnd(strm); 1766231200Smm free(strm); 1767231200Smm lastrm->real_stream = NULL; 1768231200Smm lastrm->valid = 0; 1769231200Smm if (r != Z_OK) { 1770231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1771231200Smm "Failed to clean up compressor"); 1772231200Smm return (ARCHIVE_FATAL); 1773231200Smm } 1774231200Smm return (ARCHIVE_OK); 1775231200Smm} 1776231200Smm#else 1777231200Smmstatic int 1778231200Smmcompression_init_encoder_deflate(struct archive *a, 1779231200Smm struct la_zstream *lastrm, int level, int withheader) 1780231200Smm{ 1781231200Smm 1782231200Smm (void) level; /* UNUSED */ 1783231200Smm (void) withheader; /* UNUSED */ 1784231200Smm if (lastrm->valid) 1785231200Smm compression_end(a, lastrm); 1786231200Smm return (compression_unsupported_encoder(a, lastrm, "deflate")); 1787231200Smm} 1788231200Smm#endif 1789231200Smm 1790231200Smm/* 1791231200Smm * _7_BZIP2 compressor. 1792231200Smm */ 1793231200Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1794231200Smmstatic int 1795231200Smmcompression_init_encoder_bzip2(struct archive *a, 1796231200Smm struct la_zstream *lastrm, int level) 1797231200Smm{ 1798231200Smm bz_stream *strm; 1799231200Smm 1800231200Smm if (lastrm->valid) 1801231200Smm compression_end(a, lastrm); 1802231200Smm strm = calloc(1, sizeof(*strm)); 1803231200Smm if (strm == NULL) { 1804231200Smm archive_set_error(a, ENOMEM, 1805231200Smm "Can't allocate memory for bzip2 stream"); 1806231200Smm return (ARCHIVE_FATAL); 1807231200Smm } 1808231200Smm /* bzlib.h is not const-correct, so we need this one bit 1809231200Smm * of ugly hackery to convert a const * pointer to 1810231200Smm * a non-const pointer. */ 1811231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1812231200Smm strm->avail_in = lastrm->avail_in; 1813231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1814231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1815231200Smm strm->next_out = (char *)lastrm->next_out; 1816231200Smm strm->avail_out = lastrm->avail_out; 1817231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1818231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1819231200Smm if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { 1820231200Smm free(strm); 1821231200Smm lastrm->real_stream = NULL; 1822231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1823231200Smm "Internal error initializing compression library"); 1824231200Smm return (ARCHIVE_FATAL); 1825231200Smm } 1826231200Smm lastrm->real_stream = strm; 1827231200Smm lastrm->valid = 1; 1828231200Smm lastrm->code = compression_code_bzip2; 1829231200Smm lastrm->end = compression_end_bzip2; 1830231200Smm return (ARCHIVE_OK); 1831231200Smm} 1832231200Smm 1833231200Smmstatic int 1834231200Smmcompression_code_bzip2(struct archive *a, 1835231200Smm struct la_zstream *lastrm, enum la_zaction action) 1836231200Smm{ 1837231200Smm bz_stream *strm; 1838231200Smm int r; 1839231200Smm 1840231200Smm strm = (bz_stream *)lastrm->real_stream; 1841231200Smm /* bzlib.h is not const-correct, so we need this one bit 1842231200Smm * of ugly hackery to convert a const * pointer to 1843231200Smm * a non-const pointer. */ 1844231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1845231200Smm strm->avail_in = lastrm->avail_in; 1846231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1847231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1848231200Smm strm->next_out = (char *)lastrm->next_out; 1849231200Smm strm->avail_out = lastrm->avail_out; 1850231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1851231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1852231200Smm r = BZ2_bzCompress(strm, 1853231200Smm (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); 1854231200Smm lastrm->next_in = (const unsigned char *)strm->next_in; 1855231200Smm lastrm->avail_in = strm->avail_in; 1856231200Smm lastrm->total_in = 1857231200Smm (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) 1858231200Smm + (uint64_t)(uint32_t)strm->total_in_lo32; 1859231200Smm lastrm->next_out = (unsigned char *)strm->next_out; 1860231200Smm lastrm->avail_out = strm->avail_out; 1861231200Smm lastrm->total_out = 1862231200Smm (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) 1863231200Smm + (uint64_t)(uint32_t)strm->total_out_lo32; 1864231200Smm switch (r) { 1865231200Smm case BZ_RUN_OK: /* Non-finishing */ 1866231200Smm case BZ_FINISH_OK: /* Finishing: There's more work to do */ 1867231200Smm return (ARCHIVE_OK); 1868231200Smm case BZ_STREAM_END: /* Finishing: all done */ 1869231200Smm /* Only occurs in finishing case */ 1870231200Smm return (ARCHIVE_EOF); 1871231200Smm default: 1872231200Smm /* Any other return value indicates an error */ 1873231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1874231200Smm "Bzip2 compression failed:" 1875231200Smm " BZ2_bzCompress() call returned status %d", r); 1876231200Smm return (ARCHIVE_FATAL); 1877231200Smm } 1878231200Smm} 1879231200Smm 1880231200Smmstatic int 1881231200Smmcompression_end_bzip2(struct archive *a, struct la_zstream *lastrm) 1882231200Smm{ 1883231200Smm bz_stream *strm; 1884231200Smm int r; 1885231200Smm 1886231200Smm strm = (bz_stream *)lastrm->real_stream; 1887231200Smm r = BZ2_bzCompressEnd(strm); 1888231200Smm free(strm); 1889231200Smm lastrm->real_stream = NULL; 1890231200Smm lastrm->valid = 0; 1891231200Smm if (r != BZ_OK) { 1892231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1893231200Smm "Failed to clean up compressor"); 1894231200Smm return (ARCHIVE_FATAL); 1895231200Smm } 1896231200Smm return (ARCHIVE_OK); 1897231200Smm} 1898231200Smm 1899231200Smm#else 1900231200Smmstatic int 1901231200Smmcompression_init_encoder_bzip2(struct archive *a, 1902231200Smm struct la_zstream *lastrm, int level) 1903231200Smm{ 1904231200Smm 1905231200Smm (void) level; /* UNUSED */ 1906231200Smm if (lastrm->valid) 1907231200Smm compression_end(a, lastrm); 1908231200Smm return (compression_unsupported_encoder(a, lastrm, "bzip2")); 1909231200Smm} 1910231200Smm#endif 1911231200Smm 1912231200Smm/* 1913231200Smm * _7_LZMA1, _7_LZMA2 compressor. 1914231200Smm */ 1915231200Smm#if defined(HAVE_LZMA_H) 1916231200Smmstatic int 1917231200Smmcompression_init_encoder_lzma(struct archive *a, 1918231200Smm struct la_zstream *lastrm, int level, uint64_t filter_id) 1919231200Smm{ 1920231200Smm static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; 1921231200Smm lzma_stream *strm; 1922231200Smm lzma_filter *lzmafilters; 1923231200Smm lzma_options_lzma lzma_opt; 1924231200Smm int r; 1925231200Smm 1926231200Smm if (lastrm->valid) 1927231200Smm compression_end(a, lastrm); 1928231200Smm strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); 1929231200Smm if (strm == NULL) { 1930231200Smm archive_set_error(a, ENOMEM, 1931231200Smm "Can't allocate memory for lzma stream"); 1932231200Smm return (ARCHIVE_FATAL); 1933231200Smm } 1934231200Smm lzmafilters = (lzma_filter *)(strm+1); 1935368707Smm if (level > 9) 1936368707Smm level = 9; 1937231200Smm if (lzma_lzma_preset(&lzma_opt, level)) { 1938238856Smm free(strm); 1939231200Smm lastrm->real_stream = NULL; 1940231200Smm archive_set_error(a, ENOMEM, 1941231200Smm "Internal error initializing compression library"); 1942231200Smm return (ARCHIVE_FATAL); 1943231200Smm } 1944231200Smm lzmafilters[0].id = filter_id; 1945231200Smm lzmafilters[0].options = &lzma_opt; 1946231200Smm lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ 1947231200Smm 1948231200Smm r = lzma_properties_size(&(lastrm->prop_size), lzmafilters); 1949231200Smm if (r != LZMA_OK) { 1950231200Smm free(strm); 1951231200Smm lastrm->real_stream = NULL; 1952231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1953231200Smm "lzma_properties_size failed"); 1954231200Smm return (ARCHIVE_FATAL); 1955231200Smm } 1956231200Smm if (lastrm->prop_size) { 1957231200Smm lastrm->props = malloc(lastrm->prop_size); 1958231200Smm if (lastrm->props == NULL) { 1959231200Smm free(strm); 1960231200Smm lastrm->real_stream = NULL; 1961231200Smm archive_set_error(a, ENOMEM, 1962231200Smm "Cannot allocate memory"); 1963231200Smm return (ARCHIVE_FATAL); 1964231200Smm } 1965231200Smm r = lzma_properties_encode(lzmafilters, lastrm->props); 1966231200Smm if (r != LZMA_OK) { 1967231200Smm free(strm); 1968231200Smm lastrm->real_stream = NULL; 1969231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1970231200Smm "lzma_properties_encode failed"); 1971231200Smm return (ARCHIVE_FATAL); 1972231200Smm } 1973231200Smm } 1974231200Smm 1975231200Smm *strm = lzma_init_data; 1976231200Smm r = lzma_raw_encoder(strm, lzmafilters); 1977231200Smm switch (r) { 1978231200Smm case LZMA_OK: 1979231200Smm lastrm->real_stream = strm; 1980231200Smm lastrm->valid = 1; 1981231200Smm lastrm->code = compression_code_lzma; 1982231200Smm lastrm->end = compression_end_lzma; 1983231200Smm r = ARCHIVE_OK; 1984231200Smm break; 1985231200Smm case LZMA_MEM_ERROR: 1986231200Smm free(strm); 1987231200Smm lastrm->real_stream = NULL; 1988231200Smm archive_set_error(a, ENOMEM, 1989231200Smm "Internal error initializing compression library: " 1990231200Smm "Cannot allocate memory"); 1991231200Smm r = ARCHIVE_FATAL; 1992231200Smm break; 1993231200Smm default: 1994231200Smm free(strm); 1995231200Smm lastrm->real_stream = NULL; 1996231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1997231200Smm "Internal error initializing compression library: " 1998231200Smm "It's a bug in liblzma"); 1999231200Smm r = ARCHIVE_FATAL; 2000231200Smm break; 2001231200Smm } 2002231200Smm return (r); 2003231200Smm} 2004231200Smm 2005231200Smmstatic int 2006231200Smmcompression_init_encoder_lzma1(struct archive *a, 2007231200Smm struct la_zstream *lastrm, int level) 2008231200Smm{ 2009231200Smm return compression_init_encoder_lzma(a, lastrm, level, 2010231200Smm LZMA_FILTER_LZMA1); 2011231200Smm} 2012231200Smm 2013231200Smmstatic int 2014231200Smmcompression_init_encoder_lzma2(struct archive *a, 2015231200Smm struct la_zstream *lastrm, int level) 2016231200Smm{ 2017231200Smm return compression_init_encoder_lzma(a, lastrm, level, 2018231200Smm LZMA_FILTER_LZMA2); 2019231200Smm} 2020231200Smm 2021231200Smmstatic int 2022231200Smmcompression_code_lzma(struct archive *a, 2023231200Smm struct la_zstream *lastrm, enum la_zaction action) 2024231200Smm{ 2025231200Smm lzma_stream *strm; 2026231200Smm int r; 2027231200Smm 2028231200Smm strm = (lzma_stream *)lastrm->real_stream; 2029231200Smm strm->next_in = lastrm->next_in; 2030231200Smm strm->avail_in = lastrm->avail_in; 2031231200Smm strm->total_in = lastrm->total_in; 2032231200Smm strm->next_out = lastrm->next_out; 2033231200Smm strm->avail_out = lastrm->avail_out; 2034231200Smm strm->total_out = lastrm->total_out; 2035231200Smm r = lzma_code(strm, 2036231200Smm (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); 2037231200Smm lastrm->next_in = strm->next_in; 2038231200Smm lastrm->avail_in = strm->avail_in; 2039231200Smm lastrm->total_in = strm->total_in; 2040231200Smm lastrm->next_out = strm->next_out; 2041231200Smm lastrm->avail_out = strm->avail_out; 2042231200Smm lastrm->total_out = strm->total_out; 2043231200Smm switch (r) { 2044231200Smm case LZMA_OK: 2045231200Smm /* Non-finishing case */ 2046231200Smm return (ARCHIVE_OK); 2047231200Smm case LZMA_STREAM_END: 2048231200Smm /* This return can only occur in finishing case. */ 2049231200Smm return (ARCHIVE_EOF); 2050231200Smm case LZMA_MEMLIMIT_ERROR: 2051231200Smm archive_set_error(a, ENOMEM, 2052231200Smm "lzma compression error:" 2053231200Smm " %ju MiB would have been needed", 2054231200Smm (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) 2055231200Smm / (1024 * 1024))); 2056231200Smm return (ARCHIVE_FATAL); 2057231200Smm default: 2058231200Smm /* Any other return value indicates an error */ 2059231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 2060231200Smm "lzma compression failed:" 2061231200Smm " lzma_code() call returned status %d", r); 2062231200Smm return (ARCHIVE_FATAL); 2063231200Smm } 2064231200Smm} 2065231200Smm 2066231200Smmstatic int 2067231200Smmcompression_end_lzma(struct archive *a, struct la_zstream *lastrm) 2068231200Smm{ 2069231200Smm lzma_stream *strm; 2070231200Smm 2071231200Smm (void)a; /* UNUSED */ 2072231200Smm strm = (lzma_stream *)lastrm->real_stream; 2073231200Smm lzma_end(strm); 2074231200Smm free(strm); 2075231200Smm lastrm->valid = 0; 2076231200Smm lastrm->real_stream = NULL; 2077231200Smm return (ARCHIVE_OK); 2078231200Smm} 2079231200Smm#else 2080231200Smmstatic int 2081231200Smmcompression_init_encoder_lzma1(struct archive *a, 2082231200Smm struct la_zstream *lastrm, int level) 2083231200Smm{ 2084231200Smm 2085231200Smm (void) level; /* UNUSED */ 2086231200Smm if (lastrm->valid) 2087231200Smm compression_end(a, lastrm); 2088231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2089231200Smm} 2090231200Smmstatic int 2091231200Smmcompression_init_encoder_lzma2(struct archive *a, 2092231200Smm struct la_zstream *lastrm, int level) 2093231200Smm{ 2094231200Smm 2095231200Smm (void) level; /* UNUSED */ 2096231200Smm if (lastrm->valid) 2097231200Smm compression_end(a, lastrm); 2098231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2099231200Smm} 2100231200Smm#endif 2101231200Smm 2102231200Smm/* 2103231200Smm * _7_PPMD compressor. 2104231200Smm */ 2105231200Smmstatic void 2106231200Smmppmd_write(void *p, Byte b) 2107231200Smm{ 2108231200Smm struct archive_write *a = ((IByteOut *)p)->a; 2109231200Smm struct _7zip *zip = (struct _7zip *)(a->format_data); 2110231200Smm struct la_zstream *lastrm = &(zip->stream); 2111231200Smm struct ppmd_stream *strm; 2112231200Smm 2113231200Smm if (lastrm->avail_out) { 2114231200Smm *lastrm->next_out++ = b; 2115231200Smm lastrm->avail_out--; 2116231200Smm lastrm->total_out++; 2117231200Smm return; 2118231200Smm } 2119231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2120231200Smm if (strm->buff_ptr < strm->buff_end) { 2121231200Smm *strm->buff_ptr++ = b; 2122231200Smm strm->buff_bytes++; 2123231200Smm } 2124231200Smm} 2125231200Smm 2126231200Smmstatic int 2127231200Smmcompression_init_encoder_ppmd(struct archive *a, 2128231200Smm struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize) 2129231200Smm{ 2130231200Smm struct ppmd_stream *strm; 2131231200Smm uint8_t *props; 2132231200Smm int r; 2133231200Smm 2134231200Smm if (lastrm->valid) 2135231200Smm compression_end(a, lastrm); 2136231200Smm strm = calloc(1, sizeof(*strm)); 2137231200Smm if (strm == NULL) { 2138231200Smm archive_set_error(a, ENOMEM, 2139231200Smm "Can't allocate memory for PPMd"); 2140231200Smm return (ARCHIVE_FATAL); 2141231200Smm } 2142231200Smm strm->buff = malloc(32); 2143231200Smm if (strm->buff == NULL) { 2144231200Smm free(strm); 2145231200Smm archive_set_error(a, ENOMEM, 2146231200Smm "Can't allocate memory for PPMd"); 2147231200Smm return (ARCHIVE_FATAL); 2148231200Smm } 2149231200Smm strm->buff_ptr = strm->buff; 2150231200Smm strm->buff_end = strm->buff + 32; 2151231200Smm 2152231200Smm props = malloc(1+4); 2153231200Smm if (props == NULL) { 2154231200Smm free(strm->buff); 2155231200Smm free(strm); 2156231200Smm archive_set_error(a, ENOMEM, 2157231200Smm "Coludn't allocate memory for PPMd"); 2158231200Smm return (ARCHIVE_FATAL); 2159231200Smm } 2160231200Smm props[0] = maxOrder; 2161231200Smm archive_le32enc(props+1, msize); 2162231200Smm __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context); 2163231200Smm r = __archive_ppmd7_functions.Ppmd7_Alloc( 2164328827Smm &strm->ppmd7_context, msize); 2165231200Smm if (r == 0) { 2166231200Smm free(strm->buff); 2167231200Smm free(strm); 2168231200Smm free(props); 2169231200Smm archive_set_error(a, ENOMEM, 2170231200Smm "Coludn't allocate memory for PPMd"); 2171231200Smm return (ARCHIVE_FATAL); 2172231200Smm } 2173231200Smm __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder); 2174231200Smm strm->byteout.a = (struct archive_write *)a; 2175231200Smm strm->byteout.Write = ppmd_write; 2176231200Smm strm->range_enc.Stream = &(strm->byteout); 2177231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc)); 2178231200Smm strm->stat = 0; 2179231200Smm 2180231200Smm lastrm->real_stream = strm; 2181231200Smm lastrm->valid = 1; 2182231200Smm lastrm->code = compression_code_ppmd; 2183231200Smm lastrm->end = compression_end_ppmd; 2184231200Smm lastrm->prop_size = 5; 2185231200Smm lastrm->props = props; 2186231200Smm return (ARCHIVE_OK); 2187231200Smm} 2188231200Smm 2189231200Smmstatic int 2190231200Smmcompression_code_ppmd(struct archive *a, 2191231200Smm struct la_zstream *lastrm, enum la_zaction action) 2192231200Smm{ 2193231200Smm struct ppmd_stream *strm; 2194231200Smm 2195232153Smm (void)a; /* UNUSED */ 2196232153Smm 2197231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2198231200Smm 2199231200Smm /* Copy encoded data if there are remaining bytes from previous call. */ 2200231200Smm if (strm->buff_bytes) { 2201231200Smm uint8_t *p = strm->buff_ptr - strm->buff_bytes; 2202231200Smm while (lastrm->avail_out && strm->buff_bytes) { 2203231200Smm *lastrm->next_out++ = *p++; 2204231200Smm lastrm->avail_out--; 2205231200Smm lastrm->total_out++; 2206231200Smm strm->buff_bytes--; 2207231200Smm } 2208231200Smm if (strm->buff_bytes) 2209231200Smm return (ARCHIVE_OK); 2210231200Smm if (strm->stat == 1) 2211231200Smm return (ARCHIVE_EOF); 2212231200Smm strm->buff_ptr = strm->buff; 2213231200Smm } 2214231200Smm while (lastrm->avail_in && lastrm->avail_out) { 2215231200Smm __archive_ppmd7_functions.Ppmd7_EncodeSymbol( 2216231200Smm &(strm->ppmd7_context), &(strm->range_enc), 2217231200Smm *lastrm->next_in++); 2218231200Smm lastrm->avail_in--; 2219231200Smm lastrm->total_in++; 2220231200Smm } 2221231200Smm if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) { 2222231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData( 2223231200Smm &(strm->range_enc)); 2224231200Smm strm->stat = 1; 2225231200Smm /* Return EOF if there are no remaining bytes. */ 2226231200Smm if (strm->buff_bytes == 0) 2227231200Smm return (ARCHIVE_EOF); 2228231200Smm } 2229231200Smm return (ARCHIVE_OK); 2230231200Smm} 2231231200Smm 2232231200Smmstatic int 2233231200Smmcompression_end_ppmd(struct archive *a, struct la_zstream *lastrm) 2234231200Smm{ 2235231200Smm struct ppmd_stream *strm; 2236231200Smm 2237232153Smm (void)a; /* UNUSED */ 2238232153Smm 2239231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2240328827Smm __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context); 2241231200Smm free(strm->buff); 2242231200Smm free(strm); 2243231200Smm lastrm->real_stream = NULL; 2244231200Smm lastrm->valid = 0; 2245231200Smm return (ARCHIVE_OK); 2246231200Smm} 2247231200Smm 2248231200Smm/* 2249231200Smm * Universal compressor initializer. 2250231200Smm */ 2251231200Smmstatic int 2252231200Smm_7z_compression_init_encoder(struct archive_write *a, unsigned compression, 2253231200Smm int compression_level) 2254231200Smm{ 2255231200Smm struct _7zip *zip; 2256231200Smm int r; 2257231200Smm 2258231200Smm zip = (struct _7zip *)a->format_data; 2259231200Smm switch (compression) { 2260231200Smm case _7Z_DEFLATE: 2261231200Smm r = compression_init_encoder_deflate( 2262231200Smm &(a->archive), &(zip->stream), 2263231200Smm compression_level, 0); 2264231200Smm break; 2265231200Smm case _7Z_BZIP2: 2266231200Smm r = compression_init_encoder_bzip2( 2267231200Smm &(a->archive), &(zip->stream), 2268231200Smm compression_level); 2269231200Smm break; 2270231200Smm case _7Z_LZMA1: 2271231200Smm r = compression_init_encoder_lzma1( 2272231200Smm &(a->archive), &(zip->stream), 2273231200Smm compression_level); 2274231200Smm break; 2275231200Smm case _7Z_LZMA2: 2276231200Smm r = compression_init_encoder_lzma2( 2277231200Smm &(a->archive), &(zip->stream), 2278231200Smm compression_level); 2279231200Smm break; 2280231200Smm case _7Z_PPMD: 2281231200Smm r = compression_init_encoder_ppmd( 2282231200Smm &(a->archive), &(zip->stream), 2283231200Smm PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE); 2284231200Smm break; 2285231200Smm case _7Z_COPY: 2286231200Smm default: 2287231200Smm r = compression_init_encoder_copy( 2288231200Smm &(a->archive), &(zip->stream)); 2289231200Smm break; 2290231200Smm } 2291231200Smm if (r == ARCHIVE_OK) { 2292231200Smm zip->stream.total_in = 0; 2293231200Smm zip->stream.next_out = zip->wbuff; 2294231200Smm zip->stream.avail_out = sizeof(zip->wbuff); 2295231200Smm zip->stream.total_out = 0; 2296231200Smm } 2297231200Smm 2298231200Smm return (r); 2299231200Smm} 2300231200Smm 2301231200Smmstatic int 2302231200Smmcompression_code(struct archive *a, struct la_zstream *lastrm, 2303231200Smm enum la_zaction action) 2304231200Smm{ 2305231200Smm if (lastrm->valid) 2306231200Smm return (lastrm->code(a, lastrm, action)); 2307231200Smm return (ARCHIVE_OK); 2308231200Smm} 2309231200Smm 2310231200Smmstatic int 2311231200Smmcompression_end(struct archive *a, struct la_zstream *lastrm) 2312231200Smm{ 2313231200Smm if (lastrm->valid) { 2314231200Smm lastrm->prop_size = 0; 2315231200Smm free(lastrm->props); 2316231200Smm lastrm->props = NULL; 2317231200Smm return (lastrm->end(a, lastrm)); 2318231200Smm } 2319231200Smm return (ARCHIVE_OK); 2320231200Smm} 2321231200Smm 2322231200Smm 2323