1228753Smm/*- 2231200Smm * Copyright (c) 2003-2010 Tim Kientzle 3232153Smm * Copyright (c) 2009-2012 Michihiro NAKAJIMA 4228753Smm * All rights reserved. 5228753Smm * 6228753Smm * Redistribution and use in source and binary forms, with or without 7228753Smm * modification, are permitted provided that the following conditions 8228753Smm * are met: 9228753Smm * 1. Redistributions of source code must retain the above copyright 10228753Smm * notice, this list of conditions and the following disclaimer. 11228753Smm * 2. Redistributions in binary form must reproduce the above copyright 12228753Smm * notice, this list of conditions and the following disclaimer in the 13228753Smm * documentation and/or other materials provided with the distribution. 14228753Smm * 15228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25228753Smm */ 26228753Smm 27228753Smm#include "archive_platform.h" 28228753Smm 29228753Smm__FBSDID("$FreeBSD: head/lib/libarchive/archive_write_set_compression_xz.c 201108 2009-12-28 03:28:21Z kientzle $"); 30228753Smm 31228753Smm#ifdef HAVE_ERRNO_H 32228753Smm#include <errno.h> 33228753Smm#endif 34228753Smm#ifdef HAVE_STDLIB_H 35228753Smm#include <stdlib.h> 36228753Smm#endif 37228753Smm#ifdef HAVE_STRING_H 38228753Smm#include <string.h> 39228753Smm#endif 40228753Smm#include <time.h> 41228753Smm#ifdef HAVE_LZMA_H 42228753Smm#include <lzma.h> 43228753Smm#endif 44228753Smm 45228753Smm#include "archive.h" 46231200Smm#include "archive_endian.h" 47228753Smm#include "archive_private.h" 48228753Smm#include "archive_write_private.h" 49228753Smm 50231200Smm#if ARCHIVE_VERSION_NUMBER < 4000000 51228753Smmint 52231200Smmarchive_write_set_compression_lzip(struct archive *a) 53231200Smm{ 54231200Smm __archive_write_filters_free(a); 55231200Smm return (archive_write_add_filter_lzip(a)); 56231200Smm} 57231200Smm 58231200Smmint 59231200Smmarchive_write_set_compression_lzma(struct archive *a) 60231200Smm{ 61231200Smm __archive_write_filters_free(a); 62231200Smm return (archive_write_add_filter_lzma(a)); 63231200Smm} 64231200Smm 65231200Smmint 66228753Smmarchive_write_set_compression_xz(struct archive *a) 67228753Smm{ 68231200Smm __archive_write_filters_free(a); 69231200Smm return (archive_write_add_filter_xz(a)); 70231200Smm} 71231200Smm 72231200Smm#endif 73231200Smm 74231200Smm#ifndef HAVE_LZMA_H 75231200Smmint 76231200Smmarchive_write_add_filter_xz(struct archive *a) 77231200Smm{ 78228753Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 79228753Smm "xz compression not supported on this platform"); 80228753Smm return (ARCHIVE_FATAL); 81228753Smm} 82228753Smm 83228753Smmint 84231200Smmarchive_write_add_filter_lzma(struct archive *a) 85228753Smm{ 86228753Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 87228753Smm "lzma compression not supported on this platform"); 88228753Smm return (ARCHIVE_FATAL); 89228753Smm} 90231200Smm 91231200Smmint 92231200Smmarchive_write_add_filter_lzip(struct archive *a) 93231200Smm{ 94231200Smm archive_set_error(a, ARCHIVE_ERRNO_MISC, 95231200Smm "lzma compression not supported on this platform"); 96231200Smm return (ARCHIVE_FATAL); 97231200Smm} 98228753Smm#else 99228753Smm/* Don't compile this if we don't have liblzma. */ 100228753Smm 101228753Smmstruct private_data { 102231200Smm int compression_level; 103302001Smm uint32_t threads; 104228753Smm lzma_stream stream; 105228753Smm lzma_filter lzmafilters[2]; 106228753Smm lzma_options_lzma lzma_opt; 107228753Smm int64_t total_in; 108228753Smm unsigned char *compressed; 109228753Smm size_t compressed_buffer_size; 110231200Smm int64_t total_out; 111231200Smm /* the CRC32 value of uncompressed data for lzip */ 112231200Smm uint32_t crc32; 113228753Smm}; 114228753Smm 115231200Smmstatic int archive_compressor_xz_options(struct archive_write_filter *, 116228753Smm const char *, const char *); 117231200Smmstatic int archive_compressor_xz_open(struct archive_write_filter *); 118231200Smmstatic int archive_compressor_xz_write(struct archive_write_filter *, 119228753Smm const void *, size_t); 120231200Smmstatic int archive_compressor_xz_close(struct archive_write_filter *); 121231200Smmstatic int archive_compressor_xz_free(struct archive_write_filter *); 122231200Smmstatic int drive_compressor(struct archive_write_filter *, 123231200Smm struct private_data *, int finishing); 124228753Smm 125231200Smmstruct option_value { 126231200Smm uint32_t dict_size; 127231200Smm uint32_t nice_len; 128231200Smm lzma_match_finder mf; 129231200Smm}; 130231200Smmstatic const struct option_value option_values[] = { 131231200Smm { 1 << 16, 32, LZMA_MF_HC3}, 132231200Smm { 1 << 20, 32, LZMA_MF_HC3}, 133231200Smm { 3 << 19, 32, LZMA_MF_HC4}, 134231200Smm { 1 << 21, 32, LZMA_MF_BT4}, 135231200Smm { 3 << 20, 32, LZMA_MF_BT4}, 136231200Smm { 1 << 22, 32, LZMA_MF_BT4}, 137231200Smm { 1 << 23, 64, LZMA_MF_BT4}, 138231200Smm { 1 << 24, 64, LZMA_MF_BT4}, 139231200Smm { 3 << 23, 64, LZMA_MF_BT4}, 140231200Smm { 1 << 25, 64, LZMA_MF_BT4} 141231200Smm}; 142228753Smm 143231200Smmstatic int 144231200Smmcommon_setup(struct archive_write_filter *f) 145228753Smm{ 146231200Smm struct private_data *data; 147231200Smm struct archive_write *a = (struct archive_write *)f->archive; 148231200Smm data = calloc(1, sizeof(*data)); 149231200Smm if (data == NULL) { 150228753Smm archive_set_error(&a->archive, ENOMEM, "Out of memory"); 151228753Smm return (ARCHIVE_FATAL); 152228753Smm } 153231200Smm f->data = data; 154231200Smm data->compression_level = LZMA_PRESET_DEFAULT; 155302001Smm data->threads = 1; 156231200Smm f->open = &archive_compressor_xz_open; 157231200Smm f->close = archive_compressor_xz_close; 158231200Smm f->free = archive_compressor_xz_free; 159231200Smm f->options = &archive_compressor_xz_options; 160228753Smm return (ARCHIVE_OK); 161228753Smm} 162228753Smm 163231200Smm/* 164231200Smm * Add an xz compression filter to this write handle. 165231200Smm */ 166231200Smmint 167231200Smmarchive_write_add_filter_xz(struct archive *_a) 168231200Smm{ 169231200Smm struct archive_write_filter *f; 170231200Smm int r; 171231200Smm 172231200Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 173231200Smm ARCHIVE_STATE_NEW, "archive_write_add_filter_xz"); 174231200Smm f = __archive_write_allocate_filter(_a); 175231200Smm r = common_setup(f); 176231200Smm if (r == ARCHIVE_OK) { 177248616Smm f->code = ARCHIVE_FILTER_XZ; 178231200Smm f->name = "xz"; 179231200Smm } 180231200Smm return (r); 181231200Smm} 182231200Smm 183228753Smm/* LZMA is handled identically, we just need a different compression 184228753Smm * code set. (The liblzma setup looks at the code to determine 185228753Smm * the one place that XZ and LZMA require different handling.) */ 186228753Smmint 187231200Smmarchive_write_add_filter_lzma(struct archive *_a) 188228753Smm{ 189231200Smm struct archive_write_filter *f; 190231200Smm int r; 191231200Smm 192231200Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 193231200Smm ARCHIVE_STATE_NEW, "archive_write_add_filter_lzma"); 194231200Smm f = __archive_write_allocate_filter(_a); 195231200Smm r = common_setup(f); 196231200Smm if (r == ARCHIVE_OK) { 197248616Smm f->code = ARCHIVE_FILTER_LZMA; 198231200Smm f->name = "lzma"; 199231200Smm } 200231200Smm return (r); 201228753Smm} 202228753Smm 203231200Smmint 204231200Smmarchive_write_add_filter_lzip(struct archive *_a) 205231200Smm{ 206231200Smm struct archive_write_filter *f; 207231200Smm int r; 208231200Smm 209231200Smm archive_check_magic(_a, ARCHIVE_WRITE_MAGIC, 210231200Smm ARCHIVE_STATE_NEW, "archive_write_add_filter_lzip"); 211231200Smm f = __archive_write_allocate_filter(_a); 212231200Smm r = common_setup(f); 213231200Smm if (r == ARCHIVE_OK) { 214248616Smm f->code = ARCHIVE_FILTER_LZIP; 215231200Smm f->name = "lzip"; 216231200Smm } 217231200Smm return (r); 218231200Smm} 219231200Smm 220228753Smmstatic int 221231200Smmarchive_compressor_xz_init_stream(struct archive_write_filter *f, 222231200Smm struct private_data *data) 223228753Smm{ 224228753Smm static const lzma_stream lzma_stream_init_data = LZMA_STREAM_INIT; 225228753Smm int ret; 226302001Smm#ifdef HAVE_LZMA_STREAM_ENCODER_MT 227302001Smm lzma_mt mt_options; 228302001Smm#endif 229228753Smm 230231200Smm data->stream = lzma_stream_init_data; 231231200Smm data->stream.next_out = data->compressed; 232231200Smm data->stream.avail_out = data->compressed_buffer_size; 233302001Smm if (f->code == ARCHIVE_FILTER_XZ) { 234302001Smm#ifdef HAVE_LZMA_STREAM_ENCODER_MT 235302001Smm if (data->threads != 1) { 236313571Smm memset(&mt_options, 0, sizeof(mt_options)); 237302001Smm mt_options.threads = data->threads; 238302001Smm mt_options.timeout = 300; 239302001Smm mt_options.filters = data->lzmafilters; 240302001Smm mt_options.check = LZMA_CHECK_CRC64; 241302001Smm ret = lzma_stream_encoder_mt(&(data->stream), 242302001Smm &mt_options); 243302001Smm } else 244302001Smm#endif 245302001Smm ret = lzma_stream_encoder(&(data->stream), 246302001Smm data->lzmafilters, LZMA_CHECK_CRC64); 247302001Smm } else if (f->code == ARCHIVE_FILTER_LZMA) { 248231200Smm ret = lzma_alone_encoder(&(data->stream), &data->lzma_opt); 249302001Smm } else { /* ARCHIVE_FILTER_LZIP */ 250231200Smm int dict_size = data->lzma_opt.dict_size; 251231200Smm int ds, log2dic, wedges; 252231200Smm 253231200Smm /* Calculate a coded dictionary size */ 254231200Smm if (dict_size < (1 << 12) || dict_size > (1 << 27)) { 255231200Smm archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, 256302001Smm "Unacceptable dictionary size for lzip: %d", 257231200Smm dict_size); 258231200Smm return (ARCHIVE_FATAL); 259231200Smm } 260231200Smm for (log2dic = 27; log2dic >= 12; log2dic--) { 261231200Smm if (dict_size & (1 << log2dic)) 262231200Smm break; 263231200Smm } 264231200Smm if (dict_size > (1 << log2dic)) { 265231200Smm log2dic++; 266231200Smm wedges = 267231200Smm ((1 << log2dic) - dict_size) / (1 << (log2dic - 4)); 268231200Smm } else 269231200Smm wedges = 0; 270231200Smm ds = ((wedges << 5) & 0xe0) | (log2dic & 0x1f); 271231200Smm 272231200Smm data->crc32 = 0; 273231200Smm /* Make a header */ 274231200Smm data->compressed[0] = 0x4C; 275231200Smm data->compressed[1] = 0x5A; 276231200Smm data->compressed[2] = 0x49; 277231200Smm data->compressed[3] = 0x50; 278231200Smm data->compressed[4] = 1;/* Version */ 279231200Smm data->compressed[5] = (unsigned char)ds; 280231200Smm data->stream.next_out += 6; 281231200Smm data->stream.avail_out -= 6; 282231200Smm 283231200Smm ret = lzma_raw_encoder(&(data->stream), data->lzmafilters); 284231200Smm } 285228753Smm if (ret == LZMA_OK) 286228753Smm return (ARCHIVE_OK); 287228753Smm 288228753Smm switch (ret) { 289228753Smm case LZMA_MEM_ERROR: 290231200Smm archive_set_error(f->archive, ENOMEM, 291228753Smm "Internal error initializing compression library: " 292228753Smm "Cannot allocate memory"); 293228753Smm break; 294228753Smm default: 295231200Smm archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, 296228753Smm "Internal error initializing compression library: " 297228753Smm "It's a bug in liblzma"); 298228753Smm break; 299228753Smm } 300228753Smm return (ARCHIVE_FATAL); 301228753Smm} 302228753Smm 303228753Smm/* 304228753Smm * Setup callback. 305228753Smm */ 306228753Smmstatic int 307231200Smmarchive_compressor_xz_open(struct archive_write_filter *f) 308228753Smm{ 309231200Smm struct private_data *data = f->data; 310228753Smm int ret; 311228753Smm 312231200Smm if (data->compressed == NULL) { 313238856Smm size_t bs = 65536, bpb; 314238856Smm if (f->archive->magic == ARCHIVE_WRITE_MAGIC) { 315238856Smm /* Buffer size should be a multiple number of the of bytes 316238856Smm * per block for performance. */ 317238856Smm bpb = archive_write_get_bytes_per_block(f->archive); 318238856Smm if (bpb > bs) 319238856Smm bs = bpb; 320238856Smm else if (bpb != 0) 321238856Smm bs -= bs % bpb; 322238856Smm } 323238856Smm data->compressed_buffer_size = bs; 324231200Smm data->compressed 325231200Smm = (unsigned char *)malloc(data->compressed_buffer_size); 326231200Smm if (data->compressed == NULL) { 327231200Smm archive_set_error(f->archive, ENOMEM, 328231200Smm "Can't allocate data for compression buffer"); 329231200Smm return (ARCHIVE_FATAL); 330231200Smm } 331228753Smm } 332228753Smm 333231200Smm f->write = archive_compressor_xz_write; 334228753Smm 335228753Smm /* Initialize compression library. */ 336248616Smm if (f->code == ARCHIVE_FILTER_LZIP) { 337231200Smm const struct option_value *val = 338231200Smm &option_values[data->compression_level]; 339231200Smm 340231200Smm data->lzma_opt.dict_size = val->dict_size; 341231200Smm data->lzma_opt.preset_dict = NULL; 342231200Smm data->lzma_opt.preset_dict_size = 0; 343231200Smm data->lzma_opt.lc = LZMA_LC_DEFAULT; 344231200Smm data->lzma_opt.lp = LZMA_LP_DEFAULT; 345231200Smm data->lzma_opt.pb = LZMA_PB_DEFAULT; 346231200Smm data->lzma_opt.mode = 347231200Smm data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL; 348231200Smm data->lzma_opt.nice_len = val->nice_len; 349231200Smm data->lzma_opt.mf = val->mf; 350231200Smm data->lzma_opt.depth = 0; 351231200Smm data->lzmafilters[0].id = LZMA_FILTER_LZMA1; 352231200Smm data->lzmafilters[0].options = &data->lzma_opt; 353231200Smm data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ 354231200Smm } else { 355231200Smm if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) { 356231200Smm archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, 357231200Smm "Internal error initializing compression library"); 358231200Smm } 359231200Smm data->lzmafilters[0].id = LZMA_FILTER_LZMA2; 360231200Smm data->lzmafilters[0].options = &data->lzma_opt; 361231200Smm data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */ 362228753Smm } 363231200Smm ret = archive_compressor_xz_init_stream(f, data); 364228753Smm if (ret == LZMA_OK) { 365231200Smm f->data = data; 366228753Smm return (0); 367228753Smm } 368228753Smm return (ARCHIVE_FATAL); 369228753Smm} 370228753Smm 371228753Smm/* 372228753Smm * Set write options. 373228753Smm */ 374228753Smmstatic int 375231200Smmarchive_compressor_xz_options(struct archive_write_filter *f, 376231200Smm const char *key, const char *value) 377228753Smm{ 378231200Smm struct private_data *data = (struct private_data *)f->data; 379228753Smm 380228753Smm if (strcmp(key, "compression-level") == 0) { 381228753Smm if (value == NULL || !(value[0] >= '0' && value[0] <= '9') || 382228753Smm value[1] != '\0') 383228753Smm return (ARCHIVE_WARN); 384231200Smm data->compression_level = value[0] - '0'; 385368708Smm if (data->compression_level > 9) 386368708Smm data->compression_level = 9; 387228753Smm return (ARCHIVE_OK); 388302001Smm } else if (strcmp(key, "threads") == 0) { 389348608Smm char *endptr; 390348608Smm 391302001Smm if (value == NULL) 392302001Smm return (ARCHIVE_WARN); 393348608Smm errno = 0; 394348608Smm data->threads = (int)strtoul(value, &endptr, 10); 395348608Smm if (errno != 0 || *endptr != '\0') { 396302001Smm data->threads = 1; 397302001Smm return (ARCHIVE_WARN); 398302001Smm } 399302001Smm if (data->threads == 0) { 400302001Smm#ifdef HAVE_LZMA_STREAM_ENCODER_MT 401302001Smm data->threads = lzma_cputhreads(); 402302001Smm#else 403302001Smm data->threads = 1; 404302001Smm#endif 405302001Smm } 406302001Smm return (ARCHIVE_OK); 407228753Smm } 408228753Smm 409232153Smm /* Note: The "warn" return is just to inform the options 410232153Smm * supervisor that we didn't handle it. It will generate 411232153Smm * a suitable error if no one used this option. */ 412228753Smm return (ARCHIVE_WARN); 413228753Smm} 414228753Smm 415228753Smm/* 416228753Smm * Write data to the compressed stream. 417228753Smm */ 418228753Smmstatic int 419231200Smmarchive_compressor_xz_write(struct archive_write_filter *f, 420231200Smm const void *buff, size_t length) 421228753Smm{ 422231200Smm struct private_data *data = (struct private_data *)f->data; 423228753Smm int ret; 424228753Smm 425228753Smm /* Update statistics */ 426231200Smm data->total_in += length; 427248616Smm if (f->code == ARCHIVE_FILTER_LZIP) 428231200Smm data->crc32 = lzma_crc32(buff, length, data->crc32); 429228753Smm 430228753Smm /* Compress input data to output buffer */ 431231200Smm data->stream.next_in = buff; 432231200Smm data->stream.avail_in = length; 433231200Smm if ((ret = drive_compressor(f, data, 0)) != ARCHIVE_OK) 434228753Smm return (ret); 435228753Smm 436228753Smm return (ARCHIVE_OK); 437228753Smm} 438228753Smm 439228753Smm 440228753Smm/* 441228753Smm * Finish the compression... 442228753Smm */ 443228753Smmstatic int 444231200Smmarchive_compressor_xz_close(struct archive_write_filter *f) 445228753Smm{ 446231200Smm struct private_data *data = (struct private_data *)f->data; 447358090Smm int ret; 448228753Smm 449231200Smm ret = drive_compressor(f, data, 1); 450231200Smm if (ret == ARCHIVE_OK) { 451231200Smm data->total_out += 452231200Smm data->compressed_buffer_size - data->stream.avail_out; 453231200Smm ret = __archive_write_filter(f->next_filter, 454231200Smm data->compressed, 455231200Smm data->compressed_buffer_size - data->stream.avail_out); 456248616Smm if (f->code == ARCHIVE_FILTER_LZIP && ret == ARCHIVE_OK) { 457231200Smm archive_le32enc(data->compressed, data->crc32); 458231200Smm archive_le64enc(data->compressed+4, data->total_in); 459231200Smm archive_le64enc(data->compressed+12, data->total_out + 20); 460231200Smm ret = __archive_write_filter(f->next_filter, 461231200Smm data->compressed, 20); 462228753Smm } 463228753Smm } 464231200Smm lzma_end(&(data->stream)); 465358090Smm return ret; 466228753Smm} 467228753Smm 468231200Smmstatic int 469231200Smmarchive_compressor_xz_free(struct archive_write_filter *f) 470231200Smm{ 471231200Smm struct private_data *data = (struct private_data *)f->data; 472231200Smm free(data->compressed); 473231200Smm free(data); 474231200Smm f->data = NULL; 475231200Smm return (ARCHIVE_OK); 476231200Smm} 477231200Smm 478228753Smm/* 479228753Smm * Utility function to push input data through compressor, 480228753Smm * writing full output blocks as necessary. 481228753Smm * 482228753Smm * Note that this handles both the regular write case (finishing == 483228753Smm * false) and the end-of-archive case (finishing == true). 484228753Smm */ 485228753Smmstatic int 486231200Smmdrive_compressor(struct archive_write_filter *f, 487231200Smm struct private_data *data, int finishing) 488228753Smm{ 489228753Smm int ret; 490228753Smm 491228753Smm for (;;) { 492231200Smm if (data->stream.avail_out == 0) { 493231200Smm data->total_out += data->compressed_buffer_size; 494231200Smm ret = __archive_write_filter(f->next_filter, 495231200Smm data->compressed, 496231200Smm data->compressed_buffer_size); 497231200Smm if (ret != ARCHIVE_OK) 498228753Smm return (ARCHIVE_FATAL); 499231200Smm data->stream.next_out = data->compressed; 500231200Smm data->stream.avail_out = data->compressed_buffer_size; 501228753Smm } 502228753Smm 503228753Smm /* If there's nothing to do, we're done. */ 504231200Smm if (!finishing && data->stream.avail_in == 0) 505228753Smm return (ARCHIVE_OK); 506228753Smm 507231200Smm ret = lzma_code(&(data->stream), 508228753Smm finishing ? LZMA_FINISH : LZMA_RUN ); 509228753Smm 510228753Smm switch (ret) { 511228753Smm case LZMA_OK: 512228753Smm /* In non-finishing case, check if compressor 513228753Smm * consumed everything */ 514231200Smm if (!finishing && data->stream.avail_in == 0) 515228753Smm return (ARCHIVE_OK); 516228753Smm /* In finishing case, this return always means 517228753Smm * there's more work */ 518228753Smm break; 519228753Smm case LZMA_STREAM_END: 520228753Smm /* This return can only occur in finishing case. */ 521228753Smm if (finishing) 522228753Smm return (ARCHIVE_OK); 523231200Smm archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, 524228753Smm "lzma compression data error"); 525228753Smm return (ARCHIVE_FATAL); 526228753Smm case LZMA_MEMLIMIT_ERROR: 527231200Smm archive_set_error(f->archive, ENOMEM, 528228753Smm "lzma compression error: " 529228753Smm "%ju MiB would have been needed", 530231200Smm (uintmax_t)((lzma_memusage(&(data->stream)) 531231200Smm + 1024 * 1024 -1) 532228753Smm / (1024 * 1024))); 533228753Smm return (ARCHIVE_FATAL); 534228753Smm default: 535228753Smm /* Any other return value indicates an error. */ 536231200Smm archive_set_error(f->archive, ARCHIVE_ERRNO_MISC, 537228753Smm "lzma compression failed:" 538228753Smm " lzma_code() call returned status %d", 539228753Smm ret); 540228753Smm return (ARCHIVE_FATAL); 541228753Smm } 542228753Smm } 543228753Smm} 544228753Smm 545228753Smm#endif /* HAVE_LZMA_H */ 546