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

📄 zzip.c

📁 zzip-zzlib-src.zip. A new archiver that uses a BWT algorithm to achieve superior compression. The
💻 C
📖 第 1 页 / 共 2 页
字号:
/*---------------------------------------------*/
/* Zzip/Zzlib compressor                zzip.c */
/*---------------------------------------------*/

/*
  This file is a part of zzip and/or zzlib, a program and
  library for lossless, block-sorting data compression.
  Copyright (C) 1999-2001 Damien Debin. All Rights Reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the 
  Free Software Foundation, Inc., 
  59 Temple Place, Suite 330, 
  Boston, MA 02111-1307 USA

  Damien Debin
  <damien@debin.net>

  This program is based on (at least) the work of: Mike Burrows, 
  David Wheeler, Peter Fenwick, Alistair Moffat, Ian H. Witten, 
  Robert Sedgewick, Jon Bentley, Brenton Chapin, Stephen R. Tate, 
  Szymon Grabowski, Bernhard Balkenhol, Stefan Kurtz
*/

#include <sys/stat.h>
#include <sys/timeb.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>

#ifdef WIN32
# include <io.h>
#else  /* WIN32 */
# include <sys/types.h>
# include <unistd.h>
# include <dirent.h>
#endif /* WIN32 */

#include "zzip.h"

/*---------------------------------------------*/

#ifdef WIN32
# define  SEP_PATH '\\'
# define  STAR_STR "\\*.*"
#else  /* WIN32 */
# define  SEP_PATH '/'
# define  STAR_STR "/*"
#endif /* WIN32 */

bool verbose = true;

static char    **file_list = NULL, *input_filename = NULL, *output_filename = NULL;
static bool    with_path = false;
static uint32  nb_input_file = 0;
static actions action = NONE;

#ifdef SFX
 static char    *exe_filename = NULL;
#else  /* SFX */
 static uint32  block_size = DEFAULT_BLOCK_SIZE;
 static bool    recurse = false;
 static uint    compression_mode = 0;
 static bool    multimedia_test = false;
#endif /* SFX */

#define IO_ERROR() { last_error = errno; return; }

/*---------------------------------------------*/

static
void PrintVersion()
{
#ifdef SFX
	printf(
		"*** ZZIP " VERSION_STRING ", SelF-eXtracting archive\n"
		"*** Copyright (c)2001 Damien Debin, all rights reserved.\n"
		);
#else  /* SFX */
	printf(
		"*** ZZIP " VERSION_STRING ", yet another block-sorting compressor.\n"
		"*** Copyright (c)2001 Damien Debin, all rights reserved.\n"
		);
#endif /* SFX */
}

/*---------------------------------------------*/

INLINE static
void MyFree(void *p)
{
	free(p);
}

INLINE static
void *MyMalloc(uint32 size)
{
	void* m = malloc(size);
	if (m == NULL) last_error = NOT_ENOUGH_MEMORY;
	return m;
}

/*---------------------------------------------*/

#ifdef GET_STAT

static
uint GetCPUIDflags()
{
	uint return_value = 0;

	asm (
	"pushfl;"						/* get extended flags				*/
	"popl	%%eax;"				/* in eax							*/
	"movl	%%eax,%%ecx;"		/* save origional extended flags	*/
	"xorl	$0x00200000,%%eax;"	/* flip id bit 21					*/
	"pushl	%%eax;"				/* save modified flags				*/
	"popfl;"						/* put modified flags in eflag reg	*/
	"pushfl;"						/* get flags again					*/
	"popl	%%eax;"				/* modified flags back to eax		*/
	"pushl	%%ecx;"
	"popfl;"
	"xorl	%%eax,%%ecx;"		/* if 0, bit 21 was set				*/
	"xorl	%%eax,%%eax;"
	"andl	$0x00200000,%%ecx;"
	"jz		0;"
	"movl	$0x00000001,%%eax;"	/* CPUID function 1					*/
	"cpuid;"						/* get signature/std feature flgs	*/
	
	"movl	$0x00000001,%%eax;"

	/* Check for time stamp counter support */

	"movl	$0x00000010,%%ecx;"	/* bit 4 indicates TSC support		*/
	"andl	%%edx,%%ecx;"		/* supports TSC ? CPUID_STD_TSC:0	*/
	"negl	%%ecx;"				/* supports TSC ? CY : NC			*/
	"sbb		%%ecx,%%ecx;"		/* supports TSC ? 0xffffffff:0		*/
	"andl	$0x00000010,%%ecx;"	/* supports TSC ? FEATURE_TSC:0		*/
	"orl		%%ecx,%%eax;"		/* merge into feature flags			*/

	/* Check for MMX support */

	"movl	$0x00800000,%%ecx;"	/* bit 23 indicates MMX support		*/
	"andl	%%edx,%%ecx;"		/* supports MMX ? CPUID_STD_MMX:0	*/
	"negl	%%ecx;"				/* supports MMX ? CY : NC			*/
	"sbb		%%ecx,%%ecx;"		/* supports MMX ? 0xffffffff:0		*/
	"andl	$0x00000020,%%ecx;"	/* supports MMX ? FEATURE_MMX:0		*/
	"orl		%%ecx,%%eax;"		/* merge into feature flags			*/

	/* Check for CMOV support */

	"movl	$0x00008000,%%ecx;"	/* bit 15 indicates CMOV support	*/
	"andl	%%edx,%%ecx;"		/* supports CMOV?CPUID_STD_CMOV:0	*/
	"negl	%%ecx;"				/* supports CMOV ? CY : NC			*/
	"sbb		%%ecx,%%ecx;"		/* supports CMOV ? 0xffffffff:0		*/
	"andl	$0x00000040,%%ecx;"	/* supports CMOV ? FEATURE_CMOV:0	*/
	"orl		%%ecx,%%eax;"		/* merge into feature flags			*/

"0:	" : "=a" (return_value) : : "ebx", "ecx", "edx");

	return return_value;
}

