aboutsummaryrefslogtreecommitdiff
path: root/src/liblzma/common/stream_flags_decoder.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/stream_flags_decoder.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/stream_flags_decoder.c')
-rw-r--r--src/liblzma/common/stream_flags_decoder.c260
1 files changed, 45 insertions, 215 deletions
diff --git a/src/liblzma/common/stream_flags_decoder.c b/src/liblzma/common/stream_flags_decoder.c
index d9c847ac..0270875a 100644
--- a/src/liblzma/common/stream_flags_decoder.c
+++ b/src/liblzma/common/stream_flags_decoder.c
@@ -1,7 +1,7 @@
///////////////////////////////////////////////////////////////////////////////
//
/// \file stream_flags_decoder.c
-/// \brief Decodes Stream Header and tail from .lzma files
+/// \brief Decodes Stream Header and Stream Footer from .lzma files
//
// Copyright (C) 2007 Lasse Collin
//
@@ -17,242 +17,72 @@
//
///////////////////////////////////////////////////////////////////////////////
-#include "stream_flags_decoder.h"
#include "stream_common.h"
-////////////
-// Common //
-////////////
-
-struct lzma_coder_s {
- enum {
- SEQ_HEADER_MAGIC,
- SEQ_HEADER_FLAGS,
- SEQ_HEADER_CRC32,
-
- SEQ_FOOTER_FLAGS,
- SEQ_FOOTER_MAGIC,
- } sequence;
-
- size_t pos;
- uint32_t crc32;
-
- lzma_stream_flags *options;
-};
-
-
-static void
-stream_header_decoder_end(lzma_coder *coder, lzma_allocator *allocator)
-{
- lzma_free(coder, allocator);
- return;
-}
-
-
static bool
-stream_flags_decode(const uint8_t *in, lzma_stream_flags *options)
+stream_flags_decode(lzma_stream_flags *options, const uint8_t *in)
{
// Reserved bits must be unset.
- if (*in & 0xE0)
+ if (in[0] != 0x00 || (in[1] & 0xF0))
return true;
- options->check = *in & 0x07;
- options->has_crc32 = (*in & 0x08) != 0;
- options->is_multi = (*in & 0x10) != 0;
+ options->check = in[1] & 0x0F;
return false;
}
-////////////
-// Header //
-////////////
-
-static lzma_ret
-stream_header_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((unused)),
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out lzma_attribute((unused)),
- size_t *restrict out_pos lzma_attribute((unused)),
- size_t out_size lzma_attribute((unused)),
- lzma_action action lzma_attribute((unused)))
-{
- while (*in_pos < in_size)
- switch (coder->sequence) {
- case SEQ_HEADER_MAGIC:
- if (in[*in_pos] != lzma_header_magic[coder->pos])
- return LZMA_DATA_ERROR;
-
- ++*in_pos;
-
- if (++coder->pos == sizeof(lzma_header_magic)) {
- coder->pos = 0;
- coder->sequence = SEQ_HEADER_FLAGS;
- }
-
- break;
-
- case SEQ_HEADER_FLAGS:
- if (stream_flags_decode(in + *in_pos, coder->options))
- return LZMA_HEADER_ERROR;
-
- coder->crc32 = lzma_crc32(in + *in_pos, 1, 0);
-
- ++*in_pos;
- coder->sequence = SEQ_HEADER_CRC32;
- break;
-
- case SEQ_HEADER_CRC32:
- if (in[*in_pos] != ((coder->crc32 >> (coder->pos * 8)) & 0xFF))
- return LZMA_DATA_ERROR;
-
- ++*in_pos;
-
- if (++coder->pos == 4)
- return LZMA_STREAM_END;
-
- break;
-
- default:
- return LZMA_PROG_ERROR;
- }
-
- return LZMA_OK;
-}
-
-
-static lzma_ret
-stream_header_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_stream_flags *options)
-{
- if (options == NULL)
- return LZMA_PROG_ERROR;
-
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
- }
-
- // Set the function pointers unconditionally, because they may
- // have been pointing to footer decoder too.
- next->code = &stream_header_decode;
- next->end = &stream_header_decoder_end;
-
- next->coder->sequence = SEQ_HEADER_MAGIC;
- next->coder->pos = 0;
- next->coder->crc32 = 0;
- next->coder->options = options;
-
- return LZMA_OK;
-}
-
-
-extern lzma_ret
-lzma_stream_header_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_stream_flags *options)
-{
- lzma_next_coder_init(
- stream_header_decoder_init, next, allocator, options);
-}
-
-
extern LZMA_API lzma_ret
-lzma_stream_header_decoder(lzma_stream *strm, lzma_stream_flags *options)
-{
- lzma_next_strm_init(strm, stream_header_decoder_init, options);
-
- strm->internal->supported_actions[LZMA_RUN] = true;
-
- return LZMA_OK;
-}
-
-
-//////////
-// Tail //
-//////////
-
-static lzma_ret
-stream_tail_decode(lzma_coder *coder,
- lzma_allocator *allocator lzma_attribute((unused)),
- const uint8_t *restrict in, size_t *restrict in_pos,
- size_t in_size, uint8_t *restrict out lzma_attribute((unused)),
- size_t *restrict out_pos lzma_attribute((unused)),
- size_t out_size lzma_attribute((unused)),
- lzma_action action lzma_attribute((unused)))
-{
- while (*in_pos < in_size)
- switch (coder->sequence) {
- case SEQ_FOOTER_FLAGS:
- if (stream_flags_decode(in + *in_pos, coder->options))
- return LZMA_HEADER_ERROR;
-
- ++*in_pos;
- coder->sequence = SEQ_FOOTER_MAGIC;
- break;
-
- case SEQ_FOOTER_MAGIC:
- if (in[*in_pos] != lzma_footer_magic[coder->pos])
- return LZMA_DATA_ERROR;
-
- ++*in_pos;
-
- if (++coder->pos == sizeof(lzma_footer_magic))
- return LZMA_STREAM_END;
-
- break;
-
- default:
- return LZMA_PROG_ERROR;
- }
-
- return LZMA_OK;
-}
-
-
-static lzma_ret
-stream_tail_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_stream_flags *options)
+lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in)
{
- if (options == NULL)
- return LZMA_PROG_ERROR;
-
- if (next->coder == NULL) {
- next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
- if (next->coder == NULL)
- return LZMA_MEM_ERROR;
- }
-
- // Set the function pointers unconditionally, because they may
- // have been pointing to footer decoder too.
- next->code = &stream_tail_decode;
- next->end = &stream_header_decoder_end;
-
- next->coder->sequence = SEQ_FOOTER_FLAGS;
- next->coder->pos = 0;
- next->coder->options = options;
+ // Magic
+ if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0)
+ return LZMA_FORMAT_ERROR;
+
+ // Verify the CRC32 so we can distinguish between corrupt
+ // and unsupported files.
+ const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic),
+ LZMA_STREAM_FLAGS_SIZE, 0);
+ if (crc != integer_read_32(in + sizeof(lzma_header_magic)
+ + LZMA_STREAM_FLAGS_SIZE))
+ return LZMA_DATA_ERROR;
+
+ // Stream Flags
+ if (stream_flags_decode(options, in + sizeof(lzma_header_magic)))
+ return LZMA_HEADER_ERROR;
+
+ // Set Backward Size to indicate unknown value. That way
+ // lzma_stream_flags_equal can be used to compare Stream Header
+ // and Stream Footer while keeping it useful also for comparing
+ // two Stream Footers.
+ options->backward_size = LZMA_VLI_VALUE_UNKNOWN;
return LZMA_OK;
}
-extern lzma_ret
-lzma_stream_tail_decoder_init(lzma_next_coder *next,
- lzma_allocator *allocator, lzma_stream_flags *options)
-{
- lzma_next_coder_init2(next, allocator, stream_header_decoder_init,
- stream_tail_decoder_init, allocator, options);
-}
-
-
extern LZMA_API lzma_ret
-lzma_stream_tail_decoder(lzma_stream *strm, lzma_stream_flags *options)
+lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in)
{
- lzma_next_strm_init2(strm, stream_header_decoder_init,
- stream_tail_decoder_init, strm->allocator, options);
-
- strm->internal->supported_actions[LZMA_RUN] = true;
+ // Magic
+ if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE,
+ lzma_footer_magic, sizeof(lzma_footer_magic)) != 0)
+ return LZMA_FORMAT_ERROR;
+
+ // CRC32
+ const uint32_t crc = lzma_crc32(in + sizeof(uint32_t),
+ sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0);
+ if (crc != integer_read_32(in))
+ return LZMA_DATA_ERROR;
+
+ // Stream Flags
+ if (stream_flags_decode(options, in + sizeof(uint32_t) * 2))
+ return LZMA_HEADER_ERROR;
+
+ // Backward Size
+ options->backward_size = integer_read_32(in + sizeof(uint32_t));
+ options->backward_size = (options->backward_size + 1) * 4;
return LZMA_OK;
}