|
kusano |
7d535a |
/* lzopack.c -- LZO example program: a simple file packer
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
This file is part of the LZO real-time data compression library.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
|
|
kusano |
7d535a |
All Rights Reserved.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
The LZO library is free software; you can redistribute it and/or
|
|
kusano |
7d535a |
modify it under the terms of the GNU General Public License as
|
|
kusano |
7d535a |
published by the Free Software Foundation; either version 2 of
|
|
kusano |
7d535a |
the License, or (at your option) any later version.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
The LZO library is distributed in the hope that it will be useful,
|
|
kusano |
7d535a |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
kusano |
7d535a |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
kusano |
7d535a |
GNU General Public License for more details.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
You should have received a copy of the GNU General Public License
|
|
kusano |
7d535a |
along with the LZO library; see the file COPYING.
|
|
kusano |
7d535a |
If not, write to the Free Software Foundation, Inc.,
|
|
kusano |
7d535a |
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
Markus F.X.J. Oberhumer
|
|
kusano |
7d535a |
<markus@oberhumer.com></markus@oberhumer.com>
|
|
kusano |
7d535a |
http://www.oberhumer.com/opensource/lzo/
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
// NOTE: this is an example program, so do not use to backup your data.
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
// This program lacks things like sophisticated file handling but is
|
|
kusano |
7d535a |
// pretty complete regarding compression - it should provide a good
|
|
kusano |
7d535a |
// starting point for adaption for your applications.
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
// Please study LZO.FAQ and simple.c first.
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#include "lzo/lzoconf.h"
|
|
kusano |
7d535a |
#include "lzo/lzo1x.h"
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* portability layer */
|
|
kusano |
7d535a |
#define WANT_LZO_MALLOC 1
|
|
kusano |
7d535a |
#define WANT_LZO_FREAD 1
|
|
kusano |
7d535a |
#define WANT_LZO_WILDARGV 1
|
|
kusano |
7d535a |
#include "examples/portab.h"
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
static const char *progname = NULL;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
static unsigned long total_in = 0;
|
|
kusano |
7d535a |
static unsigned long total_out = 0;
|
|
kusano |
7d535a |
static lzo_bool opt_debug = 0;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* magic file header for lzopack-compressed files */
|
|
kusano |
7d535a |
static const unsigned char magic[7] =
|
|
kusano |
7d535a |
{ 0x00, 0xe9, 0x4c, 0x5a, 0x4f, 0xff, 0x1a };
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
// file IO
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
lzo_uint xread(FILE *fp, lzo_voidp buf, lzo_uint len, lzo_bool allow_eof)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
lzo_uint l;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
l = (lzo_uint) lzo_fread(fp, buf, len);
|
|
kusano |
7d535a |
if (l > len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
fprintf(stderr, "\nsomething's wrong with your C library !!!\n");
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
if (l != len && !allow_eof)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
fprintf(stderr, "\nread error - premature end of file\n");
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
total_in += (unsigned long) l;
|
|
kusano |
7d535a |
return l;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
lzo_uint xwrite(FILE *fp, const lzo_voidp buf, lzo_uint len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
if (fp != NULL && lzo_fwrite(fp, buf, len) != len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
fprintf(stderr, "\nwrite error (disk full ?)\n");
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
total_out += (unsigned long) len;
|
|
kusano |
7d535a |
return len;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
int xgetc(FILE *fp)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
unsigned char c;
|
|
kusano |
7d535a |
xread(fp, (lzo_voidp) &c, 1, 0);
|
|
kusano |
7d535a |
return c;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
void xputc(FILE *fp, int c)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
unsigned char cc = (unsigned char) (c & 0xff);
|
|
kusano |
7d535a |
xwrite(fp, (const lzo_voidp) &cc, 1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* read and write portable 32-bit integers */
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
lzo_uint32 xread32(FILE *fp)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
unsigned char b[4];
|
|
kusano |
7d535a |
lzo_uint32 v;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
xread(fp, b, 4, 0);
|
|
kusano |
7d535a |
v = (lzo_uint32) b[3] << 0;
|
|
kusano |
7d535a |
v |= (lzo_uint32) b[2] << 8;
|
|
kusano |
7d535a |
v |= (lzo_uint32) b[1] << 16;
|
|
kusano |
7d535a |
v |= (lzo_uint32) b[0] << 24;
|
|
kusano |
7d535a |
return v;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
void xwrite32(FILE *fp, lzo_xint v)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
unsigned char b[4];
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
b[3] = (unsigned char) ((v >> 0) & 0xff);
|
|
kusano |
7d535a |
b[2] = (unsigned char) ((v >> 8) & 0xff);
|
|
kusano |
7d535a |
b[1] = (unsigned char) ((v >> 16) & 0xff);
|
|
kusano |
7d535a |
b[0] = (unsigned char) ((v >> 24) & 0xff);
|
|
kusano |
7d535a |
xwrite(fp, b, 4);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
// compress
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
// possible improvement: we could use overlapping compression to
|
|
kusano |
7d535a |
// save some memory - see overlap.c. This would require some minor
|
|
kusano |
7d535a |
// changes in the decompression code as well, because if a block
|
|
kusano |
7d535a |
// turns out to be incompressible we would still have to store it in its
|
|
kusano |
7d535a |
// "compressed" (i.e. then slightly enlarged) form because the original
|
|
kusano |
7d535a |
// (uncompressed) data would have been lost during the overlapping
|
|
kusano |
7d535a |
// compression.
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
int do_compress(FILE *fi, FILE *fo, int level, lzo_uint block_size)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
int r = 0;
|
|
kusano |
7d535a |
lzo_bytep in = NULL;
|
|
kusano |
7d535a |
lzo_bytep out = NULL;
|
|
kusano |
7d535a |
lzo_bytep wrkmem = NULL;
|
|
kusano |
7d535a |
lzo_uint in_len;
|
|
kusano |
7d535a |
lzo_uint out_len;
|
|
kusano |
7d535a |
lzo_uint32 wrk_len = 0;
|
|
kusano |
7d535a |
lzo_uint32 flags = 1; /* do compute a checksum */
|
|
kusano |
7d535a |
int method = 1; /* compression method: LZO1X */
|
|
kusano |
7d535a |
lzo_uint32 checksum;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
total_in = total_out = 0;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 1: write magic header, flags & block size, init checksum
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
xwrite(fo, magic, sizeof(magic));
|
|
kusano |
7d535a |
xwrite32(fo, flags);
|
|
kusano |
7d535a |
xputc(fo, method); /* compression method */
|
|
kusano |
7d535a |
xputc(fo, level); /* compression level */
|
|
kusano |
7d535a |
xwrite32(fo, block_size);
|
|
kusano |
7d535a |
checksum = lzo_adler32(0, NULL, 0);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 2: allocate compression buffers and work-memory
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
in = (lzo_bytep) lzo_malloc(block_size);
|
|
kusano |
7d535a |
out = (lzo_bytep) lzo_malloc(block_size + block_size / 16 + 64 + 3);
|
|
kusano |
7d535a |
if (level == 9)
|
|
kusano |
7d535a |
wrk_len = LZO1X_999_MEM_COMPRESS;
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
wrk_len = LZO1X_1_MEM_COMPRESS;
|
|
kusano |
7d535a |
wrkmem = (lzo_bytep) lzo_malloc(wrk_len);
|
|
kusano |
7d535a |
if (in == NULL || out == NULL || wrkmem == NULL)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: out of memory\n", progname);
|
|
kusano |
7d535a |
r = 1;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 3: process blocks
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
for (;;)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* read block */
|
|
kusano |
7d535a |
in_len = xread(fi, in, block_size, 1);
|
|
kusano |
7d535a |
if (in_len <= 0)
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* update checksum */
|
|
kusano |
7d535a |
if (flags & 1)
|
|
kusano |
7d535a |
checksum = lzo_adler32(checksum, in, in_len);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* clear wrkmem (not needed, only for debug/benchmark purposes) */
|
|
kusano |
7d535a |
if (opt_debug)
|
|
kusano |
7d535a |
lzo_memset(wrkmem, 0xff, wrk_len);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* compress block */
|
|
kusano |
7d535a |
if (level == 9)
|
|
kusano |
7d535a |
r = lzo1x_999_compress(in, in_len, out, &out_len, wrkmem);
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
r = lzo1x_1_compress(in, in_len, out, &out_len, wrkmem);
|
|
kusano |
7d535a |
if (r != LZO_E_OK || out_len > in_len + in_len / 16 + 64 + 3)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* this should NEVER happen */
|
|
kusano |
7d535a |
printf("internal error - compression failed: %d\n", r);
|
|
kusano |
7d535a |
r = 2;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* write uncompressed block size */
|
|
kusano |
7d535a |
xwrite32(fo, in_len);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (out_len < in_len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* write compressed block */
|
|
kusano |
7d535a |
xwrite32(fo, out_len);
|
|
kusano |
7d535a |
xwrite(fo, out, out_len);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* not compressible - write uncompressed block */
|
|
kusano |
7d535a |
xwrite32(fo, in_len);
|
|
kusano |
7d535a |
xwrite(fo, in, in_len);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* write EOF marker */
|
|
kusano |
7d535a |
xwrite32(fo, 0);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* write checksum */
|
|
kusano |
7d535a |
if (flags & 1)
|
|
kusano |
7d535a |
xwrite32(fo, checksum);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
r = 0;
|
|
kusano |
7d535a |
err:
|
|
kusano |
7d535a |
lzo_free(wrkmem);
|
|
kusano |
7d535a |
lzo_free(out);
|
|
kusano |
7d535a |
lzo_free(in);
|
|
kusano |
7d535a |
return r;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
// decompress / test
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
// We are using overlapping (in-place) decompression to save some
|
|
kusano |
7d535a |
// memory - see overlap.c.
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
int do_decompress(FILE *fi, FILE *fo)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
int r = 0;
|
|
kusano |
7d535a |
lzo_bytep buf = NULL;
|
|
kusano |
7d535a |
lzo_uint buf_len;
|
|
kusano |
7d535a |
unsigned char m [ sizeof(magic) ];
|
|
kusano |
7d535a |
lzo_uint32 flags;
|
|
kusano |
7d535a |
int method;
|
|
kusano |
7d535a |
int level;
|
|
kusano |
7d535a |
lzo_uint block_size;
|
|
kusano |
7d535a |
lzo_uint32 checksum;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
total_in = total_out = 0;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 1: check magic header, read flags & block size, init checksum
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
if (xread(fi, m, sizeof(magic),1) != sizeof(magic) ||
|
|
kusano |
7d535a |
memcmp(m, magic, sizeof(magic)) != 0)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: header error - this file is not compressed by lzopack\n", progname);
|
|
kusano |
7d535a |
r = 1;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
flags = xread32(fi);
|
|
kusano |
7d535a |
method = xgetc(fi);
|
|
kusano |
7d535a |
level = xgetc(fi);
|
|
kusano |
7d535a |
if (method != 1)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: header error - invalid method %d (level %d)\n",
|
|
kusano |
7d535a |
progname, method, level);
|
|
kusano |
7d535a |
r = 2;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
block_size = xread32(fi);
|
|
kusano |
7d535a |
if (block_size < 1024 || block_size > 8*1024*1024L)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: header error - invalid block size %ld\n",
|
|
kusano |
7d535a |
progname, (long) block_size);
|
|
kusano |
7d535a |
r = 3;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
checksum = lzo_adler32(0,NULL,0);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 2: allocate buffer for in-place decompression
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
buf_len = block_size + block_size / 16 + 64 + 3;
|
|
kusano |
7d535a |
buf = (lzo_bytep) lzo_malloc(buf_len);
|
|
kusano |
7d535a |
if (buf == NULL)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: out of memory\n", progname);
|
|
kusano |
7d535a |
r = 4;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 3: process blocks
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
for (;;)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
lzo_bytep in;
|
|
kusano |
7d535a |
lzo_bytep out;
|
|
kusano |
7d535a |
lzo_uint in_len;
|
|
kusano |
7d535a |
lzo_uint out_len;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* read uncompressed size */
|
|
kusano |
7d535a |
out_len = xread32(fi);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* exit if last block (EOF marker) */
|
|
kusano |
7d535a |
if (out_len == 0)
|
|
kusano |
7d535a |
break;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* read compressed size */
|
|
kusano |
7d535a |
in_len = xread32(fi);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* sanity check of the size values */
|
|
kusano |
7d535a |
if (in_len > block_size || out_len > block_size ||
|
|
kusano |
7d535a |
in_len == 0 || in_len > out_len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: block size error - data corrupted\n", progname);
|
|
kusano |
7d535a |
r = 5;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* place compressed block at the top of the buffer */
|
|
kusano |
7d535a |
in = buf + buf_len - in_len;
|
|
kusano |
7d535a |
out = buf;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* read compressed block data */
|
|
kusano |
7d535a |
xread(fi, in, in_len, 0);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (in_len < out_len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* decompress - use safe decompressor as data might be corrupted
|
|
kusano |
7d535a |
* during a file transfer */
|
|
kusano |
7d535a |
lzo_uint new_len = out_len;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
r = lzo1x_decompress_safe(in, in_len, out, &new_len, NULL);
|
|
kusano |
7d535a |
if (r != LZO_E_OK || new_len != out_len)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: compressed data violation\n", progname);
|
|
kusano |
7d535a |
r = 6;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
/* write decompressed block */
|
|
kusano |
7d535a |
xwrite(fo, out, out_len);
|
|
kusano |
7d535a |
/* update checksum */
|
|
kusano |
7d535a |
if (flags & 1)
|
|
kusano |
7d535a |
checksum = lzo_adler32(checksum, out, out_len);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
/* write original (incompressible) block */
|
|
kusano |
7d535a |
xwrite(fo, in, in_len);
|
|
kusano |
7d535a |
/* update checksum */
|
|
kusano |
7d535a |
if (flags & 1)
|
|
kusano |
7d535a |
checksum = lzo_adler32(checksum, in, in_len);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* read and verify checksum */
|
|
kusano |
7d535a |
if (flags & 1)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
lzo_uint32 c = xread32(fi);
|
|
kusano |
7d535a |
if (c != checksum)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: checksum error - data corrupted\n", progname);
|
|
kusano |
7d535a |
r = 7;
|
|
kusano |
7d535a |
goto err;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
r = 0;
|
|
kusano |
7d535a |
err:
|
|
kusano |
7d535a |
lzo_free(buf);
|
|
kusano |
7d535a |
return r;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
static void usage(void)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("usage: %s [-9] input-file output-file (compress)\n", progname);
|
|
kusano |
7d535a |
printf("usage: %s -d input-file output-file (decompress)\n", progname);
|
|
kusano |
7d535a |
printf("usage: %s -t input-file... (test)\n", progname);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* open input file */
|
|
kusano |
7d535a |
static FILE *xopen_fi(const char *name)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
FILE *fp;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
fp = fopen(name, "rb");
|
|
kusano |
7d535a |
if (fp == NULL)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: cannot open input file %s\n", progname, name);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
#if defined(HAVE_STAT) && defined(S_ISREG)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
struct stat st;
|
|
kusano |
7d535a |
int is_regular = 1;
|
|
kusano |
7d535a |
if (stat(name, &st) != 0 || !S_ISREG(st.st_mode))
|
|
kusano |
7d535a |
is_regular = 0;
|
|
kusano |
7d535a |
if (!is_regular)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: %s is not a regular file\n", progname, name);
|
|
kusano |
7d535a |
fclose(fp); fp = NULL;
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
return fp;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* open output file */
|
|
kusano |
7d535a |
static FILE *xopen_fo(const char *name)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
FILE *fp;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#if 0
|
|
kusano |
7d535a |
/* this is an example program, so make sure we don't overwrite a file */
|
|
kusano |
7d535a |
fp = fopen(name, "rb");
|
|
kusano |
7d535a |
if (fp != NULL)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: file %s already exists -- not overwritten\n", progname, name);
|
|
kusano |
7d535a |
fclose(fp); fp = NULL;
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
fp = fopen(name, "wb");
|
|
kusano |
7d535a |
if (fp == NULL)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: cannot open output file %s\n", progname, name);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
return fp;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/* close file */
|
|
kusano |
7d535a |
static void xclose(FILE *fp)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
if (fp)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
int err;
|
|
kusano |
7d535a |
err = ferror(fp);
|
|
kusano |
7d535a |
if (fclose(fp) != 0)
|
|
kusano |
7d535a |
err = 1;
|
|
kusano |
7d535a |
if (err)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: error while closing file\n", progname);
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*************************************************************************
|
|
kusano |
7d535a |
//
|
|
kusano |
7d535a |
**************************************************************************/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
int __lzo_cdecl_main main(int argc, char *argv[])
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
int i = 1;
|
|
kusano |
7d535a |
int r = 0;
|
|
kusano |
7d535a |
FILE *fi = NULL;
|
|
kusano |
7d535a |
FILE *fo = NULL;
|
|
kusano |
7d535a |
const char *in_name = NULL;
|
|
kusano |
7d535a |
const char *out_name = NULL;
|
|
kusano |
7d535a |
lzo_bool opt_decompress = 0;
|
|
kusano |
7d535a |
lzo_bool opt_test = 0;
|
|
kusano |
7d535a |
int opt_level = 1;
|
|
kusano |
7d535a |
lzo_uint opt_block_size;
|
|
kusano |
7d535a |
const char *s;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
lzo_wildargv(&argc, &argv);
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
progname = argv[0];
|
|
kusano |
7d535a |
for (s = progname; *s; s++)
|
|
kusano |
7d535a |
if ((*s == '/' || *s == '\\') && s[1])
|
|
kusano |
7d535a |
progname = s + 1;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
printf("\nLZO real-time data compression library (v%s, %s).\n",
|
|
kusano |
7d535a |
lzo_version_string(), lzo_version_date());
|
|
kusano |
7d535a |
printf("Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer\nAll Rights Reserved.\n\n");
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#if 0
|
|
kusano |
7d535a |
printf(
|
|
kusano |
7d535a |
"*** DISCLAIMER ***\n"
|
|
kusano |
7d535a |
" This is an example program, do not use to backup your data !\n"
|
|
kusano |
7d535a |
" Get LZOP if you're interested into a full-featured packer.\n"
|
|
kusano |
7d535a |
" See http://www.oberhumer.com/opensource/lzop/\n"
|
|
kusano |
7d535a |
"\n");
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 1: initialize the LZO library
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
if (lzo_init() != LZO_E_OK)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("internal error - lzo_init() failed !!!\n");
|
|
kusano |
7d535a |
printf("(this usually indicates a compiler bug - try recompiling\nwithout optimizations, and enable `-DLZO_DEBUG' for diagnostics)\n");
|
|
kusano |
7d535a |
exit(1);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 2: setup memory
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
opt_block_size = 256 * 1024L;
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
#if defined(ACC_MM_AHSHIFT)
|
|
kusano |
7d535a |
/* reduce memory requirements for ancient 16-bit DOS 640kB real-mode */
|
|
kusano |
7d535a |
if (ACC_MM_AHSHIFT != 3)
|
|
kusano |
7d535a |
opt_block_size = 16 * 1024L;
|
|
kusano |
7d535a |
#endif
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 3: get options
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
while (i < argc && argv[i][0] == '-')
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
if (strcmp(argv[i],"-d") == 0)
|
|
kusano |
7d535a |
opt_decompress = 1;
|
|
kusano |
7d535a |
else if (strcmp(argv[i],"-t") == 0)
|
|
kusano |
7d535a |
opt_test = 1;
|
|
kusano |
7d535a |
else if (strcmp(argv[i],"-9") == 0)
|
|
kusano |
7d535a |
opt_level = 9;
|
|
kusano |
7d535a |
else if (argv[i][1] == 'b' && argv[i][2])
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
long b = atol(&argv[i][2]);
|
|
kusano |
7d535a |
if (b >= 1024L && b <= 8*1024*1024L)
|
|
kusano |
7d535a |
opt_block_size = (lzo_uint) b;
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
printf("%s: invalid block_size in option `%s'.\n", progname, argv[i]);
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else if (strcmp(argv[i],"--debug") == 0)
|
|
kusano |
7d535a |
opt_debug += 1;
|
|
kusano |
7d535a |
else
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
i++;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
if (opt_test && i >= argc)
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
if (!opt_test && i + 2 != argc)
|
|
kusano |
7d535a |
usage();
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
* Step 4: process file(s)
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
if (opt_test)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
while (i < argc && r == 0)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
in_name = argv[i++];
|
|
kusano |
7d535a |
fi = xopen_fi(in_name);
|
|
kusano |
7d535a |
r = do_decompress(fi, NULL);
|
|
kusano |
7d535a |
if (r == 0)
|
|
kusano |
7d535a |
printf("%s: %s tested ok (%lu -> %lu bytes)\n",
|
|
kusano |
7d535a |
progname, in_name, total_in, total_out);
|
|
kusano |
7d535a |
xclose(fi); fi = NULL;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else if (opt_decompress)
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
in_name = argv[i++];
|
|
kusano |
7d535a |
out_name = argv[i++];
|
|
kusano |
7d535a |
fi = xopen_fi(in_name);
|
|
kusano |
7d535a |
fo = xopen_fo(out_name);
|
|
kusano |
7d535a |
r = do_decompress(fi, fo);
|
|
kusano |
7d535a |
if (r == 0)
|
|
kusano |
7d535a |
printf("%s: decompressed %lu into %lu bytes\n",
|
|
kusano |
7d535a |
progname, total_in, total_out);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
else /* compress */
|
|
kusano |
7d535a |
{
|
|
kusano |
7d535a |
in_name = argv[i++];
|
|
kusano |
7d535a |
out_name = argv[i++];
|
|
kusano |
7d535a |
fi = xopen_fi(in_name);
|
|
kusano |
7d535a |
fo = xopen_fo(out_name);
|
|
kusano |
7d535a |
r = do_compress(fi, fo, opt_level, opt_block_size);
|
|
kusano |
7d535a |
if (r == 0)
|
|
kusano |
7d535a |
printf("%s: compressed %lu into %lu bytes\n",
|
|
kusano |
7d535a |
progname, total_in, total_out);
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
xclose(fi); fi = NULL;
|
|
kusano |
7d535a |
xclose(fo); fo = NULL;
|
|
kusano |
7d535a |
return r;
|
|
kusano |
7d535a |
}
|
|
kusano |
7d535a |
|
|
kusano |
7d535a |
/*
|
|
kusano |
7d535a |
vi:ts=4:et
|
|
kusano |
7d535a |
*/
|
|
kusano |
7d535a |
|