archive_write_set_format_7zip.c revision 248616
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. 208231200Smm * We use 'next' a menber 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 1361231200Smm /* Write Nume 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 1453231200Smm file_free_register(zip); 1454231200Smm compression_end(&(a->archive), &(zip->stream)); 1455231200Smm free(zip->coder.props); 1456231200Smm free(zip); 1457231200Smm 1458231200Smm return (ARCHIVE_OK); 1459231200Smm} 1460231200Smm 1461231200Smmstatic int 1462231200Smmfile_cmp_node(const struct archive_rb_node *n1, 1463231200Smm const struct archive_rb_node *n2) 1464231200Smm{ 1465232153Smm const struct file *f1 = (const struct file *)n1; 1466232153Smm const struct file *f2 = (const struct file *)n2; 1467231200Smm 1468231200Smm if (f1->name_len == f2->name_len) 1469231200Smm return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); 1470231200Smm return (f1->name_len > f2->name_len)?1:-1; 1471231200Smm} 1472231200Smm 1473231200Smmstatic int 1474231200Smmfile_cmp_key(const struct archive_rb_node *n, const void *key) 1475231200Smm{ 1476232153Smm const struct file *f = (const struct file *)n; 1477231200Smm 1478231200Smm return (f->name_len - *(const char *)key); 1479231200Smm} 1480231200Smm 1481231200Smmstatic int 1482231200Smmfile_new(struct archive_write *a, struct archive_entry *entry, 1483231200Smm struct file **newfile) 1484231200Smm{ 1485231200Smm struct _7zip *zip; 1486231200Smm struct file *file; 1487231200Smm const char *u16; 1488231200Smm size_t u16len; 1489231200Smm int ret = ARCHIVE_OK; 1490231200Smm 1491231200Smm zip = (struct _7zip *)a->format_data; 1492231200Smm *newfile = NULL; 1493231200Smm 1494231200Smm file = calloc(1, sizeof(*file)); 1495231200Smm if (file == NULL) { 1496231200Smm archive_set_error(&a->archive, ENOMEM, 1497231200Smm "Can't allocate memory"); 1498231200Smm return (ARCHIVE_FATAL); 1499231200Smm } 1500231200Smm 1501231200Smm if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { 1502231200Smm if (errno == ENOMEM) { 1503238856Smm free(file); 1504231200Smm archive_set_error(&a->archive, ENOMEM, 1505231200Smm "Can't allocate memory for UTF-16LE"); 1506231200Smm return (ARCHIVE_FATAL); 1507231200Smm } 1508231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1509231200Smm "A filename cannot be converted to UTF-16LE;" 1510231200Smm "You should disable making Joliet extension"); 1511231200Smm ret = ARCHIVE_WARN; 1512231200Smm } 1513231200Smm file->utf16name = malloc(u16len + 2); 1514231200Smm if (file->utf16name == NULL) { 1515238856Smm free(file); 1516231200Smm archive_set_error(&a->archive, ENOMEM, 1517231200Smm "Can't allocate memory for Name"); 1518231200Smm return (ARCHIVE_FATAL); 1519231200Smm } 1520231200Smm memcpy(file->utf16name, u16, u16len); 1521231200Smm file->utf16name[u16len+0] = 0; 1522231200Smm file->utf16name[u16len+1] = 0; 1523248616Smm file->name_len = (unsigned)u16len; 1524231200Smm file->mode = archive_entry_mode(entry); 1525231200Smm if (archive_entry_filetype(entry) == AE_IFREG) 1526231200Smm file->size = archive_entry_size(entry); 1527231200Smm else 1528231200Smm archive_entry_set_size(entry, 0); 1529231200Smm if (archive_entry_filetype(entry) == AE_IFDIR) 1530231200Smm file->dir = 1; 1531231200Smm else if (archive_entry_filetype(entry) == AE_IFLNK) 1532231200Smm file->size = strlen(archive_entry_symlink(entry)); 1533231200Smm if (archive_entry_mtime_is_set(entry)) { 1534231200Smm file->flg |= MTIME_IS_SET; 1535231200Smm file->times[MTIME].time = archive_entry_mtime(entry); 1536231200Smm file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry); 1537231200Smm } 1538231200Smm if (archive_entry_atime_is_set(entry)) { 1539231200Smm file->flg |= ATIME_IS_SET; 1540231200Smm file->times[ATIME].time = archive_entry_atime(entry); 1541231200Smm file->times[ATIME].time_ns = archive_entry_atime_nsec(entry); 1542231200Smm } 1543231200Smm if (archive_entry_ctime_is_set(entry)) { 1544231200Smm file->flg |= CTIME_IS_SET; 1545231200Smm file->times[CTIME].time = archive_entry_ctime(entry); 1546231200Smm file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry); 1547231200Smm } 1548231200Smm 1549231200Smm *newfile = file; 1550231200Smm return (ret); 1551231200Smm} 1552231200Smm 1553231200Smmstatic void 1554231200Smmfile_free(struct file *file) 1555231200Smm{ 1556231200Smm free(file->utf16name); 1557231200Smm free(file); 1558231200Smm} 1559231200Smm 1560231200Smmstatic void 1561231200Smmfile_register(struct _7zip *zip, struct file *file) 1562231200Smm{ 1563231200Smm file->next = NULL; 1564231200Smm *zip->file_list.last = file; 1565231200Smm zip->file_list.last = &(file->next); 1566231200Smm} 1567231200Smm 1568231200Smmstatic void 1569231200Smmfile_init_register(struct _7zip *zip) 1570231200Smm{ 1571231200Smm zip->file_list.first = NULL; 1572231200Smm zip->file_list.last = &(zip->file_list.first); 1573231200Smm} 1574231200Smm 1575231200Smmstatic void 1576231200Smmfile_free_register(struct _7zip *zip) 1577231200Smm{ 1578231200Smm struct file *file, *file_next; 1579231200Smm 1580231200Smm file = zip->file_list.first; 1581231200Smm while (file != NULL) { 1582231200Smm file_next = file->next; 1583231200Smm file_free(file); 1584231200Smm file = file_next; 1585231200Smm } 1586231200Smm} 1587231200Smm 1588231200Smmstatic void 1589231200Smmfile_register_empty(struct _7zip *zip, struct file *file) 1590231200Smm{ 1591231200Smm file->next = NULL; 1592231200Smm *zip->empty_list.last = file; 1593231200Smm zip->empty_list.last = &(file->next); 1594231200Smm} 1595231200Smm 1596231200Smmstatic void 1597231200Smmfile_init_register_empty(struct _7zip *zip) 1598231200Smm{ 1599231200Smm zip->empty_list.first = NULL; 1600231200Smm zip->empty_list.last = &(zip->empty_list.first); 1601231200Smm} 1602231200Smm 1603232153Smm#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ 1604232153Smm !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) 1605231200Smmstatic int 1606231200Smmcompression_unsupported_encoder(struct archive *a, 1607231200Smm struct la_zstream *lastrm, const char *name) 1608231200Smm{ 1609231200Smm 1610231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1611231200Smm "%s compression not supported on this platform", name); 1612231200Smm lastrm->valid = 0; 1613231200Smm lastrm->real_stream = NULL; 1614231200Smm return (ARCHIVE_FAILED); 1615231200Smm} 1616231200Smm#endif 1617231200Smm 1618231200Smm/* 1619231200Smm * _7_COPY compressor. 1620231200Smm */ 1621231200Smmstatic int 1622231200Smmcompression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) 1623231200Smm{ 1624231200Smm 1625231200Smm if (lastrm->valid) 1626231200Smm compression_end(a, lastrm); 1627231200Smm lastrm->valid = 1; 1628231200Smm lastrm->code = compression_code_copy; 1629231200Smm lastrm->end = compression_end_copy; 1630231200Smm return (ARCHIVE_OK); 1631231200Smm} 1632231200Smm 1633231200Smmstatic int 1634231200Smmcompression_code_copy(struct archive *a, 1635231200Smm struct la_zstream *lastrm, enum la_zaction action) 1636231200Smm{ 1637231200Smm size_t bytes; 1638231200Smm 1639231200Smm (void)a; /* UNUSED */ 1640231200Smm if (lastrm->avail_out > lastrm->avail_in) 1641231200Smm bytes = lastrm->avail_in; 1642231200Smm else 1643231200Smm bytes = lastrm->avail_out; 1644231200Smm if (bytes) { 1645231200Smm memcpy(lastrm->next_out, lastrm->next_in, bytes); 1646231200Smm lastrm->next_in += bytes; 1647231200Smm lastrm->avail_in -= bytes; 1648231200Smm lastrm->total_in += bytes; 1649231200Smm lastrm->next_out += bytes; 1650231200Smm lastrm->avail_out -= bytes; 1651231200Smm lastrm->total_out += bytes; 1652231200Smm } 1653231200Smm if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0) 1654231200Smm return (ARCHIVE_EOF); 1655231200Smm return (ARCHIVE_OK); 1656231200Smm} 1657231200Smm 1658231200Smmstatic int 1659231200Smmcompression_end_copy(struct archive *a, struct la_zstream *lastrm) 1660231200Smm{ 1661231200Smm (void)a; /* UNUSED */ 1662231200Smm lastrm->valid = 0; 1663231200Smm return (ARCHIVE_OK); 1664231200Smm} 1665231200Smm 1666231200Smm/* 1667231200Smm * _7_DEFLATE compressor. 1668231200Smm */ 1669231200Smm#ifdef HAVE_ZLIB_H 1670231200Smmstatic int 1671231200Smmcompression_init_encoder_deflate(struct archive *a, 1672231200Smm struct la_zstream *lastrm, int level, int withheader) 1673231200Smm{ 1674231200Smm z_stream *strm; 1675231200Smm 1676231200Smm if (lastrm->valid) 1677231200Smm compression_end(a, lastrm); 1678231200Smm strm = calloc(1, sizeof(*strm)); 1679231200Smm if (strm == NULL) { 1680231200Smm archive_set_error(a, ENOMEM, 1681231200Smm "Can't allocate memory for gzip stream"); 1682231200Smm return (ARCHIVE_FATAL); 1683231200Smm } 1684231200Smm /* zlib.h is not const-correct, so we need this one bit 1685231200Smm * of ugly hackery to convert a const * pointer to 1686231200Smm * a non-const pointer. */ 1687231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1688248616Smm strm->avail_in = (uInt)lastrm->avail_in; 1689238856Smm strm->total_in = (uLong)lastrm->total_in; 1690231200Smm strm->next_out = lastrm->next_out; 1691248616Smm strm->avail_out = (uInt)lastrm->avail_out; 1692238856Smm strm->total_out = (uLong)lastrm->total_out; 1693231200Smm if (deflateInit2(strm, level, Z_DEFLATED, 1694231200Smm (withheader)?15:-15, 1695231200Smm 8, Z_DEFAULT_STRATEGY) != Z_OK) { 1696231200Smm free(strm); 1697231200Smm lastrm->real_stream = NULL; 1698231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1699231200Smm "Internal error initializing compression library"); 1700231200Smm return (ARCHIVE_FATAL); 1701231200Smm } 1702231200Smm lastrm->real_stream = strm; 1703231200Smm lastrm->valid = 1; 1704231200Smm lastrm->code = compression_code_deflate; 1705231200Smm lastrm->end = compression_end_deflate; 1706231200Smm return (ARCHIVE_OK); 1707231200Smm} 1708231200Smm 1709231200Smmstatic int 1710231200Smmcompression_code_deflate(struct archive *a, 1711231200Smm struct la_zstream *lastrm, enum la_zaction action) 1712231200Smm{ 1713231200Smm z_stream *strm; 1714231200Smm int r; 1715231200Smm 1716231200Smm strm = (z_stream *)lastrm->real_stream; 1717231200Smm /* zlib.h is not const-correct, so we need this one bit 1718231200Smm * of ugly hackery to convert a const * pointer to 1719231200Smm * a non-const pointer. */ 1720231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1721248616Smm strm->avail_in = (uInt)lastrm->avail_in; 1722238856Smm strm->total_in = (uLong)lastrm->total_in; 1723231200Smm strm->next_out = lastrm->next_out; 1724248616Smm strm->avail_out = (uInt)lastrm->avail_out; 1725238856Smm strm->total_out = (uLong)lastrm->total_out; 1726231200Smm r = deflate(strm, 1727231200Smm (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); 1728231200Smm lastrm->next_in = strm->next_in; 1729231200Smm lastrm->avail_in = strm->avail_in; 1730231200Smm lastrm->total_in = strm->total_in; 1731231200Smm lastrm->next_out = strm->next_out; 1732231200Smm lastrm->avail_out = strm->avail_out; 1733231200Smm lastrm->total_out = strm->total_out; 1734231200Smm switch (r) { 1735231200Smm case Z_OK: 1736231200Smm return (ARCHIVE_OK); 1737231200Smm case Z_STREAM_END: 1738231200Smm return (ARCHIVE_EOF); 1739231200Smm default: 1740231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1741231200Smm "GZip compression failed:" 1742231200Smm " deflate() call returned status %d", r); 1743231200Smm return (ARCHIVE_FATAL); 1744231200Smm } 1745231200Smm} 1746231200Smm 1747231200Smmstatic int 1748231200Smmcompression_end_deflate(struct archive *a, struct la_zstream *lastrm) 1749231200Smm{ 1750231200Smm z_stream *strm; 1751231200Smm int r; 1752231200Smm 1753231200Smm strm = (z_stream *)lastrm->real_stream; 1754231200Smm r = deflateEnd(strm); 1755231200Smm free(strm); 1756231200Smm lastrm->real_stream = NULL; 1757231200Smm lastrm->valid = 0; 1758231200Smm if (r != Z_OK) { 1759231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1760231200Smm "Failed to clean up compressor"); 1761231200Smm return (ARCHIVE_FATAL); 1762231200Smm } 1763231200Smm return (ARCHIVE_OK); 1764231200Smm} 1765231200Smm#else 1766231200Smmstatic int 1767231200Smmcompression_init_encoder_deflate(struct archive *a, 1768231200Smm struct la_zstream *lastrm, int level, int withheader) 1769231200Smm{ 1770231200Smm 1771231200Smm (void) level; /* UNUSED */ 1772231200Smm (void) withheader; /* UNUSED */ 1773231200Smm if (lastrm->valid) 1774231200Smm compression_end(a, lastrm); 1775231200Smm return (compression_unsupported_encoder(a, lastrm, "deflate")); 1776231200Smm} 1777231200Smm#endif 1778231200Smm 1779231200Smm/* 1780231200Smm * _7_BZIP2 compressor. 1781231200Smm */ 1782231200Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1783231200Smmstatic int 1784231200Smmcompression_init_encoder_bzip2(struct archive *a, 1785231200Smm struct la_zstream *lastrm, int level) 1786231200Smm{ 1787231200Smm bz_stream *strm; 1788231200Smm 1789231200Smm if (lastrm->valid) 1790231200Smm compression_end(a, lastrm); 1791231200Smm strm = calloc(1, sizeof(*strm)); 1792231200Smm if (strm == NULL) { 1793231200Smm archive_set_error(a, ENOMEM, 1794231200Smm "Can't allocate memory for bzip2 stream"); 1795231200Smm return (ARCHIVE_FATAL); 1796231200Smm } 1797231200Smm /* bzlib.h is not const-correct, so we need this one bit 1798231200Smm * of ugly hackery to convert a const * pointer to 1799231200Smm * a non-const pointer. */ 1800231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1801231200Smm strm->avail_in = lastrm->avail_in; 1802231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1803231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1804231200Smm strm->next_out = (char *)lastrm->next_out; 1805231200Smm strm->avail_out = lastrm->avail_out; 1806231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1807231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1808231200Smm if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { 1809231200Smm free(strm); 1810231200Smm lastrm->real_stream = NULL; 1811231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1812231200Smm "Internal error initializing compression library"); 1813231200Smm return (ARCHIVE_FATAL); 1814231200Smm } 1815231200Smm lastrm->real_stream = strm; 1816231200Smm lastrm->valid = 1; 1817231200Smm lastrm->code = compression_code_bzip2; 1818231200Smm lastrm->end = compression_end_bzip2; 1819231200Smm return (ARCHIVE_OK); 1820231200Smm} 1821231200Smm 1822231200Smmstatic int 1823231200Smmcompression_code_bzip2(struct archive *a, 1824231200Smm struct la_zstream *lastrm, enum la_zaction action) 1825231200Smm{ 1826231200Smm bz_stream *strm; 1827231200Smm int r; 1828231200Smm 1829231200Smm strm = (bz_stream *)lastrm->real_stream; 1830231200Smm /* bzlib.h is not const-correct, so we need this one bit 1831231200Smm * of ugly hackery to convert a const * pointer to 1832231200Smm * a non-const pointer. */ 1833231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1834231200Smm strm->avail_in = lastrm->avail_in; 1835231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1836231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1837231200Smm strm->next_out = (char *)lastrm->next_out; 1838231200Smm strm->avail_out = lastrm->avail_out; 1839231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1840231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1841231200Smm r = BZ2_bzCompress(strm, 1842231200Smm (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); 1843231200Smm lastrm->next_in = (const unsigned char *)strm->next_in; 1844231200Smm lastrm->avail_in = strm->avail_in; 1845231200Smm lastrm->total_in = 1846231200Smm (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) 1847231200Smm + (uint64_t)(uint32_t)strm->total_in_lo32; 1848231200Smm lastrm->next_out = (unsigned char *)strm->next_out; 1849231200Smm lastrm->avail_out = strm->avail_out; 1850231200Smm lastrm->total_out = 1851231200Smm (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) 1852231200Smm + (uint64_t)(uint32_t)strm->total_out_lo32; 1853231200Smm switch (r) { 1854231200Smm case BZ_RUN_OK: /* Non-finishing */ 1855231200Smm case BZ_FINISH_OK: /* Finishing: There's more work to do */ 1856231200Smm return (ARCHIVE_OK); 1857231200Smm case BZ_STREAM_END: /* Finishing: all done */ 1858231200Smm /* Only occurs in finishing case */ 1859231200Smm return (ARCHIVE_EOF); 1860231200Smm default: 1861231200Smm /* Any other return value indicates an error */ 1862231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1863231200Smm "Bzip2 compression failed:" 1864231200Smm " BZ2_bzCompress() call returned status %d", r); 1865231200Smm return (ARCHIVE_FATAL); 1866231200Smm } 1867231200Smm} 1868231200Smm 1869231200Smmstatic int 1870231200Smmcompression_end_bzip2(struct archive *a, struct la_zstream *lastrm) 1871231200Smm{ 1872231200Smm bz_stream *strm; 1873231200Smm int r; 1874231200Smm 1875231200Smm strm = (bz_stream *)lastrm->real_stream; 1876231200Smm r = BZ2_bzCompressEnd(strm); 1877231200Smm free(strm); 1878231200Smm lastrm->real_stream = NULL; 1879231200Smm lastrm->valid = 0; 1880231200Smm if (r != BZ_OK) { 1881231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1882231200Smm "Failed to clean up compressor"); 1883231200Smm return (ARCHIVE_FATAL); 1884231200Smm } 1885231200Smm return (ARCHIVE_OK); 1886231200Smm} 1887231200Smm 1888231200Smm#else 1889231200Smmstatic int 1890231200Smmcompression_init_encoder_bzip2(struct archive *a, 1891231200Smm struct la_zstream *lastrm, int level) 1892231200Smm{ 1893231200Smm 1894231200Smm (void) level; /* UNUSED */ 1895231200Smm if (lastrm->valid) 1896231200Smm compression_end(a, lastrm); 1897231200Smm return (compression_unsupported_encoder(a, lastrm, "bzip2")); 1898231200Smm} 1899231200Smm#endif 1900231200Smm 1901231200Smm/* 1902231200Smm * _7_LZMA1, _7_LZMA2 compressor. 1903231200Smm */ 1904231200Smm#if defined(HAVE_LZMA_H) 1905231200Smmstatic int 1906231200Smmcompression_init_encoder_lzma(struct archive *a, 1907231200Smm struct la_zstream *lastrm, int level, uint64_t filter_id) 1908231200Smm{ 1909231200Smm static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; 1910231200Smm lzma_stream *strm; 1911231200Smm lzma_filter *lzmafilters; 1912231200Smm lzma_options_lzma lzma_opt; 1913231200Smm int r; 1914231200Smm 1915231200Smm if (lastrm->valid) 1916231200Smm compression_end(a, lastrm); 1917231200Smm strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); 1918231200Smm if (strm == NULL) { 1919231200Smm archive_set_error(a, ENOMEM, 1920231200Smm "Can't allocate memory for lzma stream"); 1921231200Smm return (ARCHIVE_FATAL); 1922231200Smm } 1923231200Smm lzmafilters = (lzma_filter *)(strm+1); 1924231200Smm if (level > 6) 1925231200Smm level = 6; 1926231200Smm if (lzma_lzma_preset(&lzma_opt, level)) { 1927238856Smm free(strm); 1928231200Smm lastrm->real_stream = NULL; 1929231200Smm archive_set_error(a, ENOMEM, 1930231200Smm "Internal error initializing compression library"); 1931231200Smm return (ARCHIVE_FATAL); 1932231200Smm } 1933231200Smm lzmafilters[0].id = filter_id; 1934231200Smm lzmafilters[0].options = &lzma_opt; 1935231200Smm lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ 1936231200Smm 1937231200Smm r = lzma_properties_size(&(lastrm->prop_size), lzmafilters); 1938231200Smm if (r != LZMA_OK) { 1939231200Smm free(strm); 1940231200Smm lastrm->real_stream = NULL; 1941231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1942231200Smm "lzma_properties_size failed"); 1943231200Smm return (ARCHIVE_FATAL); 1944231200Smm } 1945231200Smm if (lastrm->prop_size) { 1946231200Smm lastrm->props = malloc(lastrm->prop_size); 1947231200Smm if (lastrm->props == NULL) { 1948231200Smm free(strm); 1949231200Smm lastrm->real_stream = NULL; 1950231200Smm archive_set_error(a, ENOMEM, 1951231200Smm "Cannot allocate memory"); 1952231200Smm return (ARCHIVE_FATAL); 1953231200Smm } 1954231200Smm r = lzma_properties_encode(lzmafilters, lastrm->props); 1955231200Smm if (r != LZMA_OK) { 1956231200Smm free(strm); 1957231200Smm lastrm->real_stream = NULL; 1958231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1959231200Smm "lzma_properties_encode failed"); 1960231200Smm return (ARCHIVE_FATAL); 1961231200Smm } 1962231200Smm } 1963231200Smm 1964231200Smm *strm = lzma_init_data; 1965231200Smm r = lzma_raw_encoder(strm, lzmafilters); 1966231200Smm switch (r) { 1967231200Smm case LZMA_OK: 1968231200Smm lastrm->real_stream = strm; 1969231200Smm lastrm->valid = 1; 1970231200Smm lastrm->code = compression_code_lzma; 1971231200Smm lastrm->end = compression_end_lzma; 1972231200Smm r = ARCHIVE_OK; 1973231200Smm break; 1974231200Smm case LZMA_MEM_ERROR: 1975231200Smm free(strm); 1976231200Smm lastrm->real_stream = NULL; 1977231200Smm archive_set_error(a, ENOMEM, 1978231200Smm "Internal error initializing compression library: " 1979231200Smm "Cannot allocate memory"); 1980231200Smm r = ARCHIVE_FATAL; 1981231200Smm break; 1982231200Smm default: 1983231200Smm free(strm); 1984231200Smm lastrm->real_stream = NULL; 1985231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1986231200Smm "Internal error initializing compression library: " 1987231200Smm "It's a bug in liblzma"); 1988231200Smm r = ARCHIVE_FATAL; 1989231200Smm break; 1990231200Smm } 1991231200Smm return (r); 1992231200Smm} 1993231200Smm 1994231200Smmstatic int 1995231200Smmcompression_init_encoder_lzma1(struct archive *a, 1996231200Smm struct la_zstream *lastrm, int level) 1997231200Smm{ 1998231200Smm return compression_init_encoder_lzma(a, lastrm, level, 1999231200Smm LZMA_FILTER_LZMA1); 2000231200Smm} 2001231200Smm 2002231200Smmstatic int 2003231200Smmcompression_init_encoder_lzma2(struct archive *a, 2004231200Smm struct la_zstream *lastrm, int level) 2005231200Smm{ 2006231200Smm return compression_init_encoder_lzma(a, lastrm, level, 2007231200Smm LZMA_FILTER_LZMA2); 2008231200Smm} 2009231200Smm 2010231200Smmstatic int 2011231200Smmcompression_code_lzma(struct archive *a, 2012231200Smm struct la_zstream *lastrm, enum la_zaction action) 2013231200Smm{ 2014231200Smm lzma_stream *strm; 2015231200Smm int r; 2016231200Smm 2017231200Smm strm = (lzma_stream *)lastrm->real_stream; 2018231200Smm strm->next_in = lastrm->next_in; 2019231200Smm strm->avail_in = lastrm->avail_in; 2020231200Smm strm->total_in = lastrm->total_in; 2021231200Smm strm->next_out = lastrm->next_out; 2022231200Smm strm->avail_out = lastrm->avail_out; 2023231200Smm strm->total_out = lastrm->total_out; 2024231200Smm r = lzma_code(strm, 2025231200Smm (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); 2026231200Smm lastrm->next_in = strm->next_in; 2027231200Smm lastrm->avail_in = strm->avail_in; 2028231200Smm lastrm->total_in = strm->total_in; 2029231200Smm lastrm->next_out = strm->next_out; 2030231200Smm lastrm->avail_out = strm->avail_out; 2031231200Smm lastrm->total_out = strm->total_out; 2032231200Smm switch (r) { 2033231200Smm case LZMA_OK: 2034231200Smm /* Non-finishing case */ 2035231200Smm return (ARCHIVE_OK); 2036231200Smm case LZMA_STREAM_END: 2037231200Smm /* This return can only occur in finishing case. */ 2038231200Smm return (ARCHIVE_EOF); 2039231200Smm case LZMA_MEMLIMIT_ERROR: 2040231200Smm archive_set_error(a, ENOMEM, 2041231200Smm "lzma compression error:" 2042231200Smm " %ju MiB would have been needed", 2043231200Smm (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) 2044231200Smm / (1024 * 1024))); 2045231200Smm return (ARCHIVE_FATAL); 2046231200Smm default: 2047231200Smm /* Any other return value indicates an error */ 2048231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 2049231200Smm "lzma compression failed:" 2050231200Smm " lzma_code() call returned status %d", r); 2051231200Smm return (ARCHIVE_FATAL); 2052231200Smm } 2053231200Smm} 2054231200Smm 2055231200Smmstatic int 2056231200Smmcompression_end_lzma(struct archive *a, struct la_zstream *lastrm) 2057231200Smm{ 2058231200Smm lzma_stream *strm; 2059231200Smm 2060231200Smm (void)a; /* UNUSED */ 2061231200Smm strm = (lzma_stream *)lastrm->real_stream; 2062231200Smm lzma_end(strm); 2063231200Smm free(strm); 2064231200Smm lastrm->valid = 0; 2065231200Smm lastrm->real_stream = NULL; 2066231200Smm return (ARCHIVE_OK); 2067231200Smm} 2068231200Smm#else 2069231200Smmstatic int 2070231200Smmcompression_init_encoder_lzma1(struct archive *a, 2071231200Smm struct la_zstream *lastrm, int level) 2072231200Smm{ 2073231200Smm 2074231200Smm (void) level; /* UNUSED */ 2075231200Smm if (lastrm->valid) 2076231200Smm compression_end(a, lastrm); 2077231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2078231200Smm} 2079231200Smmstatic int 2080231200Smmcompression_init_encoder_lzma2(struct archive *a, 2081231200Smm struct la_zstream *lastrm, int level) 2082231200Smm{ 2083231200Smm 2084231200Smm (void) level; /* UNUSED */ 2085231200Smm if (lastrm->valid) 2086231200Smm compression_end(a, lastrm); 2087231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2088231200Smm} 2089231200Smm#endif 2090231200Smm 2091231200Smm/* 2092231200Smm * _7_PPMD compressor. 2093231200Smm */ 2094231200Smmstatic void * 2095231200Smmppmd_alloc(void *p, size_t size) 2096231200Smm{ 2097231200Smm (void)p; 2098231200Smm return malloc(size); 2099231200Smm} 2100231200Smmstatic void 2101231200Smmppmd_free(void *p, void *address) 2102231200Smm{ 2103231200Smm (void)p; 2104231200Smm free(address); 2105231200Smm} 2106231200Smmstatic ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free }; 2107231200Smmstatic void 2108231200Smmppmd_write(void *p, Byte b) 2109231200Smm{ 2110231200Smm struct archive_write *a = ((IByteOut *)p)->a; 2111231200Smm struct _7zip *zip = (struct _7zip *)(a->format_data); 2112231200Smm struct la_zstream *lastrm = &(zip->stream); 2113231200Smm struct ppmd_stream *strm; 2114231200Smm 2115231200Smm if (lastrm->avail_out) { 2116231200Smm *lastrm->next_out++ = b; 2117231200Smm lastrm->avail_out--; 2118231200Smm lastrm->total_out++; 2119231200Smm return; 2120231200Smm } 2121231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2122231200Smm if (strm->buff_ptr < strm->buff_end) { 2123231200Smm *strm->buff_ptr++ = b; 2124231200Smm strm->buff_bytes++; 2125231200Smm } 2126231200Smm} 2127231200Smm 2128231200Smmstatic int 2129231200Smmcompression_init_encoder_ppmd(struct archive *a, 2130231200Smm struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize) 2131231200Smm{ 2132231200Smm struct ppmd_stream *strm; 2133231200Smm uint8_t *props; 2134231200Smm int r; 2135231200Smm 2136231200Smm if (lastrm->valid) 2137231200Smm compression_end(a, lastrm); 2138231200Smm strm = calloc(1, sizeof(*strm)); 2139231200Smm if (strm == NULL) { 2140231200Smm archive_set_error(a, ENOMEM, 2141231200Smm "Can't allocate memory for PPMd"); 2142231200Smm return (ARCHIVE_FATAL); 2143231200Smm } 2144231200Smm strm->buff = malloc(32); 2145231200Smm if (strm->buff == NULL) { 2146231200Smm free(strm); 2147231200Smm archive_set_error(a, ENOMEM, 2148231200Smm "Can't allocate memory for PPMd"); 2149231200Smm return (ARCHIVE_FATAL); 2150231200Smm } 2151231200Smm strm->buff_ptr = strm->buff; 2152231200Smm strm->buff_end = strm->buff + 32; 2153231200Smm 2154231200Smm props = malloc(1+4); 2155231200Smm if (props == NULL) { 2156231200Smm free(strm->buff); 2157231200Smm free(strm); 2158231200Smm archive_set_error(a, ENOMEM, 2159231200Smm "Coludn't allocate memory for PPMd"); 2160231200Smm return (ARCHIVE_FATAL); 2161231200Smm } 2162231200Smm props[0] = maxOrder; 2163231200Smm archive_le32enc(props+1, msize); 2164231200Smm __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context); 2165231200Smm r = __archive_ppmd7_functions.Ppmd7_Alloc( 2166231200Smm &strm->ppmd7_context, msize, &g_szalloc); 2167231200Smm if (r == 0) { 2168231200Smm free(strm->buff); 2169231200Smm free(strm); 2170231200Smm free(props); 2171231200Smm archive_set_error(a, ENOMEM, 2172231200Smm "Coludn't allocate memory for PPMd"); 2173231200Smm return (ARCHIVE_FATAL); 2174231200Smm } 2175231200Smm __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder); 2176231200Smm strm->byteout.a = (struct archive_write *)a; 2177231200Smm strm->byteout.Write = ppmd_write; 2178231200Smm strm->range_enc.Stream = &(strm->byteout); 2179231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc)); 2180231200Smm strm->stat = 0; 2181231200Smm 2182231200Smm lastrm->real_stream = strm; 2183231200Smm lastrm->valid = 1; 2184231200Smm lastrm->code = compression_code_ppmd; 2185231200Smm lastrm->end = compression_end_ppmd; 2186231200Smm lastrm->prop_size = 5; 2187231200Smm lastrm->props = props; 2188231200Smm return (ARCHIVE_OK); 2189231200Smm} 2190231200Smm 2191231200Smmstatic int 2192231200Smmcompression_code_ppmd(struct archive *a, 2193231200Smm struct la_zstream *lastrm, enum la_zaction action) 2194231200Smm{ 2195231200Smm struct ppmd_stream *strm; 2196231200Smm 2197232153Smm (void)a; /* UNUSED */ 2198232153Smm 2199231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2200231200Smm 2201231200Smm /* Copy encoded data if there are remaining bytes from previous call. */ 2202231200Smm if (strm->buff_bytes) { 2203231200Smm uint8_t *p = strm->buff_ptr - strm->buff_bytes; 2204231200Smm while (lastrm->avail_out && strm->buff_bytes) { 2205231200Smm *lastrm->next_out++ = *p++; 2206231200Smm lastrm->avail_out--; 2207231200Smm lastrm->total_out++; 2208231200Smm strm->buff_bytes--; 2209231200Smm } 2210231200Smm if (strm->buff_bytes) 2211231200Smm return (ARCHIVE_OK); 2212231200Smm if (strm->stat == 1) 2213231200Smm return (ARCHIVE_EOF); 2214231200Smm strm->buff_ptr = strm->buff; 2215231200Smm } 2216231200Smm while (lastrm->avail_in && lastrm->avail_out) { 2217231200Smm __archive_ppmd7_functions.Ppmd7_EncodeSymbol( 2218231200Smm &(strm->ppmd7_context), &(strm->range_enc), 2219231200Smm *lastrm->next_in++); 2220231200Smm lastrm->avail_in--; 2221231200Smm lastrm->total_in++; 2222231200Smm } 2223231200Smm if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) { 2224231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData( 2225231200Smm &(strm->range_enc)); 2226231200Smm strm->stat = 1; 2227231200Smm /* Return EOF if there are no remaining bytes. */ 2228231200Smm if (strm->buff_bytes == 0) 2229231200Smm return (ARCHIVE_EOF); 2230231200Smm } 2231231200Smm return (ARCHIVE_OK); 2232231200Smm} 2233231200Smm 2234231200Smmstatic int 2235231200Smmcompression_end_ppmd(struct archive *a, struct la_zstream *lastrm) 2236231200Smm{ 2237231200Smm struct ppmd_stream *strm; 2238231200Smm 2239232153Smm (void)a; /* UNUSED */ 2240232153Smm 2241231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2242231200Smm __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc); 2243231200Smm free(strm->buff); 2244231200Smm free(strm); 2245231200Smm lastrm->real_stream = NULL; 2246231200Smm lastrm->valid = 0; 2247231200Smm return (ARCHIVE_OK); 2248231200Smm} 2249231200Smm 2250231200Smm/* 2251231200Smm * Universal compressor initializer. 2252231200Smm */ 2253231200Smmstatic int 2254231200Smm_7z_compression_init_encoder(struct archive_write *a, unsigned compression, 2255231200Smm int compression_level) 2256231200Smm{ 2257231200Smm struct _7zip *zip; 2258231200Smm int r; 2259231200Smm 2260231200Smm zip = (struct _7zip *)a->format_data; 2261231200Smm switch (compression) { 2262231200Smm case _7Z_DEFLATE: 2263231200Smm r = compression_init_encoder_deflate( 2264231200Smm &(a->archive), &(zip->stream), 2265231200Smm compression_level, 0); 2266231200Smm break; 2267231200Smm case _7Z_BZIP2: 2268231200Smm r = compression_init_encoder_bzip2( 2269231200Smm &(a->archive), &(zip->stream), 2270231200Smm compression_level); 2271231200Smm break; 2272231200Smm case _7Z_LZMA1: 2273231200Smm r = compression_init_encoder_lzma1( 2274231200Smm &(a->archive), &(zip->stream), 2275231200Smm compression_level); 2276231200Smm break; 2277231200Smm case _7Z_LZMA2: 2278231200Smm r = compression_init_encoder_lzma2( 2279231200Smm &(a->archive), &(zip->stream), 2280231200Smm compression_level); 2281231200Smm break; 2282231200Smm case _7Z_PPMD: 2283231200Smm r = compression_init_encoder_ppmd( 2284231200Smm &(a->archive), &(zip->stream), 2285231200Smm PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE); 2286231200Smm break; 2287231200Smm case _7Z_COPY: 2288231200Smm default: 2289231200Smm r = compression_init_encoder_copy( 2290231200Smm &(a->archive), &(zip->stream)); 2291231200Smm break; 2292231200Smm } 2293231200Smm if (r == ARCHIVE_OK) { 2294231200Smm zip->stream.total_in = 0; 2295231200Smm zip->stream.next_out = zip->wbuff; 2296231200Smm zip->stream.avail_out = sizeof(zip->wbuff); 2297231200Smm zip->stream.total_out = 0; 2298231200Smm } 2299231200Smm 2300231200Smm return (r); 2301231200Smm} 2302231200Smm 2303231200Smmstatic int 2304231200Smmcompression_code(struct archive *a, struct la_zstream *lastrm, 2305231200Smm enum la_zaction action) 2306231200Smm{ 2307231200Smm if (lastrm->valid) 2308231200Smm return (lastrm->code(a, lastrm, action)); 2309231200Smm return (ARCHIVE_OK); 2310231200Smm} 2311231200Smm 2312231200Smmstatic int 2313231200Smmcompression_end(struct archive *a, struct la_zstream *lastrm) 2314231200Smm{ 2315231200Smm if (lastrm->valid) { 2316231200Smm lastrm->prop_size = 0; 2317231200Smm free(lastrm->props); 2318231200Smm lastrm->props = NULL; 2319231200Smm return (lastrm->end(a, lastrm)); 2320231200Smm } 2321231200Smm return (ARCHIVE_OK); 2322231200Smm} 2323231200Smm 2324231200Smm 2325