Пример #1
0
static int
LZMAVSetField(TIFF* tif, uint32 tag, va_list ap)
{
	static const char module[] = "LZMAVSetField";
	LZMAState* sp = LState(tif);

	switch (tag) {
	case TIFFTAG_LZMAPRESET:
		sp->preset = (int) va_arg(ap, int);
		lzma_lzma_preset(&sp->opt_lzma, sp->preset);
		if (sp->state & LSTATE_INIT_ENCODE) {
			lzma_ret ret = lzma_stream_encoder(&sp->stream,
							   sp->filters,
							   sp->check);
			if (ret != LZMA_OK) {
				TIFFErrorExt(tif->tif_clientdata, module,
					     "Liblzma error: %s",
					     LZMAStrerror(ret));
			}
		}
		return 1;
	default:
		return (*sp->vsetparent)(tif, tag, ap);
	}
	/*NOTREACHED*/
}
Пример #2
0
void *
mkuz_lzma_init(uint32_t blksz)
{
	struct mkuz_lzma *ulp;

	if (blksz % USED_BLOCKSIZE != 0) {
		errx(1, "cluster size should be multiple of %d",
		    USED_BLOCKSIZE);
		/* Not reached */
	}
	if (blksz > MAXPHYS) {
		errx(1, "cluster size is too large");
		/* Not reached */
	}
	ulp = mkuz_safe_zmalloc(sizeof(struct mkuz_lzma));

	/* Init lzma encoder */
	ulp->strm = lzma_stream_init;
	if (lzma_lzma_preset(&ulp->opt_lzma, LZMA_PRESET_DEFAULT))
		errx(1, "Error loading LZMA preset");

	ulp->filters[0].id = LZMA_FILTER_LZMA2;
	ulp->filters[0].options = &ulp->opt_lzma;
	ulp->filters[1].id = LZMA_VLI_UNKNOWN;

	ulp->blksz = blksz;

	return (void *)ulp;
}
Пример #3
0
static int
Compressor_init_alone(lzma_stream *lzs, uint32_t preset, PyObject *filterspecs)
{
    lzma_ret lzret;

    if (filterspecs == Py_None) {
        lzma_options_lzma options;

        if (lzma_lzma_preset(&options, preset)) {
            PyErr_Format(Error, "Invalid compression preset: %d", preset);
            return -1;
        }
        lzret = lzma_alone_encoder(lzs, &options);
    } else {
        lzma_filter filters[LZMA_FILTERS_MAX + 1];

        if (parse_filter_chain_spec(filters, filterspecs) == -1)
            return -1;
        if (filters[0].id == LZMA_FILTER_LZMA1 &&
            filters[1].id == LZMA_VLI_UNKNOWN) {
            lzret = lzma_alone_encoder(lzs, filters[0].options);
        } else {
            PyErr_SetString(PyExc_ValueError,
                            "Invalid filter chain for FORMAT_ALONE - "
                            "must be a single LZMA1 filter");
            lzret = LZMA_PROG_ERROR;
        }
        free_filter_chain(filters);
    }
    if (PyErr_Occurred() || catch_lzma_error(lzret))
        return -1;
    else
        return 0;
}
Пример #4
0
/*@null@*/
static XZFILE *xzopen_internal(const char *path, const char *mode, int fdno, int xz)
	/*@globals fileSystem @*/
	/*@modifies fileSystem @*/
{
    int level = LZMA_PRESET_DEFAULT;
    int encoding = 0;
    FILE *fp;
    XZFILE *xzfile;
    lzma_stream tmp;
    lzma_ret ret;

    for (; *mode != '\0'; mode++) {
	if (*mode == 'w')
	    encoding = 1;
	else if (*mode == 'r')
	    encoding = 0;
	else if (*mode >= '0' && *mode <= '9')
	    level = (int)(*mode - '0');
    }
    if (fdno != -1)
	fp = fdopen(fdno, encoding ? "w" : "r");
    else
	fp = fopen(path, encoding ? "w" : "r");
    if (!fp)
	return NULL;
    xzfile = calloc(1, sizeof(*xzfile));
    if (!xzfile) {
	(void) fclose(fp);
	return NULL;
    }
    xzfile->fp = fp;
    xzfile->encoding = encoding;
    xzfile->eof = 0;
    tmp = (lzma_stream)LZMA_STREAM_INIT;
    xzfile->strm = tmp;
    if (encoding) {
	if (xz) {
	    ret = lzma_easy_encoder(&xzfile->strm, level, LZMA_CHECK_CRC32);
	} else {
	    lzma_options_lzma options;
	    (void) lzma_lzma_preset(&options, level);
	    ret = lzma_alone_encoder(&xzfile->strm, &options);
	}
    } else {
	/* We set the memlimit for decompression to 100MiB which should be
	 * more than enough to be sufficient for level 9 which requires 65 MiB.
	 */
	ret = lzma_auto_decoder(&xzfile->strm, 100<<20, 0);
    }
    if (ret != LZMA_OK) {
	(void) fclose(fp);
	memset(xzfile, 0, sizeof(*xzfile));
	free(xzfile);
	return NULL;
    }
    return xzfile;
}
/*
 * Setup callback.
 */
