Rizin
unix-like reverse engineering framework and cli tools
zran.h File Reference
#include <stdio.h>
#include "zlib.h"

Go to the source code of this file.

Classes

struct  deflate_index
 

Functions

int deflate_index_build (FILE *in, off_t span, struct deflate_index **built)
 
void deflate_index_free (struct deflate_index *index)
 
int deflate_index_extract (FILE *in, struct deflate_index *index, off_t offset, unsigned char *buf, int len)
 

Function Documentation

◆ deflate_index_build()

int deflate_index_build ( FILE *  in,
off_t  span,
struct deflate_index **  built 
)

Definition at line 135 of file zran.c.

136 {
137  int ret;
138  int gzip = 0; /* true if reading a gzip file */
139  off_t totin, totout; /* our own total counters to avoid 4GB limit */
140  off_t last; /* totout value of last access point */
141  struct deflate_index *index; /* access points being generated */
142  z_stream strm;
143  unsigned char input[CHUNK];
144  unsigned char window[WINSIZE];
145 
146  /* initialize inflate */
147  strm.zalloc = Z_NULL;
148  strm.zfree = Z_NULL;
149  strm.opaque = Z_NULL;
150  strm.avail_in = 0;
151  strm.next_in = Z_NULL;
152  ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
153  if (ret != Z_OK)
154  return ret;
155 
156  /* inflate the input, maintain a sliding window, and build an index -- this
157  also validates the integrity of the compressed data using the check
158  information in the gzip or zlib stream */
159  totin = totout = last = 0;
160  index = NULL; /* will be allocated by first addpoint() */
161  strm.avail_out = 0;
162  do {
163  /* get some compressed data from input file */
164  strm.avail_in = fread(input, 1, CHUNK, in);
165  if (ferror(in)) {
166  ret = Z_ERRNO;
167  goto deflate_index_build_error;
168  }
169  if (strm.avail_in == 0) {
170  ret = Z_DATA_ERROR;
171  goto deflate_index_build_error;
172  }
173  strm.next_in = input;
174 
175  /* check for a gzip stream */
176  if (totin == 0 && strm.avail_in >= 3 &&
177  input[0] == 31 && input[1] == 139 && input[2] == 8)
178  gzip = 1;
179 
180  /* process all of that, or until end of stream */
181  do {
182  /* reset sliding window if necessary */
183  if (strm.avail_out == 0) {
185  strm.next_out = window;
186  }
187 
188  /* inflate until out of input, output, or at end of block --
189  update the total input and output counters */
190  totin += strm.avail_in;
191  totout += strm.avail_out;
192  ret = inflate(&strm, Z_BLOCK); /* return at end of block */
193  totin -= strm.avail_in;
194  totout -= strm.avail_out;
195  if (ret == Z_NEED_DICT)
196  ret = Z_DATA_ERROR;
197  if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
198  goto deflate_index_build_error;
199  if (ret == Z_STREAM_END) {
200  if (gzip &&
201  (strm.avail_in || ungetc(getc(in), in) != EOF)) {
202  ret = inflateReset(&strm);
203  if (ret != Z_OK)
204  goto deflate_index_build_error;
205  continue;
206  }
207  break;
208  }
209 
210  /* if at end of block, consider adding an index entry (note that if
211  data_type indicates an end-of-block, then all of the
212  uncompressed data from that block has been delivered, and none
213  of the compressed data after that block has been consumed,
214  except for up to seven bits) -- the totout == 0 provides an
215  entry point after the zlib or gzip header, and assures that the
216  index always has at least one access point; we avoid creating an
217  access point after the last block by checking bit 6 of data_type
218  */
219  if ((strm.data_type & 128) && !(strm.data_type & 64) &&
220  (totout == 0 || totout - last > span)) {
221  index = addpoint(index, strm.data_type & 7, totin,
222  totout, strm.avail_out, window);
223  if (index == NULL) {
224  ret = Z_MEM_ERROR;
225  goto deflate_index_build_error;
226  }
227  last = totout;
228  }
229  } while (strm.avail_in != 0);
230  } while (ret != Z_STREAM_END);
231 
232  /* clean up and return index (release unused entries in list) */
233  (void)inflateEnd(&strm);
234  index->list = realloc(index->list, sizeof(struct point) * index->have);
235  index->gzip = gzip;
236  index->length = totout;
237  *built = index;
238  return index->have;
239 
240  /* return error */
241  deflate_index_build_error:
242  (void)inflateEnd(&strm);
243  deflate_index_free(index);
244  return ret;
245 }
const lzma_allocator const uint8_t * in
Definition: block.h:527
#define NULL
Definition: cris-opc.c:27
static lzma_stream strm
Definition: full_flush.c:20
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:623
int ZEXPORT inflateReset(z_streamp strm)
Definition: inflate.c:145
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1301
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
int off_t
Definition: sftypes.h:41
int gzip
Definition: zran.h:12
int have
Definition: zran.h:11
void * list
Definition: zran.h:15
off_t length
Definition: zran.h:14
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
Definition: zran.c:68
struct _window window
static bool input(void *ud, zip_uint8_t *data, zip_uint64_t length)
#define Z_NEED_DICT
Definition: zlib.h:179
#define Z_ERRNO
Definition: zlib.h:180
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1817
#define Z_BLOCK
Definition: zlib.h:173
#define Z_STREAM_END
Definition: zlib.h:178
#define Z_OK
Definition: zlib.h:177
#define Z_DATA_ERROR
Definition: zlib.h:182
#define Z_NULL
Definition: zlib.h:212
#define Z_MEM_ERROR
Definition: zlib.h:183
#define CHUNK
Definition: zran.c:65
void deflate_index_free(struct deflate_index *index)
Definition: zran.c:76
static struct deflate_index * addpoint(struct deflate_index *index, int bits, off_t in, off_t out, unsigned left, unsigned char *window)
Definition: zran.c:89
#define WINSIZE
Definition: zran.c:64

