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 |
|
17 |
extern LZMA_API(lzma_ret) |
18 |
lzma_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 |
|
45 |
extern LZMA_API(lzma_vli) |
46 |
lzma_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 |
|
81 |
extern LZMA_API(lzma_vli) |
82 |
lzma_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 |
} |