📄 bzip2.c
字号:
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
" LICENSE file for more details.\n"
" \n",
BZ2_bzlibVersion()
);
}
/*---------------------------------------------*/
static
void usage ( Char *fullProgName )
{
fprintf (
stderr,
"bzip2, a block-sorting file compressor. "
"Version %s.\n"
"\n usage: %s [flags and input files in any order]\n"
"\n"
" -h --help print this message\n"
" -d --decompress force decompression\n"
" -z --compress force compression\n"
" -k --keep keep (don't delete) input files\n"
" -f --force overwrite existing output files\n"
" -t --test test compressed file integrity\n"
" -c --stdout output to standard out\n"
" -q --quiet suppress noncritical error messages\n"
" -v --verbose be verbose (a 2nd -v gives more)\n"
" -L --license display software version & license\n"
" -V --version display software version & license\n"
" -s --small use less memory (at most 2500k)\n"
" -1 .. -9 set block size to 100k .. 900k\n"
" --fast alias for -1\n"
" --best alias for -9\n"
"\n"
" If invoked as `bzip2', default action is to compress.\n"
" as `bunzip2', default action is to decompress.\n"
" as `bzcat', default action is to decompress to stdout.\n"
"\n"
" If no file names are given, bzip2 compresses or decompresses\n"
" from standard input to standard output. You can combine\n"
" short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
# if BZ_UNIX
"\n"
# endif
,
BZ2_bzlibVersion(),
fullProgName
);
}
/*---------------------------------------------*/
static
void redundant ( Char* flag )
{
fprintf (
stderr,
"%s: %s is redundant in versions 0.9.5 and above\n",
progName, flag );
}
/*---------------------------------------------*/
/*--
All the garbage from here to main() is purely to
implement a linked list of command-line arguments,
into which main() copies argv[1 .. argc-1].
The purpose of this exercise is to facilitate
the expansion of wildcard characters * and ? in
filenames for OSs which don't know how to do it
themselves, like MSDOS, Windows 95 and NT.
The actual Dirty Work is done by the platform-
specific macro APPEND_FILESPEC.
--*/
typedef
struct zzzz {
Char *name;
struct zzzz *link;
}
Cell;
/*---------------------------------------------*/
static
void *myMalloc ( Int32 n )
{
void* p;
p = malloc ( (size_t)n );
if (p == NULL) outOfMemory ();
return p;
}
/*---------------------------------------------*/
static
Cell *mkCell ( void )
{
Cell *c;
c = (Cell*) myMalloc ( sizeof ( Cell ) );
c->name = NULL;
c->link = NULL;
return c;
}
/*---------------------------------------------*/
static
Cell *snocString ( Cell *root, Char *name )
{
if (root == NULL) {
Cell *tmp = mkCell();
tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
strcpy ( tmp->name, name );
return tmp;
} else {
Cell *tmp = root;
while (tmp->link != NULL) tmp = tmp->link;
tmp->link = snocString ( tmp->link, name );
return root;
}
}
/*---------------------------------------------*/
static
void addFlagsFromEnvVar ( Cell** argList, Char* varName )
{
Int32 i, j, k;
Char *envbase, *p;
envbase = getenv(varName);
if (envbase != NULL) {
p = envbase;
i = 0;
while (True) {
if (p[i] == 0) break;
p += i;
i = 0;
while (isspace((Int32)(p[0]))) p++;
while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
if (i > 0) {
k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
for (j = 0; j < k; j++) tmpName[j] = p[j];
tmpName[k] = 0;
APPEND_FLAG(*argList, tmpName);
}
}
}
}
/*---------------------------------------------*/
#define ISFLAG(s) (strcmp(aa->name, (s))==0)
IntNative main ( IntNative argc, Char *argv[] )
{
Int32 i, j;
Char *tmp;
Cell *argList;
Cell *aa;
Bool decode;
/*-- Be really really really paranoid :-) --*/
if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 ||
sizeof(Int16) != 2 || sizeof(UInt16) != 2 ||
sizeof(Char) != 1 || sizeof(UChar) != 1)
configError();
/*-- Initialise --*/
outputHandleJustInCase = NULL;
smallMode = False;
keepInputFiles = False;
forceOverwrite = False;
noisy = True;
verbosity = 0;
blockSize100k = 9;
testFailsExist = False;
unzFailsExist = False;
numFileNames = 0;
numFilesProcessed = 0;
workFactor = 30;
deleteOutputOnInterrupt = False;
exitValue = 0;
i = j = 0; /* avoid bogus warning from egcs-1.1.X */
/*-- Set up signal handlers for mem access errors --*/
signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
# if BZ_UNIX
# ifndef __DJGPP__
signal (SIGBUS, mySIGSEGVorSIGBUScatcher);
# endif
# endif
copyFileName ( inName, "(none)" );
copyFileName ( outName, "(none)" );
copyFileName ( progNameReally, argv[0] );
progName = &progNameReally[0];
for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
if (*tmp == PATH_SEP) progName = tmp + 1;
/*-- Copy flags from env var BZIP2, and
expand filename wildcards in arg list.
--*/
argList = NULL;
addFlagsFromEnvVar ( &argList, "BZIP2" );
addFlagsFromEnvVar ( &argList, "BZIP" );
for (i = 1; i <= argc-1; i++)
APPEND_FILESPEC(argList, argv[i]);
/*-- Find the length of the longest filename --*/
longestFileName = 7;
numFileNames = 0;
decode = True;
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) { decode = False; continue; }
if (aa->name[0] == '-' && decode) continue;
numFileNames++;
if (longestFileName < (Int32)strlen(aa->name) )
longestFileName = (Int32)strlen(aa->name);
}
/*-- Determine source modes; flag handling may change this too. --*/
if (numFileNames == 0)
srcMode = SM_I2O; else srcMode = SM_F2F;
/*-- Determine what to do (compress/uncompress/test/cat). --*/
/*-- Note that subsequent flag handling may change this. --*/
opMode = OM_Z;
if ( (strstr ( progName, "unzip" ) != 0) ||
(strstr ( progName, "UNZIP" ) != 0) )
opMode = OM_UNZ;
if ( (strstr ( progName, "z2cat" ) != 0) ||
(strstr ( progName, "Z2CAT" ) != 0) ||
(strstr ( progName, "zcat" ) != 0) ||
(strstr ( progName, "ZCAT" ) != 0) ) {
opMode = OM_UNZ;
srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
}
/*-- Look at the flags. --*/
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) break;
if (aa->name[0] == '-' && aa->name[1] != '-') {
for (j = 1; aa->name[j] != '\0'; j++) {
switch (aa->name[j]) {
case 'c': srcMode = SM_F2O; break;
case 'd': opMode = OM_UNZ; break;
case 'z': opMode = OM_Z; break;
case 'f': forceOverwrite = True; break;
case 't': opMode = OM_TEST; break;
case 'k': keepInputFiles = True; break;
case 's': smallMode = True; break;
case 'q': noisy = False; break;
case '1': blockSize100k = 1; break;
case '2': blockSize100k = 2; break;
case '3': blockSize100k = 3; break;
case '4': blockSize100k = 4; break;
case '5': blockSize100k = 5; break;
case '6': blockSize100k = 6; break;
case '7': blockSize100k = 7; break;
case '8': blockSize100k = 8; break;
case '9': blockSize100k = 9; break;
case 'V':
case 'L': license(); break;
case 'v': verbosity++; break;
case 'h': usage ( progName );
exit ( 0 );
break;
default: fprintf ( stderr, "%s: Bad flag `%s'\n",
progName, aa->name );
usage ( progName );
exit ( 1 );
break;
}
}
}
}
/*-- And again ... --*/
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) break;
if (ISFLAG("--stdout")) srcMode = SM_F2O; else
if (ISFLAG("--decompress")) opMode = OM_UNZ; else
if (ISFLAG("--compress")) opMode = OM_Z; else
if (ISFLAG("--force")) forceOverwrite = True; else
if (ISFLAG("--test")) opMode = OM_TEST; else
if (ISFLAG("--keep")) keepInputFiles = True; else
if (ISFLAG("--small")) smallMode = True; else
if (ISFLAG("--quiet")) noisy = False; else
if (ISFLAG("--version")) license(); else
if (ISFLAG("--license")) license(); else
if (ISFLAG("--exponential")) workFactor = 1; else
if (ISFLAG("--repetitive-best")) redundant(aa->name); else
if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
if (ISFLAG("--fast")) blockSize100k = 1; else
if (ISFLAG("--best")) blockSize100k = 9; else
if (ISFLAG("--verbose")) verbosity++; else
if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); }
else
if (strncmp ( aa->name, "--", 2) == 0) {
fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
usage ( progName );
exit ( 1 );
}
}
if (verbosity > 4) verbosity = 4;
if (opMode == OM_Z && smallMode && blockSize100k > 2)
blockSize100k = 2;
if (opMode == OM_TEST && srcMode == SM_F2O) {
fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
progName );
exit ( 1 );
}
if (srcMode == SM_F2O && numFileNames == 0)
srcMode = SM_I2O;
if (opMode != OM_Z) blockSize100k = 0;
if (srcMode == SM_F2F) {
signal (SIGINT, mySignalCatcher);
signal (SIGTERM, mySignalCatcher);
# if BZ_UNIX
signal (SIGHUP, mySignalCatcher);
# endif
}
if (opMode == OM_Z) {
if (srcMode == SM_I2O) {
compress ( NULL );
} else {
decode = True;
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) { decode = False; continue; }
if (aa->name[0] == '-' && decode) continue;
numFilesProcessed++;
compress ( aa->name );
}
}
}
else
if (opMode == OM_UNZ) {
unzFailsExist = False;
if (srcMode == SM_I2O) {
uncompress ( NULL );
} else {
decode = True;
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) { decode = False; continue; }
if (aa->name[0] == '-' && decode) continue;
numFilesProcessed++;
uncompress ( aa->name );
}
}
if (unzFailsExist) {
setExit(2);
exit(exitValue);
}
}
else {
testFailsExist = False;
if (srcMode == SM_I2O) {
testf ( NULL );
} else {
decode = True;
for (aa = argList; aa != NULL; aa = aa->link) {
if (ISFLAG("--")) { decode = False; continue; }
if (aa->name[0] == '-' && decode) continue;
numFilesProcessed++;
testf ( aa->name );
}
}
if (testFailsExist && noisy) {
fprintf ( stderr,
"\n"
"You can use the `bzip2recover' program to attempt to recover\n"
"data from undamaged sections of corrupted files.\n\n"
);
setExit(2);
exit(exitValue);
}
}
/* Free the argument list memory to mollify leak detectors
(eg) Purify, Checker. Serves no other useful purpose.
*/
aa = argList;
while (aa != NULL) {
Cell* aa2 = aa->link;
if (aa->name != NULL) free(aa->name);
free(aa);
aa = aa2;
}
return exitValue;
}
/*-----------------------------------------------------------*/
/*--- end bzip2.c ---*/
/*-----------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -