Rizin
unix-like reverse engineering framework and cli tools
stream_encoder.c File Reference

Encodes .xz Streams. More...

#include "block_encoder.h"
#include "index_encoder.h"

Go to the source code of this file.

Classes

struct  lzma_stream_coder
 

Functions

static lzma_ret block_encoder_init (lzma_stream_coder *coder, const lzma_allocator *allocator)
 
static lzma_ret stream_encode (void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, lzma_action action)
 
static void stream_encoder_end (void *coder_ptr, const lzma_allocator *allocator)
 
static lzma_ret stream_encoder_update (void *coder_ptr, const lzma_allocator *allocator, const lzma_filter *filters, const lzma_filter *reversed_filters)
 
static lzma_ret stream_encoder_init (lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter *filters, lzma_check check)
 
 LZMA_API (lzma_ret)
 

Detailed Description

Encodes .xz Streams.

Definition in file stream_encoder.c.

Function Documentation

◆ block_encoder_init()

static lzma_ret block_encoder_init ( lzma_stream_coder coder,
const lzma_allocator allocator 
)
static

Definition at line 62 of file stream_encoder.c.

63 {
64  // Prepare the Block options. Even though Block encoder doesn't need
65  // compressed_size, uncompressed_size, and header_size to be
66  // initialized, it is a good idea to do it here, because this way
67  // we catch if someone gave us Filter ID that cannot be used in
68  // Blocks/Streams.
71 
72  return_if_error(lzma_block_header_size(&coder->block_options));
73 
74  // Initialize the actual Block encoder.
76  &coder->block_options);
77 }
const lzma_allocator * allocator
Definition: block.h:377
lzma_ret lzma_block_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, lzma_block *block)
lzma_vli uncompressed_size
Uncompressed Size in bytes.
Definition: block.h:172
lzma_vli compressed_size
Size of the Compressed Data in bytes.
Definition: block.h:148
lzma_block block_options
Options for the Block encoder.
lzma_next_coder block_encoder
Block.
#define return_if_error(expr)
Return if expression doesn't evaluate to LZMA_OK.
Definition: common.h:278
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39

References allocator, lzma_stream_coder::block_encoder, lzma_stream_coder::block_options, lzma_block::compressed_size, lzma_block_encoder_init(), LZMA_VLI_UNKNOWN, return_if_error, and lzma_block::uncompressed_size.

Referenced by stream_encode(), and stream_encoder_update().

◆ LZMA_API()

LZMA_API ( lzma_ret  )

Definition at line 327 of file stream_encoder.c.

330 {
332 
338 
339  return LZMA_OK;
340 }
lzma_check check
Definition: container.h:292
const lzma_filter * filters
Definition: container.h:315
static lzma_stream strm
Definition: full_flush.c:20
static lzma_ret stream_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_filter *filters, lzma_check check)
bool supported_actions[LZMA_ACTION_MAX+1]
Indicates which lzma_action values are allowed by next.code.
Definition: common.h:220
lzma_internal * internal
Definition: base.h:505
#define lzma_next_strm_init(func, strm,...)
Definition: common.h:303
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
@ LZMA_SYNC_FLUSH
Make all the input available at output.
Definition: base.h:265
@ LZMA_FINISH
Finish the coding operation.
Definition: base.h:328
@ LZMA_RUN
Continue coding.
Definition: base.h:251
@ LZMA_FULL_FLUSH
Finish encoding of the current Block.
Definition: base.h:290
@ LZMA_FULL_BARRIER
Finish encoding of the current Block.
Definition: base.h:305

References check, filters, lzma_stream::internal, LZMA_FINISH, LZMA_FULL_BARRIER, LZMA_FULL_FLUSH, lzma_next_strm_init, LZMA_OK, LZMA_RUN, LZMA_SYNC_FLUSH, stream_encoder_init(), strm, and lzma_internal_s::supported_actions.

◆ stream_encode()

static lzma_ret stream_encode ( void *  coder_ptr,
const lzma_allocator allocator,
const uint8_t *restrict  in,
size_t *restrict  in_pos,
size_t  in_size,
uint8_t *restrict  out,
size_t *restrict  out_pos,
size_t  out_size,
lzma_action  action 
)
static

Definition at line 81 of file stream_encoder.c.

