lzma_easy_decoder_memusage(uint32_t preset)
{
	lzma_options_easy opt_easy;
	if (lzma_easy_preset(&opt_easy, preset))
		return UINT32_MAX;

	return lzma_raw_decoder_memusage(opt_easy.filters);
}
示例#2
0
Handle<Value> lzmaRawDecoderMemusage(const Arguments& args) {
	HandleScope scope;
	Local<Array> arg = Local<Array>::Cast(args[0]);
	if (arg.IsEmpty() || args[0]->IsUndefined()) {
		ThrowException(Exception::TypeError(String::New("rawdecoderMemusage requires filter array as arguments")));
		return scope.Close(Undefined());
	}
	
	const FilterArray fa(arg);
	if (!fa.ok()) 
		return scope.Close(Undefined());
	
	return scope.Close(Uint64ToNumberMaxNull(lzma_raw_decoder_memusage(fa.array())));
}
示例#3
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;
}
示例#4
0
		.lc = 3,
		.lp = 0,
		.pb = 2,
		.preset_dict = NULL,
		.preset_dict_size = 0,
		.mode = LZMA_MODE_NORMAL,
		.nice_len = 48,
		.mf = LZMA_MF_BT4,
		.depth = 0,
	};

/*
	lzma_options_filter filters[] = {
		{ LZMA_FILTER_LZMA1,
			(lzma_options_lzma *)&lzma_preset_lzma[6 - 1] },
		{ UINT64_MAX, NULL }
	};
*/
	lzma_filter filters[] = {
		{ LZMA_FILTER_LZMA1, &lzma },
		{ UINT64_MAX, NULL }
	};

	printf("Encoder: %10" PRIu64 " B\n",
			lzma_raw_encoder_memusage(filters));
	printf("Decoder: %10" PRIu64 " B\n",
			lzma_raw_decoder_memusage(filters));

	return 0;
}
示例#5
0
/// \brief      Parse the Block Header
///
/// The result is stored into *bhi. The caller takes care of initializing it.
///
/// \return     False on success, true on error.
static bool
parse_block_header(file_pair *pair, const lzma_index_iter *iter,
		block_header_info *bhi, xz_file_info *xfi)
{
#if IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
#	error IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
#endif

	// Get the whole Block Header with one read, but don't read past
	// the end of the Block (or even its Check field).
	const uint32_t size = my_min(iter->block.total_size
				- lzma_check_size(iter->stream.flags->check),
			LZMA_BLOCK_HEADER_SIZE_MAX);
	io_buf buf;
	if (io_pread(pair, &buf, size, iter->block.compressed_file_offset))
		return true;

	// Zero would mean Index Indicator and thus not a valid Block.
	if (buf.u8[0] == 0)
		goto data_error;

	// Initialize the block structure and decode Block Header Size.
	lzma_filter filters[LZMA_FILTERS_MAX + 1];
	lzma_block block;
	block.version = 0;
	block.check = iter->stream.flags->check;
	block.filters = filters;

	block.header_size = lzma_block_header_size_decode(buf.u8[0]);
	if (block.header_size > size)
		goto data_error;

	// Decode the Block Header.
	switch (lzma_block_header_decode(&block, NULL, buf.u8)) {
	case LZMA_OK:
		break;

	case LZMA_OPTIONS_ERROR:
		message_error("%s: %s", pair->src_name,
				message_strm(LZMA_OPTIONS_ERROR));
		return true;

	case LZMA_DATA_ERROR:
		goto data_error;

	default:
		message_bug();
	}

	// Check the Block Flags. These must be done before calling
	// lzma_block_compressed_size(), because it overwrites
	// block.compressed_size.
	bhi->flags[0] = block.compressed_size != LZMA_VLI_UNKNOWN
			? 'c' : '-';
	bhi->flags[1] = block.uncompressed_size != LZMA_VLI_UNKNOWN
			? 'u' : '-';
	bhi->flags[2] = '\0';

	// Collect information if all Blocks have both Compressed Size
	// and Uncompressed Size fields. They can be useful e.g. for
	// multi-threaded decompression so it can be useful to know it.
	xfi->all_have_sizes &= block.compressed_size != LZMA_VLI_UNKNOWN
			&& block.uncompressed_size != LZMA_VLI_UNKNOWN;

	// Validate or set block.compressed_size.
	switch (lzma_block_compressed_size(&block,
			iter->block.unpadded_size)) {
	case LZMA_OK:
		// Validate also block.uncompressed_size if it is present.
		// If it isn't present, there's no need to set it since
		// we aren't going to actually decompress the Block; if
		// we were decompressing, then we should set it so that
		// the Block decoder could validate the Uncompressed Size
		// that was stored in the Index.
		if (block.uncompressed_size == LZMA_VLI_UNKNOWN
				|| block.uncompressed_size
					== iter->block.uncompressed_size)
			break;

		// If the above fails, the file is corrupt so
		// LZMA_DATA_ERROR is a good error code.

	// Fall through

	case LZMA_DATA_ERROR:
		// Free the memory allocated by lzma_block_header_decode().
		for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
			free(filters[i].options);

		goto data_error;

	default:
		message_bug();
	}

	// Copy the known sizes.
	bhi->header_size = block.header_size;
	bhi->compressed_size = block.compressed_size;

	// Calculate the decoder memory usage and update the maximum
	// memory usage of this Block.
	bhi->memusage = lzma_raw_decoder_memusage(filters);
	if (xfi->memusage_max < bhi->memusage)
		xfi->memusage_max = bhi->memusage;

	// Determine the minimum XZ Utils version that supports this Block.
	//
	// Currently the only thing that 5.0.0 doesn't support is empty
	// LZMA2 Block. This decoder bug was fixed in 5.0.2.
	{
		size_t i = 0;
		while (filters[i + 1].id != LZMA_VLI_UNKNOWN)
			++i;

		if (filters[i].id == LZMA_FILTER_LZMA2
				&& iter->block.uncompressed_size == 0
				&& xfi->min_version < 50000022U)
			xfi->min_version = 50000022U;
	}

	// Convert the filter chain to human readable form.
	message_filters_to_str(bhi->filter_chain, filters, false);

	// Free the memory allocated by lzma_block_header_decode().
	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
		free(filters[i].options);

	return false;

data_error:
	// Show the error message.
	message_error("%s: %s", pair->src_name,
			message_strm(LZMA_DATA_ERROR));
	return true;
}
示例#6
0
文件: list.c 项目: AgamAgarwal/minix
/// \brief      Parse the Block Header
///
/// The result is stored into *bhi. The caller takes care of initializing it.
///
/// \return     False on success, true on error.
static bool
parse_block_header(file_pair *pair, const lzma_index_iter *iter,
		block_header_info *bhi, xz_file_info *xfi)
{
#if IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
#	error IO_BUFFER_SIZE < LZMA_BLOCK_HEADER_SIZE_MAX
#endif

	// Get the whole Block Header with one read, but don't read past
	// the end of the Block (or even its Check field).
	const uint32_t size = my_min(iter->block.total_size
				- lzma_check_size(iter->stream.flags->check),
			LZMA_BLOCK_HEADER_SIZE_MAX);
	io_buf buf;
	if (io_pread(pair, &buf, size, iter->block.compressed_file_offset))
		return true;

	// Zero would mean Index Indicator and thus not a valid Block.
	if (buf.u8[0] == 0)
		goto data_error;

	lzma_block block;
	lzma_filter filters[LZMA_FILTERS_MAX + 1];

	// Initialize the pointers so that they can be passed to free().
	for (size_t i = 0; i < ARRAY_SIZE(filters); ++i)
		filters[i].options = NULL;

	// Initialize the block structure and decode Block Header Size.
	block.version = 0;
	block.check = iter->stream.flags->check;
	block.filters = filters;

	block.header_size = lzma_block_header_size_decode(buf.u8[0]);
	if (block.header_size > size)
		goto data_error;

	// Decode the Block Header.
	switch (lzma_block_header_decode(&block, NULL, buf.u8)) {
	case LZMA_OK:
		break;

	case LZMA_OPTIONS_ERROR:
		message_error("%s: %s", pair->src_name,
				message_strm(LZMA_OPTIONS_ERROR));
		return true;

	case LZMA_DATA_ERROR:
		goto data_error;

	default:
		message_bug();
	}

	// Check the Block Flags. These must be done before calling
	// lzma_block_compressed_size(), because it overwrites
	// block.compressed_size.
	bhi->flags[0] = block.compressed_size != LZMA_VLI_UNKNOWN
			? 'c' : '-';
	bhi->flags[1] = block.uncompressed_size != LZMA_VLI_UNKNOWN
			? 'u' : '-';
	bhi->flags[2] = '\0';

	// Collect information if all Blocks have both Compressed Size
	// and Uncompressed Size fields. They can be useful e.g. for
	// multi-threaded decompression so it can be useful to know it.
	xfi->all_have_sizes &= block.compressed_size != LZMA_VLI_UNKNOWN
			&& block.uncompressed_size != LZMA_VLI_UNKNOWN;

	// Validate or set block.compressed_size.
	switch (lzma_block_compressed_size(&block,
			iter->block.unpadded_size)) {
	case LZMA_OK:
		break;

	case LZMA_DATA_ERROR:
		goto data_error;

	default:
		message_bug();
	}

	// Copy the known sizes.
	bhi->header_size = block.header_size;
	bhi->compressed_size = block.compressed_size;

	// Calculate the decoder memory usage and update the maximum
	// memory usage of this Block.
	bhi->memusage = lzma_raw_decoder_memusage(filters);
	if (xfi->memusage_max < bhi->memusage)
		xfi->memusage_max = bhi->memusage;

	// Convert the filter chain to human readable form.
	message_filters_to_str(bhi->filter_chain, filters, false);

	// Free the memory allocated by lzma_block_header_decode().
	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
		free(filters[i].options);

	return false;

data_error:
	// Show the error message.
	message_error("%s: %s", pair->src_name,
			message_strm(LZMA_DATA_ERROR));

	// Free the memory allocated by lzma_block_header_decode().
	// This is truly needed only if we get here after a succcessful
	// call to lzma_block_header_decode() but it doesn't hurt to
	// always do it.
	for (size_t i = 0; filters[i].id != LZMA_VLI_UNKNOWN; ++i)
		free(filters[i].options);

	return true;
}