References addpoint(), lzma_stream::avail_in, lzma_stream::avail_out, CHUNK, deflate_index_free(), deflate_index::gzip, deflate_index::have, in, inflate(), inflateEnd(), inflateInit2, inflateReset(), input(), deflate_index::length, deflate_index::list, lzma_stream::next_in, lzma_stream::next_out, NULL, realloc(), strm, WINSIZE, Z_BLOCK, Z_DATA_ERROR, Z_ERRNO, Z_MEM_ERROR, Z_NEED_DICT, Z_NULL, Z_OK, and Z_STREAM_END.

◆ deflate_index_extract()

int deflate_index_extract ( FILE *  in,
struct deflate_index index,
off_t  offset,
unsigned char *  buf,
int  len 
)

Definition at line 248 of file zran.c.

250 {
251  int ret, skip;
252  z_stream strm;
253  struct point *here;
254  unsigned char input[CHUNK];
255  unsigned char discard[WINSIZE];
256 
257  /* proceed only if something reasonable to do */
258  if (len < 0)
259  return 0;
260 
261  /* find where in stream to start */
262  here = index->list;
263  ret = index->have;
264  while (--ret && here[1].out <= offset)
265  here++;
266 
267  /* initialize file and inflate state to start there */
268  strm.zalloc = Z_NULL;
269  strm.zfree = Z_NULL;
270  strm.opaque = Z_NULL;
271  strm.avail_in = 0;
272  strm.next_in = Z_NULL;
273  ret = inflateInit2(&strm, -15); /* raw inflate */
274  if (ret != Z_OK)
275  return ret;
276  ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
277  if (ret == -1)
278  goto deflate_index_extract_ret;
279  if (here->bits) {
280  ret = getc(in);
281  if (ret == -1) {
282  ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
283  goto deflate_index_extract_ret;
284  }
285  (void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
286  }
287  (void)inflateSetDictionary(&strm, here->window, WINSIZE);
288 
289  /* skip uncompressed bytes until offset reached, then satisfy request */
290  offset -= here->out;
291  strm.avail_in = 0;
292  skip = 1; /* while skipping to offset */
293  do {
294  /* define where to put uncompressed data, and how much */
295  if (offset > WINSIZE) { /* skip WINSIZE bytes */
297  strm.next_out = discard;
298  offset -= WINSIZE;
299  }
300  else if (offset > 0) { /* last skip */
302  strm.next_out = discard;
303  offset = 0;
304  }
305  else if (skip) { /* at offset now */
306  strm.avail_out = len;
307  strm.next_out = buf;
308  skip = 0; /* only do this once */
309  }
310 
311  /* uncompress until avail_out filled, or end of stream */
312  do {
313  if (strm.avail_in == 0) {
314  strm.avail_in = fread(input, 1, CHUNK, in);
315  if (ferror(in)) {
316  ret = Z_ERRNO;
317  goto deflate_index_extract_ret;
318  }
319  if (strm.avail_in == 0) {
320  ret = Z_DATA_ERROR;
321  goto deflate_index_extract_ret;
322  }
323  strm.next_in = input;
324  }
325  ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */
326  if (ret == Z_NEED_DICT)
327  ret = Z_DATA_ERROR;
328  if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
329  goto deflate_index_extract_ret;
330  if (ret == Z_STREAM_END) {
331  /* the raw deflate stream has ended */
332  if (index->gzip == 0)
333  /* this is a zlib stream that has ended -- done */
334  break;
335 
336  /* near the end of a gzip member, which might be followed by
337  another gzip member -- skip the gzip trailer and see if
338  there is more input after it */
339  if (strm.avail_in < 8) {
340  fseeko(in, 8 - strm.avail_in, SEEK_CUR);
341  strm.avail_in = 0;
342  }
343  else {
344  strm.avail_in -= 8;
345  strm.next_in += 8;
346  }
347  if (strm.avail_in == 0 && ungetc(getc(in), in) == EOF)
348  /* the input ended after the gzip trailer -- done */
349  break;
350 
351  /* there is more input, so another gzip member should follow --
352  validate and skip the gzip header */
353  ret = inflateReset2(&strm, 31);
354  if (ret != Z_OK)
355  goto deflate_index_extract_ret;
356  do {
357  if (strm.avail_in == 0) {
358  strm.avail_in = fread(input, 1, CHUNK, in);
359  if (ferror(in)) {
360  ret = Z_ERRNO;
361  goto deflate_index_extract_ret;
362  }
363  if (strm.avail_in == 0) {
364  ret = Z_DATA_ERROR;
365  goto deflate_index_extract_ret;
366  }
367  strm.next_in = input;
368  }
369  ret = inflate(&strm, Z_BLOCK);
370  if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
371  goto deflate_index_extract_ret;
372  } while ((strm.data_type & 128) == 0);
373 
374  /* set up to continue decompression of the raw deflate stream
375  that follows the gzip header */
376  ret = inflateReset2(&strm, -15);
377  if (ret != Z_OK)
378  goto deflate_index_extract_ret;
379  }
380 
381  /* continue to process the available input before reading more */
382  } while (strm.avail_out != 0);
383 
384  if (ret == Z_STREAM_END)
385  /* reached the end of the compressed data -- return the data that
386  was available, possibly less than requested */
387  break;
388 
389  /* do until offset reached and requested data read */
390  } while (skip);
391 
392  /* compute the number of uncompressed bytes read after the offset */
393  ret = skip ? 0 : len - strm.avail_out;
394 
395  /* clean up and return the bytes read, or the negative error */
396  deflate_index_extract_ret:
397  (void)inflateEnd(&strm);
398  return ret;
399 }
size_t len
Definition: 6502dis.c:15
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define fseeko(s, o, w)
Definition: compat.h:121
void skip(file *in, unsigned n)
Definition: gzappend.c:202
int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
Definition: inflate.c:1338
int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
Definition: inflate.c:248
int ZEXPORT inflateReset2(z_streamp strm, int windowBits)
Definition: inflate.c:158
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf struct sembuf unsigned
Definition: sflib.h:97
off_t in
Definition: zran.c:70
unsigned char window[WINSIZE]
Definition: zran.c:72
int bits
Definition: zran.c:71
off_t out
Definition: zran.c:69
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
#define Z_NO_FLUSH
Definition: zlib.h:168

References lzma_stream::avail_in, lzma_stream::avail_out, point::bits, CHUNK, fseeko, deflate_index::gzip, deflate_index::have, in, point::in, inflate(), inflateEnd(), inflateInit2, inflatePrime(), inflateReset2(), inflateSetDictionary(), input(), len, deflate_index::list, lzma_stream::next_in, lzma_stream::next_out, out, point::out, SEEK_CUR, SEEK_SET, skip(), strm, unsigned, point::window, WINSIZE, Z_BLOCK, Z_DATA_ERROR, Z_ERRNO, Z_MEM_ERROR, Z_NEED_DICT, Z_NO_FLUSH, Z_NULL, Z_OK, and Z_STREAM_END.

◆ deflate_index_free()

void deflate_index_free ( struct deflate_index index)

Definition at line 76 of file zran.c.

77 {
78  if (index != NULL) {
79  free(index->list);
80  free(index);
81  }
82 }
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130

References free(), deflate_index::list, and NULL.

Referenced by addpoint(), and deflate_index_build().