aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/block_header_encoder.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2008-06-18 18:02:10 +0300
committerLasse Collin <lasse.collin@tukaani.org>2008-06-18 18:02:10 +0300
commit7d17818cec8597f847b0a2537fde991bbc3d9e96 (patch)
tree9c41502e3eb96f103fe98e13456b382fbba7a292 /src/liblzma/common/block_header_encoder.c
parentUpdate the file format specification draft. The new one is (diff)
downloadxz-7d17818cec8597f847b0a2537fde991bbc3d9e96.tar.xz
Update the code to mostly match the new simpler file format
specification. Simplify things by removing most of the support for known uncompressed size in most places. There are some miscellaneous changes here and there too. The API of liblzma has got many changes and still some more will be done soon. While most of the code has been updated, some things are not fixed (the command line tool will choke with invalid filter chain, if nothing else). Subblock filter is somewhat broken for now. It will be updated once the encoded format of the Subblock filter has been decided.
Diffstat (limited to 'src/liblzma/common/block_header_encoder.c')
-rw-r--r--src/liblzma/common/block_header_encoder.c207
1 files changed, 74 insertions, 133 deletions
diff --git a/src/liblzma/common/block_header_encoder.c b/src/liblzma/common/block_header_encoder.c
index 594b4fc0..ed0c88ba 100644
--- a/src/liblzma/common/block_header_encoder.c
+++ b/src/liblzma/common/block_header_encoder.c
@@ -24,188 +24,129 @@
extern LZMA_API lzma_ret
lzma_block_header_size(lzma_options_block *options)
{
- // Block Flags take two bytes.
- size_t size = 2;
+ // Block Header Size + Block Flags + CRC32.
+ size_t size = 1 + 1 + 4;
// Compressed Size
- if (!lzma_vli_is_valid(options->compressed_size)) {
- return LZMA_PROG_ERROR;
-
- } else if (options->compressed_reserve != 0) {
- // Make sure that the known Compressed Size fits into the
- // reserved space. Note that lzma_vli_size() will return zero
- // if options->compressed_size is LZMA_VLI_VALUE_UNKNOWN, so
- // we don't need to handle that special case separately.
- if (options->compressed_reserve > LZMA_VLI_BYTES_MAX
- || lzma_vli_size(options->compressed_size)
- > (size_t)(options->compressed_reserve))
+ if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
+ if (options->compressed_size > LZMA_VLI_VALUE_MAX / 4 - 1
+ || options->compressed_size == 0
+ || (options->compressed_size & 3))
return LZMA_PROG_ERROR;
- size += options->compressed_reserve;
-
- } else if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
- // Compressed Size is known. We have already checked
- // that is is a valid VLI, and since it isn't
- // LZMA_VLI_VALUE_UNKNOWN, we can be sure that
- // lzma_vli_size() will succeed.
- size += lzma_vli_size(options->compressed_size);
+ size += lzma_vli_size(options->compressed_size / 4 - 1);
}
// Uncompressed Size
- if (!lzma_vli_is_valid(options->uncompressed_size)) {
- return LZMA_PROG_ERROR;
-
- } else if (options->uncompressed_reserve != 0) {
- if (options->uncompressed_reserve > LZMA_VLI_BYTES_MAX
- || lzma_vli_size(options->uncompressed_size)
- > (size_t)(options->uncompressed_reserve))
+ if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
+ const size_t add = lzma_vli_size(options->uncompressed_size);
+ if (add == 0)
return LZMA_PROG_ERROR;
- size += options->uncompressed_reserve;
-
- } else if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN) {
- size += lzma_vli_size(options->uncompressed_size);
+ size += add;
}
// List of Filter Flags
+ if (options->filters == NULL
+ || options->filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
+ return LZMA_PROG_ERROR;
+
for (size_t i = 0; options->filters[i].id != LZMA_VLI_VALUE_UNKNOWN;
++i) {
// Don't allow too many filters.
- if (i == 7)
+ if (i == 4)
return LZMA_PROG_ERROR;
- uint32_t tmp;
- const lzma_ret ret = lzma_filter_flags_size(&tmp,
- options->filters + i);
- if (ret != LZMA_OK)
- return ret;
+ uint32_t add;
+ return_if_error(lzma_filter_flags_size(&add,
+ options->filters + i));
- size += tmp;
+ size += add;
}
- // CRC32
- if (options->has_crc32)
- size += 4;
-
- // Padding
- int32_t padding;
- if (options->padding == LZMA_BLOCK_HEADER_PADDING_AUTO) {
- const uint32_t preferred = lzma_alignment_output(
- options->filters, 1);
- const uint32_t unaligned = size + options->alignment;
- padding = (int32_t)(unaligned % preferred);
- if (padding != 0)
- padding = preferred - padding;
- } else if (options->padding >= LZMA_BLOCK_HEADER_PADDING_MIN
- && options->padding <= LZMA_BLOCK_HEADER_PADDING_MAX) {
- padding = options->padding;
- } else {
- return LZMA_PROG_ERROR;
- }
+ // Pad to a multiple of four bytes.
+ options->header_size = (size + 3) & ~(size_t)(3);
- // All success. Copy the calculated values to the options structure.
- options->padding = padding;
- options->header_size = size + (size_t)(padding);
+ // NOTE: We don't verify that Total Size of the Block stays within
+ // limits. This is because it is possible that we are called with
+ // exaggerated values to reserve space for Block Header, and later
+ // called again with lower, real values.
return LZMA_OK;
}
extern LZMA_API lzma_ret
-lzma_block_header_encode(uint8_t *out, const lzma_options_block *options)
+lzma_block_header_encode(const lzma_options_block *options, uint8_t *out)
{
- // We write the Block Flags later.
- if (options->header_size < 2)
+ if ((options->header_size & 3)
+ || options->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
+ || options->header_size > LZMA_BLOCK_HEADER_SIZE_MAX)
return LZMA_PROG_ERROR;
- const size_t out_size = options->header_size;
+ // Indicate the size of the buffer _excluding_ the CRC32 field.
+ const size_t out_size = options->header_size - 4;
+
+ // Store the Block Header Size.
+ out[0] = out_size / 4;
+
+ // We write Block Flags a little later.
size_t out_pos = 2;
// Compressed Size
- if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN
- || options->compressed_reserve != 0) {
- const lzma_vli size = options->compressed_size
- != LZMA_VLI_VALUE_UNKNOWN
- ? options->compressed_size : 0;
- size_t vli_pos = 0;
- if (lzma_vli_encode(
- size, &vli_pos, options->compressed_reserve,
- out, &out_pos, out_size) != LZMA_STREAM_END)
+ if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN) {
+ // Compressed Size must be non-zero, fit into a 63-bit
+ // integer and be a multiple of four. Also the Total Size
+ // of the Block must fit into 63-bit integer.
+ if (options->compressed_size == 0
+ || (options->compressed_size & 3)
+ || options->compressed_size
+ > LZMA_VLI_VALUE_MAX
+ || lzma_block_total_size_get(options) == 0)
return LZMA_PROG_ERROR;
+ return_if_error(lzma_vli_encode(
+ options->compressed_size / 4 - 1, NULL,
+ out, &out_pos, out_size));
}
// Uncompressed Size
- if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
- || options->uncompressed_reserve != 0) {
- const lzma_vli size = options->uncompressed_size
- != LZMA_VLI_VALUE_UNKNOWN
- ? options->uncompressed_size : 0;
- size_t vli_pos = 0;
- if (lzma_vli_encode(
- size, &vli_pos, options->uncompressed_reserve,
- out, &out_pos, out_size) != LZMA_STREAM_END)
- return LZMA_PROG_ERROR;
-
- }
+ if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
+ return_if_error(lzma_vli_encode(
+ options->uncompressed_size, NULL,
+ out, &out_pos, out_size));
// Filter Flags
- size_t filter_count;
- for (filter_count = 0; options->filters[filter_count].id
- != LZMA_VLI_VALUE_UNKNOWN; ++filter_count) {
- // There can be at maximum of seven filters.
- if (filter_count == 7)
- return LZMA_PROG_ERROR;
-
- const lzma_ret ret = lzma_filter_flags_encode(out, &out_pos,
- out_size, options->filters + filter_count);
- // FIXME: Don't return LZMA_BUF_ERROR.
- if (ret != LZMA_OK)
- return ret;
- }
-
- // Block Flags 1
- out[0] = filter_count;
-
- if (options->has_eopm)
- out[0] |= 0x08;
- else if (options->uncompressed_size == LZMA_VLI_VALUE_UNKNOWN)
+ if (options->filters == NULL
+ || options->filters[0].id == LZMA_VLI_VALUE_UNKNOWN)
return LZMA_PROG_ERROR;
- if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN
- || options->compressed_reserve != 0)
- out[0] |= 0x10;
-
- if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN
- || options->uncompressed_reserve != 0)
- out[0] |= 0x20;
+ size_t filter_count = 0;
+ do {
+ // There can be at maximum of four filters.
+ if (filter_count == 4)
+ return LZMA_PROG_ERROR;
- if (options->is_metadata)
- out[0] |= 0x80;
+ return_if_error(lzma_filter_flags_encode(out, &out_pos,
+ out_size, options->filters + filter_count));
- // Block Flags 2
- if (options->padding < LZMA_BLOCK_HEADER_PADDING_MIN
- || options->padding > LZMA_BLOCK_HEADER_PADDING_MAX)
- return LZMA_PROG_ERROR;
+ } while (options->filters[++filter_count].id
+ != LZMA_VLI_VALUE_UNKNOWN);
- out[1] = (uint8_t)(options->padding);
+ // Block Flags
+ out[1] = filter_count - 1;
- // CRC32
- if (options->has_crc32) {
- if (out_size - out_pos < 4)
- return LZMA_PROG_ERROR;
+ if (options->compressed_size != LZMA_VLI_VALUE_UNKNOWN)
+ out[1] |= 0x40;
- const uint32_t crc = lzma_crc32(out, out_pos, 0);
- for (size_t i = 0; i < 4; ++i)
- out[out_pos++] = crc >> (i * 8);
- }
+ if (options->uncompressed_size != LZMA_VLI_VALUE_UNKNOWN)
+ out[1] |= 0x80;
- // Padding - the amount of available space must now match with
- // the size of the Padding field.
- if (out_size - out_pos != (size_t)(options->padding))
- return LZMA_PROG_ERROR;
+ // Padding
+ memzero(out + out_pos, out_size - out_pos);
- memzero(out + out_pos, (size_t)(options->padding));
+ // CRC32
+ integer_write_32(out + out_size, lzma_crc32(out, out_size, 0));
return LZMA_OK;
}