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

Compress in multi-call mode using LZMA2 in multi-threaded mode. More...

#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <lzma.h>

Go to the source code of this file.

Functions

static bool init_encoder (lzma_stream *strm)
 
static bool compress (lzma_stream *strm, FILE *infile, FILE *outfile)
 
int main (void)
 

Detailed Description

Compress in multi-call mode using LZMA2 in multi-threaded mode.

Usage: ./04_compress_easy_mt < INFILE > OUTFILE

Example: ./04_compress_easy_mt < foo > foo.xz

Definition in file 04_compress_easy_mt.c.

Function Documentation

◆ compress()

static bool compress ( lzma_stream strm,
FILE *  infile,
FILE *  outfile 
)
static

Definition at line 118 of file 04_compress_easy_mt.c.

119 {
121 
122  uint8_t inbuf[BUFSIZ];
123  uint8_t outbuf[BUFSIZ];
124 
125  strm->next_in = NULL;
126  strm->avail_in = 0;
127  strm->next_out = outbuf;
128  strm->avail_out = sizeof(outbuf);
129 
130  while (true) {
131  if (strm->avail_in == 0 && !feof(infile)) {
132  strm->next_in = inbuf;
133  strm->avail_in = fread(inbuf, 1, sizeof(inbuf),
134  infile);
135 
136  if (ferror(infile)) {
137  fprintf(stderr, "Read error: %s\n",
138  strerror(errno));
139  return false;
140  }
141 
142  if (feof(infile))
144  }
145 
146  lzma_ret ret = lzma_code(strm, action);
147 
148  if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
149  size_t write_size = sizeof(outbuf) - strm->avail_out;
150 
151  if (fwrite(outbuf, 1, write_size, outfile)
152  != write_size) {
153  fprintf(stderr, "Write error: %s\n",
154  strerror(errno));
155  return false;
156  }
157 
158  strm->next_out = outbuf;
159  strm->avail_out = sizeof(outbuf);
160  }
161 
162  if (ret != LZMA_OK) {
163  if (ret == LZMA_STREAM_END)
164  return true;
165 
166  const char *msg;
167  switch (ret) {
168  case LZMA_MEM_ERROR:
169  msg = "Memory allocation failed";
170  break;
171 
172  case LZMA_DATA_ERROR:
173  msg = "File size limits exceeded";
174  break;
175 
176  default:
177  msg = "Unknown error, possibly a bug";
178  break;
179  }
180 
181  fprintf(stderr, "Encoder error: %s (error code %u)\n",
182  msg, ret);
183  return false;
184  }
185  }
186 }
#define NULL
Definition: cris-opc.c:27
static lzma_stream strm
Definition: full_flush.c:20
FILE * outfile
Definition: fuzz_diff.c:16
unsigned char outbuf[SIZE]
Definition: gun.c:162
unsigned char inbuf[SIZE]
Definition: gun.c:161
static struct sockaddr static addrlen static backlog const void msg
Definition: sfsocketcall.h:119
unsigned char uint8_t
Definition: sftypes.h:31
Definition: z80asm.h:95
uint8_t * next_out
Definition: base.h:490
size_t avail_out
Definition: base.h:491
const uint8_t * next_in
Definition: base.h:486
size_t avail_in
Definition: base.h:487
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
lzma_ret
Return values used by several functions in liblzma.
Definition: base.h:57
@ LZMA_DATA_ERROR
Data is corrupt.
Definition: base.h:172
@ LZMA_MEM_ERROR
Cannot allocate memory.
Definition: base.h:128
@ LZMA_STREAM_END
End of stream was reached.
Definition: base.h:63
@ LZMA_OK
Operation completed successfully.
Definition: base.h:58
lzma_action
The ‘action’ argument for lzma_code()
Definition: base.h:250
@ LZMA_FINISH
Finish the coding operation.
Definition: base.h:328
@ LZMA_RUN
Continue coding.
Definition: base.h:251

References test-lz4-speed::action, lzma_stream::avail_in, lzma_stream::avail_out, if(), inbuf, LZMA_DATA_ERROR, LZMA_FINISH, LZMA_MEM_ERROR, LZMA_OK, LZMA_RUN, LZMA_STREAM_END, msg, lzma_stream::next_in, lzma_stream::next_out, NULL, outbuf, outfile, and strm.

Referenced by main().

◆ init_encoder()

static bool init_encoder ( lzma_stream strm)
static

Definition at line 26 of file 04_compress_easy_mt.c.

