Rizin
unix-like reverse engineering framework and cli tools
gzappend.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "zlib.h"

Go to the source code of this file.

Classes

struct  file
 

Macros

#define local   static
 
#define LGCHUNK   14
 
#define CHUNK   (1U << LGCHUNK)
 
#define DSIZE   32768U
 
#define read1(in)
 

Functions

void bye (char *msg1, char *msg2)
 
unsigned gcd (unsigned a, unsigned b)
 
void rotate (unsigned char *list, unsigned len, unsigned rot)
 
int readin (file *in)
 
int readmore (file *in)
 
void skip (file *in, unsigned n)
 
unsigned long read4 (file *in)
 
void gzheader (file *in)
 
int gzscan (char *name, z_stream *strm, int level)
 
void gztack (char *name, int gd, z_stream *strm, int last)
 
int main (int argc, char **argv)
 

Macro Definition Documentation

◆ CHUNK

#define CHUNK   (1U << LGCHUNK)

Definition at line 89 of file gzappend.c.

◆ DSIZE

#define DSIZE   32768U

Definition at line 90 of file gzappend.c.

◆ LGCHUNK

#define LGCHUNK   14

Definition at line 88 of file gzappend.c.

◆ local

#define local   static

Definition at line 87 of file gzappend.c.

◆ read1

#define read1 (   in)
Value:
(in->left == 0 ? readmore(in) : 0, \
in->left--, *(in->next)++)
const lzma_allocator const uint8_t * in
Definition: block.h:527
int readmore(file *in)
Definition: gzappend.c:192

Definition at line 198 of file gzappend.c.

Function Documentation

◆ bye()

void bye ( char *  msg1,
char *  msg2 
)

Definition at line 93 of file gzappend.c.

94 {
95  fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2);
96  exit(1);
97 }

References test-lz4-list::exit.

Referenced by gzheader(), gzscan(), gztack(), main(), readin(), readmore(), sh_assembler(), and skip().

◆ gcd()

unsigned gcd ( unsigned  a,
unsigned  b 
)

Definition at line 102 of file gzappend.c.

103 {
104  unsigned c;
105 
106  while (a && b)
107  if (a > b) {
108  c = b;
109  while (a - c >= c)
110  c <<= 1;
111  a -= c;
112  }
113  else {
114  c = a;
115  while (b - c >= c)
116  c <<= 1;
117  b -= c;
118  }
119  return a + b;
120 }
#define b(i)
Definition: sha256.c:42
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41

References a, b, and c.

Referenced by rotate().

◆ gzheader()

void gzheader ( file in)

Definition at line 235 of file gzappend.c.

236 {
237  int flags;
238  unsigned n;
239 
240  if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file");
241  if (read1(in) != 8) bye("unknown compression method in", in->name);
242  flags = read1(in);
243  if (flags & 0xe0) bye("unknown header flags set in", in->name);
244  skip(in, 6);
245  if (flags & 4) {
246  n = read1(in);
247  n += (unsigned)(read1(in)) << 8;
248  skip(in, n);
249  }
250  if (flags & 8) while (read1(in) != 0) ;
251  if (flags & 16) while (read1(in) != 0) ;
252  if (flags & 2) skip(in, 2);
253 }
void skip(file *in, unsigned n)
Definition: gzappend.c:202
#define read1(in)
Definition: gzappend.c:198
void bye(char *msg1, char *msg2)
Definition: gzappend.c:93
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
int n
Definition: mipsasm.c:19
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123

References bye(), flags, in, n, read1, skip(), and unsigned.

Referenced by gzscan().

◆ gzscan()

int gzscan ( char *  name,
z_stream strm,
int  level 
)

Definition at line 259 of file gzappend.c.

