1207753Smm///////////////////////////////////////////////////////////////////////////////
2207753Smm//
3207753Smm/// \file       block_header.c
4207753Smm/// \brief      Utility functions to handle lzma_block
5207753Smm//
6207753Smm//  Author:     Lasse Collin
7207753Smm//
8207753Smm//  This file has been put into the public domain.
9207753Smm//  You can do whatever you want with this file.
10207753Smm//
11207753Smm///////////////////////////////////////////////////////////////////////////////
12207753Smm
13207753Smm#include "common.h"
14207753Smm#include "index.h"
15207753Smm
16207753Smm
17207753Smmextern LZMA_API(lzma_ret)
18213700Smmlzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
19207753Smm{
20207753Smm	// Validate everything but Uncompressed Size and filters.
21207753Smm	if (lzma_block_unpadded_size(block) == 0)
22207753Smm		return LZMA_PROG_ERROR;
23207753Smm
24207753Smm	const uint32_t container_size = block->header_size
25207753Smm			+ lzma_check_size(block->check);
26207753Smm
27207753Smm	// Validate that Compressed Size will be greater than zero.
28213700Smm	if (unpadded_size <= container_size)
29207753Smm		return LZMA_DATA_ERROR;
30207753Smm
31207753Smm	// Calculate what Compressed Size is supposed to be.
32207753Smm	// If Compressed Size was present in Block Header,
33207753Smm	// compare that the new value matches it.
34213700Smm	const lzma_vli compressed_size = unpadded_size - container_size;
35207753Smm	if (block->compressed_size != LZMA_VLI_UNKNOWN
36207753Smm			&& block->compressed_size != compressed_size)
37207753Smm		return LZMA_DATA_ERROR;
38207753Smm
39207753Smm	block->compressed_size = compressed_size;
40207753Smm
41207753Smm	return LZMA_OK;
42207753Smm}
43207753Smm
44207753Smm
45207753Smmextern LZMA_API(lzma_vli)
46207753Smmlzma_block_unpadded_size(const lzma_block *block)
47207753Smm{
48207753Smm	// Validate the values that we are interested in i.e. all but
49207753Smm	// Uncompressed Size and the filters.
50207753Smm	//
51207753Smm	// NOTE: This function is used for validation too, so it is
52207753Smm	// essential that these checks are always done even if
53207753Smm	// Compressed Size is unknown.
54207753Smm	if (block == NULL || block->version != 0
55207753Smm			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
56207753Smm			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
57207753Smm			|| (block->header_size & 3)
58207753Smm			|| !lzma_vli_is_valid(block->compressed_size)
59207753Smm			|| block->compressed_size == 0
60207753Smm			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
61207753Smm		return 0;
62207753Smm
63207753Smm	// If Compressed Size is unknown, return that we cannot know
64207753Smm	// size of the Block either.
65207753Smm	if (block->compressed_size == LZMA_VLI_UNKNOWN)
66207753Smm		return LZMA_VLI_UNKNOWN;
67207753Smm
68207753Smm	// Calculate Unpadded Size and validate it.
69207753Smm	const lzma_vli unpadded_size = block->compressed_size
70207753Smm				+ block->header_size
71207753Smm				+ lzma_check_size(block->check);
72207753Smm
73207753Smm	assert(unpadded_size >= UNPADDED_SIZE_MIN);
74207753Smm	if (unpadded_size > UNPADDED_SIZE_MAX)
75207753Smm		return 0;
76207753Smm
77207753Smm	return unpadded_size;
78207753Smm}
79207753Smm
80207753Smm
81207753Smmextern LZMA_API(lzma_vli)
82207753Smmlzma_block_total_size(const lzma_block *block)
83207753Smm{
84207753Smm	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
85207753Smm
86207753Smm	if (unpadded_size != LZMA_VLI_UNKNOWN)
87207753Smm		unpadded_size = vli_ceil4(unpadded_size);
88207753Smm
89207753Smm	return unpadded_size;
90207753Smm}
91