1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file stream_flags_decoder.c 4207753Smm/// \brief Decodes Stream Header and Stream Footer from .xz files 5207753Smm// 6207753Smm// Author: Lasse Collin 7207753Smm// 8207753Smm// This file has been put into the public domain. 9207753Smm// You can do whatever you want with this file. 10207753Smm// 11207753Smm/////////////////////////////////////////////////////////////////////////////// 12207753Smm 13207753Smm#include "stream_flags_common.h" 14207753Smm 15207753Smm 16207753Smmstatic bool 17207753Smmstream_flags_decode(lzma_stream_flags *options, const uint8_t *in) 18207753Smm{ 19207753Smm // Reserved bits must be unset. 20207753Smm if (in[0] != 0x00 || (in[1] & 0xF0)) 21207753Smm return true; 22207753Smm 23207753Smm options->version = 0; 24207753Smm options->check = in[1] & 0x0F; 25207753Smm 26207753Smm return false; 27207753Smm} 28207753Smm 29207753Smm 30207753Smmextern LZMA_API(lzma_ret) 31207753Smmlzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in) 32207753Smm{ 33207753Smm // Magic 34207753Smm if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0) 35207753Smm return LZMA_FORMAT_ERROR; 36207753Smm 37207753Smm // Verify the CRC32 so we can distinguish between corrupt 38207753Smm // and unsupported files. 39207753Smm const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic), 40207753Smm LZMA_STREAM_FLAGS_SIZE, 0); 41207753Smm if (crc != unaligned_read32le(in + sizeof(lzma_header_magic) 42207753Smm + LZMA_STREAM_FLAGS_SIZE)) 43207753Smm return LZMA_DATA_ERROR; 44207753Smm 45207753Smm // Stream Flags 46207753Smm if (stream_flags_decode(options, in + sizeof(lzma_header_magic))) 47207753Smm return LZMA_OPTIONS_ERROR; 48207753Smm 49207753Smm // Set Backward Size to indicate unknown value. That way 50207753Smm // lzma_stream_flags_compare() can be used to compare Stream Header 51207753Smm // and Stream Footer while keeping it useful also for comparing 52207753Smm // two Stream Footers. 53207753Smm options->backward_size = LZMA_VLI_UNKNOWN; 54207753Smm 55207753Smm return LZMA_OK; 56207753Smm} 57207753Smm 58207753Smm 59207753Smmextern LZMA_API(lzma_ret) 60207753Smmlzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) 61207753Smm{ 62207753Smm // Magic 63207753Smm if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE, 64207753Smm lzma_footer_magic, sizeof(lzma_footer_magic)) != 0) 65207753Smm return LZMA_FORMAT_ERROR; 66207753Smm 67207753Smm // CRC32 68207753Smm const uint32_t crc = lzma_crc32(in + sizeof(uint32_t), 69207753Smm sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0); 70207753Smm if (crc != unaligned_read32le(in)) 71207753Smm return LZMA_DATA_ERROR; 72207753Smm 73207753Smm // Stream Flags 74207753Smm if (stream_flags_decode(options, in + sizeof(uint32_t) * 2)) 75207753Smm return LZMA_OPTIONS_ERROR; 76207753Smm 77207753Smm // Backward Size 78207753Smm options->backward_size = unaligned_read32le(in + sizeof(uint32_t)); 79207753Smm options->backward_size = (options->backward_size + 1) * 4; 80207753Smm 81207753Smm return LZMA_OK; 82207753Smm} 83