static int
archive_compressor_xz_init(struct archive_write *a)
{
	int ret;
	struct private_data *state;
	struct private_config *config;

	if (a->client_opener != NULL) {
		ret = (a->client_opener)(&a->archive, a->client_data);
		if (ret != ARCHIVE_OK)
			return (ret);
	}

	state = (struct private_data *)malloc(sizeof(*state));
	if (state == NULL) {
		archive_set_error(&a->archive, ENOMEM,
		    "Can't allocate data for compression");
		return (ARCHIVE_FATAL);
	}
	memset(state, 0, sizeof(*state));
	config = a->compressor.config;

	/*
	 * See comment above.  We should set compressed_buffer_size to
	 * max(bytes_per_block, 65536), but the code can't handle that yet.
	 */
	state->compressed_buffer_size = a->bytes_per_block;
	state->compressed = (unsigned char *)malloc(state->compressed_buffer_size);
	if (state->compressed == NULL) {
		archive_set_error(&a->archive, ENOMEM,
		    "Can't allocate data for compression buffer");
		free(state);
		return (ARCHIVE_FATAL);
	}
	a->compressor.write = archive_compressor_xz_write;

	/* Initialize compression library. */
	if (lzma_lzma_preset(&state->lzma_opt, config->compression_level)) {
		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
		    "Internal error initializing compression library");
		free(state->compressed);
		free(state);
	}
	state->lzmafilters[0].id = LZMA_FILTER_LZMA2;
	state->lzmafilters[0].options = &state->lzma_opt;
	state->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
	ret = archive_compressor_xz_init_stream(a, state);
	if (ret == LZMA_OK) {
		a->compressor.data = state;
		return (0);
	}
	/* Library setup failed: clean up. */
	free(state->compressed);
	free(state);

	return (ARCHIVE_FATAL);
}
Пример #6
0
static void *
parse_filter_spec_lzma(PyObject *spec)
{
    static char *optnames[] = {"id", "preset", "dict_size", "lc", "lp",
                               "pb", "mode", "nice_len", "mf", "depth", NULL};
    PyObject *id;
    PyObject *preset_obj;
    uint32_t preset = LZMA_PRESET_DEFAULT;
    lzma_options_lzma *options;

    /* First, fill in default values for all the options using a preset.
       Then, override the defaults with any values given by the caller. */

    preset_obj = PyMapping_GetItemString(spec, "preset");
    if (preset_obj == NULL) {
        if (PyErr_ExceptionMatches(PyExc_KeyError))
            PyErr_Clear();
        else
            return NULL;
    } else {
        int ok = uint32_converter(preset_obj, &preset);
        Py_DECREF(preset_obj);
        if (!ok)
            return NULL;
    }

    options = (lzma_options_lzma *)PyMem_Malloc(sizeof *options);
    if (options == NULL)
        return PyErr_NoMemory();
    memset(options, 0, sizeof *options);

    if (lzma_lzma_preset(options, preset)) {
        PyMem_Free(options);
        PyErr_Format(Error, "Invalid compression preset: %d", preset);
        return NULL;
    }

    if (!PyArg_ParseTupleAndKeywords(empty_tuple, spec,
                                     "|OOO&O&O&O&O&O&O&O&", optnames,
                                     &id, &preset_obj,
                                     uint32_converter, &options->dict_size,
                                     uint32_converter, &options->lc,
                                     uint32_converter, &options->lp,
                                     uint32_converter, &options->pb,
                                     lzma_mode_converter, &options->mode,
                                     uint32_converter, &options->nice_len,
                                     lzma_mf_converter, &options->mf,
                                     uint32_converter, &options->depth)) {
        PyErr_SetString(PyExc_ValueError,
                        "Invalid filter specifier for LZMA filter");
        PyMem_Free(options);
        options = NULL;
    }
    return options;
}
Пример #7
0
size_t fa_decompress_block(fa_compression_t compression, void* out, size_t outSize, const void* in, size_t inSize)
{
	switch (compression)
	{
		default: return 0;

		case FA_COMPRESSION_FASTLZ:
		{
			return fastlz_decompress(in, inSize, out, outSize);
		}
		break;
#if defined(FA_ZLIB_ENABLE)
		case FA_COMPRESSION_DEFLATE:
		{
			uLongf destLen = outSize;

			if (uncompress(out, &destLen, in, inSize) != Z_OK)
			{
				return 0;
			}

			return destLen;
		}
		break;
#endif

#if defined(FA_LZMA_ENABLE) 
		case FA_COMPRESSION_LZMA2:
		{
			size_t inPos = 0, outPos = 0;
			lzma_filter filters[2];
			lzma_options_lzma options;

			if (lzma_lzma_preset(&options, 6))
			{
				return 0;
			}

			filters[0].id = LZMA_FILTER_LZMA2;
			filters[0].options = &options;
			filters[1].id = LZMA_VLI_UNKNOWN;

			lzma_ret ret = lzma_raw_buffer_decode(filters, NULL, in, &inPos, inSize, out, &outPos, outSize);
			if (ret != LZMA_OK)
			{
				return 0;
			}

			return outPos; 
		}
		break;
#endif
	}
}
Пример #8
0
static int php_xz_init_encoder(struct php_xz_stream_data_t *self)
{
  lzma_stream *strm = &self->strm;
  lzma_options_lzma opt_lzma2;
  if (lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT)) {
    return 0;
  }
  
  lzma_filter filters[] = {
    { .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
    { .id = LZMA_VLI_UNKNOWN, .options = NULL },
Пример #9
0
extern bool
lzma_easy_preset(lzma_options_easy *opt_easy, uint32_t preset)
{
	if (lzma_lzma_preset(&opt_easy->opt_lzma, preset))
		return true;

	opt_easy->filters[0].id = LZMA_FILTER_LZMA2;
	opt_easy->filters[0].options = &opt_easy->opt_lzma;
	opt_easy->filters[1].id = LZMA_VLI_UNKNOWN;

	return false;
}
Пример #10
0
static LZFILE *lzopen_internal(const char *path, const char *mode, int fd, int xz)
{
    int level = 7;	/* Use XZ's default compression level if unspecified */
    int encoding = 0;
    FILE *fp;
    LZFILE *lzfile;
    lzma_ret ret;
    lzma_stream init_strm = LZMA_STREAM_INIT;

    for (; *mode; mode++) {
	if (*mode == 'w')
	    encoding = 1;
	else if (*mode == 'r')
	    encoding = 0;
	else if (*mode >= '1' && *mode <= '9')
	    level = *mode - '0';
    }
    if (fd != -1)
	fp = fdopen(fd, encoding ? "w" : "r");
    else
	fp = fopen(path, encoding ? "w" : "r");
    if (!fp)
	return 0;
    lzfile = calloc(1, sizeof(*lzfile));
    if (!lzfile) {
	fclose(fp);
	return 0;
    }
    
    lzfile->file = fp;
    lzfile->encoding = encoding;
    lzfile->eof = 0;
    lzfile->strm = init_strm;
    if (encoding) {
	if (xz) {
	    ret = lzma_easy_encoder(&lzfile->strm, level, LZMA_CHECK_SHA256);
	} else {
	    lzma_options_lzma options;
	    lzma_lzma_preset(&options, level);
	    ret = lzma_alone_encoder(&lzfile->strm, &options);
	}
    } else {	/* lzma_easy_decoder_memusage(level) is not ready yet, use hardcoded limit for now */
	ret = lzma_auto_decoder(&lzfile->strm, 100<<20, 0);
    }
    if (ret != LZMA_OK) {
	fclose(fp);
	free(lzfile);
	return 0;
    }
    return lzfile;
}
Пример #11
0
static void io_do_compress(io_private_t *io_ptr)
{
	lzma_stream l = LZMA_STREAM_INIT;
	io_ptr->lzma_handle = l;

	lzma_filter lzf[2];
	lzma_options_lzma lzo;
	lzma_lzma_preset(&lzo, LZMA_PRESET_DEFAULT);
	lzf[0].id = LZMA_FILTER_LZMA2;
	lzf[0].options = &lzo;
	lzf[1].id = LZMA_VLI_UNKNOWN;
	if (lzma_stream_encoder(&io_ptr->lzma_handle, lzf, LZMA_CHECK_NONE) != LZMA_OK)
		return;
	io_ptr->lzma_init = true;
	return;
}
Пример #12
0
static void
filter_lzma_init(struct io_lzma *io, lzma_stream *s)
{
	uint32_t preset;
	lzma_options_lzma options;
	lzma_ret ret;

	io->status |= DPKG_STREAM_COMPRESS;

	preset = io->params->level;
	if (io->params->strategy == COMPRESSOR_STRATEGY_EXTREME)
		preset |= LZMA_PRESET_EXTREME;
	if (lzma_lzma_preset(&options, preset))
		filter_lzma_error(io, LZMA_OPTIONS_ERROR);

	ret = lzma_alone_encoder(s, &options);
	if (ret != LZMA_OK)
		filter_lzma_error(io, ret);
}
Пример #13
0
int
TIFFInitLZMA(TIFF* tif, int scheme)
{
    static const char module[] = "TIFFInitLZMA";
    LZMAState* sp;
    lzma_stream tmp_stream = LZMA_STREAM_INIT;

    assert( scheme == COMPRESSION_LZMA );

    /*
     * Merge codec-specific tag information.
     */
    if (!_TIFFMergeFields(tif, lzmaFields, TIFFArrayCount(lzmaFields))) {
        TIFFErrorExt(tif->tif_clientdata, module,
                 "Merging LZMA2 codec-specific tags failed");
        return 0;
    }

    /*
     * Allocate state block so tag methods have storage to record values.
     */
    tif->tif_data = (uint8*) _TIFFmalloc(sizeof(LZMAState));
    if (tif->tif_data == NULL)
        goto bad;
    sp = LState(tif);
    memcpy(&sp->stream, &tmp_stream, sizeof(lzma_stream));

    /*
     * Override parent get/set field methods.
     */
    sp->vgetparent = tif->tif_tagmethods.vgetfield;
    tif->tif_tagmethods.vgetfield = LZMAVGetField;	/* hook for codec tags */
    sp->vsetparent = tif->tif_tagmethods.vsetfield;
    tif->tif_tagmethods.vsetfield = LZMAVSetField;	/* hook for codec tags */

    /* Default values for codec-specific fields */
    sp->preset = LZMA_PRESET_DEFAULT;		/* default comp. level */
    sp->check = LZMA_CHECK_NONE;
    sp->state = 0;

    /* Data filters. So far we are using delta and LZMA2 filters only. */
    sp->opt_delta.type = LZMA_DELTA_TYPE_BYTE;
    /*
     * The sample size in bytes seems to be reasonable distance for delta
     * filter.
     */
    sp->opt_delta.dist = (tif->tif_dir.td_bitspersample % 8) ?
        1 : tif->tif_dir.td_bitspersample / 8;
    sp->filters[0].id = LZMA_FILTER_DELTA;
    sp->filters[0].options = &sp->opt_delta;

    lzma_lzma_preset(&sp->opt_lzma, sp->preset);
    sp->filters[1].id = LZMA_FILTER_LZMA2;
    sp->filters[1].options = &sp->opt_lzma;

    sp->filters[2].id = LZMA_VLI_UNKNOWN;
    sp->filters[2].options = NULL;

    /*
     * Install codec methods.
     */
    tif->tif_fixuptags = LZMAFixupTags;
    tif->tif_setupdecode = LZMASetupDecode;
    tif->tif_predecode = LZMAPreDecode;
    tif->tif_decoderow = LZMADecode;
    tif->tif_decodestrip = LZMADecode;
    tif->tif_decodetile = LZMADecode;
    tif->tif_setupencode = LZMASetupEncode;
    tif->tif_preencode = LZMAPreEncode;
    tif->tif_postencode = LZMAPostEncode;
    tif->tif_encoderow = LZMAEncode;
    tif->tif_encodestrip = LZMAEncode;
    tif->tif_encodetile = LZMAEncode;
    tif->tif_cleanup = LZMACleanup;
    /*
     * Setup predictor setup.
     */
    (void) TIFFPredictorInit(tif);
    return 1;
bad:
    TIFFErrorExt(tif->tif_clientdata, module,
             "No space for LZMA2 state block");
    return 0;
}
Пример #14
0
static inline lzma_ret setup_alone_encoder(lzma_stream *strm, int level)
{
  lzma_options_lzma options;
  lzma_lzma_preset(&options, level);
  return lzma_alone_encoder(strm, &options);
}
Пример #15
0
/*
 * Setup callback.
 */
static int
archive_compressor_xz_open(struct archive_write_filter *f)
{
	struct private_data *data = f->data;
	int ret;

	ret = __archive_write_open_filter(f->next_filter);
	if (ret != ARCHIVE_OK)
		return (ret);

	if (data->compressed == NULL) {
		size_t bs = 65536, bpb;
		if (f->archive->magic == ARCHIVE_WRITE_MAGIC) {
			/* Buffer size should be a multiple number of the of bytes
			 * per block for performance. */
			bpb = archive_write_get_bytes_per_block(f->archive);
			if (bpb > bs)
				bs = bpb;
			else if (bpb != 0)
				bs -= bs % bpb;
		}
		data->compressed_buffer_size = bs;
		data->compressed
		    = (unsigned char *)malloc(data->compressed_buffer_size);
		if (data->compressed == NULL) {
			archive_set_error(f->archive, ENOMEM,
			    "Can't allocate data for compression buffer");
			return (ARCHIVE_FATAL);
		}
	}

	f->write = archive_compressor_xz_write;

	/* Initialize compression library. */
	if (f->code == ARCHIVE_FILTER_LZIP) {
		const struct option_value *val =
		    &option_values[data->compression_level];

		data->lzma_opt.dict_size = val->dict_size;
		data->lzma_opt.preset_dict = NULL;
		data->lzma_opt.preset_dict_size = 0;
		data->lzma_opt.lc = LZMA_LC_DEFAULT;
		data->lzma_opt.lp = LZMA_LP_DEFAULT;
		data->lzma_opt.pb = LZMA_PB_DEFAULT;
		data->lzma_opt.mode =
		    data->compression_level<= 2? LZMA_MODE_FAST:LZMA_MODE_NORMAL;
		data->lzma_opt.nice_len = val->nice_len;
		data->lzma_opt.mf = val->mf;
		data->lzma_opt.depth = 0;
		data->lzmafilters[0].id = LZMA_FILTER_LZMA1;
		data->lzmafilters[0].options = &data->lzma_opt;
		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
	} else {
		if (lzma_lzma_preset(&data->lzma_opt, data->compression_level)) {
			archive_set_error(f->archive, ARCHIVE_ERRNO_MISC,
			    "Internal error initializing compression library");
		}
		data->lzmafilters[0].id = LZMA_FILTER_LZMA2;
		data->lzmafilters[0].options = &data->lzma_opt;
		data->lzmafilters[1].id = LZMA_VLI_UNKNOWN;/* Terminate */
	}
	ret = archive_compressor_xz_init_stream(f, data);
	if (ret == LZMA_OK) {
		f->data = data;
		return (0);
	}
	return (ARCHIVE_FATAL);
}
Пример #16
0
Файл: coder.c Проект: Garen/xz
extern void
coder_set_compression_settings(void)
{
	// The default check type is CRC64, but fallback to CRC32
	// if CRC64 isn't supported by the copy of liblzma we are
	// using. CRC32 is always supported.
	if (check_default) {
		check = LZMA_CHECK_CRC64;
		if (!lzma_check_is_supported(check))
			check = LZMA_CHECK_CRC32;
	}

	// Options for LZMA1 or LZMA2 in case we are using a preset.
	static lzma_options_lzma opt_lzma;

	if (filters_count == 0) {
		// We are using a preset. This is not a good idea in raw mode
		// except when playing around with things. Different versions
		// of this software may use different options in presets, and
		// thus make uncompressing the raw data difficult.
		if (opt_format == FORMAT_RAW) {
			// The message is shown only if warnings are allowed
			// but the exit status isn't changed.
			message(V_WARNING, _("Using a preset in raw mode "
					"is discouraged."));
			message(V_WARNING, _("The exact options of the "
					"presets may vary between software "
					"versions."));
		}

		// Get the preset for LZMA1 or LZMA2.
		if (lzma_lzma_preset(&opt_lzma, preset_number))
			message_bug();

		// Use LZMA2 except with --format=lzma we use LZMA1.
		filters[0].id = opt_format == FORMAT_LZMA
				? LZMA_FILTER_LZMA1 : LZMA_FILTER_LZMA2;
		filters[0].options = &opt_lzma;
		filters_count = 1;
	}

	// Terminate the filter options array.
	filters[filters_count].id = LZMA_VLI_UNKNOWN;

	// If we are using the .lzma format, allow exactly one filter
	// which has to be LZMA1.
	if (opt_format == FORMAT_LZMA && (filters_count != 1
			|| filters[0].id != LZMA_FILTER_LZMA1))
		message_fatal(_("The .lzma format supports only "
				"the LZMA1 filter"));

	// If we are using the .xz format, make sure that there is no LZMA1
	// filter to prevent LZMA_PROG_ERROR.
	if (opt_format == FORMAT_XZ)
		for (size_t i = 0; i < filters_count; ++i)
			if (filters[i].id == LZMA_FILTER_LZMA1)
				message_fatal(_("LZMA1 cannot be used "
						"with the .xz format"));

	// Print the selected filter chain.
	message_filters_show(V_DEBUG, filters);

	// Get the memory usage. Note that if --format=raw was used,
	// we can be decompressing.
	const uint64_t memory_limit = hardware_memlimit_get(opt_mode);
	uint64_t memory_usage;
	if (opt_mode == MODE_COMPRESS) {
#ifdef MYTHREAD_ENABLED
		if (opt_format == FORMAT_XZ && hardware_threads_get() > 1) {
			mt_options.threads = hardware_threads_get();
			mt_options.block_size = opt_block_size;
			mt_options.check = check;
			memory_usage = lzma_stream_encoder_mt_memusage(
					&mt_options);
			if (memory_usage != UINT64_MAX)
				message(V_DEBUG, _("Using up to %" PRIu32
						" threads."),
						mt_options.threads);
		} else
#endif
		{
			memory_usage = lzma_raw_encoder_memusage(filters);
		}
	} else {
		memory_usage = lzma_raw_decoder_memusage(filters);
	}

	if (memory_usage == UINT64_MAX)
		message_fatal(_("Unsupported filter chain or filter options"));

	// Print memory usage info before possible dictionary
	// size auto-adjusting.
	message_mem_needed(V_DEBUG, memory_usage);
	if (opt_mode == MODE_COMPRESS) {
		const uint64_t decmem = lzma_raw_decoder_memusage(filters);
		if (decmem != UINT64_MAX)
			message(V_DEBUG, _("Decompression will need "
					"%s MiB of memory."), uint64_to_str(
						round_up_to_mib(decmem), 0));
	}

	if (memory_usage <= memory_limit)
		return;

	// If --no-auto-adjust was used or we didn't find LZMA1 or
	// LZMA2 as the last filter, give an error immediately.
	// --format=raw implies --no-auto-adjust.
	if (!opt_auto_adjust || opt_format == FORMAT_RAW)
		memlimit_too_small(memory_usage);

	assert(opt_mode == MODE_COMPRESS);

#ifdef MYTHREAD_ENABLED
	if (opt_format == FORMAT_XZ && mt_options.threads > 1) {
		// Try to reduce the number of threads before
		// adjusting the compression settings down.
		do {
			// FIXME? The real single-threaded mode has
			// lower memory usage, but it's not comparable
			// because it doesn't write the size info
			// into Block Headers.
			if (--mt_options.threads == 0)
				memlimit_too_small(memory_usage);

			memory_usage = lzma_stream_encoder_mt_memusage(
					&mt_options);
			if (memory_usage == UINT64_MAX)
				message_bug();

		} while (memory_usage > memory_limit);

		message(V_WARNING, _("Adjusted the number of threads "
			"from %s to %s to not exceed "
			"the memory usage limit of %s MiB"),
			uint64_to_str(hardware_threads_get(), 0),
			uint64_to_str(mt_options.threads, 1),
			uint64_to_str(round_up_to_mib(
				memory_limit), 2));
	}
#endif

	if (memory_usage <= memory_limit) {
		return;
	}
	// Look for the last filter if it is LZMA2 or LZMA1, so we can make
	// it use less RAM. With other filters we don't know what to do.
	size_t i = 0;
	while (filters[i].id != LZMA_FILTER_LZMA2
			&& filters[i].id != LZMA_FILTER_LZMA1) {
		if (filters[i].id == LZMA_VLI_UNKNOWN)
			memlimit_too_small(memory_usage);

		++i;
	}

	// Decrease the dictionary size until we meet the memory
	// usage limit. First round down to full mebibytes.
	lzma_options_lzma *opt = filters[i].options;
	const uint32_t orig_dict_size = opt->dict_size;
	opt->dict_size &= ~((UINT32_C(1) << 20) - 1);
	while (true) {
		// If it is below 1 MiB, auto-adjusting failed. We could be
		// more sophisticated and scale it down even more, but let's
		// see if many complain about this version.
		//
		// FIXME: Displays the scaled memory usage instead
		// of the original.
		if (opt->dict_size < (UINT32_C(1) << 20))
			memlimit_too_small(memory_usage);

		memory_usage = lzma_raw_encoder_memusage(filters);
		if (memory_usage == UINT64_MAX)
			message_bug();

		// Accept it if it is low enough.
		if (memory_usage <= memory_limit)
			break;

		// Otherwise 1 MiB down and try again. I hope this
		// isn't too slow method for cases where the original
		// dict_size is very big.
		opt->dict_size -= UINT32_C(1) << 20;
	}

	// Tell the user that we decreased the dictionary size.
	message(V_WARNING, _("Adjusted LZMA%c dictionary size "
			"from %s MiB to %s MiB to not exceed "
			"the memory usage limit of %s MiB"),
			filters[i].id == LZMA_FILTER_LZMA2
				? '2' : '1',
			uint64_to_str(orig_dict_size >> 20, 0),
			uint64_to_str(opt->dict_size >> 20, 1),
			uint64_to_str(round_up_to_mib(memory_limit), 2));

	return;
}
Пример #17
0
Файл: pxz.c Проект: bagre/pxz
int main( int argc, char **argv ) {
    int i;
    uint64_t p, threads, chunk_size;
    uint8_t *m;
    struct stat s;
    ssize_t rd, ts = 0;
    size_t page_size;
    struct sigaction new_action, old_action;
    struct utimbuf u;
    lzma_filter filters[LZMA_FILTERS_MAX + 1];
    lzma_options_lzma lzma_options;

    xzcmd_max = sysconf(_SC_ARG_MAX);
    page_size = sysconf(_SC_PAGE_SIZE);
    xzcmd = malloc(xzcmd_max);
    snprintf(xzcmd, xzcmd_max, XZ_BINARY);

    parse_args(argc, argv);

    lzma_lzma_preset(&lzma_options, opt_complevel);

    filters[0].id = LZMA_FILTER_LZMA2;
    filters[0].options = &lzma_options;
    filters[1].id = LZMA_VLI_UNKNOWN;


    for (i=0; i<files; i++) {
        int std_in = file[i][0] == '-' && file[i][1] == '\0';
#ifdef _OPENMP
        threads = omp_get_max_threads();
#else
        threads = 1;
#endif
        if ( (rd=strlen(file[i])) >= 3 && !strncmp(&file[i][rd-3], ".xz", 3) ) {
            if (opt_verbose) {
                error(EXIT_FAILURE, 0, "ignoring '%s', it seems to be already compressed", file[i]);
            }
            continue;
        }

        if ( !std_in ) {
            if ( stat(file[i], &s)) {
                error(EXIT_FAILURE, errno, "can't stat '%s'", file[i]);
            }
        }

        chunk_size = opt_context_size * lzma_options.dict_size;
        chunk_size = (chunk_size + page_size)&~(page_size-1);

        if ( opt_verbose ) {
            fprintf(stderr, "context size per thread: %"PRIu64" B\n", chunk_size);
        }

        if ( opt_threads && (threads > opt_threads || opt_force) ) {
            threads = opt_threads;
        }

        fo = stdout;
        if ( std_in ) {
            fi = stdin;
        } else {
            if ( !(fi=fopen(file[i], "rb")) ) {
                error(EXIT_FAILURE, errno, "can't open '%s' for reading", file[i]);
            }
            if ( !opt_stdout ) {
                snprintf(str, sizeof(str), "%s.xz", file[i]);
                if ( !(fo=fopen(str, "wb")) ) {
                    error(EXIT_FAILURE, errno, "error creating target archive '%s'", str);
                }
            }
        }

        if ( opt_verbose ) {
            if ( fo != stdout ) {
                fprintf(stderr, "%s -> %"PRIu64"/%"PRIu64" thread%c: [", file[i], threads, (s.st_size+chunk_size-1)/chunk_size, threads != 1 ? 's' : ' ');
            } else {
                fprintf(stderr, "%"PRIu64" thread%c: [", threads, threads != 1 ? 's' : ' ');
            }
            fflush(stderr);
        }

        m  = malloc(threads*chunk_size);

        new_action.sa_handler = term_handler;
        sigemptyset (&new_action.sa_mask);
        new_action.sa_flags = 0;

        sigaction(SIGINT, NULL, &old_action);
        if (old_action.sa_handler != SIG_IGN) sigaction(SIGINT, &new_action, NULL);
        sigaction(SIGHUP, NULL, &old_action);
        if (old_action.sa_handler != SIG_IGN) sigaction(SIGHUP, &new_action, NULL);
        sigaction(SIGTERM, NULL, &old_action);
        if (old_action.sa_handler != SIG_IGN) sigaction(SIGTERM, &new_action, NULL);

        ftemp = malloc(threads*sizeof(ftemp[0]));

        while ( !feof(fi) ) {
            size_t actrd;

            for (p=0; p<threads; p++) {
                ftemp[p] = tmpfile();
            }

            for ( actrd=rd=0; !feof(fi) && !ferror(fi) && (uint64_t)rd < threads*chunk_size; rd += actrd) {
                actrd = fread(&m[rd], 1, threads*chunk_size-actrd, fi);
            }
            if (ferror(fi)) {
                error(EXIT_FAILURE, errno, "error in reading input");
            }

            #pragma omp parallel for private(p) num_threads(threads)
            for ( p=0; p<(rd+chunk_size-1)/chunk_size; p++ ) {
                off_t pt, len = rd-p*chunk_size >= chunk_size ? chunk_size : rd-p*chunk_size;
                uint8_t *mo;
                lzma_stream strm = LZMA_STREAM_INIT;
                lzma_ret ret;

                mo = malloc(BUFFSIZE);

                if ( lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC64) != LZMA_OK ) {
                    error(EXIT_FAILURE, errno, "unable to initialize LZMA encoder");
                }

                for (pt=0; pt<len; pt+=BUFFSIZE) {
                    strm.next_in = &m[p*chunk_size+pt];
                    strm.avail_in = len-pt >= BUFFSIZE ? BUFFSIZE : len-pt;
                    strm.next_out = mo;
                    strm.avail_out = BUFFSIZE;
                    do {
                        ret = lzma_code(&strm, LZMA_RUN);
                        if ( ret != LZMA_OK ) {
                            error(EXIT_FAILURE, 0, "error in LZMA_RUN");
                        }
                        if ( BUFFSIZE - strm.avail_out > 0 ) {
                            if ( !fwrite(mo, 1, BUFFSIZE - strm.avail_out, ftemp[p]) ) {
                                error(EXIT_FAILURE, errno, "writing to temp file failed");
                            }
                            strm.next_out = mo;
                            strm.avail_out = BUFFSIZE;
                        }
                    } while ( strm.avail_in );
                }

                strm.next_out = mo;
                strm.avail_out = BUFFSIZE;
                do {
                    ret = lzma_code(&strm, LZMA_FINISH);
                    if ( ret != LZMA_OK && ret != LZMA_STREAM_END ) {
                        error(EXIT_FAILURE, 0, "error in LZMA_FINISH");
                    }
                    if ( BUFFSIZE - strm.avail_out > 0 ) {
                        if ( !fwrite(mo, 1, BUFFSIZE - strm.avail_out, ftemp[p]) ) {
                            error(EXIT_FAILURE, errno, "writing to temp file failed");
                        }
                        strm.next_out = mo;
                        strm.avail_out = BUFFSIZE;
                    }
                } while ( ret == LZMA_OK );
                lzma_end(&strm);

                free(mo);

                if ( opt_verbose ) {
                    fprintf(stderr, "%"PRIu64" ", p);
                    fflush(stderr);
                }
            }

            for ( p=0; p<threads; p++ ) {
                rewind(ftemp[p]);
                while ( (rd=fread(buf, 1, sizeof(buf), ftemp[p])) > 0 ) {
                    if ( fwrite(buf, 1, rd, fo) != (size_t)rd ) {
                        error(0, errno, "writing to archive failed");
                        if ( fo != stdout && unlink(str) ) {
                            error(0, errno, "error deleting corrupted target archive %s", str);
                        }
                        exit(EXIT_FAILURE);
                    } else ts += rd;
                }
                if (rd < 0) {
                    error(0, errno, "reading from temporary file failed");
                    if ( fo != stdout && unlink(str) ) {
                        error(0, errno, "error deleting corrupted target archive %s", str);
                    }
                    exit(EXIT_FAILURE);
                }
                if ( close_stream(ftemp[p]) ) {
                    error(0, errno, "I/O error in temp file");
                }
            }
        }

        if ( fi != stdin && close_stream(fi) ) {
            error(0, errno, "I/O error in input file");
        }

        if ( opt_verbose ) {
            fprintf(stderr, "] ");
        }

        free(ftemp);

        if ( fo != stdout ) {
            if ( close_stream(fo) ) {
                error(0, errno, "I/O error in target archive");
            }
        } else return 0;

        if ( chmod(str, s.st_mode) ) {
            error(0, errno, "warning: unable to change archive permissions");
        }

        u.actime = s.st_atime;
        u.modtime = s.st_mtime;

        if ( utime(str, &u) ) {
            error(0, errno, "warning: unable to change archive timestamp");
        }

        sigaction(SIGINT, &old_action, NULL);
        sigaction(SIGHUP, &old_action, NULL);
        sigaction(SIGTERM, &old_action, NULL);

        if ( opt_verbose ) {
            fprintf(stderr, "%"PRIu64" -> %zd %3.3f%%\n", s.st_size, ts, ts*100./s.st_size);
        }

        if ( !opt_keep && unlink(file[i]) ) {
            error(0, errno, "error deleting input file %s", file[i]);
        }
    }

    return 0;
}