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