85 {
86  lzma_stream_coder *coder = coder_ptr;
87 
88  // Main loop
89  while (*out_pos < out_size)
90  switch (coder->sequence) {
91  case SEQ_STREAM_HEADER:
92  case SEQ_BLOCK_HEADER:
93  case SEQ_STREAM_FOOTER:
94  lzma_bufcpy(coder->buffer, &coder->buffer_pos,
95  coder->buffer_size, out, out_pos, out_size);
96  if (coder->buffer_pos < coder->buffer_size)
97  return LZMA_OK;
98 
99  if (coder->sequence == SEQ_STREAM_FOOTER)
100  return LZMA_STREAM_END;
101 
102  coder->buffer_pos = 0;
103  ++coder->sequence;
104  break;
105 
106  case SEQ_BLOCK_INIT: {
107  if (*in_pos == in_size) {
108  // If we are requested to flush or finish the current
109  // Block, return LZMA_STREAM_END immediately since
110  // there's nothing to do.
111  if (action != LZMA_FINISH)
112  return action == LZMA_RUN
114 
115  // The application had used LZMA_FULL_FLUSH to finish
116  // the previous Block, but now wants to finish without
117  // encoding new data, or it is simply creating an
118  // empty Stream with no Blocks.
119  //
120  // Initialize the Index encoder, and continue to
121  // actually encoding the Index.
123  &coder->index_encoder, allocator,
124  coder->index));
125  coder->sequence = SEQ_INDEX_ENCODE;
126  break;
127  }
128 
129  // Initialize the Block encoder unless it was already
130  // initialized by stream_encoder_init() or
131  // stream_encoder_update().
132  if (!coder->block_encoder_is_initialized)
134 
135  // Make it false so that we don't skip the initialization
136  // with the next Block.
137  coder->block_encoder_is_initialized = false;
138 
139  // Encode the Block Header. This shouldn't fail since we have
140  // already initialized the Block encoder.
141  if (lzma_block_header_encode(&coder->block_options,
142  coder->buffer) != LZMA_OK)
143  return LZMA_PROG_ERROR;
144 
145  coder->buffer_size = coder->block_options.header_size;
146  coder->sequence = SEQ_BLOCK_HEADER;
147  break;
148  }
149 
150  case SEQ_BLOCK_ENCODE: {
151  static const lzma_action convert[LZMA_ACTION_MAX + 1] = {
152  LZMA_RUN,
154  LZMA_FINISH,
155  LZMA_FINISH,
156  LZMA_FINISH,
157  };
158 
159  const lzma_ret ret = coder->block_encoder.code(
160  coder->block_encoder.coder, allocator,
161  in, in_pos, in_size,
162  out, out_pos, out_size, convert[action]);
163  if (ret != LZMA_STREAM_END || action == LZMA_SYNC_FLUSH)
164  return ret;
165 
166  // Add a new Index Record.
167  const lzma_vli unpadded_size = lzma_block_unpadded_size(
168  &coder->block_options);
169  assert(unpadded_size != 0);
170  return_if_error(lzma_index_append(coder->index, allocator,
173 
174  coder->sequence = SEQ_BLOCK_INIT;
175  break;
176  }
177 
178  case SEQ_INDEX_ENCODE: {
179  // Call the Index encoder. It doesn't take any input, so
180  // those pointers can be NULL.
181  const lzma_ret ret = coder->index_encoder.code(
182  coder->index_encoder.coder, allocator,
183  NULL, NULL, 0,
184  out, out_pos, out_size, LZMA_RUN);
185  if (ret != LZMA_STREAM_END)
186  return ret;
187 
188  // Encode the Stream Footer into coder->buffer.
189  const lzma_stream_flags stream_flags = {
190  .version = 0,
191  .backward_size = lzma_index_size(coder->index),
192  .check = coder->block_options.check,
193  };
194 
195  if (lzma_stream_footer_encode(&stream_flags, coder->buffer)
196  != LZMA_OK)
197  return LZMA_PROG_ERROR;
198 
200  coder->sequence = SEQ_STREAM_FOOTER;
201  break;
202  }
203 
204  default:
205  assert(0);
206  return LZMA_PROG_ERROR;
207  }
208 
209  return LZMA_OK;
210 }
const lzma_allocator lzma_vli unpadded_size
Definition: index.h:345
const lzma_allocator const uint8_t size_t uint8_t size_t * out_pos
Definition: block.h:528
const lzma_allocator const uint8_t size_t * in_pos
Definition: block.h:579
const lzma_allocator const uint8_t size_t in_size
Definition: block.h:527
const lzma_allocator const uint8_t * in
Definition: block.h:527
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define NULL
Definition: cris-opc.c:27
lzma_ret lzma_index_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator, const lzma_index *i)
assert(limit<=UINT32_MAX/2)
def convert(trace_codes, trap_json)
static lzma_ret block_encoder_init(lzma_stream_coder *coder, const lzma_allocator *allocator)
#define LZMA_STREAM_HEADER_SIZE
Size of Stream Header and Stream Footer.
Definition: stream_flags.h:27
uint32_t header_size
Size of the Block Header field.
Definition: block.h:72
lzma_check check
Type of integrity Check.
Definition: block.h:93
lzma_code_function code
Pointer to function to do the actual coding.
Definition: common.h:150
void * coder
Pointer to coder-specific data.
Definition: common.h:137
uint8_t buffer[LZMA_BLOCK_HEADER_SIZE_MAX]
lzma_next_coder index_encoder
lzma_index * index
Index to hold sizes of the Blocks.
enum lzma_stream_coder::@652 sequence
size_t buffer_pos
Read position in buffer[].
bool block_encoder_is_initialized
size_t buffer_size
Total number of bytes in buffer[].
Options for encoding/decoding Stream Header and Stream Footer.
Definition: stream_flags.h:33
uint32_t version
Stream Flags format version.
Definition: stream_flags.h:51
#define LZMA_ACTION_MAX
Largest valid lzma_action value as unsigned integer.
Definition: common.h:81
uint64_t lzma_vli
Variable-length integer type.
Definition: vli.h:63
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_PROG_ERROR
Programming error.
Definition: base.h:218
@ LZMA_STREAM_END
End of stream was reached.
Definition: base.h:63
lzma_action
The ‘action’ argument for lzma_code()
Definition: base.h:250
size_t lzma_bufcpy(const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size)
Definition: common.c:94