260 {
261  int ret, lastbit, left, full;
262  unsigned have;
263  unsigned long crc, tot;
264  unsigned char *window;
265  off_t lastoff, end;
266  file gz;
267 
268  /* open gzip file */
269  gz.name = name;
270  gz.fd = open(name, O_RDWR, 0);
271  if (gz.fd == -1) bye("cannot open ", name);
272  gz.buf = malloc(CHUNK);
273  if (gz.buf == NULL) bye("out of memory", "");
274  gz.size = LGCHUNK;
275  gz.left = 0;
276 
277  /* skip gzip header */
278  gzheader(&gz);
279 
280  /* prepare to decompress */
281  window = malloc(DSIZE);
282  if (window == NULL) bye("out of memory", "");
283  strm->zalloc = Z_NULL;
284  strm->zfree = Z_NULL;
285  strm->opaque = Z_NULL;
286  ret = inflateInit2(strm, -15);
287  if (ret != Z_OK) bye("out of memory", " or library mismatch");
288 
289  /* decompress the deflate stream, saving append information */
290  lastbit = 0;
291  lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
292  left = 0;
293  strm->avail_in = gz.left;
294  strm->next_in = gz.next;
295  crc = crc32(0L, Z_NULL, 0);
296  have = full = 0;
297  do {
298  /* if needed, get more input */
299  if (strm->avail_in == 0) {
300  readmore(&gz);
301  strm->avail_in = gz.left;
302  strm->next_in = gz.next;
303  }
304 
305  /* set up output to next available section of sliding window */
306  strm->avail_out = DSIZE - have;
307  strm->next_out = window + have;
308 
309  /* inflate and check for errors */
310  ret = inflate(strm, Z_BLOCK);
311  if (ret == Z_STREAM_ERROR) bye("internal stream error!", "");
312  if (ret == Z_MEM_ERROR) bye("out of memory", "");
313  if (ret == Z_DATA_ERROR)
314  bye("invalid compressed data--format violated in", name);
315 
316  /* update crc and sliding window pointer */
317  crc = crc32(crc, window + have, DSIZE - have - strm->avail_out);
318  if (strm->avail_out)
319  have = DSIZE - strm->avail_out;
320  else {
321  have = 0;
322  full = 1;
323  }
324 
325  /* process end of block */
326  if (strm->data_type & 128) {
327  if (strm->data_type & 64)
328  left = strm->data_type & 0x1f;
329  else {
330  lastbit = strm->data_type & 0x1f;
331  lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in;
332  }
333  }
334  } while (ret != Z_STREAM_END);
335  inflateEnd(strm);
336  gz.left = strm->avail_in;
337  gz.next = strm->next_in;
338 
339  /* save the location of the end of the compressed data */
340  end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
341 
342  /* check gzip trailer and save total for deflate */
343  if (crc != read4(&gz))
344  bye("invalid compressed data--crc mismatch in ", name);
345  tot = strm->total_out;
346  if ((tot & 0xffffffffUL) != read4(&gz))
347  bye("invalid compressed data--length mismatch in", name);
348 
349  /* if not at end of file, warn */
350  if (gz.left || readin(&gz))
351  fprintf(stderr,
352  "gzappend warning: junk at end of gzip file overwritten\n");
353 
354  /* clear last block bit */
355  lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET);
356  if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
357  *gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7)));
358  lseek(gz.fd, -1L, SEEK_CUR);
359  if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name);
360 
361  /* if window wrapped, build dictionary from window by rotating */
362  if (full) {
363  rotate(window, DSIZE, have);
364  have = DSIZE;
365  }
366 
367  /* set up deflate stream with window, crc, total_in, and leftover bits */
369  if (ret != Z_OK) bye("out of memory", "");
371  strm->adler = crc;
372  strm->total_in = tot;
373  if (left) {
374  lseek(gz.fd, --end, SEEK_SET);
375  if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
376  deflatePrime(strm, 8 - left, *gz.buf);
377  }
378  lseek(gz.fd, end, SEEK_SET);
379 
380  /* clean up and return */
381  free(window);
382  free(gz.buf);
383  return gz.fd;
384 }
#define NULL
Definition: cris-opc.c:27
static static fork write
Definition: sflib.h:33
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep lseek
Definition: sflib.h:113
int ZEXPORT deflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength)
Definition: deflate.c:416
int ZEXPORT deflatePrime(z_streamp strm, int bits, int value)
Definition: deflate.c:582
big_t tot
Definition: enough.c:229
static lzma_stream strm
Definition: full_flush.c:20
#define CHUNK
Definition: gzappend.c:89
#define DSIZE
Definition: gzappend.c:90
unsigned long read4(file *in)
Definition: gzappend.c:223
#define LGCHUNK
Definition: gzappend.c:88
void gzheader(file *in)
Definition: gzappend.c:235
int readin(file *in)
Definition: gzappend.c:180
void rotate(unsigned char *list, unsigned len, unsigned rot)
Definition: gzappend.c:123
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:623
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1301
void * malloc(size_t size)
Definition: malloc.c:123
const char * name
Definition: op.c:541
int off_t
Definition: sftypes.h:41
#define O_RDWR
Definition: sftypes.h:488
Definition: gzappend.c:170
unsigned left
Definition: gzappend.c:173
unsigned char * buf
Definition: gzappend.c:174
int size
Definition: gzappend.c:172
char * name
Definition: gzappend.c:176
z_const unsigned char * next
Definition: gzappend.c:175
int fd
Definition: gzappend.c:171
uint8_t * next_out
Definition: base.h:490
uint64_t total_in
Definition: base.h:488
size_t avail_out
Definition: base.h:491
const uint8_t * next_in
Definition: base.h:486
uint64_t total_out
Definition: base.h:492
size_t avail_in
Definition: base.h:487
Definition: z80asm.h:102
static int level
Definition: vmenus.c:2424
struct _window window
#define SEEK_SET
Definition: zip.c:88
#define SEEK_CUR
Definition: zip.c:80
#define L
Definition: zip_err_str.c:7
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:1063
#define Z_DEFLATED
Definition: zlib.h:209
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:200
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1814
#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_STREAM_ERROR
Definition: zlib.h:181
#define Z_NULL
Definition: zlib.h:212
#define Z_MEM_ERROR
Definition: zlib.h:183
int read(izstream &zs, T *x, Items items)
Definition: zstream.h:115

