Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / lzo / examples / lzopack.c
blobe4e745df6d2c3f4fce451162abc911f937313b46
1 /* lzopack.c -- LZO example program: a simple file packer
3 This file is part of the LZO real-time data compression library.
5 Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
6 Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
7 Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
8 Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
9 Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
10 Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
11 Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
12 Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
13 Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
14 Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
15 Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
16 Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
17 Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
18 Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
19 Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
20 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
21 All Rights Reserved.
23 The LZO library is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation; either version 2 of
26 the License, or (at your option) any later version.
28 The LZO library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with the LZO library; see the file COPYING.
35 If not, write to the Free Software Foundation, Inc.,
36 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38 Markus F.X.J. Oberhumer
39 <markus@oberhumer.com>
40 http://www.oberhumer.com/opensource/lzo/
44 /*************************************************************************
45 // NOTE: this is an example program, so do not use to backup your data.
47 // This program lacks things like sophisticated file handling but is
48 // pretty complete regarding compression - it should provide a good
49 // starting point for adaption for your applications.
51 // Please study LZO.FAQ and simple.c first.
52 **************************************************************************/
54 #include "lzo/lzoconf.h"
55 #include "lzo/lzo1x.h"
57 /* portability layer */
58 static const char *progname = NULL;
59 #define WANT_LZO_MALLOC 1
60 #define WANT_LZO_FREAD 1
61 #define WANT_LZO_WILDARGV 1
62 #define WANT_XMALLOC 1
63 #include "examples/portab.h"
66 static unsigned long total_in = 0;
67 static unsigned long total_out = 0;
68 static lzo_bool opt_debug = 0;
70 /* magic file header for lzopack-compressed files */
71 static const unsigned char magic[7] =
72 { 0x00, 0xe9, 0x4c, 0x5a, 0x4f, 0xff, 0x1a };
75 /*************************************************************************
76 // file IO
77 **************************************************************************/
79 lzo_uint xread(FILE *fp, lzo_voidp buf, lzo_uint len, lzo_bool allow_eof)
81 lzo_uint l;
83 l = (lzo_uint) lzo_fread(fp, buf, len);
84 if (l > len)
86 fprintf(stderr, "\nsomething's wrong with your C library !!!\n");
87 exit(1);
89 if (l != len && !allow_eof)
91 fprintf(stderr, "\nread error - premature end of file\n");
92 exit(1);
94 total_in += (unsigned long) l;
95 return l;
98 lzo_uint xwrite(FILE *fp, const lzo_voidp buf, lzo_uint len)
100 if (fp != NULL && lzo_fwrite(fp, buf, len) != len)
102 fprintf(stderr, "\nwrite error (disk full ?)\n");
103 exit(1);
105 total_out += (unsigned long) len;
106 return len;
110 int xgetc(FILE *fp)
112 unsigned char c;
113 xread(fp, (lzo_voidp) &c, 1, 0);
114 return c;
117 void xputc(FILE *fp, int c)
119 unsigned char cc = (unsigned char) (c & 0xff);
120 xwrite(fp, (const lzo_voidp) &cc, 1);
123 /* read and write portable 32-bit integers */
125 lzo_uint32 xread32(FILE *fp)
127 unsigned char b[4];
128 lzo_uint32 v;
130 xread(fp, b, 4, 0);
131 v = (lzo_uint32) b[3] << 0;
132 v |= (lzo_uint32) b[2] << 8;
133 v |= (lzo_uint32) b[1] << 16;
134 v |= (lzo_uint32) b[0] << 24;
135 return v;
138 void xwrite32(FILE *fp, lzo_xint v)
140 unsigned char b[4];
142 b[3] = (unsigned char) ((v >> 0) & 0xff);
143 b[2] = (unsigned char) ((v >> 8) & 0xff);
144 b[1] = (unsigned char) ((v >> 16) & 0xff);
145 b[0] = (unsigned char) ((v >> 24) & 0xff);
146 xwrite(fp, b, 4);
150 /*************************************************************************
151 // compress
153 // possible improvement: we could use overlapping compression to
154 // save some memory - see overlap.c. This would require some minor
155 // changes in the decompression code as well, because if a block
156 // turns out to be incompressible we would still have to store it in its
157 // "compressed" (i.e. then slightly enlarged) form because the original
158 // (uncompressed) data would have been lost during the overlapping
159 // compression.
160 **************************************************************************/
162 int do_compress(FILE *fi, FILE *fo, int compression_level, lzo_uint block_size)
164 int r = 0;
165 lzo_bytep in = NULL;
166 lzo_bytep out = NULL;
167 lzo_voidp wrkmem = NULL;
168 lzo_uint in_len;
169 lzo_uint out_len;
170 lzo_uint32 wrk_len = 0;
171 lzo_uint32 flags = 1; /* do compute a checksum */
172 int method = 1; /* compression method: LZO1X */
173 lzo_uint32 checksum;
175 total_in = total_out = 0;
178 * Step 1: write magic header, flags & block size, init checksum
180 xwrite(fo, magic, sizeof(magic));
181 xwrite32(fo, flags);
182 xputc(fo, method); /* compression method */
183 xputc(fo, compression_level); /* compression level */
184 xwrite32(fo, block_size);
185 checksum = lzo_adler32(0, NULL, 0);
188 * Step 2: allocate compression buffers and work-memory
190 in = (lzo_bytep) xmalloc(block_size);
191 out = (lzo_bytep) xmalloc(block_size + block_size / 16 + 64 + 3);
192 if (compression_level == 9)
193 wrk_len = LZO1X_999_MEM_COMPRESS;
194 else
195 wrk_len = LZO1X_1_MEM_COMPRESS;
196 wrkmem = (lzo_voidp) xmalloc(wrk_len);
197 if (in == NULL || out == NULL || wrkmem == NULL)
199 printf("%s: out of memory\n", progname);
200 r = 1;
201 goto err;
205 * Step 3: process blocks
207 for (;;)
209 /* read block */
210 in_len = xread(fi, in, block_size, 1);
211 if (in_len == 0)
212 break;
214 /* update checksum */
215 if (flags & 1)
216 checksum = lzo_adler32(checksum, in, in_len);
218 /* clear wrkmem (not needed, only for debug/benchmark purposes) */
219 if (opt_debug)
220 lzo_memset(wrkmem, 0xff, wrk_len);
222 /* compress block */
223 if (compression_level == 9)
224 r = lzo1x_999_compress(in, in_len, out, &out_len, wrkmem);
225 else
226 r = lzo1x_1_compress(in, in_len, out, &out_len, wrkmem);
227 if (r != LZO_E_OK || out_len > in_len + in_len / 16 + 64 + 3)
229 /* this should NEVER happen */
230 printf("internal error - compression failed: %d\n", r);
231 r = 2;
232 goto err;
235 /* write uncompressed block size */
236 xwrite32(fo, in_len);
238 if (out_len < in_len)
240 /* write compressed block */
241 xwrite32(fo, out_len);
242 xwrite(fo, out, out_len);
244 else
246 /* not compressible - write uncompressed block */
247 xwrite32(fo, in_len);
248 xwrite(fo, in, in_len);
252 /* write EOF marker */
253 xwrite32(fo, 0);
255 /* write checksum */
256 if (flags & 1)
257 xwrite32(fo, checksum);
259 r = 0;
260 err:
261 lzo_free(wrkmem);
262 lzo_free(out);
263 lzo_free(in);
264 return r;
268 /*************************************************************************
269 // decompress / test
271 // We are using overlapping (in-place) decompression to save some
272 // memory - see overlap.c.
273 **************************************************************************/
275 int do_decompress(FILE *fi, FILE *fo)
277 int r = 0;
278 lzo_bytep buf = NULL;
279 lzo_uint buf_len;
280 unsigned char m [ sizeof(magic) ];
281 lzo_uint32 flags;
282 int method;
283 int compression_level;
284 lzo_uint block_size;
285 lzo_uint32 checksum;
287 total_in = total_out = 0;
290 * Step 1: check magic header, read flags & block size, init checksum
292 if (xread(fi, m, sizeof(magic),1) != sizeof(magic) ||
293 memcmp(m, magic, sizeof(magic)) != 0)
295 printf("%s: header error - this file is not compressed by lzopack\n", progname);
296 r = 1;
297 goto err;
299 flags = xread32(fi);
300 method = xgetc(fi);
301 compression_level = xgetc(fi);
302 if (method != 1)
304 printf("%s: header error - invalid method %d (level %d)\n",
305 progname, method, compression_level);
306 r = 2;
307 goto err;
309 block_size = xread32(fi);
310 if (block_size < 1024 || block_size > 8*1024*1024L)
312 printf("%s: header error - invalid block size %ld\n",
313 progname, (long) block_size);
314 r = 3;
315 goto err;
317 checksum = lzo_adler32(0,NULL,0);
320 * Step 2: allocate buffer for in-place decompression
322 buf_len = block_size + block_size / 16 + 64 + 3;
323 buf = (lzo_bytep) xmalloc(buf_len);
324 if (buf == NULL)
326 printf("%s: out of memory\n", progname);
327 r = 4;
328 goto err;
332 * Step 3: process blocks
334 for (;;)
336 lzo_bytep in;
337 lzo_bytep out;
338 lzo_uint in_len;
339 lzo_uint out_len;
341 /* read uncompressed size */
342 out_len = xread32(fi);
344 /* exit if last block (EOF marker) */
345 if (out_len == 0)
346 break;
348 /* read compressed size */
349 in_len = xread32(fi);
351 /* sanity check of the size values */
352 if (in_len > block_size || out_len > block_size ||
353 in_len == 0 || in_len > out_len)
355 printf("%s: block size error - data corrupted\n", progname);
356 r = 5;
357 goto err;
360 /* place compressed block at the top of the buffer */
361 in = buf + buf_len - in_len;
362 out = buf;
364 /* read compressed block data */
365 xread(fi, in, in_len, 0);
367 if (in_len < out_len)
369 /* decompress - use safe decompressor as data might be corrupted
370 * during a file transfer */
371 lzo_uint new_len = out_len;
373 r = lzo1x_decompress_safe(in, in_len, out, &new_len, NULL);
374 if (r != LZO_E_OK || new_len != out_len)
376 printf("%s: compressed data violation\n", progname);
377 r = 6;
378 goto err;
380 /* write decompressed block */
381 xwrite(fo, out, out_len);
382 /* update checksum */
383 if (flags & 1)
384 checksum = lzo_adler32(checksum, out, out_len);
386 else
388 /* write original (incompressible) block */
389 xwrite(fo, in, in_len);
390 /* update checksum */
391 if (flags & 1)
392 checksum = lzo_adler32(checksum, in, in_len);
396 /* read and verify checksum */
397 if (flags & 1)
399 lzo_uint32 c = xread32(fi);
400 if (c != checksum)
402 printf("%s: checksum error - data corrupted\n", progname);
403 r = 7;
404 goto err;
408 r = 0;
409 err:
410 lzo_free(buf);
411 return r;
415 /*************************************************************************
417 **************************************************************************/
419 static void usage(void)
421 printf("usage: %s [-9] input-file output-file (compress)\n", progname);
422 printf("usage: %s -d input-file output-file (decompress)\n", progname);
423 printf("usage: %s -t input-file... (test)\n", progname);
424 exit(1);
428 /* open input file */
429 static FILE *xopen_fi(const char *name)
431 FILE *fp;
433 fp = fopen(name, "rb");
434 if (fp == NULL)
436 printf("%s: cannot open input file %s\n", progname, name);
437 exit(1);
439 #if defined(HAVE_STAT) && defined(S_ISREG)
441 struct stat st;
442 int is_regular = 1;
443 if (stat(name, &st) != 0 || !S_ISREG(st.st_mode))
444 is_regular = 0;
445 if (!is_regular)
447 printf("%s: %s is not a regular file\n", progname, name);
448 fclose(fp); fp = NULL;
449 exit(1);
452 #endif
453 return fp;
457 /* open output file */
458 static FILE *xopen_fo(const char *name)
460 FILE *fp;
462 #if 0
463 /* this is an example program, so make sure we don't overwrite a file */
464 fp = fopen(name, "rb");
465 if (fp != NULL)
467 printf("%s: file %s already exists -- not overwritten\n", progname, name);
468 fclose(fp); fp = NULL;
469 exit(1);
471 #endif
472 fp = fopen(name, "wb");
473 if (fp == NULL)
475 printf("%s: cannot open output file %s\n", progname, name);
476 exit(1);
478 return fp;
482 /* close file */
483 static void xclose(FILE *fp)
485 if (fp)
487 int err;
488 err = ferror(fp);
489 if (fclose(fp) != 0)
490 err = 1;
491 if (err)
493 printf("%s: error while closing file\n", progname);
494 exit(1);
500 /*************************************************************************
502 **************************************************************************/
504 int __lzo_cdecl_main main(int argc, char *argv[])
506 int i = 1;
507 int r = 0;
508 FILE *fi = NULL;
509 FILE *fo = NULL;
510 const char *in_name = NULL;
511 const char *out_name = NULL;
512 unsigned opt_decompress = 0;
513 unsigned opt_test = 0;
514 int opt_compression_level = 1;
515 lzo_uint opt_block_size;
516 const char *s;
518 lzo_wildargv(&argc, &argv);
520 progname = argv[0];
521 for (s = progname; *s; s++)
522 if ((*s == '/' || *s == '\\') && s[1])
523 progname = s + 1;
525 printf("\nLZO real-time data compression library (v%s, %s).\n",
526 lzo_version_string(), lzo_version_date());
527 printf("Copyright (C) 1996-2011 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
529 #if 0
530 printf(
531 "*** DISCLAIMER ***\n"
532 " This is an example program, do not use to backup your data !\n"
533 " Get LZOP if you're interested into a full-featured packer.\n"
534 " See http://www.oberhumer.com/opensource/lzop/\n"
535 "\n");
536 #endif
540 * Step 1: initialize the LZO library
542 if (lzo_init() != LZO_E_OK)
544 printf("internal error - lzo_init() failed !!!\n");
545 printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable '-DLZO_DEBUG' for diagnostics)\n");
546 exit(1);
551 * Step 2: setup memory
553 opt_block_size = 256 * 1024L;
555 #if defined(ACC_MM_AHSHIFT)
556 /* reduce memory requirements for ancient 16-bit DOS 640kB real-mode */
557 if (ACC_MM_AHSHIFT != 3)
558 opt_block_size = 16 * 1024L;
559 #endif
563 * Step 3: get options
566 while (i < argc && argv[i][0] == '-')
568 if (strcmp(argv[i],"-d") == 0)
569 opt_decompress = 1;
570 else if (strcmp(argv[i],"-t") == 0)
571 opt_test = 1;
572 else if (strcmp(argv[i],"-9") == 0)
573 opt_compression_level = 9;
574 else if (argv[i][1] == 'b' && argv[i][2])
576 long b = atol(&argv[i][2]);
577 if (b >= 1024L && b <= 8*1024*1024L)
578 opt_block_size = (lzo_uint) b;
579 else
581 printf("%s: invalid block_size in option '%s'.\n", progname, argv[i]);
582 usage();
585 else if (strcmp(argv[i],"--debug") == 0)
586 opt_debug += 1;
587 else
588 usage();
589 i++;
591 if (opt_test && i >= argc)
592 usage();
593 if (!opt_test && i + 2 != argc)
594 usage();
598 * Step 4: process file(s)
601 if (opt_test)
603 while (i < argc && r == 0)
605 in_name = argv[i++];
606 fi = xopen_fi(in_name);
607 r = do_decompress(fi, NULL);
608 if (r == 0)
609 printf("%s: %s tested ok (%lu -> %lu bytes)\n",
610 progname, in_name, total_in, total_out);
611 xclose(fi); fi = NULL;
614 else if (opt_decompress)
616 in_name = argv[i++];
617 out_name = argv[i++];
618 fi = xopen_fi(in_name);
619 fo = xopen_fo(out_name);
620 r = do_decompress(fi, fo);
621 if (r == 0)
622 printf("%s: decompressed %lu into %lu bytes\n",
623 progname, total_in, total_out);
625 else /* compress */
627 in_name = argv[i++];
628 out_name = argv[i++];
629 fi = xopen_fi(in_name);
630 fo = xopen_fo(out_name);
631 r = do_compress(fi, fo, opt_compression_level, opt_block_size);
632 if (r == 0)
633 printf("%s: compressed %lu into %lu bytes\n",
634 progname, total_in, total_out);
637 xclose(fi); fi = NULL;
638 xclose(fo); fo = NULL;
639 return r;
643 vi:ts=4:et