static
void GetCpuSpeed()
{
	struct _timeb timeStart, timeStop;
	uint64 StartTicks, EndTicks, TotalTicks;

	do _ftime(&timeStart);
	while (timeStart.millitm > 700);

	GET_TSC(StartTicks);

	do _ftime(&timeStop);
	while ((timeStop.millitm - timeStart.millitm) < 200);

	GET_TSC(EndTicks);
	
	TotalTicks = EndTicks - StartTicks;
	
	time_stat.cpuspeed = /*300;*/ TotalTicks / 200000; /* CPU speed (Mhz) */
	time_stat.cpuspeed *= 1000000;            /* cycles for 1 second */
}

#endif /* GET_STAT */

/*---------------------------------------------*/

static
void Help()
{
	printf("\n");

	PrintVersion();

#ifndef SFX
	printf(
		"\n usage: zzip [<command>] [<sw1><sw2>...] [<archive>] file1 file2 ...\n\n"
		" <commands>\n"
		"   a  Add files to archive\n"
		"   e  Extract files from archive\n"
		"   x  eXtract files with full path\n"
		"   d  Delete files from archive\n"
		"   t  Test files in archive\n"
		"   l  List contents of archive\n\n"
		" <switches>\n"
		"  -...  Block size (e.g. -3m,-3072k)\n"
		"  -a    Adaptive block size reduction\n"
		"  -mx   MaXimum compression\n"
		"  -mm   MultiMedia compression\n"
		"  -q    Quiet output to screen\n"
		"  -r    Recurse subdirectories\n"
		"  -s    Statistics\n\n"
		" http://debin.org/zzip/\n"
		" damien@debin.net\n"
		);
#else  /* !SFX */
	printf(
		"\n usage: %s [<sw1><sw2>...] [files_to_extract]\n\n"
		" <switches>\n"
		"  -x  eXtract files without path\n"
		"  -t  Test files in archive\n"
		"  -l  List contents of archive\n"
		"  -q  Quiet output to screen\n"
		, exe_filename);
#endif /* !SFX */
	exit(1);
}

/*---------------------------------------------*/

static
void Options(char *s)
{
	while (*(++s) != '\0')
		switch (*s)
		{
#ifndef SFX
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			{
				char *ss = s;
				while ((*s >= '0') && (*s <= '9')) s++;
				if (*s == 'm')
				{ *s = 0; block_size = atoi(ss) * 1024 * 1024; }
				else if (*s == 'k')
				{ *s = 0; block_size = atoi(ss) * 1024; }
				else Help();
			} 
			break;
		case 'b': /* for compatibility with older versions */
			s++;
			{
				char *ss = s, c;
				while ((*s >= '0') && (*s <= '9')) s++;
				c = *s;
				*s = 0; 
				block_size = atoi(ss) * 256 * 1024;
				*s = c;
				s--;
			} 
			break;
		case 'a': 
			compression_mode |= 2;
			break;
		case 'm': 
			s++; 
			switch (*s)
			{
			case 'm': multimedia_test = true; break;
			case 'x': compression_mode |= 1; break;
			default : Help();
			} 
			break;
		case 'r': 
			recurse = true;
			break;
#ifdef GET_STAT
		case 's': 
			time_stat.t_stamp = ((GetCPUIDflags() & FEATURE_TSC) == FEATURE_TSC);
			break;
#endif /* GET_STAT */
#else  /* !SFX */
		case 't': 
			action = TEST;
			break;
		case 'l': 
			action = LIST;
			break;
		case 'x': 
			with_path = false;
			break;
#endif /* !SFX */
		case 'q': 
			verbose = false; 
			break;
		case '-': 
			Options(s);
			break;
		default :
			Help();
			break;
		}
}

