⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpack.c

📁 lzo-1.08-src.zip 高效的压缩解压代码
💻 C
字号:
/* lpack.c -- LZO example program: a simple file packer   This file is part of the LZO real-time data compression library.   Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer   All Rights Reserved.   The LZO library is free software; you can redistribute it and/or   modify it under the terms of the GNU General Public License as   published by the Free Software Foundation; either version 2 of   the License, or (at your option) any later version.   The LZO library is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with the LZO library; see the file COPYING.   If not, write to the Free Software Foundation, Inc.,   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   Markus F.X.J. Oberhumer   <markus@oberhumer.com> *//*************************************************************************// NOTE: this is an example program, so do not use to backup your data//// This program lacks things like sophisticated file handling but is// pretty complete regarding compression - it should provide a good// starting point for adaption for you applications.//// Please study LZO.FAQ and simple.c first.**************************************************************************/#include <lzo1x.h>#include "lutil.h"static const char *progname = NULL;static unsigned long total_in = 0;static unsigned long total_out = 0;static lzo_bool debug = 0;/* magic file header for lpack-compressed files */static const unsigned char magic[7] =	{ 0x00, 0xe9, 0x4c, 0x5a, 0x4f, 0xff, 0x1a };/*************************************************************************// file IO**************************************************************************/lzo_uint xread(FILE *f, lzo_voidp buf, lzo_uint len, lzo_bool allow_eof){	lzo_uint l;	l = lzo_fread(f,buf,len);	if (l > len)	{		fprintf(stderr,"\nsomething's wrong with your C library !!!\n");		exit(1);	}	if (l != len && !allow_eof)	{		fprintf(stderr,"\nread error - premature end of file\n");		exit(1);	}	total_in += l;	return l;}lzo_uint xwrite(FILE *f, const lzo_voidp buf, lzo_uint len){	if (f != NULL && lzo_fwrite(f,buf,len) != len)	{		fprintf(stderr,"\nwrite error  (disk full ?)\n");		exit(1);	}	total_out += len;	return len;}int xgetc(FILE *f){	unsigned char c;	xread(f,(lzo_bytep) &c,1,0);	return c;}void xputc(FILE *f, int c){	unsigned char cc = (unsigned char) c;	xwrite(f,(lzo_bytep) &cc,1);}/* read and write portable 32-bit integers */lzo_uint32 xread32(FILE *f){	unsigned char b[4];	lzo_uint32 v;	xread(f,b,4,0);	v  = (lzo_uint32) b[3] <<  0;	v |= (lzo_uint32) b[2] <<  8;	v |= (lzo_uint32) b[1] << 16;	v |= (lzo_uint32) b[0] << 24;	return v;}void xwrite32(FILE *f, lzo_uint32 v){	unsigned char b[4];	b[3] = (unsigned char) (v >>  0);	b[2] = (unsigned char) (v >>  8);	b[1] = (unsigned char) (v >> 16);	b[0] = (unsigned char) (v >> 24);	xwrite(f,b,4);}/*************************************************************************// compress//// possible improvement: we could use overlapping compression to//   save some memory - see overlap.c. This would require some minor//   changes in the decompression code as well, because if a block//   turns out to be incompressible we would still have to store it in its//   compressed (slightly enlarged) form because the original (uncompressed)//   data would have been lost during the overlapping compression.**************************************************************************/int do_compress(FILE *fi, FILE *fo, int level, lzo_uint block_size){	int r = 0;	lzo_byte *in = NULL;	lzo_byte *out = NULL;	lzo_byte *wrkmem = NULL;	lzo_uint in_len;	lzo_uint out_len;	lzo_uint32 wrk_len = 0;	lzo_uint32 flags = 1;	int method = 0x1;	lzo_uint32 checksum;	total_in = total_out = 0;/* * Step 1: write magic header, flags & block size, init checksum */ 	xwrite(fo,magic,sizeof(magic));	xwrite32(fo,flags);	xputc(fo,method);			/* compression method */	xputc(fo,level);			/* compression level */	xwrite32(fo,block_size);	checksum = lzo_adler32(0,NULL,0);/* * Step 2: allocate compression buffers and work-memory */	in = (lzo_bytep) lzo_malloc(block_size);	out = (lzo_bytep) lzo_malloc(block_size + block_size / 64 + 16 + 3);#if !defined(LZO_999_UNSUPPORTED)	if (level == 9)		wrk_len = LZO1X_999_MEM_COMPRESS;	else#endif		wrk_len = LZO1X_1_MEM_COMPRESS;	wrkmem = (lzo_bytep) lzo_malloc(wrk_len);	if (in == NULL || out == NULL || wrkmem == NULL)	{		printf("%s: out of memory\n", progname);		r = 1;		goto err;	}/* * Step 3: process blocks */ 	for (;;)	{		/* read block */		in_len = xread(fi,in,block_size,1);		if (in_len <= 0)			break;		/* update checksum */		checksum = lzo_adler32(checksum,in,in_len);		/* clear wrkmem (not needed, only for debug purposes) */		if (debug)			lzo_memset(wrkmem,0xff,wrk_len);		/* compress block */#if !defined(LZO_999_UNSUPPORTED)		if (level == 9)			r = lzo1x_999_compress(in,in_len,out,&out_len,wrkmem);		else#endif			r = lzo1x_1_compress(in,in_len,out,&out_len,wrkmem);		if (r != LZO_E_OK || out_len > in_len + in_len / 64 + 16 + 3)		{			/* this should NEVER happen */			printf("internal error - compression failed: %d\n", r);			r = 2;			goto err;		}		/* write uncompressed block size */		xwrite32(fo,in_len);		if (out_len < in_len)		{			/* write compressed block */			xwrite32(fo,out_len);			xwrite(fo,out,out_len);		}		else		{			/* not compressible - write uncompressed block */			xwrite32(fo,in_len);			xwrite(fo,in,in_len);		}	}	/* write EOF marker */	xwrite32(fo,0);	/* write checksum */	xwrite32(fo,checksum);	r = 0;err:	lzo_free(wrkmem);	lzo_free(out);	lzo_free(in);	return r;}/*************************************************************************// decompress / test//// We are using overlapping (in-place) decompression to save some// memory - see overlap.c.**************************************************************************/int do_decompress(FILE *fi, FILE *fo){	int r = 0;	lzo_byte *buf = NULL;	lzo_uint buf_len;	unsigned char m [ sizeof(magic) ];	lzo_uint32 flags;	int method;	int level;	lzo_uint block_size;	lzo_uint32 checksum;	total_in = total_out = 0;/* * Step 1: check magic header, read flags & block size, init checksum */ 	if (xread(fi,m,sizeof(magic),1) != sizeof(magic) ||	    memcmp(m,magic,sizeof(magic)) != 0)    {		printf("%s: header error - this file is not compressed by lpack\n", progname);		r = 1;		goto err;	}	flags = xread32(fi);	method = xgetc(fi);	level = xgetc(fi);	if (method != 1)	{		printf("%s: header error - invalid method %d (level %d)\n",		        progname, method, level);		r = 2;		goto err;	}	block_size = xread32(fi);	if (block_size < 1024 || block_size > 1024*1024L)	{		printf("%s: header error - invalid block size %ld\n",		        progname, (long) block_size);		r = 3;		goto err;	}	checksum = lzo_adler32(0,NULL,0);/* * Step 2: allocate buffer for in-place decompression */	buf_len = block_size + block_size / 64 + 16 + 3;	buf = (lzo_bytep) lzo_malloc(buf_len);	if (buf == NULL)	{		printf("%s: out of memory\n", progname);		r = 4;		goto err;	}/* * Step 3: process blocks */ 	for (;;)	{		lzo_byte *in;		lzo_byte *out;		lzo_uint in_len;		lzo_uint out_len;		/* read uncompressed size */		out_len = xread32(fi);		/* exit if last block (EOF marker) */		if (out_len == 0)			break;		/* read compressed size */		in_len = xread32(fi);		/* sanity check of the size values */		if (in_len > block_size || out_len > block_size ||		    in_len == 0 || in_len > out_len)		{			printf("%s: block size error - data corrupted\n", progname);			r = 5;			goto err;		}		/* place compressed block at the top of the buffer */ 		in = buf + buf_len - in_len; 		out = buf;		/* read compressed block data */		xread(fi,in,in_len,0);		if (in_len < out_len)		{			/* decompress - use safe decompressor as data might be corrupted			 * during a file transfer */			lzo_uint new_len = out_len;			r = lzo1x_decompress_safe(in,in_len,out,&new_len,NULL);			if (r != LZO_E_OK || new_len != out_len)			{				printf("%s: compressed data violation\n", progname);				r = 6;				goto err;			}			/* write decompressed block */			xwrite(fo,out,out_len);			/* update checksum */			if (flags & 1)				checksum = lzo_adler32(checksum,out,out_len);		}		else		{			/* write original (incompressible) block */			xwrite(fo,in,in_len);			/* update checksum */			if (flags & 1)				checksum = lzo_adler32(checksum,in,in_len);		}	}	/* read and verify checksum */	if (flags & 1)	{		lzo_uint32 c = xread32(fi);		if (c != checksum)		{			printf("%s: checksum error - data corrupted\n", progname);			r = 7;			goto err;		}	}	r = 0;err:	lzo_free(buf);	return r;}/*************************************************************************//**************************************************************************/static void usage(void){	printf("usage: %s [-9] input-file output-file  (compress)\n", progname);	printf("usage: %s -d   input-file output-file  (decompress)\n", progname);	printf("usage: %s -t   input-file...           (test)\n", progname);	exit(1);}/* open input file */static FILE *xopen_fi(const char *name){	FILE *f;	f = fopen(name,"rb");	if (f == NULL)	{		printf("%s: cannot open input file %s\n", progname, name);		exit(1);	}#if defined(HAVE_STAT) && defined(S_ISREG)	{		struct stat st;#if defined(HAVE_LSTAT)		if (lstat(name,&st) != 0 || !S_ISREG(st.st_mode))#else		if (stat(name,&st) != 0 || !S_ISREG(st.st_mode))#endif		{			printf("%s: %s is not a regular file\n", progname, name);			fclose(f);			exit(1);		}	}#endif	return f;}/* open output file */static FILE *xopen_fo(const char *name){	FILE *f;#if 1	/* this is an example program, so make sure we don't overwrite a file */	f = fopen(name,"rb");	if (f != NULL)	{		printf("%s: file %s already exists -- not overwritten\n", progname, name);		fclose(f);		exit(1);	}#endif	f = fopen(name,"wb");	if (f == NULL)	{		printf("%s: cannot open output file %s\n", progname, name);		exit(1);	}	return f;}/*************************************************************************//**************************************************************************/int main(int argc, char *argv[]){	int i = 1;	int r = 0;	FILE *fi = NULL;	FILE *fo = NULL;	const char *in_name = NULL;	const char *out_name = NULL;	lzo_bool opt_decompress = 0;	lzo_bool opt_test = 0;	int opt_level = 1;	lzo_uint opt_block_size = (256*1024L);#if defined(__EMX__)	_response(&argc,&argv);	_wildcard(&argc,&argv);#endif	printf("\nLZO real-time data compression library (v%s, %s).\n",	        lzo_version_string(), lzo_version_date());	printf("Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer\n\n");	printf("*** DISCLAIMER ***\n""   This is an example program, do not use to backup your data !\n""   Get LZOP if you're interested into a full-featured packer.\n""   See http://www.oberhumer.com/opensource/lzop/\n""\n");	progname = argv[0];	while (i < argc && argv[i][0] == '-')	{		if (strcmp(argv[i],"-d") == 0)			opt_decompress = 1;		else if (strcmp(argv[i],"-t") == 0)			opt_test = 1;#if !defined(LZO_999_UNSUPPORTED)		else if (strcmp(argv[i],"-9") == 0)			opt_level = 9;#endif		else if (argv[i][1] == 'b' && argv[i][2])		{#if (LZO_UINT_MAX > UINT_MAX) && defined(HAVE_ATOL)			lzo_int b = atol(&argv[i][2]);#else			lzo_int b = atoi(&argv[i][2]);#endif			if (b >= 1024L && b <= 1024*1024L)				opt_block_size = b;		}		else if (strcmp(argv[i],"--debug") == 0)			debug = 1;		else			usage();		i++;	}	if (opt_test && i >= argc)		usage();	if (!opt_test && i + 2 != argc)		usage();/* * Step 1: initialize the LZO library */	if (lzo_init() != LZO_E_OK)	{		printf("lzo_init() failed !!!\n");		exit(1);	}/* * Step 2: process file */ 	if (opt_test)	{		while (i < argc && r == 0)		{ 			in_name = argv[i++];			fi = xopen_fi(in_name);			r = do_decompress(fi,NULL);			if (r == 0)				printf("%s: %s tested ok (%ld -> %ld bytes)\n",			        	progname, in_name, total_in, total_out);			fclose(fi);			fi = NULL;		}	} 	else if (opt_decompress)	{ 		in_name = argv[i++]; 		out_name = argv[i++];		fi = xopen_fi(in_name);		fo = xopen_fo(out_name);		r = do_decompress(fi,fo);		if (r == 0)			printf("%s: decompressed %ld into %ld bytes\n",			        progname, total_in, total_out);	}	else	{ 		in_name = argv[i++]; 		out_name = argv[i++];		fi = xopen_fi(in_name);		fo = xopen_fo(out_name);		r = do_compress(fi,fo,opt_level,opt_block_size);		if (r == 0)			printf("%s: compressed %ld into %ld bytes\n",			        progname, total_in, total_out);	}	if (fi) fclose(fi);	if (fo) fclose(fo);	return r;}/*vi:ts=4*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -