Rizin
unix-like reverse engineering framework and cli tools
03_compress_custom.c
Go to the documentation of this file.
1 //
9 //
10 // Author: Lasse Collin
11 //
12 // This file has been put into the public domain.
13 // You can do whatever you want with this file.
14 //
16 
17 #include <stdbool.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <errno.h>
22 #include <lzma.h>
23 
24 
25 static bool
27 {
28  // Use the default preset (6) for LZMA2.
29  //
30  // The lzma_options_lzma structure and the lzma_lzma_preset() function
31  // are declared in lzma/lzma12.h (src/liblzma/api/lzma/lzma12.h in the
32  // source package or e.g. /usr/include/lzma/lzma12.h depending on
33  // the install prefix).
34  lzma_options_lzma opt_lzma2;
35  if (lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT)) {
36  // It should never fail because the default preset
37  // (and presets 0-9 optionally with LZMA_PRESET_EXTREME)
38  // are supported by all stable liblzma versions.
39  //
40  // (The encoder initialization later in this function may
41  // still fail due to unsupported preset *if* the features
42  // required by the preset have been disabled at build time,
43  // but no-one does such things except on embedded systems.)
44  fprintf(stderr, "Unsupported preset, possibly a bug\n");
45  return false;
46  }
47 
48  // Now we could customize the LZMA2 options if we wanted. For example,
49  // we could set the the dictionary size (opt_lzma2.dict_size) to
50  // something else than the default (8 MiB) of the default preset.
51  // See lzma/lzma12.h for details of all LZMA2 options.
52  //
53  // The x86 BCJ filter will try to modify the x86 instruction stream so
54  // that LZMA2 can compress it better. The x86 BCJ filter doesn't need
55  // any options so it will be set to NULL below.
56  //
57  // Construct the filter chain. The uncompressed data goes first to
58  // the first filter in the array, in this case the x86 BCJ filter.
59  // The array is always terminated by setting .id = LZMA_VLI_UNKNOWN.
60  //
61  // See lzma/filter.h for more information about the lzma_filter
62  // structure.
63  lzma_filter filters[] = {
64  { .id = LZMA_FILTER_X86, .options = NULL },
65  { .id = LZMA_FILTER_LZMA2, .options = &opt_lzma2 },
66  { .id = LZMA_VLI_UNKNOWN, .options = NULL },
67  };
68 
69  // Initialize the encoder using the custom filter chain.
70  lzma_ret ret = lzma_stream_encoder(strm, filters, LZMA_CHECK_CRC64);
71 
72  if (ret == LZMA_OK)
73  return true;
74 
75  const char *msg;
76  switch (ret) {
77  case LZMA_MEM_ERROR:
78  msg = "Memory allocation failed";
79  break;
80 
81  case LZMA_OPTIONS_ERROR:
82  // We are no longer using a plain preset so this error
83  // message has been edited accordingly compared to
84  // 01_compress_easy.c.
85  msg = "Specified filter chain is not supported";
86  break;
87 
89  msg = "Specified integrity check is not supported";
90  break;
91 
92  default:
93  msg = "Unknown error, possibly a bug";
94  break;
95  }
96 
97  fprintf(stderr, "Error initializing the encoder: %s (error code %u)\n",
98  msg, ret);
99  return false;
100 }
101 
102 
103 // This function is identical to the one in 01_compress_easy.c.
104 static bool
106 {
108 
109  uint8_t inbuf[BUFSIZ];
110  uint8_t outbuf[BUFSIZ];
111 
112  strm->next_in = NULL;
113  strm->avail_in = 0;
114  strm->next_out = outbuf;
115  strm->avail_out = sizeof(outbuf);
116 
117  while (true) {
118  if (strm->avail_in == 0 && !feof(infile)) {
119  strm->next_in = inbuf;
120  strm->avail_in = fread(inbuf, 1, sizeof(inbuf),
121  infile);
122 
123  if (ferror(infile)) {
124  fprintf(stderr, "Read error: %s\n",
125  strerror(errno));
126  return false;
127  }
128 
129  if (feof(infile))
131  }
132 
133  lzma_ret ret = lzma_code(strm, action);
134 
135  if (strm->avail_out == 0 || ret == LZMA_STREAM_END) {
136  size_t write_size = sizeof(outbuf) - strm->avail_out;
137 
138  if (fwrite(outbuf, 1, write_size, outfile)
139  != write_size) {
140  fprintf(stderr, "Write error: %s\n",
141  strerror(errno));
142  return false;
143  }
144 
145  strm->next_out = outbuf;
146  strm->avail_out = sizeof(outbuf);
147  }
148 
149  if (ret != LZMA_OK) {
150  if (ret == LZMA_STREAM_END)
151  return true;
152 
153  const char *msg;
154  switch (ret) {
155  case LZMA_MEM_ERROR:
156  msg = "Memory allocation failed";
157  break;
158 
159  case LZMA_DATA_ERROR:
160  msg = "File size limits exceeded";
161  break;
162 
163  default:
164  msg = "Unknown error, possibly a bug";
165  break;
166  }
167 
168  fprintf(stderr, "Encoder error: %s (error code %u)\n",
169  msg, ret);
170  return false;
171  }
172  }
173 }
174 
175 
176 extern int
177 main(void)
178 {
180 
181  bool success = init_encoder(&strm);
182  if (success)
183  success = compress(&strm, stdin, stdout);
184 
185  lzma_end(&strm);
186 
187  if (fclose(stdout)) {
188  fprintf(stderr, "Write error: %s\n", strerror(errno));
189  success = false;
190  }
191 
192  return success ? EXIT_SUCCESS : EXIT_FAILURE;
193 }
int main(void)
static bool compress(lzma_stream *strm, FILE *infile, FILE *outfile)
static bool init_encoder(lzma_stream *strm)
@ LZMA_CHECK_CRC64
Definition: check.h:42
#define LZMA_FILTER_X86
Definition: bcj.h:22
const lzma_filter * filters
Definition: container.h:315
#define LZMA_PRESET_DEFAULT
Default compression preset.
Definition: container.h:31
#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
#define LZMA_FILTER_LZMA2
LZMA2 Filter ID.
Definition: lzma12.h:40
The public API of liblzma data compression library.
string FILE
Definition: benchmark.py:21
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
Filter options.
Definition: filter.h:43
lzma_vli id
Filter ID.
Definition: filter.h:54
Options specific to the LZMA1 and LZMA2 filters.
Definition: lzma12.h:185
Passing data to and from liblzma.
Definition: base.h:485
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
#define LZMA_VLI_UNKNOWN
VLI value to denote that the value is unknown.
Definition: vli.h:39
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_UNSUPPORTED_CHECK
Cannot calculate the integrity check.
Definition: base.h:90
@ LZMA_OPTIONS_ERROR
Invalid or unsupported options.
Definition: base.h:160
@ 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
#define LZMA_STREAM_INIT
Initialization for lzma_stream.
Definition: base.h:545