Path: blob/master/Utilities/cmliblzma/liblzma/common/block_header_encoder.c
3153 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file block_header_encoder.c5/// \brief Encodes Block Header for .xz files6//7// Author: Lasse Collin8//9///////////////////////////////////////////////////////////////////////////////1011#include "common.h"12#include "check.h"131415extern LZMA_API(lzma_ret)16lzma_block_header_size(lzma_block *block)17{18if (block->version > 1)19return LZMA_OPTIONS_ERROR;2021// Block Header Size + Block Flags + CRC32.22uint32_t size = 1 + 1 + 4;2324// Compressed Size25if (block->compressed_size != LZMA_VLI_UNKNOWN) {26const uint32_t add = lzma_vli_size(block->compressed_size);27if (add == 0 || block->compressed_size == 0)28return LZMA_PROG_ERROR;2930size += add;31}3233// Uncompressed Size34if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {35const uint32_t add = lzma_vli_size(block->uncompressed_size);36if (add == 0)37return LZMA_PROG_ERROR;3839size += add;40}4142// List of Filter Flags43if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)44return LZMA_PROG_ERROR;4546for (size_t i = 0; block->filters[i].id != LZMA_VLI_UNKNOWN; ++i) {47// Don't allow too many filters.48if (i == LZMA_FILTERS_MAX)49return LZMA_PROG_ERROR;5051uint32_t add;52return_if_error(lzma_filter_flags_size(&add,53block->filters + i));5455size += add;56}5758// Pad to a multiple of four bytes.59block->header_size = (size + 3) & ~UINT32_C(3);6061// NOTE: We don't verify that the encoded size of the Block stays62// within limits. This is because it is possible that we are called63// with exaggerated Compressed Size (e.g. LZMA_VLI_MAX) to reserve64// space for Block Header, and later called again with lower,65// real values.6667return LZMA_OK;68}697071extern LZMA_API(lzma_ret)72lzma_block_header_encode(const lzma_block *block, uint8_t *out)73{74// Validate everything but filters.75if (lzma_block_unpadded_size(block) == 076|| !lzma_vli_is_valid(block->uncompressed_size))77return LZMA_PROG_ERROR;7879// Indicate the size of the buffer _excluding_ the CRC32 field.80const size_t out_size = block->header_size - 4;8182// Store the Block Header Size.83out[0] = out_size / 4;8485// We write Block Flags in pieces.86out[1] = 0x00;87size_t out_pos = 2;8889// Compressed Size90if (block->compressed_size != LZMA_VLI_UNKNOWN) {91return_if_error(lzma_vli_encode(block->compressed_size, NULL,92out, &out_pos, out_size));9394out[1] |= 0x40;95}9697// Uncompressed Size98if (block->uncompressed_size != LZMA_VLI_UNKNOWN) {99return_if_error(lzma_vli_encode(block->uncompressed_size, NULL,100out, &out_pos, out_size));101102out[1] |= 0x80;103}104105// Filter Flags106if (block->filters == NULL || block->filters[0].id == LZMA_VLI_UNKNOWN)107return LZMA_PROG_ERROR;108109size_t filter_count = 0;110do {111// There can be a maximum of four filters.112if (filter_count == LZMA_FILTERS_MAX)113return LZMA_PROG_ERROR;114115return_if_error(lzma_filter_flags_encode(116block->filters + filter_count,117out, &out_pos, out_size));118119} while (block->filters[++filter_count].id != LZMA_VLI_UNKNOWN);120121out[1] |= filter_count - 1;122123// Padding124memzero(out + out_pos, out_size - out_pos);125126// CRC32127write32le(out + out_size, lzma_crc32(out, out_size, 0));128129return LZMA_OK;130}131132133