1 ///////////////////////////////////////////////////////////////////////////////
3 /// \file auto_decoder.c
4 /// \brief Autodetect between .xz, .lzma (LZMA_Alone), and .lz (lzip)
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
13 #include "stream_decoder.h"
14 #include "alone_decoder.h"
15 #ifdef HAVE_LZIP_DECODER
16 # include "lzip_decoder.h"
21 /// .xz Stream decoder, LZMA_Alone decoder, or lzip decoder
36 auto_decode(void *coder_ptr
, const lzma_allocator
*allocator
,
37 const uint8_t *restrict in
, size_t *restrict in_pos
,
38 size_t in_size
, uint8_t *restrict out
,
39 size_t *restrict out_pos
, size_t out_size
, lzma_action action
)
41 lzma_auto_coder
*coder
= coder_ptr
;
43 switch (coder
->sequence
) {
45 if (*in_pos
>= in_size
)
48 // Update the sequence now, because we want to continue from
49 // SEQ_CODE even if we return some LZMA_*_CHECK.
50 coder
->sequence
= SEQ_CODE
;
52 // Detect the file format. .xz files start with 0xFD which
53 // cannot be the first byte of .lzma (LZMA_Alone) format.
54 // The .lz format starts with 0x4C which could be the
55 // first byte of a .lzma file but luckily it would mean
56 // lc/lp/pb being 4/3/1 which liblzma doesn't support because
57 // lc + lp > 4. So using just 0x4C to detect .lz is OK here.
58 if (in
[*in_pos
] == 0xFD) {
59 return_if_error(lzma_stream_decoder_init(
60 &coder
->next
, allocator
,
61 coder
->memlimit
, coder
->flags
));
62 #ifdef HAVE_LZIP_DECODER
63 } else if (in
[*in_pos
] == 0x4C) {
64 return_if_error(lzma_lzip_decoder_init(
65 &coder
->next
, allocator
,
66 coder
->memlimit
, coder
->flags
));
69 return_if_error(lzma_alone_decoder_init(&coder
->next
,
70 allocator
, coder
->memlimit
, true));
72 // If the application wants to know about missing
73 // integrity check or about the check in general, we
74 // need to handle it here, because LZMA_Alone decoder
75 // doesn't accept any flags.
76 if (coder
->flags
& LZMA_TELL_NO_CHECK
)
79 if (coder
->flags
& LZMA_TELL_ANY_CHECK
)
80 return LZMA_GET_CHECK
;
86 const lzma_ret ret
= coder
->next
.code(
87 coder
->next
.coder
, allocator
,
89 out
, out_pos
, out_size
, action
);
90 if (ret
!= LZMA_STREAM_END
91 || (coder
->flags
& LZMA_CONCATENATED
) == 0)
94 coder
->sequence
= SEQ_FINISH
;
100 // When LZMA_CONCATENATED was used and we were decoding
101 // a LZMA_Alone file, we need to check that there is no
102 // trailing garbage and wait for LZMA_FINISH.
103 if (*in_pos
< in_size
)
104 return LZMA_DATA_ERROR
;
106 return action
== LZMA_FINISH
? LZMA_STREAM_END
: LZMA_OK
;
110 return LZMA_PROG_ERROR
;
116 auto_decoder_end(void *coder_ptr
, const lzma_allocator
*allocator
)
118 lzma_auto_coder
*coder
= coder_ptr
;
119 lzma_next_end(&coder
->next
, allocator
);
120 lzma_free(coder
, allocator
);
126 auto_decoder_get_check(const void *coder_ptr
)
128 const lzma_auto_coder
*coder
= coder_ptr
;
130 // It is LZMA_Alone if get_check is NULL.
131 return coder
->next
.get_check
== NULL
? LZMA_CHECK_NONE
132 : coder
->next
.get_check(coder
->next
.coder
);
137 auto_decoder_memconfig(void *coder_ptr
, uint64_t *memusage
,
138 uint64_t *old_memlimit
, uint64_t new_memlimit
)
140 lzma_auto_coder
*coder
= coder_ptr
;
144 if (coder
->next
.memconfig
!= NULL
) {
145 ret
= coder
->next
.memconfig(coder
->next
.coder
,
146 memusage
, old_memlimit
, new_memlimit
);
147 assert(*old_memlimit
== coder
->memlimit
);
149 // No coder is configured yet. Use the base value as
150 // the current memory usage.
151 *memusage
= LZMA_MEMUSAGE_BASE
;
152 *old_memlimit
= coder
->memlimit
;
155 if (new_memlimit
!= 0 && new_memlimit
< *memusage
)
156 ret
= LZMA_MEMLIMIT_ERROR
;
159 if (ret
== LZMA_OK
&& new_memlimit
!= 0)
160 coder
->memlimit
= new_memlimit
;
167 auto_decoder_init(lzma_next_coder
*next
, const lzma_allocator
*allocator
,
168 uint64_t memlimit
, uint32_t flags
)
170 lzma_next_coder_init(&auto_decoder_init
, next
, allocator
);
172 if (flags
& ~LZMA_SUPPORTED_FLAGS
)
173 return LZMA_OPTIONS_ERROR
;
175 lzma_auto_coder
*coder
= next
->coder
;
177 coder
= lzma_alloc(sizeof(lzma_auto_coder
), allocator
);
179 return LZMA_MEM_ERROR
;
182 next
->code
= &auto_decode
;
183 next
->end
= &auto_decoder_end
;
184 next
->get_check
= &auto_decoder_get_check
;
185 next
->memconfig
= &auto_decoder_memconfig
;
186 coder
->next
= LZMA_NEXT_CODER_INIT
;
189 coder
->memlimit
= my_max(1, memlimit
);
190 coder
->flags
= flags
;
191 coder
->sequence
= SEQ_INIT
;
197 extern LZMA_API(lzma_ret
)
198 lzma_auto_decoder(lzma_stream
*strm
, uint64_t memlimit
, uint32_t flags
)
200 lzma_next_strm_init(auto_decoder_init
, strm
, memlimit
, flags
);
202 strm
->internal
->supported_actions
[LZMA_RUN
] = true;
203 strm
->internal
->supported_actions
[LZMA_FINISH
] = true;