References lzma_stream::avail_in, lzma_stream::avail_out, file::buf, bye(), CHUNK, crc32(), deflateInit2, deflatePrime(), deflateSetDictionary(), DSIZE, test_evm::end, file::fd, free(), gzheader(), inflate(), inflateEnd(), inflateInit2, L, file::left, level, LGCHUNK, lseek, malloc(), name, file::name, file::next, lzma_stream::next_in, lzma_stream::next_out, NULL, O_RDWR, read(), read4(), readin(), readmore(), rotate(), SEEK_CUR, SEEK_SET, file::size, strm, tot, lzma_stream::total_in, lzma_stream::total_out, write, Z_BLOCK, Z_DATA_ERROR, Z_DEFAULT_STRATEGY, Z_DEFLATED, Z_MEM_ERROR, Z_NULL, Z_OK, Z_STREAM_END, and Z_STREAM_ERROR.

Referenced by main().

◆ gztack()

void gztack ( char *  name,
int  gd,
z_stream strm,
int  last 
)

Definition at line 388 of file gzappend.c.

389 {
390  int fd, len, ret;
391  unsigned left;
392  unsigned char *in, *out;
393 
394  /* open file to compress and append */
395  fd = 0;
396  if (name != NULL) {
397  fd = open(name, O_RDONLY, 0);
398  if (fd == -1)
399  fprintf(stderr, "gzappend warning: %s not found, skipping ...\n",
400  name);
401  }
402 
403  /* allocate buffers */
404  in = malloc(CHUNK);
405  out = malloc(CHUNK);
406  if (in == NULL || out == NULL) bye("out of memory", "");
407 
408  /* compress input file and append to gzip file */
409  do {
410  /* get more input */
411  len = read(fd, in, CHUNK);
412  if (len == -1) {
413  fprintf(stderr,
414  "gzappend warning: error reading %s, skipping rest ...\n",
415  name);
416  len = 0;
417  }
419  strm->next_in = in;
420  if (len) strm->adler = crc32(strm->adler, in, (unsigned)len);
421 
422  /* compress and write all available output */
423  do {
424  strm->avail_out = CHUNK;
425  strm->next_out = out;
426  ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH);
427  left = CHUNK - strm->avail_out;
428  while (left) {
429  len = write(gd, out + CHUNK - strm->avail_out - left, left);
430  if (len == -1) bye("writing gzip file", "");
431  left -= (unsigned)len;
432  }
433  } while (strm->avail_out == 0 && ret != Z_STREAM_END);
434  } while (len != 0);
435 
436  /* write trailer after last entry */
437  if (last) {
438  deflateEnd(strm);
439  out[0] = (unsigned char)(strm->adler);
440  out[1] = (unsigned char)(strm->adler >> 8);
441  out[2] = (unsigned char)(strm->adler >> 16);
442  out[3] = (unsigned char)(strm->adler >> 24);
443  out[4] = (unsigned char)(strm->total_in);
444  out[5] = (unsigned char)(strm->total_in >> 8);
445  out[6] = (unsigned char)(strm->total_in >> 16);
446  out[7] = (unsigned char)(strm->total_in >> 24);
447  len = 8;
448  do {
449  ret = write(gd, out + 8 - len, len);
450  if (ret == -1) bye("writing gzip file", "");
451  len -= ret;
452  } while (len);
453  close(gd);
454  }
455 
456  /* clean up and return */
457  free(out);
458  free(in);
459  if (fd > 0) close(fd);
460 }
size_t len
Definition: 6502dis.c:15
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static static fork const void static count close
Definition: sflib.h:33
int ZEXPORT deflateEnd(z_streamp strm)
Definition: deflate.c:1119
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:804
#define O_RDONLY
Definition: sftypes.h:486
static const z80_opcode fd[]
Definition: z80_tab.h:997
#define Z_FINISH
Definition: zlib.h:172
#define Z_NO_FLUSH
Definition: zlib.h:168

