archive_write_set_format_7zip.c revision 232153
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 */ 202231200Smm unsigned char wbuff[1024 * 64]; 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, 388231200Smm "Unkonwn 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, 408231200Smm "Illeagal 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 } 445231200Smm 446231200Smm if (file->flg & MTIME_IS_SET) 447231200Smm zip->total_number_time_defined[MTIME]++; 448231200Smm if (file->flg & CTIME_IS_SET) 449231200Smm zip->total_number_time_defined[CTIME]++; 450231200Smm if (file->flg & ATIME_IS_SET) 451231200Smm zip->total_number_time_defined[ATIME]++; 452231200Smm 453231200Smm if (file->size == 0 && file->dir) { 454231200Smm if (!__archive_rb_tree_insert_node(&(zip->rbtree), 455231200Smm (struct archive_rb_node *)file)) 456231200Smm file_free(file); 457231200Smm } 458231200Smm zip->total_number_entry++; 459231200Smm zip->total_bytes_entry_name += file->name_len + 2; 460231200Smm if (file->size == 0) { 461231200Smm /* Count up the number of empty files. */ 462231200Smm zip->total_number_empty_entry++; 463231200Smm if (file->dir) 464231200Smm zip->total_number_dir_entry++; 465231200Smm else 466231200Smm file_register_empty(zip, file); 467231200Smm return (r); 468231200Smm } 469231200Smm 470231200Smm /* 471231200Smm * Init compression. 472231200Smm */ 473231200Smm if ((zip->total_number_entry - zip->total_number_empty_entry) == 1) { 474231200Smm r = _7z_compression_init_encoder(a, zip->opt_compression, 475231200Smm zip->opt_compression_level); 476231200Smm if (r < 0) { 477231200Smm file_free(file); 478231200Smm return (ARCHIVE_FATAL); 479231200Smm } 480231200Smm } 481231200Smm 482231200Smm /* Register a non-empty file. */ 483231200Smm file_register(zip, file); 484231200Smm 485231200Smm /* 486231200Smm * Set the current file to cur_file to read its contents. 487231200Smm */ 488231200Smm zip->cur_file = file; 489231200Smm 490231200Smm 491231200Smm /* Save a offset of current file in temporary file. */ 492231200Smm zip->entry_bytes_remaining = file->size; 493231200Smm zip->entry_crc32 = 0; 494231200Smm 495231200Smm /* 496231200Smm * Store a symbolic link name as file contents. 497231200Smm */ 498231200Smm if (archive_entry_filetype(entry) == AE_IFLNK) { 499231200Smm ssize_t bytes; 500231200Smm const void *p = (const void *)archive_entry_symlink(entry); 501231200Smm bytes = compress_out(a, p, file->size, ARCHIVE_Z_RUN); 502231200Smm if (bytes < 0) 503231200Smm return ((int)bytes); 504231200Smm zip->entry_crc32 = crc32(zip->entry_crc32, p, bytes); 505231200Smm zip->entry_bytes_remaining -= bytes; 506231200Smm } 507231200Smm 508231200Smm return (r); 509231200Smm} 510231200Smm 511231200Smm/* 512231200Smm * Write data to a temporary file. 513231200Smm */ 514231200Smmstatic int 515231200Smmwrite_to_temp(struct archive_write *a, const void *buff, size_t s) 516231200Smm{ 517231200Smm struct _7zip *zip; 518232153Smm const unsigned char *p; 519231200Smm ssize_t ws; 520231200Smm 521231200Smm zip = (struct _7zip *)a->format_data; 522231200Smm 523231200Smm /* 524231200Smm * Open a temporary file. 525231200Smm */ 526231200Smm if (zip->temp_fd == -1) { 527231200Smm zip->temp_offset = 0; 528231200Smm zip->temp_fd = __archive_mktemp(NULL); 529231200Smm if (zip->temp_fd < 0) { 530231200Smm archive_set_error(&a->archive, errno, 531231200Smm "Couldn't create temporary file"); 532231200Smm return (ARCHIVE_FATAL); 533231200Smm } 534231200Smm } 535231200Smm 536232153Smm p = (const unsigned char *)buff; 537231200Smm while (s) { 538231200Smm ws = write(zip->temp_fd, p, s); 539231200Smm if (ws < 0) { 540231200Smm archive_set_error(&(a->archive), errno, 541231200Smm "fwrite function failed"); 542231200Smm return (ARCHIVE_FATAL); 543231200Smm } 544231200Smm s -= ws; 545231200Smm p += ws; 546231200Smm zip->temp_offset += ws; 547231200Smm } 548231200Smm return (ARCHIVE_OK); 549231200Smm} 550231200Smm 551231200Smmstatic ssize_t 552231200Smmcompress_out(struct archive_write *a, const void *buff, size_t s, 553231200Smm enum la_zaction run) 554231200Smm{ 555231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 556231200Smm int r; 557231200Smm 558231200Smm if (run == ARCHIVE_Z_FINISH && zip->stream.total_in == 0 && s == 0) 559231200Smm return (0); 560231200Smm 561231200Smm if ((zip->crc32flg & PRECODE_CRC32) && s) 562231200Smm zip->precode_crc32 = crc32(zip->precode_crc32, buff, s); 563231200Smm zip->stream.next_in = (const unsigned char *)buff; 564231200Smm zip->stream.avail_in = s; 565231200Smm do { 566231200Smm /* Compress file data. */ 567231200Smm r = compression_code(&(a->archive), &(zip->stream), run); 568231200Smm if (r != ARCHIVE_OK && r != ARCHIVE_EOF) 569231200Smm return (ARCHIVE_FATAL); 570231200Smm if (zip->stream.avail_out == 0) { 571231200Smm if (write_to_temp(a, zip->wbuff, sizeof(zip->wbuff)) 572231200Smm != ARCHIVE_OK) 573231200Smm return (ARCHIVE_FATAL); 574231200Smm zip->stream.next_out = zip->wbuff; 575231200Smm zip->stream.avail_out = sizeof(zip->wbuff); 576231200Smm if (zip->crc32flg & ENCODED_CRC32) 577231200Smm zip->encoded_crc32 = crc32(zip->encoded_crc32, 578231200Smm zip->wbuff, sizeof(zip->wbuff)); 579231200Smm } 580231200Smm } while (zip->stream.avail_in); 581231200Smm if (run == ARCHIVE_Z_FINISH) { 582231200Smm uint64_t bytes = sizeof(zip->wbuff) - zip->stream.avail_out; 583231200Smm if (write_to_temp(a, zip->wbuff, bytes) != ARCHIVE_OK) 584231200Smm return (ARCHIVE_FATAL); 585231200Smm if ((zip->crc32flg & ENCODED_CRC32) && bytes) 586231200Smm zip->encoded_crc32 = crc32(zip->encoded_crc32, 587231200Smm zip->wbuff, bytes); 588231200Smm } 589231200Smm 590231200Smm return (s); 591231200Smm} 592231200Smm 593231200Smmstatic ssize_t 594231200Smm_7z_write_data(struct archive_write *a, const void *buff, size_t s) 595231200Smm{ 596231200Smm struct _7zip *zip; 597231200Smm ssize_t bytes; 598231200Smm 599231200Smm zip = (struct _7zip *)a->format_data; 600231200Smm 601231200Smm if (s > zip->entry_bytes_remaining) 602231200Smm s = zip->entry_bytes_remaining; 603231200Smm if (s == 0 || zip->cur_file == NULL) 604231200Smm return (0); 605231200Smm bytes = compress_out(a, buff, s, ARCHIVE_Z_RUN); 606231200Smm if (bytes < 0) 607231200Smm return (bytes); 608231200Smm zip->entry_crc32 = crc32(zip->entry_crc32, buff, bytes); 609231200Smm zip->entry_bytes_remaining -= bytes; 610231200Smm return (bytes); 611231200Smm} 612231200Smm 613231200Smmstatic int 614231200Smm_7z_finish_entry(struct archive_write *a) 615231200Smm{ 616231200Smm struct _7zip *zip; 617231200Smm size_t s; 618231200Smm ssize_t r; 619231200Smm 620231200Smm zip = (struct _7zip *)a->format_data; 621231200Smm if (zip->cur_file == NULL) 622231200Smm return (ARCHIVE_OK); 623231200Smm 624231200Smm while (zip->entry_bytes_remaining > 0) { 625231200Smm s = zip->entry_bytes_remaining; 626231200Smm if (s > a->null_length) 627231200Smm s = a->null_length; 628231200Smm r = _7z_write_data(a, a->nulls, s); 629231200Smm if (r < 0) 630231200Smm return (r); 631231200Smm } 632231200Smm zip->total_bytes_compressed += zip->stream.total_in; 633231200Smm zip->total_bytes_uncompressed += zip->stream.total_out; 634231200Smm zip->cur_file->crc32 = zip->entry_crc32; 635231200Smm zip->cur_file = NULL; 636231200Smm 637231200Smm return (ARCHIVE_OK); 638231200Smm} 639231200Smm 640231200Smmstatic int 641231200Smmflush_wbuff(struct archive_write *a) 642231200Smm{ 643231200Smm struct _7zip *zip; 644231200Smm int r; 645231200Smm size_t s; 646231200Smm 647231200Smm zip = (struct _7zip *)a->format_data; 648231200Smm s = sizeof(zip->wbuff) - zip->wbuff_remaining; 649231200Smm r = __archive_write_output(a, zip->wbuff, s); 650231200Smm if (r != ARCHIVE_OK) 651231200Smm return (r); 652231200Smm zip->wbuff_remaining = sizeof(zip->wbuff); 653231200Smm return (r); 654231200Smm} 655231200Smm 656231200Smmstatic int 657231200Smmcopy_out(struct archive_write *a, uint64_t offset, uint64_t length) 658231200Smm{ 659231200Smm struct _7zip *zip; 660231200Smm int r; 661231200Smm 662231200Smm zip = (struct _7zip *)a->format_data; 663231200Smm if (zip->temp_offset > 0 && 664231200Smm lseek(zip->temp_fd, offset, SEEK_SET) < 0) { 665231200Smm archive_set_error(&(a->archive), errno, "lseek failed"); 666231200Smm return (ARCHIVE_FATAL); 667231200Smm } 668231200Smm while (length) { 669231200Smm size_t rsize; 670231200Smm ssize_t rs; 671231200Smm unsigned char *wb; 672231200Smm 673231200Smm if (length > zip->wbuff_remaining) 674231200Smm rsize = zip->wbuff_remaining; 675231200Smm else 676231200Smm rsize = (size_t)length; 677231200Smm wb = zip->wbuff + (sizeof(zip->wbuff) - zip->wbuff_remaining); 678231200Smm rs = read(zip->temp_fd, wb, rsize); 679231200Smm if (rs < 0) { 680231200Smm archive_set_error(&(a->archive), errno, 681231200Smm "Can't read temporary file(%jd)", 682231200Smm (intmax_t)rs); 683231200Smm return (ARCHIVE_FATAL); 684231200Smm } 685231200Smm if (rs == 0) { 686231200Smm archive_set_error(&(a->archive), 0, 687231200Smm "Truncated 7-Zip archive"); 688231200Smm return (ARCHIVE_FATAL); 689231200Smm } 690231200Smm zip->wbuff_remaining -= rs; 691231200Smm length -= rs; 692231200Smm if (zip->wbuff_remaining == 0) { 693231200Smm r = flush_wbuff(a); 694231200Smm if (r != ARCHIVE_OK) 695231200Smm return (r); 696231200Smm } 697231200Smm } 698231200Smm return (ARCHIVE_OK); 699231200Smm} 700231200Smm 701231200Smmstatic int 702231200Smm_7z_close(struct archive_write *a) 703231200Smm{ 704231200Smm struct _7zip *zip; 705231200Smm unsigned char *wb; 706231200Smm uint64_t header_offset, header_size, header_unpacksize; 707231200Smm uint64_t length; 708231200Smm uint32_t header_crc32; 709231200Smm int r; 710231200Smm 711231200Smm zip = (struct _7zip *)a->format_data; 712231200Smm 713231200Smm if (zip->total_number_entry > 0) { 714231200Smm struct archive_rb_node *n; 715231200Smm uint64_t data_offset, data_size, data_unpacksize; 716231200Smm unsigned header_compression; 717231200Smm 718231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 719231200Smm if (r < 0) 720231200Smm return (r); 721231200Smm data_offset = 0; 722231200Smm data_size = zip->stream.total_out; 723231200Smm data_unpacksize = zip->stream.total_in; 724231200Smm zip->coder.codec = zip->opt_compression; 725231200Smm zip->coder.prop_size = zip->stream.prop_size; 726231200Smm zip->coder.props = zip->stream.props; 727231200Smm zip->stream.prop_size = 0; 728231200Smm zip->stream.props = NULL; 729231200Smm zip->total_number_nonempty_entry = 730231200Smm zip->total_number_entry - zip->total_number_empty_entry; 731231200Smm 732231200Smm /* Connect an empty file list. */ 733231200Smm if (zip->empty_list.first != NULL) { 734231200Smm *zip->file_list.last = zip->empty_list.first; 735231200Smm zip->file_list.last = zip->empty_list.last; 736231200Smm } 737231200Smm /* Connect a directory file list. */ 738231200Smm ARCHIVE_RB_TREE_FOREACH(n, &(zip->rbtree)) { 739231200Smm file_register(zip, (struct file *)n); 740231200Smm } 741231200Smm 742231200Smm /* 743231200Smm * NOTE: 7z command supports just LZMA1, LZMA2 and COPY for 744231200Smm * the compression type for encoding the header. 745231200Smm */ 746231200Smm#if HAVE_LZMA_H 747231200Smm header_compression = _7Z_LZMA1; 748231200Smm /* If the stored file is only one, do not encode the header. 749231200Smm * This is the same way 7z command does. */ 750231200Smm if (zip->total_number_entry == 1) 751231200Smm header_compression = _7Z_COPY; 752231200Smm#else 753231200Smm header_compression = _7Z_COPY; 754231200Smm#endif 755231200Smm r = _7z_compression_init_encoder(a, header_compression, 6); 756231200Smm if (r < 0) 757231200Smm return (r); 758231200Smm zip->crc32flg = PRECODE_CRC32; 759231200Smm zip->precode_crc32 = 0; 760231200Smm r = make_header(a, data_offset, data_size, data_unpacksize, 761231200Smm 1, &(zip->coder)); 762231200Smm if (r < 0) 763231200Smm return (r); 764231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 765231200Smm if (r < 0) 766231200Smm return (r); 767231200Smm header_offset = data_offset + data_size; 768231200Smm header_size = zip->stream.total_out; 769231200Smm header_crc32 = zip->precode_crc32; 770231200Smm header_unpacksize = zip->stream.total_in; 771231200Smm 772231200Smm if (header_compression != _7Z_COPY) { 773231200Smm /* 774231200Smm * Encode the header in order to reduce the size 775231200Smm * of the archive. 776231200Smm */ 777231200Smm free(zip->coder.props); 778231200Smm zip->coder.codec = header_compression; 779231200Smm zip->coder.prop_size = zip->stream.prop_size; 780231200Smm zip->coder.props = zip->stream.props; 781231200Smm zip->stream.prop_size = 0; 782231200Smm zip->stream.props = NULL; 783231200Smm 784231200Smm r = _7z_compression_init_encoder(a, _7Z_COPY, 0); 785231200Smm if (r < 0) 786231200Smm return (r); 787231200Smm zip->crc32flg = ENCODED_CRC32; 788231200Smm zip->encoded_crc32 = 0; 789231200Smm 790231200Smm /* 791231200Smm * Make EncodedHeader. 792231200Smm */ 793231200Smm r = enc_uint64(a, kEncodedHeader); 794231200Smm if (r < 0) 795231200Smm return (r); 796231200Smm r = make_streamsInfo(a, header_offset, header_size, 797231200Smm header_unpacksize, 1, &(zip->coder), 0, 798231200Smm header_crc32); 799231200Smm if (r < 0) 800231200Smm return (r); 801231200Smm r = (int)compress_out(a, NULL, 0, ARCHIVE_Z_FINISH); 802231200Smm if (r < 0) 803231200Smm return (r); 804231200Smm header_offset = header_offset + header_size; 805231200Smm header_size = zip->stream.total_out; 806231200Smm header_crc32 = zip->encoded_crc32; 807231200Smm } 808231200Smm zip->crc32flg = 0; 809231200Smm } else { 810231200Smm header_offset = header_size = 0; 811231200Smm header_crc32 = 0; 812231200Smm } 813231200Smm 814231200Smm length = zip->temp_offset; 815231200Smm 816231200Smm /* 817231200Smm * Make the zip header on wbuff(write buffer). 818231200Smm */ 819231200Smm wb = zip->wbuff; 820231200Smm zip->wbuff_remaining = sizeof(zip->wbuff); 821231200Smm memcpy(&wb[0], "7z\xBC\xAF\x27\x1C", 6); 822231200Smm wb[6] = 0;/* Major version. */ 823231200Smm wb[7] = 3;/* Minor version. */ 824231200Smm archive_le64enc(&wb[12], header_offset);/* Next Header Offset */ 825231200Smm archive_le64enc(&wb[20], header_size);/* Next Header Size */ 826231200Smm archive_le32enc(&wb[28], header_crc32);/* Next Header CRC */ 827231200Smm archive_le32enc(&wb[8], crc32(0, &wb[12], 20));/* Start Header CRC */ 828231200Smm zip->wbuff_remaining -= 32; 829231200Smm 830231200Smm /* 831231200Smm * Read all file contents and an encoded header from the temporary 832231200Smm * file and write out it. 833231200Smm */ 834231200Smm r = copy_out(a, 0, length); 835231200Smm if (r != ARCHIVE_OK) 836231200Smm return (r); 837231200Smm r = flush_wbuff(a); 838231200Smm return (r); 839231200Smm} 840231200Smm 841231200Smm/* 842231200Smm * Encode 64 bits value into 7-Zip's encoded UINT64 value. 843231200Smm */ 844231200Smmstatic int 845231200Smmenc_uint64(struct archive_write *a, uint64_t val) 846231200Smm{ 847231200Smm unsigned mask = 0x80; 848231200Smm uint8_t numdata[9]; 849231200Smm int i; 850231200Smm 851231200Smm numdata[0] = 0; 852232153Smm for (i = 1; i < (int)sizeof(numdata); i++) { 853231200Smm if (val < mask) { 854231200Smm numdata[0] |= (uint8_t)val; 855231200Smm break; 856231200Smm } 857231200Smm numdata[i] = (uint8_t)val; 858231200Smm val >>= 8; 859231200Smm numdata[0] |= mask; 860231200Smm mask >>= 1; 861231200Smm } 862231200Smm return (compress_out(a, numdata, i, ARCHIVE_Z_RUN)); 863231200Smm} 864231200Smm 865231200Smmstatic int 866231200Smmmake_substreamsInfo(struct archive_write *a, struct coder *coders) 867231200Smm{ 868231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 869231200Smm struct file *file; 870231200Smm int r; 871231200Smm 872231200Smm /* 873231200Smm * Make SubStreamsInfo. 874231200Smm */ 875231200Smm r = enc_uint64(a, kSubStreamsInfo); 876231200Smm if (r < 0) 877231200Smm return (r); 878231200Smm 879231200Smm if (zip->total_number_nonempty_entry > 1 && coders->codec != _7Z_COPY) { 880231200Smm /* 881231200Smm * Make NumUnPackStream. 882231200Smm */ 883231200Smm r = enc_uint64(a, kNumUnPackStream); 884231200Smm if (r < 0) 885231200Smm return (r); 886231200Smm 887231200Smm /* Write numUnpackStreams */ 888231200Smm r = enc_uint64(a, zip->total_number_nonempty_entry); 889231200Smm if (r < 0) 890231200Smm return (r); 891231200Smm 892231200Smm /* 893231200Smm * Make kSize. 894231200Smm */ 895231200Smm r = enc_uint64(a, kSize); 896231200Smm if (r < 0) 897231200Smm return (r); 898231200Smm file = zip->file_list.first; 899231200Smm for (;file != NULL; file = file->next) { 900231200Smm if (file->next == NULL || 901231200Smm file->next->size == 0) 902231200Smm break; 903231200Smm r = enc_uint64(a, file->size); 904231200Smm if (r < 0) 905231200Smm return (r); 906231200Smm } 907231200Smm } 908231200Smm 909231200Smm /* 910231200Smm * Make CRC. 911231200Smm */ 912231200Smm r = enc_uint64(a, kCRC); 913231200Smm if (r < 0) 914231200Smm return (r); 915231200Smm 916231200Smm 917231200Smm /* All are defined */ 918231200Smm r = enc_uint64(a, 1); 919231200Smm if (r < 0) 920231200Smm return (r); 921231200Smm file = zip->file_list.first; 922231200Smm for (;file != NULL; file = file->next) { 923231200Smm uint8_t crc[4]; 924231200Smm if (file->size == 0) 925231200Smm break; 926231200Smm archive_le32enc(crc, file->crc32); 927231200Smm r = compress_out(a, crc, 4, ARCHIVE_Z_RUN); 928231200Smm if (r < 0) 929231200Smm return (r); 930231200Smm } 931231200Smm 932231200Smm /* Write End. */ 933231200Smm r = enc_uint64(a, kEnd); 934231200Smm if (r < 0) 935231200Smm return (r); 936231200Smm return (ARCHIVE_OK); 937231200Smm} 938231200Smm 939231200Smmstatic int 940231200Smmmake_streamsInfo(struct archive_write *a, uint64_t offset, uint64_t pack_size, 941231200Smm uint64_t unpack_size, int num_coder, struct coder *coders, int substrm, 942231200Smm uint32_t header_crc) 943231200Smm{ 944231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 945231200Smm uint8_t codec_buff[8]; 946231200Smm int numFolders, fi; 947231200Smm int codec_size; 948231200Smm int i, r; 949231200Smm 950231200Smm if (coders->codec == _7Z_COPY) 951231200Smm numFolders = zip->total_number_nonempty_entry; 952231200Smm else 953231200Smm numFolders = 1; 954231200Smm 955231200Smm /* 956231200Smm * Make PackInfo. 957231200Smm */ 958231200Smm r = enc_uint64(a, kPackInfo); 959231200Smm if (r < 0) 960231200Smm return (r); 961231200Smm 962231200Smm /* Write PackPos. */ 963231200Smm r = enc_uint64(a, offset); 964231200Smm if (r < 0) 965231200Smm return (r); 966231200Smm 967231200Smm /* Write NumPackStreams. */ 968231200Smm r = enc_uint64(a, numFolders); 969231200Smm if (r < 0) 970231200Smm return (r); 971231200Smm 972231200Smm /* Make Size. */ 973231200Smm r = enc_uint64(a, kSize); 974231200Smm if (r < 0) 975231200Smm return (r); 976231200Smm 977231200Smm if (numFolders > 1) { 978231200Smm struct file *file = zip->file_list.first; 979231200Smm for (;file != NULL; file = file->next) { 980231200Smm if (file->size == 0) 981231200Smm break; 982231200Smm r = enc_uint64(a, file->size); 983231200Smm if (r < 0) 984231200Smm return (r); 985231200Smm } 986231200Smm } else { 987231200Smm /* Write size. */ 988231200Smm r = enc_uint64(a, pack_size); 989231200Smm if (r < 0) 990231200Smm return (r); 991231200Smm } 992231200Smm 993231200Smm r = enc_uint64(a, kEnd); 994231200Smm if (r < 0) 995231200Smm return (r); 996231200Smm 997231200Smm /* 998231200Smm * Make UnPackInfo. 999231200Smm */ 1000231200Smm r = enc_uint64(a, kUnPackInfo); 1001231200Smm if (r < 0) 1002231200Smm return (r); 1003231200Smm 1004231200Smm /* 1005231200Smm * Make Folder. 1006231200Smm */ 1007231200Smm r = enc_uint64(a, kFolder); 1008231200Smm if (r < 0) 1009231200Smm return (r); 1010231200Smm 1011231200Smm /* Write NumFolders. */ 1012231200Smm r = enc_uint64(a, numFolders); 1013231200Smm if (r < 0) 1014231200Smm return (r); 1015231200Smm 1016231200Smm /* Write External. */ 1017231200Smm r = enc_uint64(a, 0); 1018231200Smm if (r < 0) 1019231200Smm return (r); 1020231200Smm 1021231200Smm for (fi = 0; fi < numFolders; fi++) { 1022231200Smm /* Write NumCoders. */ 1023231200Smm r = enc_uint64(a, num_coder); 1024231200Smm if (r < 0) 1025231200Smm return (r); 1026231200Smm 1027231200Smm for (i = 0; i < num_coder; i++) { 1028231200Smm unsigned codec_id = coders[i].codec; 1029231200Smm 1030231200Smm /* Write Codec flag. */ 1031231200Smm archive_be64enc(codec_buff, codec_id); 1032231200Smm for (codec_size = 8; codec_size > 0; codec_size--) { 1033231200Smm if (codec_buff[8 - codec_size]) 1034231200Smm break; 1035231200Smm } 1036231200Smm if (codec_size == 0) 1037231200Smm codec_size = 1; 1038231200Smm if (coders[i].prop_size) 1039231200Smm r = enc_uint64(a, codec_size | 0x20); 1040231200Smm else 1041231200Smm r = enc_uint64(a, codec_size); 1042231200Smm if (r < 0) 1043231200Smm return (r); 1044231200Smm 1045231200Smm /* Write Codec ID. */ 1046231200Smm codec_size &= 0x0f; 1047231200Smm r = compress_out(a, &codec_buff[8-codec_size], 1048231200Smm codec_size, ARCHIVE_Z_RUN); 1049231200Smm if (r < 0) 1050231200Smm return (r); 1051231200Smm 1052231200Smm if (coders[i].prop_size) { 1053231200Smm /* Write Codec property size. */ 1054231200Smm r = enc_uint64(a, coders[i].prop_size); 1055231200Smm if (r < 0) 1056231200Smm return (r); 1057231200Smm 1058231200Smm /* Write Codec properties. */ 1059231200Smm r = compress_out(a, coders[i].props, 1060231200Smm coders[i].prop_size, ARCHIVE_Z_RUN); 1061231200Smm if (r < 0) 1062231200Smm return (r); 1063231200Smm } 1064231200Smm } 1065231200Smm } 1066231200Smm 1067231200Smm /* 1068231200Smm * Make CodersUnPackSize. 1069231200Smm */ 1070231200Smm r = enc_uint64(a, kCodersUnPackSize); 1071231200Smm if (r < 0) 1072231200Smm return (r); 1073231200Smm 1074231200Smm if (numFolders > 1) { 1075231200Smm struct file *file = zip->file_list.first; 1076231200Smm for (;file != NULL; file = file->next) { 1077231200Smm if (file->size == 0) 1078231200Smm break; 1079231200Smm r = enc_uint64(a, file->size); 1080231200Smm if (r < 0) 1081231200Smm return (r); 1082231200Smm } 1083231200Smm 1084231200Smm } else { 1085231200Smm /* Write UnPackSize. */ 1086231200Smm r = enc_uint64(a, unpack_size); 1087231200Smm if (r < 0) 1088231200Smm return (r); 1089231200Smm } 1090231200Smm 1091231200Smm if (!substrm) { 1092231200Smm uint8_t crc[4]; 1093231200Smm /* 1094231200Smm * Make CRC. 1095231200Smm */ 1096231200Smm r = enc_uint64(a, kCRC); 1097231200Smm if (r < 0) 1098231200Smm return (r); 1099231200Smm 1100231200Smm /* All are defined */ 1101231200Smm r = enc_uint64(a, 1); 1102231200Smm if (r < 0) 1103231200Smm return (r); 1104231200Smm archive_le32enc(crc, header_crc); 1105231200Smm r = compress_out(a, crc, 4, ARCHIVE_Z_RUN); 1106231200Smm if (r < 0) 1107231200Smm return (r); 1108231200Smm } 1109231200Smm 1110231200Smm /* Write End. */ 1111231200Smm r = enc_uint64(a, kEnd); 1112231200Smm if (r < 0) 1113231200Smm return (r); 1114231200Smm 1115231200Smm if (substrm) { 1116231200Smm /* 1117231200Smm * Make SubStreamsInfo. 1118231200Smm */ 1119231200Smm r = make_substreamsInfo(a, coders); 1120231200Smm if (r < 0) 1121231200Smm return (r); 1122231200Smm } 1123231200Smm 1124231200Smm 1125231200Smm /* Write End. */ 1126231200Smm r = enc_uint64(a, kEnd); 1127231200Smm if (r < 0) 1128231200Smm return (r); 1129231200Smm 1130231200Smm return (ARCHIVE_OK); 1131231200Smm} 1132231200Smm 1133231200Smm 1134231200Smm#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000) 1135231200Smmstatic uint64_t 1136232153SmmutcToFiletime(time_t t, long ns) 1137231200Smm{ 1138231200Smm uint64_t fileTime; 1139231200Smm 1140232153Smm fileTime = t; 1141231200Smm fileTime *= 10000000; 1142231200Smm fileTime += ns / 100; 1143231200Smm fileTime += EPOC_TIME; 1144231200Smm return (fileTime); 1145231200Smm} 1146231200Smm 1147231200Smmstatic int 1148231200Smmmake_time(struct archive_write *a, uint8_t type, unsigned flg, int ti) 1149231200Smm{ 1150231200Smm uint8_t filetime[8]; 1151231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1152231200Smm struct file *file; 1153231200Smm int r; 1154231200Smm uint8_t mask, byte; 1155231200Smm 1156231200Smm /* 1157231200Smm * Make Time Bools. 1158231200Smm */ 1159231200Smm if (zip->total_number_time_defined[ti] == zip->total_number_entry) { 1160231200Smm /* Write Time Type. */ 1161231200Smm r = enc_uint64(a, type); 1162231200Smm if (r < 0) 1163231200Smm return (r); 1164231200Smm /* Write EmptyStream Size. */ 1165231200Smm r = enc_uint64(a, 2 + zip->total_number_entry * 8); 1166231200Smm if (r < 0) 1167231200Smm return (r); 1168231200Smm /* All are defined. */ 1169231200Smm r = enc_uint64(a, 1); 1170231200Smm if (r < 0) 1171231200Smm return (r); 1172231200Smm } else { 1173231200Smm if (zip->total_number_time_defined[ti] == 0) 1174231200Smm return (ARCHIVE_OK); 1175231200Smm 1176231200Smm /* Write Time Type. */ 1177231200Smm r = enc_uint64(a, type); 1178231200Smm if (r < 0) 1179231200Smm return (r); 1180231200Smm /* Write EmptyStream Size. */ 1181231200Smm r = enc_uint64(a, 2 + ((zip->total_number_entry + 7) >> 3) 1182231200Smm + zip->total_number_time_defined[ti] * 8); 1183231200Smm if (r < 0) 1184231200Smm return (r); 1185231200Smm 1186231200Smm /* All are not defined. */ 1187231200Smm r = enc_uint64(a, 0); 1188231200Smm if (r < 0) 1189231200Smm return (r); 1190231200Smm 1191231200Smm byte = 0; 1192231200Smm mask = 0x80; 1193231200Smm file = zip->file_list.first; 1194231200Smm for (;file != NULL; file = file->next) { 1195231200Smm if (file->flg & flg) 1196231200Smm byte |= mask; 1197231200Smm mask >>= 1; 1198231200Smm if (mask == 0) { 1199231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1200231200Smm if (r < 0) 1201231200Smm return (r); 1202231200Smm mask = 0x80; 1203231200Smm byte = 0; 1204231200Smm } 1205231200Smm } 1206231200Smm if (mask != 0x80) { 1207231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1208231200Smm if (r < 0) 1209231200Smm return (r); 1210231200Smm } 1211231200Smm } 1212231200Smm 1213231200Smm /* External. */ 1214231200Smm r = enc_uint64(a, 0); 1215231200Smm if (r < 0) 1216231200Smm return (r); 1217231200Smm 1218231200Smm 1219231200Smm /* 1220231200Smm * Make Times. 1221231200Smm */ 1222231200Smm file = zip->file_list.first; 1223231200Smm for (;file != NULL; file = file->next) { 1224231200Smm if ((file->flg & flg) == 0) 1225231200Smm continue; 1226231200Smm archive_le64enc(filetime, utcToFiletime(file->times[ti].time, 1227231200Smm file->times[ti].time_ns)); 1228231200Smm r = compress_out(a, filetime, 8, ARCHIVE_Z_RUN); 1229231200Smm if (r < 0) 1230231200Smm return (r); 1231231200Smm } 1232231200Smm 1233231200Smm return (ARCHIVE_OK); 1234231200Smm} 1235231200Smm 1236231200Smmstatic int 1237231200Smmmake_header(struct archive_write *a, uint64_t offset, uint64_t pack_size, 1238231200Smm uint64_t unpack_size, int codernum, struct coder *coders) 1239231200Smm{ 1240231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1241231200Smm struct file *file; 1242231200Smm int r; 1243231200Smm uint8_t mask, byte; 1244231200Smm 1245231200Smm /* 1246231200Smm * Make FilesInfo. 1247231200Smm */ 1248231200Smm r = enc_uint64(a, kHeader); 1249231200Smm if (r < 0) 1250231200Smm return (r); 1251231200Smm 1252231200Smm /* 1253231200Smm * If there are empty files only, do not write MainStreamInfo. 1254231200Smm */ 1255231200Smm if (zip->total_number_nonempty_entry) { 1256231200Smm /* 1257231200Smm * Make MainStreamInfo. 1258231200Smm */ 1259231200Smm r = enc_uint64(a, kMainStreamsInfo); 1260231200Smm if (r < 0) 1261231200Smm return (r); 1262231200Smm r = make_streamsInfo(a, offset, pack_size, unpack_size, 1263231200Smm codernum, coders, 1, 0); 1264231200Smm if (r < 0) 1265231200Smm return (r); 1266231200Smm } 1267231200Smm 1268231200Smm /* 1269231200Smm * Make FilesInfo. 1270231200Smm */ 1271231200Smm r = enc_uint64(a, kFilesInfo); 1272231200Smm if (r < 0) 1273231200Smm return (r); 1274231200Smm 1275231200Smm /* Write numFiles. */ 1276231200Smm r = enc_uint64(a, zip->total_number_entry); 1277231200Smm if (r < 0) 1278231200Smm return (r); 1279231200Smm 1280231200Smm if (zip->total_number_empty_entry > 0) { 1281231200Smm /* Make EmptyStream. */ 1282231200Smm r = enc_uint64(a, kEmptyStream); 1283231200Smm if (r < 0) 1284231200Smm return (r); 1285231200Smm 1286231200Smm /* Write EmptyStream Size. */ 1287231200Smm r = enc_uint64(a, (zip->total_number_entry+7)>>3); 1288231200Smm if (r < 0) 1289231200Smm return (r); 1290231200Smm 1291231200Smm byte = 0; 1292231200Smm mask = 0x80; 1293231200Smm file = zip->file_list.first; 1294231200Smm for (;file != NULL; file = file->next) { 1295231200Smm if (file->size == 0) 1296231200Smm byte |= mask; 1297231200Smm mask >>= 1; 1298231200Smm if (mask == 0) { 1299231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1300231200Smm if (r < 0) 1301231200Smm return (r); 1302231200Smm mask = 0x80; 1303231200Smm byte = 0; 1304231200Smm } 1305231200Smm } 1306231200Smm if (mask != 0x80) { 1307231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1308231200Smm if (r < 0) 1309231200Smm return (r); 1310231200Smm } 1311231200Smm } 1312231200Smm 1313231200Smm if (zip->total_number_empty_entry > zip->total_number_dir_entry) { 1314231200Smm /* Make EmptyFile. */ 1315231200Smm r = enc_uint64(a, kEmptyFile); 1316231200Smm if (r < 0) 1317231200Smm return (r); 1318231200Smm 1319231200Smm /* Write EmptyFile Size. */ 1320231200Smm r = enc_uint64(a, (zip->total_number_empty_entry + 7) >> 3); 1321231200Smm if (r < 0) 1322231200Smm return (r); 1323231200Smm 1324231200Smm byte = 0; 1325231200Smm mask = 0x80; 1326231200Smm file = zip->file_list.first; 1327231200Smm for (;file != NULL; file = file->next) { 1328231200Smm if (file->size) 1329231200Smm continue; 1330231200Smm if (!file->dir) 1331231200Smm byte |= mask; 1332231200Smm mask >>= 1; 1333231200Smm if (mask == 0) { 1334231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1335231200Smm if (r < 0) 1336231200Smm return (r); 1337231200Smm mask = 0x80; 1338231200Smm byte = 0; 1339231200Smm } 1340231200Smm } 1341231200Smm if (mask != 0x80) { 1342231200Smm r = compress_out(a, &byte, 1, ARCHIVE_Z_RUN); 1343231200Smm if (r < 0) 1344231200Smm return (r); 1345231200Smm } 1346231200Smm } 1347231200Smm 1348231200Smm /* Make Name. */ 1349231200Smm r = enc_uint64(a, kName); 1350231200Smm if (r < 0) 1351231200Smm return (r); 1352231200Smm 1353231200Smm /* Write Nume size. */ 1354231200Smm r = enc_uint64(a, zip->total_bytes_entry_name+1); 1355231200Smm if (r < 0) 1356231200Smm return (r); 1357231200Smm 1358231200Smm /* Write dmy byte. */ 1359231200Smm r = enc_uint64(a, 0); 1360231200Smm if (r < 0) 1361231200Smm return (r); 1362231200Smm 1363231200Smm file = zip->file_list.first; 1364231200Smm for (;file != NULL; file = file->next) { 1365231200Smm r = compress_out(a, file->utf16name, file->name_len+2, 1366231200Smm ARCHIVE_Z_RUN); 1367231200Smm if (r < 0) 1368231200Smm return (r); 1369231200Smm } 1370231200Smm 1371231200Smm /* Make MTime. */ 1372231200Smm r = make_time(a, kMTime, MTIME_IS_SET, MTIME); 1373231200Smm if (r < 0) 1374231200Smm return (r); 1375231200Smm 1376231200Smm /* Make CTime. */ 1377231200Smm r = make_time(a, kCTime, CTIME_IS_SET, CTIME); 1378231200Smm if (r < 0) 1379231200Smm return (r); 1380231200Smm 1381231200Smm /* Make ATime. */ 1382231200Smm r = make_time(a, kATime, ATIME_IS_SET, ATIME); 1383231200Smm if (r < 0) 1384231200Smm return (r); 1385231200Smm 1386231200Smm /* Make Attributes. */ 1387231200Smm r = enc_uint64(a, kAttributes); 1388231200Smm if (r < 0) 1389231200Smm return (r); 1390231200Smm 1391231200Smm /* Write Attributes size. */ 1392231200Smm r = enc_uint64(a, 2 + zip->total_number_entry * 4); 1393231200Smm if (r < 0) 1394231200Smm return (r); 1395231200Smm 1396231200Smm /* Write "All Are Defined". */ 1397231200Smm r = enc_uint64(a, 1); 1398231200Smm if (r < 0) 1399231200Smm return (r); 1400231200Smm 1401231200Smm /* Write dmy byte. */ 1402231200Smm r = enc_uint64(a, 0); 1403231200Smm if (r < 0) 1404231200Smm return (r); 1405231200Smm 1406231200Smm file = zip->file_list.first; 1407231200Smm for (;file != NULL; file = file->next) { 1408231200Smm /* 1409231200Smm * High 16bits is unix mode. 1410231200Smm * Low 16bits is Windows attributes. 1411231200Smm */ 1412231200Smm uint32_t encattr, attr; 1413231200Smm if (file->dir) 1414231200Smm attr = 0x8010; 1415231200Smm else 1416231200Smm attr = 0x8020; 1417231200Smm if ((file->mode & 0222) == 0) 1418231200Smm attr |= 1;/* Read Only. */ 1419231200Smm attr |= ((uint32_t)file->mode) << 16; 1420231200Smm archive_le32enc(&encattr, attr); 1421231200Smm r = compress_out(a, &encattr, 4, ARCHIVE_Z_RUN); 1422231200Smm if (r < 0) 1423231200Smm return (r); 1424231200Smm } 1425231200Smm 1426231200Smm /* Write End. */ 1427231200Smm r = enc_uint64(a, kEnd); 1428231200Smm if (r < 0) 1429231200Smm return (r); 1430231200Smm 1431231200Smm /* Write End. */ 1432231200Smm r = enc_uint64(a, kEnd); 1433231200Smm if (r < 0) 1434231200Smm return (r); 1435231200Smm 1436231200Smm return (ARCHIVE_OK); 1437231200Smm} 1438231200Smm 1439231200Smm 1440231200Smmstatic int 1441231200Smm_7z_free(struct archive_write *a) 1442231200Smm{ 1443231200Smm struct _7zip *zip = (struct _7zip *)a->format_data; 1444231200Smm 1445231200Smm file_free_register(zip); 1446231200Smm compression_end(&(a->archive), &(zip->stream)); 1447231200Smm free(zip->coder.props); 1448231200Smm free(zip); 1449231200Smm 1450231200Smm return (ARCHIVE_OK); 1451231200Smm} 1452231200Smm 1453231200Smmstatic int 1454231200Smmfile_cmp_node(const struct archive_rb_node *n1, 1455231200Smm const struct archive_rb_node *n2) 1456231200Smm{ 1457232153Smm const struct file *f1 = (const struct file *)n1; 1458232153Smm const struct file *f2 = (const struct file *)n2; 1459231200Smm 1460231200Smm if (f1->name_len == f2->name_len) 1461231200Smm return (memcmp(f1->utf16name, f2->utf16name, f1->name_len)); 1462231200Smm return (f1->name_len > f2->name_len)?1:-1; 1463231200Smm} 1464231200Smm 1465231200Smmstatic int 1466231200Smmfile_cmp_key(const struct archive_rb_node *n, const void *key) 1467231200Smm{ 1468232153Smm const struct file *f = (const struct file *)n; 1469231200Smm 1470231200Smm return (f->name_len - *(const char *)key); 1471231200Smm} 1472231200Smm 1473231200Smmstatic int 1474231200Smmfile_new(struct archive_write *a, struct archive_entry *entry, 1475231200Smm struct file **newfile) 1476231200Smm{ 1477231200Smm struct _7zip *zip; 1478231200Smm struct file *file; 1479231200Smm const char *u16; 1480231200Smm size_t u16len; 1481231200Smm int ret = ARCHIVE_OK; 1482231200Smm 1483231200Smm zip = (struct _7zip *)a->format_data; 1484231200Smm *newfile = NULL; 1485231200Smm 1486231200Smm file = calloc(1, sizeof(*file)); 1487231200Smm if (file == NULL) { 1488231200Smm archive_set_error(&a->archive, ENOMEM, 1489231200Smm "Can't allocate memory"); 1490231200Smm return (ARCHIVE_FATAL); 1491231200Smm } 1492231200Smm 1493231200Smm if (0 > archive_entry_pathname_l(entry, &u16, &u16len, zip->sconv)) { 1494231200Smm if (errno == ENOMEM) { 1495231200Smm archive_set_error(&a->archive, ENOMEM, 1496231200Smm "Can't allocate memory for UTF-16LE"); 1497231200Smm return (ARCHIVE_FATAL); 1498231200Smm } 1499231200Smm archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1500231200Smm "A filename cannot be converted to UTF-16LE;" 1501231200Smm "You should disable making Joliet extension"); 1502231200Smm ret = ARCHIVE_WARN; 1503231200Smm } 1504231200Smm file->utf16name = malloc(u16len + 2); 1505231200Smm if (file->utf16name == NULL) { 1506231200Smm archive_set_error(&a->archive, ENOMEM, 1507231200Smm "Can't allocate memory for Name"); 1508231200Smm return (ARCHIVE_FATAL); 1509231200Smm } 1510231200Smm memcpy(file->utf16name, u16, u16len); 1511231200Smm file->utf16name[u16len+0] = 0; 1512231200Smm file->utf16name[u16len+1] = 0; 1513231200Smm file->name_len = u16len; 1514231200Smm file->mode = archive_entry_mode(entry); 1515231200Smm if (archive_entry_filetype(entry) == AE_IFREG) 1516231200Smm file->size = archive_entry_size(entry); 1517231200Smm else 1518231200Smm archive_entry_set_size(entry, 0); 1519231200Smm if (archive_entry_filetype(entry) == AE_IFDIR) 1520231200Smm file->dir = 1; 1521231200Smm else if (archive_entry_filetype(entry) == AE_IFLNK) 1522231200Smm file->size = strlen(archive_entry_symlink(entry)); 1523231200Smm if (archive_entry_mtime_is_set(entry)) { 1524231200Smm file->flg |= MTIME_IS_SET; 1525231200Smm file->times[MTIME].time = archive_entry_mtime(entry); 1526231200Smm file->times[MTIME].time_ns = archive_entry_mtime_nsec(entry); 1527231200Smm } 1528231200Smm if (archive_entry_atime_is_set(entry)) { 1529231200Smm file->flg |= ATIME_IS_SET; 1530231200Smm file->times[ATIME].time = archive_entry_atime(entry); 1531231200Smm file->times[ATIME].time_ns = archive_entry_atime_nsec(entry); 1532231200Smm } 1533231200Smm if (archive_entry_ctime_is_set(entry)) { 1534231200Smm file->flg |= CTIME_IS_SET; 1535231200Smm file->times[CTIME].time = archive_entry_ctime(entry); 1536231200Smm file->times[CTIME].time_ns = archive_entry_ctime_nsec(entry); 1537231200Smm } 1538231200Smm 1539231200Smm *newfile = file; 1540231200Smm return (ret); 1541231200Smm} 1542231200Smm 1543231200Smmstatic void 1544231200Smmfile_free(struct file *file) 1545231200Smm{ 1546231200Smm free(file->utf16name); 1547231200Smm free(file); 1548231200Smm} 1549231200Smm 1550231200Smmstatic void 1551231200Smmfile_register(struct _7zip *zip, struct file *file) 1552231200Smm{ 1553231200Smm file->next = NULL; 1554231200Smm *zip->file_list.last = file; 1555231200Smm zip->file_list.last = &(file->next); 1556231200Smm} 1557231200Smm 1558231200Smmstatic void 1559231200Smmfile_init_register(struct _7zip *zip) 1560231200Smm{ 1561231200Smm zip->file_list.first = NULL; 1562231200Smm zip->file_list.last = &(zip->file_list.first); 1563231200Smm} 1564231200Smm 1565231200Smmstatic void 1566231200Smmfile_free_register(struct _7zip *zip) 1567231200Smm{ 1568231200Smm struct file *file, *file_next; 1569231200Smm 1570231200Smm file = zip->file_list.first; 1571231200Smm while (file != NULL) { 1572231200Smm file_next = file->next; 1573231200Smm file_free(file); 1574231200Smm file = file_next; 1575231200Smm } 1576231200Smm} 1577231200Smm 1578231200Smmstatic void 1579231200Smmfile_register_empty(struct _7zip *zip, struct file *file) 1580231200Smm{ 1581231200Smm file->next = NULL; 1582231200Smm *zip->empty_list.last = file; 1583231200Smm zip->empty_list.last = &(file->next); 1584231200Smm} 1585231200Smm 1586231200Smmstatic void 1587231200Smmfile_init_register_empty(struct _7zip *zip) 1588231200Smm{ 1589231200Smm zip->empty_list.first = NULL; 1590231200Smm zip->empty_list.last = &(zip->empty_list.first); 1591231200Smm} 1592231200Smm 1593232153Smm#if !defined(HAVE_ZLIB_H) || !defined(HAVE_BZLIB_H) ||\ 1594232153Smm !defined(BZ_CONFIG_ERROR) || !defined(HAVE_LZMA_H) 1595231200Smmstatic int 1596231200Smmcompression_unsupported_encoder(struct archive *a, 1597231200Smm struct la_zstream *lastrm, const char *name) 1598231200Smm{ 1599231200Smm 1600231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1601231200Smm "%s compression not supported on this platform", name); 1602231200Smm lastrm->valid = 0; 1603231200Smm lastrm->real_stream = NULL; 1604231200Smm return (ARCHIVE_FAILED); 1605231200Smm} 1606231200Smm#endif 1607231200Smm 1608231200Smm/* 1609231200Smm * _7_COPY compressor. 1610231200Smm */ 1611231200Smmstatic int 1612231200Smmcompression_init_encoder_copy(struct archive *a, struct la_zstream *lastrm) 1613231200Smm{ 1614231200Smm 1615231200Smm if (lastrm->valid) 1616231200Smm compression_end(a, lastrm); 1617231200Smm lastrm->valid = 1; 1618231200Smm lastrm->code = compression_code_copy; 1619231200Smm lastrm->end = compression_end_copy; 1620231200Smm return (ARCHIVE_OK); 1621231200Smm} 1622231200Smm 1623231200Smmstatic int 1624231200Smmcompression_code_copy(struct archive *a, 1625231200Smm struct la_zstream *lastrm, enum la_zaction action) 1626231200Smm{ 1627231200Smm size_t bytes; 1628231200Smm 1629231200Smm (void)a; /* UNUSED */ 1630231200Smm if (lastrm->avail_out > lastrm->avail_in) 1631231200Smm bytes = lastrm->avail_in; 1632231200Smm else 1633231200Smm bytes = lastrm->avail_out; 1634231200Smm if (bytes) { 1635231200Smm memcpy(lastrm->next_out, lastrm->next_in, bytes); 1636231200Smm lastrm->next_in += bytes; 1637231200Smm lastrm->avail_in -= bytes; 1638231200Smm lastrm->total_in += bytes; 1639231200Smm lastrm->next_out += bytes; 1640231200Smm lastrm->avail_out -= bytes; 1641231200Smm lastrm->total_out += bytes; 1642231200Smm } 1643231200Smm if (action == ARCHIVE_Z_FINISH && lastrm->avail_in == 0) 1644231200Smm return (ARCHIVE_EOF); 1645231200Smm return (ARCHIVE_OK); 1646231200Smm} 1647231200Smm 1648231200Smmstatic int 1649231200Smmcompression_end_copy(struct archive *a, struct la_zstream *lastrm) 1650231200Smm{ 1651231200Smm (void)a; /* UNUSED */ 1652231200Smm lastrm->valid = 0; 1653231200Smm return (ARCHIVE_OK); 1654231200Smm} 1655231200Smm 1656231200Smm/* 1657231200Smm * _7_DEFLATE compressor. 1658231200Smm */ 1659231200Smm#ifdef HAVE_ZLIB_H 1660231200Smmstatic int 1661231200Smmcompression_init_encoder_deflate(struct archive *a, 1662231200Smm struct la_zstream *lastrm, int level, int withheader) 1663231200Smm{ 1664231200Smm z_stream *strm; 1665231200Smm 1666231200Smm if (lastrm->valid) 1667231200Smm compression_end(a, lastrm); 1668231200Smm strm = calloc(1, sizeof(*strm)); 1669231200Smm if (strm == NULL) { 1670231200Smm archive_set_error(a, ENOMEM, 1671231200Smm "Can't allocate memory for gzip stream"); 1672231200Smm return (ARCHIVE_FATAL); 1673231200Smm } 1674231200Smm /* zlib.h is not const-correct, so we need this one bit 1675231200Smm * of ugly hackery to convert a const * pointer to 1676231200Smm * a non-const pointer. */ 1677231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1678231200Smm strm->avail_in = lastrm->avail_in; 1679231200Smm strm->total_in = lastrm->total_in; 1680231200Smm strm->next_out = lastrm->next_out; 1681231200Smm strm->avail_out = lastrm->avail_out; 1682231200Smm strm->total_out = lastrm->total_out; 1683231200Smm if (deflateInit2(strm, level, Z_DEFLATED, 1684231200Smm (withheader)?15:-15, 1685231200Smm 8, Z_DEFAULT_STRATEGY) != Z_OK) { 1686231200Smm free(strm); 1687231200Smm lastrm->real_stream = NULL; 1688231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1689231200Smm "Internal error initializing compression library"); 1690231200Smm return (ARCHIVE_FATAL); 1691231200Smm } 1692231200Smm lastrm->real_stream = strm; 1693231200Smm lastrm->valid = 1; 1694231200Smm lastrm->code = compression_code_deflate; 1695231200Smm lastrm->end = compression_end_deflate; 1696231200Smm return (ARCHIVE_OK); 1697231200Smm} 1698231200Smm 1699231200Smmstatic int 1700231200Smmcompression_code_deflate(struct archive *a, 1701231200Smm struct la_zstream *lastrm, enum la_zaction action) 1702231200Smm{ 1703231200Smm z_stream *strm; 1704231200Smm int r; 1705231200Smm 1706231200Smm strm = (z_stream *)lastrm->real_stream; 1707231200Smm /* zlib.h is not const-correct, so we need this one bit 1708231200Smm * of ugly hackery to convert a const * pointer to 1709231200Smm * a non-const pointer. */ 1710231200Smm strm->next_in = (Bytef *)(uintptr_t)(const void *)lastrm->next_in; 1711231200Smm strm->avail_in = lastrm->avail_in; 1712231200Smm strm->total_in = lastrm->total_in; 1713231200Smm strm->next_out = lastrm->next_out; 1714231200Smm strm->avail_out = lastrm->avail_out; 1715231200Smm strm->total_out = lastrm->total_out; 1716231200Smm r = deflate(strm, 1717231200Smm (action == ARCHIVE_Z_FINISH)? Z_FINISH: Z_NO_FLUSH); 1718231200Smm lastrm->next_in = strm->next_in; 1719231200Smm lastrm->avail_in = strm->avail_in; 1720231200Smm lastrm->total_in = strm->total_in; 1721231200Smm lastrm->next_out = strm->next_out; 1722231200Smm lastrm->avail_out = strm->avail_out; 1723231200Smm lastrm->total_out = strm->total_out; 1724231200Smm switch (r) { 1725231200Smm case Z_OK: 1726231200Smm return (ARCHIVE_OK); 1727231200Smm case Z_STREAM_END: 1728231200Smm return (ARCHIVE_EOF); 1729231200Smm default: 1730231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1731231200Smm "GZip compression failed:" 1732231200Smm " deflate() call returned status %d", r); 1733231200Smm return (ARCHIVE_FATAL); 1734231200Smm } 1735231200Smm} 1736231200Smm 1737231200Smmstatic int 1738231200Smmcompression_end_deflate(struct archive *a, struct la_zstream *lastrm) 1739231200Smm{ 1740231200Smm z_stream *strm; 1741231200Smm int r; 1742231200Smm 1743231200Smm strm = (z_stream *)lastrm->real_stream; 1744231200Smm r = deflateEnd(strm); 1745231200Smm free(strm); 1746231200Smm lastrm->real_stream = NULL; 1747231200Smm lastrm->valid = 0; 1748231200Smm if (r != Z_OK) { 1749231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1750231200Smm "Failed to clean up compressor"); 1751231200Smm return (ARCHIVE_FATAL); 1752231200Smm } 1753231200Smm return (ARCHIVE_OK); 1754231200Smm} 1755231200Smm#else 1756231200Smmstatic int 1757231200Smmcompression_init_encoder_deflate(struct archive *a, 1758231200Smm struct la_zstream *lastrm, int level, int withheader) 1759231200Smm{ 1760231200Smm 1761231200Smm (void) level; /* UNUSED */ 1762231200Smm (void) withheader; /* UNUSED */ 1763231200Smm if (lastrm->valid) 1764231200Smm compression_end(a, lastrm); 1765231200Smm return (compression_unsupported_encoder(a, lastrm, "deflate")); 1766231200Smm} 1767231200Smm#endif 1768231200Smm 1769231200Smm/* 1770231200Smm * _7_BZIP2 compressor. 1771231200Smm */ 1772231200Smm#if defined(HAVE_BZLIB_H) && defined(BZ_CONFIG_ERROR) 1773231200Smmstatic int 1774231200Smmcompression_init_encoder_bzip2(struct archive *a, 1775231200Smm struct la_zstream *lastrm, int level) 1776231200Smm{ 1777231200Smm bz_stream *strm; 1778231200Smm 1779231200Smm if (lastrm->valid) 1780231200Smm compression_end(a, lastrm); 1781231200Smm strm = calloc(1, sizeof(*strm)); 1782231200Smm if (strm == NULL) { 1783231200Smm archive_set_error(a, ENOMEM, 1784231200Smm "Can't allocate memory for bzip2 stream"); 1785231200Smm return (ARCHIVE_FATAL); 1786231200Smm } 1787231200Smm /* bzlib.h is not const-correct, so we need this one bit 1788231200Smm * of ugly hackery to convert a const * pointer to 1789231200Smm * a non-const pointer. */ 1790231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1791231200Smm strm->avail_in = lastrm->avail_in; 1792231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1793231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1794231200Smm strm->next_out = (char *)lastrm->next_out; 1795231200Smm strm->avail_out = lastrm->avail_out; 1796231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1797231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1798231200Smm if (BZ2_bzCompressInit(strm, level, 0, 30) != BZ_OK) { 1799231200Smm free(strm); 1800231200Smm lastrm->real_stream = NULL; 1801231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1802231200Smm "Internal error initializing compression library"); 1803231200Smm return (ARCHIVE_FATAL); 1804231200Smm } 1805231200Smm lastrm->real_stream = strm; 1806231200Smm lastrm->valid = 1; 1807231200Smm lastrm->code = compression_code_bzip2; 1808231200Smm lastrm->end = compression_end_bzip2; 1809231200Smm return (ARCHIVE_OK); 1810231200Smm} 1811231200Smm 1812231200Smmstatic int 1813231200Smmcompression_code_bzip2(struct archive *a, 1814231200Smm struct la_zstream *lastrm, enum la_zaction action) 1815231200Smm{ 1816231200Smm bz_stream *strm; 1817231200Smm int r; 1818231200Smm 1819231200Smm strm = (bz_stream *)lastrm->real_stream; 1820231200Smm /* bzlib.h is not const-correct, so we need this one bit 1821231200Smm * of ugly hackery to convert a const * pointer to 1822231200Smm * a non-const pointer. */ 1823231200Smm strm->next_in = (char *)(uintptr_t)(const void *)lastrm->next_in; 1824231200Smm strm->avail_in = lastrm->avail_in; 1825231200Smm strm->total_in_lo32 = (uint32_t)(lastrm->total_in & 0xffffffff); 1826231200Smm strm->total_in_hi32 = (uint32_t)(lastrm->total_in >> 32); 1827231200Smm strm->next_out = (char *)lastrm->next_out; 1828231200Smm strm->avail_out = lastrm->avail_out; 1829231200Smm strm->total_out_lo32 = (uint32_t)(lastrm->total_out & 0xffffffff); 1830231200Smm strm->total_out_hi32 = (uint32_t)(lastrm->total_out >> 32); 1831231200Smm r = BZ2_bzCompress(strm, 1832231200Smm (action == ARCHIVE_Z_FINISH)? BZ_FINISH: BZ_RUN); 1833231200Smm lastrm->next_in = (const unsigned char *)strm->next_in; 1834231200Smm lastrm->avail_in = strm->avail_in; 1835231200Smm lastrm->total_in = 1836231200Smm (((uint64_t)(uint32_t)strm->total_in_hi32) << 32) 1837231200Smm + (uint64_t)(uint32_t)strm->total_in_lo32; 1838231200Smm lastrm->next_out = (unsigned char *)strm->next_out; 1839231200Smm lastrm->avail_out = strm->avail_out; 1840231200Smm lastrm->total_out = 1841231200Smm (((uint64_t)(uint32_t)strm->total_out_hi32) << 32) 1842231200Smm + (uint64_t)(uint32_t)strm->total_out_lo32; 1843231200Smm switch (r) { 1844231200Smm case BZ_RUN_OK: /* Non-finishing */ 1845231200Smm case BZ_FINISH_OK: /* Finishing: There's more work to do */ 1846231200Smm return (ARCHIVE_OK); 1847231200Smm case BZ_STREAM_END: /* Finishing: all done */ 1848231200Smm /* Only occurs in finishing case */ 1849231200Smm return (ARCHIVE_EOF); 1850231200Smm default: 1851231200Smm /* Any other return value indicates an error */ 1852231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1853231200Smm "Bzip2 compression failed:" 1854231200Smm " BZ2_bzCompress() call returned status %d", r); 1855231200Smm return (ARCHIVE_FATAL); 1856231200Smm } 1857231200Smm} 1858231200Smm 1859231200Smmstatic int 1860231200Smmcompression_end_bzip2(struct archive *a, struct la_zstream *lastrm) 1861231200Smm{ 1862231200Smm bz_stream *strm; 1863231200Smm int r; 1864231200Smm 1865231200Smm strm = (bz_stream *)lastrm->real_stream; 1866231200Smm r = BZ2_bzCompressEnd(strm); 1867231200Smm free(strm); 1868231200Smm lastrm->real_stream = NULL; 1869231200Smm lastrm->valid = 0; 1870231200Smm if (r != BZ_OK) { 1871231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1872231200Smm "Failed to clean up compressor"); 1873231200Smm return (ARCHIVE_FATAL); 1874231200Smm } 1875231200Smm return (ARCHIVE_OK); 1876231200Smm} 1877231200Smm 1878231200Smm#else 1879231200Smmstatic int 1880231200Smmcompression_init_encoder_bzip2(struct archive *a, 1881231200Smm struct la_zstream *lastrm, int level) 1882231200Smm{ 1883231200Smm 1884231200Smm (void) level; /* UNUSED */ 1885231200Smm if (lastrm->valid) 1886231200Smm compression_end(a, lastrm); 1887231200Smm return (compression_unsupported_encoder(a, lastrm, "bzip2")); 1888231200Smm} 1889231200Smm#endif 1890231200Smm 1891231200Smm/* 1892231200Smm * _7_LZMA1, _7_LZMA2 compressor. 1893231200Smm */ 1894231200Smm#if defined(HAVE_LZMA_H) 1895231200Smmstatic int 1896231200Smmcompression_init_encoder_lzma(struct archive *a, 1897231200Smm struct la_zstream *lastrm, int level, uint64_t filter_id) 1898231200Smm{ 1899231200Smm static const lzma_stream lzma_init_data = LZMA_STREAM_INIT; 1900231200Smm lzma_stream *strm; 1901231200Smm lzma_filter *lzmafilters; 1902231200Smm lzma_options_lzma lzma_opt; 1903231200Smm int r; 1904231200Smm 1905231200Smm if (lastrm->valid) 1906231200Smm compression_end(a, lastrm); 1907231200Smm strm = calloc(1, sizeof(*strm) + sizeof(*lzmafilters) * 2); 1908231200Smm if (strm == NULL) { 1909231200Smm archive_set_error(a, ENOMEM, 1910231200Smm "Can't allocate memory for lzma stream"); 1911231200Smm return (ARCHIVE_FATAL); 1912231200Smm } 1913231200Smm lzmafilters = (lzma_filter *)(strm+1); 1914231200Smm if (level > 6) 1915231200Smm level = 6; 1916231200Smm if (lzma_lzma_preset(&lzma_opt, level)) { 1917231200Smm lastrm->real_stream = NULL; 1918231200Smm archive_set_error(a, ENOMEM, 1919231200Smm "Internal error initializing compression library"); 1920231200Smm return (ARCHIVE_FATAL); 1921231200Smm } 1922231200Smm lzmafilters[0].id = filter_id; 1923231200Smm lzmafilters[0].options = &lzma_opt; 1924231200Smm lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ 1925231200Smm 1926231200Smm r = lzma_properties_size(&(lastrm->prop_size), lzmafilters); 1927231200Smm if (r != LZMA_OK) { 1928231200Smm free(strm); 1929231200Smm lastrm->real_stream = NULL; 1930231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1931231200Smm "lzma_properties_size failed"); 1932231200Smm return (ARCHIVE_FATAL); 1933231200Smm } 1934231200Smm if (lastrm->prop_size) { 1935231200Smm lastrm->props = malloc(lastrm->prop_size); 1936231200Smm if (lastrm->props == NULL) { 1937231200Smm free(strm); 1938231200Smm lastrm->real_stream = NULL; 1939231200Smm archive_set_error(a, ENOMEM, 1940231200Smm "Cannot allocate memory"); 1941231200Smm return (ARCHIVE_FATAL); 1942231200Smm } 1943231200Smm r = lzma_properties_encode(lzmafilters, lastrm->props); 1944231200Smm if (r != LZMA_OK) { 1945231200Smm free(strm); 1946231200Smm lastrm->real_stream = NULL; 1947231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1948231200Smm "lzma_properties_encode failed"); 1949231200Smm return (ARCHIVE_FATAL); 1950231200Smm } 1951231200Smm } 1952231200Smm 1953231200Smm *strm = lzma_init_data; 1954231200Smm r = lzma_raw_encoder(strm, lzmafilters); 1955231200Smm switch (r) { 1956231200Smm case LZMA_OK: 1957231200Smm lastrm->real_stream = strm; 1958231200Smm lastrm->valid = 1; 1959231200Smm lastrm->code = compression_code_lzma; 1960231200Smm lastrm->end = compression_end_lzma; 1961231200Smm r = ARCHIVE_OK; 1962231200Smm break; 1963231200Smm case LZMA_MEM_ERROR: 1964231200Smm free(strm); 1965231200Smm lastrm->real_stream = NULL; 1966231200Smm archive_set_error(a, ENOMEM, 1967231200Smm "Internal error initializing compression library: " 1968231200Smm "Cannot allocate memory"); 1969231200Smm r = ARCHIVE_FATAL; 1970231200Smm break; 1971231200Smm default: 1972231200Smm free(strm); 1973231200Smm lastrm->real_stream = NULL; 1974231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 1975231200Smm "Internal error initializing compression library: " 1976231200Smm "It's a bug in liblzma"); 1977231200Smm r = ARCHIVE_FATAL; 1978231200Smm break; 1979231200Smm } 1980231200Smm return (r); 1981231200Smm} 1982231200Smm 1983231200Smmstatic int 1984231200Smmcompression_init_encoder_lzma1(struct archive *a, 1985231200Smm struct la_zstream *lastrm, int level) 1986231200Smm{ 1987231200Smm return compression_init_encoder_lzma(a, lastrm, level, 1988231200Smm LZMA_FILTER_LZMA1); 1989231200Smm} 1990231200Smm 1991231200Smmstatic int 1992231200Smmcompression_init_encoder_lzma2(struct archive *a, 1993231200Smm struct la_zstream *lastrm, int level) 1994231200Smm{ 1995231200Smm return compression_init_encoder_lzma(a, lastrm, level, 1996231200Smm LZMA_FILTER_LZMA2); 1997231200Smm} 1998231200Smm 1999231200Smmstatic int 2000231200Smmcompression_code_lzma(struct archive *a, 2001231200Smm struct la_zstream *lastrm, enum la_zaction action) 2002231200Smm{ 2003231200Smm lzma_stream *strm; 2004231200Smm int r; 2005231200Smm 2006231200Smm strm = (lzma_stream *)lastrm->real_stream; 2007231200Smm strm->next_in = lastrm->next_in; 2008231200Smm strm->avail_in = lastrm->avail_in; 2009231200Smm strm->total_in = lastrm->total_in; 2010231200Smm strm->next_out = lastrm->next_out; 2011231200Smm strm->avail_out = lastrm->avail_out; 2012231200Smm strm->total_out = lastrm->total_out; 2013231200Smm r = lzma_code(strm, 2014231200Smm (action == ARCHIVE_Z_FINISH)? LZMA_FINISH: LZMA_RUN); 2015231200Smm lastrm->next_in = strm->next_in; 2016231200Smm lastrm->avail_in = strm->avail_in; 2017231200Smm lastrm->total_in = strm->total_in; 2018231200Smm lastrm->next_out = strm->next_out; 2019231200Smm lastrm->avail_out = strm->avail_out; 2020231200Smm lastrm->total_out = strm->total_out; 2021231200Smm switch (r) { 2022231200Smm case LZMA_OK: 2023231200Smm /* Non-finishing case */ 2024231200Smm return (ARCHIVE_OK); 2025231200Smm case LZMA_STREAM_END: 2026231200Smm /* This return can only occur in finishing case. */ 2027231200Smm return (ARCHIVE_EOF); 2028231200Smm case LZMA_MEMLIMIT_ERROR: 2029231200Smm archive_set_error(a, ENOMEM, 2030231200Smm "lzma compression error:" 2031231200Smm " %ju MiB would have been needed", 2032231200Smm (uintmax_t)((lzma_memusage(strm) + 1024 * 1024 -1) 2033231200Smm / (1024 * 1024))); 2034231200Smm return (ARCHIVE_FATAL); 2035231200Smm default: 2036231200Smm /* Any other return value indicates an error */ 2037231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 2038231200Smm "lzma compression failed:" 2039231200Smm " lzma_code() call returned status %d", r); 2040231200Smm return (ARCHIVE_FATAL); 2041231200Smm } 2042231200Smm} 2043231200Smm 2044231200Smmstatic int 2045231200Smmcompression_end_lzma(struct archive *a, struct la_zstream *lastrm) 2046231200Smm{ 2047231200Smm lzma_stream *strm; 2048231200Smm 2049231200Smm (void)a; /* UNUSED */ 2050231200Smm strm = (lzma_stream *)lastrm->real_stream; 2051231200Smm lzma_end(strm); 2052231200Smm free(strm); 2053231200Smm lastrm->valid = 0; 2054231200Smm lastrm->real_stream = NULL; 2055231200Smm return (ARCHIVE_OK); 2056231200Smm} 2057231200Smm#else 2058231200Smmstatic int 2059231200Smmcompression_init_encoder_lzma1(struct archive *a, 2060231200Smm struct la_zstream *lastrm, int level) 2061231200Smm{ 2062231200Smm 2063231200Smm (void) level; /* UNUSED */ 2064231200Smm if (lastrm->valid) 2065231200Smm compression_end(a, lastrm); 2066231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2067231200Smm} 2068231200Smmstatic int 2069231200Smmcompression_init_encoder_lzma2(struct archive *a, 2070231200Smm struct la_zstream *lastrm, int level) 2071231200Smm{ 2072231200Smm 2073231200Smm (void) level; /* UNUSED */ 2074231200Smm if (lastrm->valid) 2075231200Smm compression_end(a, lastrm); 2076231200Smm return (compression_unsupported_encoder(a, lastrm, "lzma")); 2077231200Smm} 2078231200Smm#endif 2079231200Smm 2080231200Smm/* 2081231200Smm * _7_PPMD compressor. 2082231200Smm */ 2083231200Smmstatic void * 2084231200Smmppmd_alloc(void *p, size_t size) 2085231200Smm{ 2086231200Smm (void)p; 2087231200Smm return malloc(size); 2088231200Smm} 2089231200Smmstatic void 2090231200Smmppmd_free(void *p, void *address) 2091231200Smm{ 2092231200Smm (void)p; 2093231200Smm free(address); 2094231200Smm} 2095231200Smmstatic ISzAlloc g_szalloc = { ppmd_alloc, ppmd_free }; 2096231200Smmstatic void 2097231200Smmppmd_write(void *p, Byte b) 2098231200Smm{ 2099231200Smm struct archive_write *a = ((IByteOut *)p)->a; 2100231200Smm struct _7zip *zip = (struct _7zip *)(a->format_data); 2101231200Smm struct la_zstream *lastrm = &(zip->stream); 2102231200Smm struct ppmd_stream *strm; 2103231200Smm 2104231200Smm if (lastrm->avail_out) { 2105231200Smm *lastrm->next_out++ = b; 2106231200Smm lastrm->avail_out--; 2107231200Smm lastrm->total_out++; 2108231200Smm return; 2109231200Smm } 2110231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2111231200Smm if (strm->buff_ptr < strm->buff_end) { 2112231200Smm *strm->buff_ptr++ = b; 2113231200Smm strm->buff_bytes++; 2114231200Smm } 2115231200Smm} 2116231200Smm 2117231200Smmstatic int 2118231200Smmcompression_init_encoder_ppmd(struct archive *a, 2119231200Smm struct la_zstream *lastrm, unsigned maxOrder, uint32_t msize) 2120231200Smm{ 2121231200Smm struct ppmd_stream *strm; 2122231200Smm uint8_t *props; 2123231200Smm int r; 2124231200Smm 2125231200Smm if (lastrm->valid) 2126231200Smm compression_end(a, lastrm); 2127231200Smm strm = calloc(1, sizeof(*strm)); 2128231200Smm if (strm == NULL) { 2129231200Smm archive_set_error(a, ENOMEM, 2130231200Smm "Can't allocate memory for PPMd"); 2131231200Smm return (ARCHIVE_FATAL); 2132231200Smm } 2133231200Smm strm->buff = malloc(32); 2134231200Smm if (strm->buff == NULL) { 2135231200Smm free(strm); 2136231200Smm archive_set_error(a, ENOMEM, 2137231200Smm "Can't allocate memory for PPMd"); 2138231200Smm return (ARCHIVE_FATAL); 2139231200Smm } 2140231200Smm strm->buff_ptr = strm->buff; 2141231200Smm strm->buff_end = strm->buff + 32; 2142231200Smm 2143231200Smm props = malloc(1+4); 2144231200Smm if (props == NULL) { 2145231200Smm free(strm->buff); 2146231200Smm free(strm); 2147231200Smm archive_set_error(a, ENOMEM, 2148231200Smm "Coludn't allocate memory for PPMd"); 2149231200Smm return (ARCHIVE_FATAL); 2150231200Smm } 2151231200Smm props[0] = maxOrder; 2152231200Smm archive_le32enc(props+1, msize); 2153231200Smm __archive_ppmd7_functions.Ppmd7_Construct(&strm->ppmd7_context); 2154231200Smm r = __archive_ppmd7_functions.Ppmd7_Alloc( 2155231200Smm &strm->ppmd7_context, msize, &g_szalloc); 2156231200Smm if (r == 0) { 2157231200Smm free(strm->buff); 2158231200Smm free(strm); 2159231200Smm free(props); 2160231200Smm archive_set_error(a, ENOMEM, 2161231200Smm "Coludn't allocate memory for PPMd"); 2162231200Smm return (ARCHIVE_FATAL); 2163231200Smm } 2164231200Smm __archive_ppmd7_functions.Ppmd7_Init(&(strm->ppmd7_context), maxOrder); 2165231200Smm strm->byteout.a = (struct archive_write *)a; 2166231200Smm strm->byteout.Write = ppmd_write; 2167231200Smm strm->range_enc.Stream = &(strm->byteout); 2168231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_Init(&(strm->range_enc)); 2169231200Smm strm->stat = 0; 2170231200Smm 2171231200Smm lastrm->real_stream = strm; 2172231200Smm lastrm->valid = 1; 2173231200Smm lastrm->code = compression_code_ppmd; 2174231200Smm lastrm->end = compression_end_ppmd; 2175231200Smm lastrm->prop_size = 5; 2176231200Smm lastrm->props = props; 2177231200Smm return (ARCHIVE_OK); 2178231200Smm} 2179231200Smm 2180231200Smmstatic int 2181231200Smmcompression_code_ppmd(struct archive *a, 2182231200Smm struct la_zstream *lastrm, enum la_zaction action) 2183231200Smm{ 2184231200Smm struct ppmd_stream *strm; 2185231200Smm 2186232153Smm (void)a; /* UNUSED */ 2187232153Smm 2188231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2189231200Smm 2190231200Smm /* Copy encoded data if there are remaining bytes from previous call. */ 2191231200Smm if (strm->buff_bytes) { 2192231200Smm uint8_t *p = strm->buff_ptr - strm->buff_bytes; 2193231200Smm while (lastrm->avail_out && strm->buff_bytes) { 2194231200Smm *lastrm->next_out++ = *p++; 2195231200Smm lastrm->avail_out--; 2196231200Smm lastrm->total_out++; 2197231200Smm strm->buff_bytes--; 2198231200Smm } 2199231200Smm if (strm->buff_bytes) 2200231200Smm return (ARCHIVE_OK); 2201231200Smm if (strm->stat == 1) 2202231200Smm return (ARCHIVE_EOF); 2203231200Smm strm->buff_ptr = strm->buff; 2204231200Smm } 2205231200Smm while (lastrm->avail_in && lastrm->avail_out) { 2206231200Smm __archive_ppmd7_functions.Ppmd7_EncodeSymbol( 2207231200Smm &(strm->ppmd7_context), &(strm->range_enc), 2208231200Smm *lastrm->next_in++); 2209231200Smm lastrm->avail_in--; 2210231200Smm lastrm->total_in++; 2211231200Smm } 2212231200Smm if (lastrm->avail_in == 0 && action == ARCHIVE_Z_FINISH) { 2213231200Smm __archive_ppmd7_functions.Ppmd7z_RangeEnc_FlushData( 2214231200Smm &(strm->range_enc)); 2215231200Smm strm->stat = 1; 2216231200Smm /* Return EOF if there are no remaining bytes. */ 2217231200Smm if (strm->buff_bytes == 0) 2218231200Smm return (ARCHIVE_EOF); 2219231200Smm } 2220231200Smm return (ARCHIVE_OK); 2221231200Smm} 2222231200Smm 2223231200Smmstatic int 2224231200Smmcompression_end_ppmd(struct archive *a, struct la_zstream *lastrm) 2225231200Smm{ 2226231200Smm struct ppmd_stream *strm; 2227231200Smm 2228232153Smm (void)a; /* UNUSED */ 2229232153Smm 2230231200Smm strm = (struct ppmd_stream *)lastrm->real_stream; 2231231200Smm __archive_ppmd7_functions.Ppmd7_Free(&strm->ppmd7_context, &g_szalloc); 2232231200Smm free(strm->buff); 2233231200Smm free(strm); 2234231200Smm lastrm->real_stream = NULL; 2235231200Smm lastrm->valid = 0; 2236231200Smm return (ARCHIVE_OK); 2237231200Smm} 2238231200Smm 2239231200Smm/* 2240231200Smm * Universal compressor initializer. 2241231200Smm */ 2242231200Smmstatic int 2243231200Smm_7z_compression_init_encoder(struct archive_write *a, unsigned compression, 2244231200Smm int compression_level) 2245231200Smm{ 2246231200Smm struct _7zip *zip; 2247231200Smm int r; 2248231200Smm 2249231200Smm zip = (struct _7zip *)a->format_data; 2250231200Smm switch (compression) { 2251231200Smm case _7Z_DEFLATE: 2252231200Smm r = compression_init_encoder_deflate( 2253231200Smm &(a->archive), &(zip->stream), 2254231200Smm compression_level, 0); 2255231200Smm break; 2256231200Smm case _7Z_BZIP2: 2257231200Smm r = compression_init_encoder_bzip2( 2258231200Smm &(a->archive), &(zip->stream), 2259231200Smm compression_level); 2260231200Smm break; 2261231200Smm case _7Z_LZMA1: 2262231200Smm r = compression_init_encoder_lzma1( 2263231200Smm &(a->archive), &(zip->stream), 2264231200Smm compression_level); 2265231200Smm break; 2266231200Smm case _7Z_LZMA2: 2267231200Smm r = compression_init_encoder_lzma2( 2268231200Smm &(a->archive), &(zip->stream), 2269231200Smm compression_level); 2270231200Smm break; 2271231200Smm case _7Z_PPMD: 2272231200Smm r = compression_init_encoder_ppmd( 2273231200Smm &(a->archive), &(zip->stream), 2274231200Smm PPMD7_DEFAULT_ORDER, PPMD7_DEFAULT_MEM_SIZE); 2275231200Smm break; 2276231200Smm case _7Z_COPY: 2277231200Smm default: 2278231200Smm r = compression_init_encoder_copy( 2279231200Smm &(a->archive), &(zip->stream)); 2280231200Smm break; 2281231200Smm } 2282231200Smm if (r == ARCHIVE_OK) { 2283231200Smm zip->stream.total_in = 0; 2284231200Smm zip->stream.next_out = zip->wbuff; 2285231200Smm zip->stream.avail_out = sizeof(zip->wbuff); 2286231200Smm zip->stream.total_out = 0; 2287231200Smm } 2288231200Smm 2289231200Smm return (r); 2290231200Smm} 2291231200Smm 2292231200Smmstatic int 2293231200Smmcompression_code(struct archive *a, struct la_zstream *lastrm, 2294231200Smm enum la_zaction action) 2295231200Smm{ 2296231200Smm if (lastrm->valid) 2297231200Smm return (lastrm->code(a, lastrm, action)); 2298231200Smm return (ARCHIVE_OK); 2299231200Smm} 2300231200Smm 2301231200Smmstatic int 2302231200Smmcompression_end(struct archive *a, struct la_zstream *lastrm) 2303231200Smm{ 2304231200Smm if (lastrm->valid) { 2305231200Smm lastrm->prop_size = 0; 2306231200Smm free(lastrm->props); 2307231200Smm lastrm->props = NULL; 2308231200Smm return (lastrm->end(a, lastrm)); 2309231200Smm } 2310231200Smm return (ARCHIVE_OK); 2311231200Smm} 2312231200Smm 2313231200Smm 2314