1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file block_header_encoder.c
4 /// \brief Encodes Block Header for .xz files
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
17 extern LZMA_API(lzma_ret
)
18 lzma_block_header_size(lzma_block
*block
)
20 if (block
->version
> 1)
21 return LZMA_OPTIONS_ERROR
;
23 // Block Header Size + Block Flags + CRC32.
24 uint32_t size
= 1 + 1 + 4;
27 if (block
->compressed_size
!= LZMA_VLI_UNKNOWN
) {
28 const uint32_t add
= lzma_vli_size(block
->compressed_size
);
29 if (add
== 0 || block
->compressed_size
== 0)
30 return LZMA_PROG_ERROR
;
36 if (block
->uncompressed_size
!= LZMA_VLI_UNKNOWN
) {
37 const uint32_t add
= lzma_vli_size(block
->uncompressed_size
);
39 return LZMA_PROG_ERROR
;
44 // List of Filter Flags
45 if (block
->filters
== NULL
|| block
->filters
[0].id
== LZMA_VLI_UNKNOWN
)
46 return LZMA_PROG_ERROR
;
48 for (size_t i
= 0; block
->filters
[i
].id
!= LZMA_VLI_UNKNOWN
; ++i
) {
49 // Don't allow too many filters.
50 if (i
== LZMA_FILTERS_MAX
)
51 return LZMA_PROG_ERROR
;
54 return_if_error(lzma_filter_flags_size(&add
,
60 // Pad to a multiple of four bytes.
61 block
->header_size
= (size
+ 3) & ~UINT32_C(3);
63 // NOTE: We don't verify that the encoded size of the Block stays
64 // within limits. This is because it is possible that we are called
65 // with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve
66 // space for Block Header, and later called again with lower,
73 extern LZMA_API(lzma_ret
)
74 lzma_block_header_encode(const lzma_block
*block
, uint8_t *out
)
76 // Validate everything but filters.
77 if (lzma_block_unpadded_size(block
) == 0
78 || !lzma_vli_is_valid(block
->uncompressed_size
))
79 return LZMA_PROG_ERROR
;
81 // Indicate the size of the buffer _excluding_ the CRC32 field.
82 const size_t out_size
= block
->header_size
- 4;
84 // Store the Block Header Size.
85 out
[0] = out_size
/ 4;
87 // We write Block Flags in pieces.
92 if (block
->compressed_size
!= LZMA_VLI_UNKNOWN
) {
93 return_if_error(lzma_vli_encode(block
->compressed_size
, NULL
,
94 out
, &out_pos
, out_size
));
100 if (block
->uncompressed_size
!= LZMA_VLI_UNKNOWN
) {
101 return_if_error(lzma_vli_encode(block
->uncompressed_size
, NULL
,
102 out
, &out_pos
, out_size
));
108 if (block
->filters
== NULL
|| block
->filters
[0].id
== LZMA_VLI_UNKNOWN
)
109 return LZMA_PROG_ERROR
;
111 size_t filter_count
= 0;
113 // There can be a maximum of four filters.
114 if (filter_count
== LZMA_FILTERS_MAX
)
115 return LZMA_PROG_ERROR
;
117 return_if_error(lzma_filter_flags_encode(
118 block
->filters
+ filter_count
,
119 out
, &out_pos
, out_size
));
121 } while (block
->filters
[++filter_count
].id
!= LZMA_VLI_UNKNOWN
);
123 out
[1] |= filter_count
- 1;
126 memzero(out
+ out_pos
, out_size
- out_pos
);
129 write32le(out
+ out_size
, lzma_crc32(out
, out_size
, 0));