27 {
28  // The threaded encoder takes the options as pointer to
29  // a lzma_mt structure.
30  lzma_mt mt = {
31  // No flags are needed.
32  .flags = 0,
33 
34  // Let liblzma determine a sane block size.
35  .block_size = 0,
36 
37  // Use no timeout for lzma_code() calls by setting timeout
38  // to zero. That is, sometimes lzma_code() might block for
39  // a long time (from several seconds to even minutes).
40  // If this is not OK, for example due to progress indicator
41  // needing updates, specify a timeout in milliseconds here.
42  // See the documentation of lzma_mt in lzma/container.h for
43  // information how to choose a reasonable timeout.
44  .timeout = 0,
45 
46  // Use the default preset (6) for LZMA2.
47  // To use a preset, filters must be set to NULL.
48  .preset = LZMA_PRESET_DEFAULT,
49  .filters = NULL,
50 
51  // Use CRC64 for integrity checking. See also
52  // 01_compress_easy.c about choosing the integrity check.
53  .check = LZMA_CHECK_CRC64,
54  };
55 
56  // Detect how many threads the CPU supports.
57  mt.threads = lzma_cputhreads();
58 
59  // If the number of CPU cores/threads cannot be detected,
60  // use one thread. Note that this isn't the same as the normal
61  // single-threaded mode as this will still split the data into
62  // blocks and use more RAM than the normal single-threaded mode.
63  // You may want to consider using lzma_easy_encoder() or
64  // lzma_stream_encoder() instead of lzma_stream_encoder_mt() if
65  // lzma_cputhreads() returns 0 or 1.
66  if (mt.threads == 0)
67  mt.threads = 1;
68 
69  // If the number of CPU cores/threads exceeds threads_max,
70  // limit the number of threads to keep memory usage lower.
71  // The number 8 is arbitrarily chosen and may be too low or
72  // high depending on the compression preset and the computer
73  // being used.
74  //
75  // FIXME: A better way could be to check the amount of RAM
76  // (or available RAM) and use lzma_stream_encoder_mt_memusage()
77  // to determine if the number of threads should be reduced.
78  const uint32_t threads_max = 8;
79  if (mt.threads > threads_max)
80  mt.threads = threads_max;
81 
82  // Initialize the threaded encoder.
83  lzma_ret ret = lzma_stream_encoder_mt(strm, &mt);
84 
85  if (ret == LZMA_OK)
86  return true;
87 
88  const char *msg;
89  switch (ret) {
90  case LZMA_MEM_ERROR:
91  msg = "Memory allocation failed";
92  break;
93 
94  case LZMA_OPTIONS_ERROR:
95  // We are no longer using a plain preset so this error
96  // message has been edited accordingly compared to
97  // 01_compress_easy.c.
98  msg = "Specified filter chain is not supported";
99  break;
100 
102  msg = "Specified integrity check is not supported";
103  break;
104 
105  default:
106  msg = "Unknown error, possibly a bug";
107  break;
108  }
109 
110  fprintf(stderr, "Error initializing the encoder: %s (error code %u)\n",
111  msg, ret);
112  return false;
113 }
@ LZMA_CHECK_CRC64
Definition: check.h:42
#define LZMA_PRESET_DEFAULT
Default compression preset.
Definition: container.h:31
static uint32_t threads_max
Definition: hardware.c:18
unsigned int uint32_t
Definition: sftypes.h:29
Multithreading options.
Definition: container.h:66
uint32_t flags
Flags.
Definition: container.h:74
uint32_t threads
Number of worker threads to use.
Definition: container.h:79
@ LZMA_UNSUPPORTED_CHECK
Cannot calculate the integrity check.
Definition: base.h:90
@ LZMA_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160

References lzma_mt::flags, LZMA_CHECK_CRC64, LZMA_MEM_ERROR, LZMA_OK, LZMA_OPTIONS_ERROR, LZMA_PRESET_DEFAULT, LZMA_UNSUPPORTED_CHECK, msg, NULL, strm, lzma_mt::threads, and threads_max.

Referenced by main().

◆ main()

int main ( void  )

Definition at line 190 of file 04_compress_easy_mt.c.

191 {
193 
194  bool success = init_encoder(&strm);
195  if (success)
196  success = compress(&strm, stdin, stdout);
197 
198  lzma_end(&strm);
199 
200  if (fclose(stdout)) {
201  fprintf(stderr, "Write error: %s\n", strerror(errno));
202  success = false;
203  }
204 
205  return success ? EXIT_SUCCESS : EXIT_FAILURE;
206 }
static bool compress(lzma_stream *strm, FILE *infile, FILE *outfile)
static bool init_encoder(lzma_stream *strm)
Passing data to and from liblzma.
Definition: base.h:485
#define LZMA_STREAM_INIT
Initialization for lzma_stream.
Definition: base.h:545

References compress(), init_encoder(), LZMA_STREAM_INIT, and strm.