]> icculus.org git repositories - icculus/xz.git/blob - src/liblzma/common/stream_flags_decoder.c
Improved the Stream Flags handling API.
[icculus/xz.git] / src / liblzma / common / stream_flags_decoder.c
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 /// \file       stream_flags_decoder.c
4 /// \brief      Decodes Stream Header and Stream Footer from .lzma files
5 //
6 //  Copyright (C) 2007 Lasse Collin
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License, or (at your option) any later version.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 ///////////////////////////////////////////////////////////////////////////////
19
20 #include "stream_flags_common.h"
21
22
23 static bool
24 stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
25 {
26         // Reserved bits must be unset.
27         if (in[0] != 0x00 || (in[1] & 0xF0))
28                 return true;
29
30         options->version = 0;
31         options->check = in[1] & 0x0F;
32
33         return false;
34 }
35
36
37 extern LZMA_API lzma_ret
38 lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
39 {
40         // Magic
41         if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
42                 return LZMA_FORMAT_ERROR;
43
44         // Verify the CRC32 so we can distinguish between corrupt
45         // and unsupported files.
46         const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
47                         LZMA_STREAM_FLAGS_SIZE, 0);
48         if (crc != integer_read_32(in + sizeof(lzma_header_magic)
49                         + LZMA_STREAM_FLAGS_SIZE))
50                 return LZMA_DATA_ERROR;
51
52         // Stream Flags
53         if (stream_flags_decode(options, in + sizeof(lzma_header_magic)))
54                 return LZMA_HEADER_ERROR;
55
56         // Set Backward Size to indicate unknown value. That way
57         // lzma_stream_flags_compare() can be used to compare Stream Header
58         // and Stream Footer while keeping it useful also for comparing
59         // two Stream Footers.
60         options->backward_size = LZMA_VLI_VALUE_UNKNOWN;
61
62         return LZMA_OK;
63 }
64
65
66 extern LZMA_API lzma_ret
67 lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
68 {
69         // Magic
70         if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
71                         lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
72                 return LZMA_FORMAT_ERROR;
73
74         // CRC32
75         const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
76                         sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
77         if (crc != integer_read_32(in))
78                 return LZMA_DATA_ERROR;
79
80         // Stream Flags
81         if (stream_flags_decode(options, in + sizeof(uint32_t) * 2))
82                 return LZMA_HEADER_ERROR;
83
84         // Backward Size
85         options->backward_size = integer_read_32(in + sizeof(uint32_t));
86         options->backward_size = (options->backward_size + 1) * 4;
87
88         return LZMA_OK;
89 }