12940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
22940b44dSPeter Avalos //
3*e151908bSDaniel Fojt /// \file       block_util.c
42940b44dSPeter Avalos /// \brief      Utility functions to handle lzma_block
52940b44dSPeter Avalos //
62940b44dSPeter Avalos //  Author:     Lasse Collin
72940b44dSPeter Avalos //
82940b44dSPeter Avalos //  This file has been put into the public domain.
92940b44dSPeter Avalos //  You can do whatever you want with this file.
102940b44dSPeter Avalos //
112940b44dSPeter Avalos ///////////////////////////////////////////////////////////////////////////////
122940b44dSPeter Avalos 
132940b44dSPeter Avalos #include "common.h"
142940b44dSPeter Avalos #include "index.h"
152940b44dSPeter Avalos 
162940b44dSPeter Avalos 
172940b44dSPeter Avalos extern LZMA_API(lzma_ret)
lzma_block_compressed_size(lzma_block * block,lzma_vli unpadded_size)182940b44dSPeter Avalos lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
192940b44dSPeter Avalos {
202940b44dSPeter Avalos 	// Validate everything but Uncompressed Size and filters.
212940b44dSPeter Avalos 	if (lzma_block_unpadded_size(block) == 0)
222940b44dSPeter Avalos 		return LZMA_PROG_ERROR;
232940b44dSPeter Avalos 
242940b44dSPeter Avalos 	const uint32_t container_size = block->header_size
252940b44dSPeter Avalos 			+ lzma_check_size(block->check);
262940b44dSPeter Avalos 
272940b44dSPeter Avalos 	// Validate that Compressed Size will be greater than zero.
282940b44dSPeter Avalos 	if (unpadded_size <= container_size)
292940b44dSPeter Avalos 		return LZMA_DATA_ERROR;
302940b44dSPeter Avalos 
312940b44dSPeter Avalos 	// Calculate what Compressed Size is supposed to be.
322940b44dSPeter Avalos 	// If Compressed Size was present in Block Header,
332940b44dSPeter Avalos 	// compare that the new value matches it.
342940b44dSPeter Avalos 	const lzma_vli compressed_size = unpadded_size - container_size;
352940b44dSPeter Avalos 	if (block->compressed_size != LZMA_VLI_UNKNOWN
362940b44dSPeter Avalos 			&& block->compressed_size != compressed_size)
372940b44dSPeter Avalos 		return LZMA_DATA_ERROR;
382940b44dSPeter Avalos 
392940b44dSPeter Avalos 	block->compressed_size = compressed_size;
402940b44dSPeter Avalos 
412940b44dSPeter Avalos 	return LZMA_OK;
422940b44dSPeter Avalos }
432940b44dSPeter Avalos 
442940b44dSPeter Avalos 
452940b44dSPeter Avalos extern LZMA_API(lzma_vli)
lzma_block_unpadded_size(const lzma_block * block)462940b44dSPeter Avalos lzma_block_unpadded_size(const lzma_block *block)
472940b44dSPeter Avalos {
482940b44dSPeter Avalos 	// Validate the values that we are interested in i.e. all but
492940b44dSPeter Avalos 	// Uncompressed Size and the filters.
502940b44dSPeter Avalos 	//
512940b44dSPeter Avalos 	// NOTE: This function is used for validation too, so it is
522940b44dSPeter Avalos 	// essential that these checks are always done even if
532940b44dSPeter Avalos 	// Compressed Size is unknown.
5415ab8c86SJohn Marino 	if (block == NULL || block->version > 1
552940b44dSPeter Avalos 			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
562940b44dSPeter Avalos 			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
572940b44dSPeter Avalos 			|| (block->header_size & 3)
582940b44dSPeter Avalos 			|| !lzma_vli_is_valid(block->compressed_size)
592940b44dSPeter Avalos 			|| block->compressed_size == 0
602940b44dSPeter Avalos 			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
612940b44dSPeter Avalos 		return 0;
622940b44dSPeter Avalos 
632940b44dSPeter Avalos 	// If Compressed Size is unknown, return that we cannot know
642940b44dSPeter Avalos 	// size of the Block either.
652940b44dSPeter Avalos 	if (block->compressed_size == LZMA_VLI_UNKNOWN)
662940b44dSPeter Avalos 		return LZMA_VLI_UNKNOWN;
672940b44dSPeter Avalos 
682940b44dSPeter Avalos 	// Calculate Unpadded Size and validate it.
692940b44dSPeter Avalos 	const lzma_vli unpadded_size = block->compressed_size
702940b44dSPeter Avalos 				+ block->header_size
712940b44dSPeter Avalos 				+ lzma_check_size(block->check);
722940b44dSPeter Avalos 
732940b44dSPeter Avalos 	assert(unpadded_size >= UNPADDED_SIZE_MIN);
742940b44dSPeter Avalos 	if (unpadded_size > UNPADDED_SIZE_MAX)
752940b44dSPeter Avalos 		return 0;
762940b44dSPeter Avalos 
772940b44dSPeter Avalos 	return unpadded_size;
782940b44dSPeter Avalos }
792940b44dSPeter Avalos 
802940b44dSPeter Avalos 
812940b44dSPeter Avalos extern LZMA_API(lzma_vli)
lzma_block_total_size(const lzma_block * block)822940b44dSPeter Avalos lzma_block_total_size(const lzma_block *block)
832940b44dSPeter Avalos {
842940b44dSPeter Avalos 	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
852940b44dSPeter Avalos 
862940b44dSPeter Avalos 	if (unpadded_size != LZMA_VLI_UNKNOWN)
872940b44dSPeter Avalos 		unpadded_size = vli_ceil4(unpadded_size);
882940b44dSPeter Avalos 
892940b44dSPeter Avalos 	return unpadded_size;
902940b44dSPeter Avalos }
91