References test-lz4-speed::action, allocator, assert(), lzma_stream_coder::block_encoder, block_encoder_init(), lzma_stream_coder::block_encoder_is_initialized, lzma_stream_coder::block_options, lzma_stream_coder::buffer, lzma_stream_coder::buffer_pos, lzma_stream_coder::buffer_size, lzma_block::check, lzma_next_coder_s::code, lzma_next_coder_s::coder, build_mig_index::convert(), lzma_block::header_size, in, in_pos, in_size, lzma_stream_coder::index, lzma_stream_coder::index_encoder, LZMA_ACTION_MAX, lzma_bufcpy(), LZMA_FINISH, lzma_index_encoder_init(), LZMA_OK, LZMA_PROG_ERROR, LZMA_RUN, LZMA_STREAM_END, LZMA_STREAM_HEADER_SIZE, LZMA_SYNC_FLUSH, NULL, out, out_pos, return_if_error, lzma_stream_coder::sequence, lzma_block::uncompressed_size, unpadded_size, and lzma_stream_flags::version.

Referenced by stream_encoder_init().

◆ stream_encoder_end()

static void stream_encoder_end ( void *  coder_ptr,
const lzma_allocator allocator 
)
static

Definition at line 214 of file stream_encoder.c.

215 {
216  lzma_stream_coder *coder = coder_ptr;
217 
220  lzma_index_end(coder->index, allocator);
221 
222  for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
223  lzma_free(coder->filters[i].options, allocator);
224 
225  lzma_free(coder, allocator);
226  return;
227 }
lzma_index ** i
Definition: index.h:629
void * options
Pointer to filter-specific options structure.
Definition: filter.h:63
lzma_vli id
Filter ID.
Definition: filter.h:54
lzma_filter filters[LZMA_FILTERS_MAX+1]
The filter chain currently in use.
void lzma_free(void *ptr, const lzma_allocator *allocator)
Frees memory.
Definition: common.c:78
void lzma_next_end(lzma_next_coder *next, const lzma_allocator *allocator)
Definition: common.c:145

References allocator, lzma_stream_coder::block_encoder, lzma_stream_coder::filters, i, lzma_filter::id, lzma_stream_coder::index, lzma_stream_coder::index_encoder, lzma_free(), lzma_next_end(), LZMA_VLI_UNKNOWN, and lzma_filter::options.

Referenced by stream_encoder_init().

◆ stream_encoder_init()

static lzma_ret stream_encoder_init ( lzma_next_coder next,
const lzma_allocator allocator,
const lzma_filter filters,
lzma_check  check 
)
static

Definition at line 272 of file stream_encoder.c.