References lzma_stream::avail_in, lzma_stream::avail_out, bye(), CHUNK, close, crc32(), deflate(), deflateEnd(), fd, free(), in, len, malloc(), lzma_stream::next_in, lzma_stream::next_out, NULL, O_RDONLY, out, read(), strm, lzma_stream::total_in, unsigned, write, Z_FINISH, Z_NO_FLUSH, and Z_STREAM_END.

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 466 of file gzappend.c.

467 {
468  int gd, level;
469  z_stream strm;
470 
471  /* ignore command name */
472  argc--; argv++;
473 
474  /* provide usage if no arguments */
475  if (*argv == NULL) {
476  printf(
477  "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n"
478  );
479  printf(
480  "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n");
481  return 0;
482  }
483 
484  /* set compression level */
486  if (argv[0][0] == '-') {
487  if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0)
488  bye("invalid compression level", "");
489  level = argv[0][1] - '0';
490  if (*++argv == NULL) bye("no gzip file name after options", "");
491  }
492 
493  /* prepare to append to gzip file */
494  gd = gzscan(*argv++, &strm, level);
495 
496  /* append files on command line, or from stdin if none */
497  if (*argv == NULL)
498  gztack(NULL, gd, &strm, 1);
499  else
500  do {
501  gztack(*argv, gd, &strm, argv[1] == NULL);
502  } while (*++argv != NULL);
503  return 0;
504 }
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
void gztack(char *name, int gd, z_stream *strm, int last)
Definition: gzappend.c:388
int gzscan(char *name, z_stream *strm, int level)
Definition: gzappend.c:259
static static fork const void static count static fd const char const char static newpath char char argv
Definition: sflib.h:40
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:193

References argv, bye(), gzscan(), gztack(), level, NULL, printf(), strm, and Z_DEFAULT_COMPRESSION.

◆ read4()

unsigned long read4 ( file in)

Definition at line 223 of file gzappend.c.

224 {
225  unsigned long val;
226 
227  val = read1(in);
228  val += (unsigned)read1(in) << 8;
229  val += (unsigned long)read1(in) << 16;
230  val += (unsigned long)read1(in) << 24;
231  return val;
232 }
ut16 val
Definition: armass64_const.h:6
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags long
Definition: sflib.h:79