/*---------------------------------------------*/

static
void CmdLineParameters(int  argc, 
					   char **argv)
{
	file_list = (char**)MyMalloc(sizeof(char*) * MAX_FILES);

	verbose = true;
	nb_input_file = 0;

#ifdef SFX

	{
		sint l;
		action = EXTRACT;
		with_path = true;

		exe_filename = argv[0];
		l = strlen(exe_filename) - 4;
		if (l < 0 || strcmp(exe_filename + l, ".exe") != 0)
		{
			exe_filename = (char*)MyMalloc(sizeof(char) * FILENAME_LENGTH_MAX);
			strcpy(exe_filename, argv[0]);
			strcat(exe_filename, ".exe");
		}

		file_list[nb_input_file++] = exe_filename;
	}

#else  /* SFX */

	with_path = false;
	compression_mode = 0;
	recurse = false;
	block_size = DEFAULT_BLOCK_SIZE;
	action = NONE;

	if (argc > 1)
	{
		if (strlen(argv[1]) == 1)
		{
			switch (*argv[1])
			{
			case 'A':
			case 'a': action = CREATE; argc--; argv++;  break;
			case 'D':
			case 'd': action = DELETE; argc--; argv++;  break;
			case 'X':
			case 'x': with_path = true;
			case 'E':
			case 'e': action = EXTRACT; argc--; argv++; break;
			case 'L':
			case 'l': action = LIST; argc--; argv++;    break;
			case 'T':
			case 't': action = TEST; argc--; argv++;    break;
			default :;
			}
		}
	}
	else Help();

#endif /* SFX */

	while ((argc > 1) && (*argv[1] == '-'))
	{
		Options(argv[1]);
		argc--;
		argv++;
	}

	while (argc > 1)
	{
		file_list[nb_input_file++] = argv[1];
		argc--;
		argv++;
	}

#ifndef SFX
	if (nb_input_file == 0) Help();
#endif /* !SFX */
}

/*---------------------------------------------*/

#ifndef SFX
/* use 'file.zz' if 'file.zz' exists and if 'file' doesn't exist */
static
void CheckFilename(char *result, 
				   char *filename)
{
    struct stat buf_stat;

	strcpy(result, filename);
	strcat(result, ".zz");
	if (stat(filename, &buf_stat) != -1 || stat(result, &buf_stat) == -1)
		strcpy(result, filename);
}
#endif /* !SFX */

/*---------------------------------------------*/

static
void DoFiles()
{
#ifndef SFX
	bool		single_archive;
    struct stat	file_stat;
	uint32		nb_archive;
#endif  /* !SFX */
	uint32		i, j;
	sint		l;
	info_s		*info;

	output_filename		= (char*)MyMalloc(sizeof(char) * FILENAME_LENGTH_MAX);
	*output_filename	= '\0';
	input_filename		= (char*)MyMalloc(sizeof(char) * FILENAME_LENGTH_MAX);
	info				= (info_s*)MyMalloc(sizeof(info_s));

#ifndef SFX
	if (action == NONE)
	{
		l = strlen(file_list[0]) - 3;
		if (l >= 0 && strcmp(file_list[0] + l, ".zz") == 0) action = EXTRACT;
	}

	if ((nb_input_file <= 1) && ((action == DELETE) || (action == CREATE))) Help();
#endif /* !SFX */

	VERBOSE PrintVersion();

	switch (action)
	{
#ifndef SFX
	case UPDATE:
	case CREATE:
		/* first filename is archive filename */
		strcpy(output_filename, file_list[0]);
		file_list++;
		nb_input_file--;
	case NONE:
		/* we process readable files only and recurse directories */
		j = 0;
		for (i = 0; i < nb_input_file; ++i)
		{
			bool go_through = false;
			char *path;
			
			path = (char*)MyMalloc(sizeof(char) * (strlen(file_list[i]) + FILENAME_LENGTH_MAX));
			strcpy(path, file_list[i]);

			if (strchr(file_list[i], '*') != NULL) go_through = true;
			else
			{
				if (stat(file_list[i], &file_stat) == -1) IO_ERROR();
				
				if (recurse == true && (file_stat.st_mode & (S_IFDIR | S_IREAD)) == (S_IFDIR | S_IREAD))
				{
					strcat(path, STAR_STR);
					go_through = true;
				}
			}

			if (go_through == true)
			{
				char *p = strrchr(path, SEP_PATH);
				if (p == NULL) p = path;
				else p++;
#ifdef WIN32
				{
					struct _finddata_t file_info;
					sint handle;

					if ((handle = _findfirst(path, &file_info)) == -1) IO_ERROR();

⌨️ 快捷键说明

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