274 {
276 
277  if (filters == NULL)
278  return LZMA_PROG_ERROR;
279 
280  lzma_stream_coder *coder = next->coder;
281 
282  if (coder == NULL) {
283  coder = lzma_alloc(sizeof(lzma_stream_coder), allocator);
284  if (coder == NULL)
285  return LZMA_MEM_ERROR;
286 
287  next->coder = coder;
288  next->code = &stream_encode;
289  next->end = &stream_encoder_end;
290  next->update = &stream_encoder_update;
291 
292  coder->filters[0].id = LZMA_VLI_UNKNOWN;
295  coder->index = NULL;
296  }
297 
298  // Basic initializations
299  coder->sequence = SEQ_STREAM_HEADER;
300  coder->block_options.version = 0;
301  coder->block_options.check = check;
302 
303  // Initialize the Index
304  lzma_index_end(coder->index, allocator);
305  coder->index = lzma_index_init(allocator);
306  if (coder->index == NULL)
307  return LZMA_MEM_ERROR;
308 
309  // Encode the Stream Header
310  lzma_stream_flags stream_flags = {
311  .version = 0,
312  .check = check,
313  };
314  return_if_error(lzma_stream_header_encode(
315  &stream_flags, coder->buffer));
316 
317  coder->buffer_pos = 0;
319 
320  // Initialize the Block encoder. This way we detect unsupported
321  // filter chains when initializing the Stream encoder instead of
322  // giving an error after Stream Header has already written out.
323  return stream_encoder_update(coder, allocator, filters, NULL);
324 }
static void stream_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
static lzma_ret stream_encode(void *coder_ptr, const lzma_allocator *allocator, const uint8_t *restrict in, size_t *restrict in_pos, size_t in_size, uint8_t *restrict out, size_t *restrict out_pos, size_t out_size, lzma_action action)
static lzma_ret stream_encoder_update(void *coder_ptr, const lzma_allocator *allocator, const lzma_filter *filters, const lzma_filter *reversed_filters)
uint32_t version
Block format version.
Definition: block.h:52
lzma_end_function end
Definition: common.h:155
lzma_ret(* update)(void *coder, const lzma_allocator *allocator, const lzma_filter *filters, const lzma_filter *reversed_filters)
Definition: common.h:173
#define LZMA_NEXT_CODER_INIT
Macro to initialize lzma_next_coder structure.
Definition: common.h:180
#define lzma_next_coder_init(func, next, allocator)
Definition: common.h:291
void * lzma_alloc(size_t size, const lzma_allocator *allocator) lzma_attribute((__malloc__)) lzma_attr_alloc_size(1)
Allocates memory.
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128

References allocator, lzma_stream_coder::block_encoder, lzma_stream_coder::block_options, lzma_stream_coder::buffer, lzma_stream_coder::buffer_pos, lzma_stream_coder::buffer_size, lzma_block::check, check, lzma_next_coder_s::code, lzma_next_coder_s::coder, lzma_next_coder_s::end, filters, lzma_stream_coder::filters, lzma_filter::id, lzma_stream_coder::index, lzma_stream_coder::index_encoder, lzma_alloc(), LZMA_MEM_ERROR, LZMA_NEXT_CODER_INIT, lzma_next_coder_init, LZMA_PROG_ERROR, LZMA_STREAM_HEADER_SIZE, LZMA_VLI_UNKNOWN, NULL, return_if_error, lzma_stream_coder::sequence, stream_encode(), stream_encoder_end(), stream_encoder_update(), lzma_next_coder_s::update, lzma_block::version, and lzma_stream_flags::version.

Referenced by LZMA_API().

◆ stream_encoder_update()

static lzma_ret stream_encoder_update ( void *  coder_ptr,
const lzma_allocator allocator,
const lzma_filter filters,
const lzma_filter reversed_filters 
)
static

Definition at line 231 of file stream_encoder.c.

234 {
235  lzma_stream_coder *coder = coder_ptr;
236 
237  if (coder->sequence <= SEQ_BLOCK_INIT) {
238  // There is no incomplete Block waiting to be finished,
239  // thus we can change the whole filter chain. Start by
240  // trying to initialize the Block encoder with the new
241  // chain. This way we detect if the chain is valid.
242  coder->block_encoder_is_initialized = false;
244  const lzma_ret ret = block_encoder_init(coder, allocator);
245  coder->block_options.filters = coder->filters;
246  if (ret != LZMA_OK)
247  return ret;
248 
249  coder->block_encoder_is_initialized = true;
250 
251  } else if (coder->sequence <= SEQ_BLOCK_ENCODE) {
252  // We are in the middle of a Block. Try to update only
253  // the filter-specific options.
255  coder->block_encoder.coder, allocator,
256  filters, reversed_filters));
257  } else {
258  // Trying to update the filter chain when we are already
259  // encoding Index or Stream Footer.
260  return LZMA_PROG_ERROR;
261  }
262 
263  // Free the copy of the old chain and make a copy of the new chain.
264  for (size_t i = 0; coder->filters[i].id != LZMA_VLI_UNKNOWN; ++i)
265  lzma_free(coder->filters[i].options, allocator);
266 
267  return lzma_filters_copy(filters, coder->filters, allocator);
268 }
lzma_filter * filters
Array of filters.
Definition: block.h:200
Filter options.
Definition: filter.h:43

References allocator, lzma_stream_coder::block_encoder, block_encoder_init(), lzma_stream_coder::block_encoder_is_initialized, lzma_stream_coder::block_options, lzma_next_coder_s::coder, lzma_block::filters, filters, lzma_stream_coder::filters, i, lzma_filter::id, lzma_free(), LZMA_OK, LZMA_PROG_ERROR, LZMA_VLI_UNKNOWN, lzma_filter::options, return_if_error, lzma_stream_coder::sequence, and lzma_next_coder_s::update.

Referenced by stream_encoder_init().