References in, long, read1, unsigned, and val.

Referenced by gzscan().

◆ readin()

int readin ( file in)

Definition at line 180 of file gzappend.c.

181 {
182  int len;
183 
184  len = read(in->fd, in->buf, 1 << in->size);
185  if (len == -1) bye("error reading ", in->name);
186  in->left = (unsigned)len;
187  in->next = in->buf;
188  return len;
189 }

References bye(), in, len, read(), and unsigned.

Referenced by gzscan(), and readmore().

◆ readmore()

int readmore ( file in)

Definition at line 192 of file gzappend.c.

193 {
194  if (readin(in) == 0) bye("unexpected end of ", in->name);
195  return 0;
196 }

References bye(), in, and readin().

Referenced by gzscan(), and skip().

◆ rotate()

void rotate ( unsigned char *  list,
unsigned  len,
unsigned  rot 
)

Definition at line 123 of file gzappend.c.

124 {
125  unsigned char tmp;
126  unsigned cycles;
127  unsigned char *start, *last, *to, *from;
128 
129  /* normalize rot and handle degenerate cases */
130  if (len < 2) return;
131  if (rot >= len) rot %= len;
132  if (rot == 0) return;
133 
134  /* pointer to last entry in list */
135  last = list + (len - 1);
136 
137  /* do simple left shift by one */
138  if (rot == 1) {
139  tmp = *list;
140  memmove(list, list + 1, len - 1);
141  *last = tmp;
142  return;
143  }
144 
145  /* do simple right shift by one */
146  if (rot == len - 1) {
147  tmp = *last;
148  memmove(list + 1, list, len - 1);
149  *list = tmp;
150  return;
151  }
152 
153  /* otherwise do rotate as a set of cycles in place */
154  cycles = gcd(len, rot); /* number of cycles */
155  do {
156  start = from = list + cycles; /* start index is arbitrary */
157  tmp = *from; /* save entry to be overwritten */
158  for (;;) {
159  to = from; /* next step in cycle */
160  from += rot; /* go right rot positions */
161  if (from > last) from -= len; /* (pointer better not wrap) */
162  if (from == start) break; /* all but one shifted */
163  *to = *from; /* shift left */
164  }
165  *to = tmp; /* complete the circle */
166  } while (--cycles);
167 }
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
unsigned gcd(unsigned a, unsigned b)
Definition: gzappend.c:102
static void list(RzEgg *egg)
Definition: rz-gg.c:52
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr from
Definition: sfsocketcall.h:123
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125

References from, gcd(), len, list(), start, autogen_x86imm::tmp, and to.

Referenced by getimmed8(), gzscan(), and LZ4HC_rotatePattern().

◆ skip()

void skip ( file in,
unsigned  n 
)

Definition at line 202 of file gzappend.c.

203 {
204  unsigned bypass;
205 
206  if (n > in->left) {
207  n -= in->left;
208  bypass = n & ~((1U << in->size) - 1);
209  if (bypass) {
210  if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1)
211  bye("seeking ", in->name);
212  n -= bypass;
213  }
214  readmore(in);
215  if (n > in->left)
216  bye("unexpected end of ", in->name);
217  }
218  in->left -= n;
219  in->next += n;
220 }

References bye(), in, lseek, n, readmore(), and SEEK_CUR.

Referenced by bskip(), deflate_index_extract(), demangle_classname(), do_extract_currentfile(), findMinMax(), get_relocs(), gzheader(), main(), parse_gdata_stream(), print_debug_maps_ascii_art(), reconstruct_chained_fixup(), rz_analysis_reflines_get(), rz_asm_pseudo_incbin(), rz_core_visual(), rz_core_visual_xrefs(), rz_main_rz_asm(), rz_print_bitstream_handler(), rz_str_widget_list(), show_analysis_classes(), show_class(), ts_lexer__advance(), ts_lexer__do_advance(), and uv_tty_init().