block_util.c revision 292588
1///////////////////////////////////////////////////////////////////////////////
2//
3/// \file       block_header.c
4/// \brief      Utility functions to handle lzma_block
5//
6//  Author:     Lasse Collin
7//
8//  This file has been put into the public domain.
9//  You can do whatever you want with this file.
10//
11///////////////////////////////////////////////////////////////////////////////
12
13#include "common.h"
14#include "index.h"
15
16
17extern LZMA_API(lzma_ret)
18lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
19{
20	// Validate everything but Uncompressed Size and filters.
21	if (lzma_block_unpadded_size(block) == 0)
22		return LZMA_PROG_ERROR;
23
24	const uint32_t container_size = block->header_size
25			+ lzma_check_size(block->check);
26
27	// Validate that Compressed Size will be greater than zero.
28	if (unpadded_size <= container_size)
29		return LZMA_DATA_ERROR;
30
31	// Calculate what Compressed Size is supposed to be.
32	// If Compressed Size was present in Block Header,
33	// compare that the new value matches it.
34	const lzma_vli compressed_size = unpadded_size - container_size;
35	if (block->compressed_size != LZMA_VLI_UNKNOWN
36			&& block->compressed_size != compressed_size)
37		return LZMA_DATA_ERROR;
38
39	block->compressed_size = compressed_size;
40
41	return LZMA_OK;
42}
43
44
45extern LZMA_API(lzma_vli)
46lzma_block_unpadded_size(const lzma_block *block)
47{
48	// Validate the values that we are interested in i.e. all but
49	// Uncompressed Size and the filters.
50	//
51	// NOTE: This function is used for validation too, so it is
52	// essential that these checks are always done even if
53	// Compressed Size is unknown.
54	if (block == NULL || block->version > 1
55			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
56			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
57			|| (block->header_size & 3)
58			|| !lzma_vli_is_valid(block->compressed_size)
59			|| block->compressed_size == 0
60			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
61		return 0;
62
63	// If Compressed Size is unknown, return that we cannot know
64	// size of the Block either.
65	if (block->compressed_size == LZMA_VLI_UNKNOWN)
66		return LZMA_VLI_UNKNOWN;
67
68	// Calculate Unpadded Size and validate it.
69	const lzma_vli unpadded_size = block->compressed_size
70				+ block->header_size
71				+ lzma_check_size(block->check);
72
73	assert(unpadded_size >= UNPADDED_SIZE_MIN);
74	if (unpadded_size > UNPADDED_SIZE_MAX)
75		return 0;
76
77	return unpadded_size;
78}
79
80
81extern LZMA_API(lzma_vli)
82lzma_block_total_size(const lzma_block *block)
83{
84	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
85
86	if (unpadded_size != LZMA_VLI_UNKNOWN)
87		unpadded_size = vli_ceil4(unpadded_size);
88
89	return unpadded_size;
90}
91