1 // SPDX-License-Identifier: 0BSD
3 ///////////////////////////////////////////////////////////////////////////////
5 /// \file block_header_encoder.c
6 /// \brief Encodes Block Header for .xz files
8 // Author: Lasse Collin
10 ///////////////////////////////////////////////////////////////////////////////
16 extern LZMA_API(lzma_ret
)
17 lzma_block_header_size(lzma_block
*block
)
19 if (block
->version
> 1)
20 return LZMA_OPTIONS_ERROR
;
22 // Block Header Size + Block Flags + CRC32.
23 uint32_t size
= 1 + 1 + 4;
26 if (block
->compressed_size
!= LZMA_VLI_UNKNOWN
) {
27 const uint32_t add
= lzma_vli_size(block
->compressed_size
);
28 if (add
== 0 || block
->compressed_size
== 0)
29 return LZMA_PROG_ERROR
;
35 if (block
->uncompressed_size
!= LZMA_VLI_UNKNOWN
) {
36 const uint32_t add
= lzma_vli_size(block
->uncompressed_size
);
38 return LZMA_PROG_ERROR
;
43 // List of Filter Flags
44 if (block
->filters
== NULL
|| block
->filters
[0].id
== LZMA_VLI_UNKNOWN
)
45 return LZMA_PROG_ERROR
;
47 for (size_t i
= 0; block
->filters
[i
].id
!= LZMA_VLI_UNKNOWN
; ++i
) {
48 // Don't allow too many filters.
49 if (i
== LZMA_FILTERS_MAX
)
50 return LZMA_PROG_ERROR
;
53 return_if_error(lzma_filter_flags_size(&add
,
59 // Pad to a multiple of four bytes.
60 block
->header_size
= (size
+ 3) & ~UINT32_C(3);
62 // NOTE: We don't verify that the encoded size of the Block stays
63 // within limits. This is because it is possible that we are called
64 // with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve
65 // space for Block Header, and later called again with lower,
72 extern LZMA_API(lzma_ret
)
73 lzma_block_header_encode(const lzma_block
*block
, uint8_t *out
)
75 // Validate everything but filters.
76 if (lzma_block_unpadded_size(block
) == 0
77 || !lzma_vli_is_valid(block
->uncompressed_size
))
78 return LZMA_PROG_ERROR
;
80 // Indicate the size of the buffer _excluding_ the CRC32 field.
81 const size_t out_size
= block
->header_size
- 4;
83 // Store the Block Header Size.
84 out
[0] = out_size
/ 4;
86 // We write Block Flags in pieces.
91 if (block
->compressed_size
!= LZMA_VLI_UNKNOWN
) {
92 return_if_error(lzma_vli_encode(block
->compressed_size
, NULL
,
93 out
, &out_pos
, out_size
));
99 if (block
->uncompressed_size
!= LZMA_VLI_UNKNOWN
) {
100 return_if_error(lzma_vli_encode(block
->uncompressed_size
, NULL
,
101 out
, &out_pos
, out_size
));
107 if (block
->filters
== NULL
|| block
->filters
[0].id
== LZMA_VLI_UNKNOWN
)
108 return LZMA_PROG_ERROR
;
110 size_t filter_count
= 0;
112 // There can be a maximum of four filters.
113 if (filter_count
== LZMA_FILTERS_MAX
)
114 return LZMA_PROG_ERROR
;
116 return_if_error(lzma_filter_flags_encode(
117 block
->filters
+ filter_count
,
118 out
, &out_pos
, out_size
));
120 } while (block
->filters
[++filter_count
].id
!= LZMA_VLI_UNKNOWN
);
122 out
[1] |= filter_count
- 1;
125 memzero(out
+ out_pos
, out_size
- out_pos
);
128 write32le(out
+ out_size
, lzma_crc32(out
, out_size
, 0));