annotate src/bzip2-1.0.6/bzip2.c @ 23:619f715526df sv_v2.1

Update Vamp plugin SDK to 2.5
author Chris Cannam
date Thu, 09 May 2013 10:52:46 +0100
parents e13257ea84a4
children
rev   line source
Chris@4 1
Chris@4 2 /*-----------------------------------------------------------*/
Chris@4 3 /*--- A block-sorting, lossless compressor bzip2.c ---*/
Chris@4 4 /*-----------------------------------------------------------*/
Chris@4 5
Chris@4 6 /* ------------------------------------------------------------------
Chris@4 7 This file is part of bzip2/libbzip2, a program and library for
Chris@4 8 lossless, block-sorting data compression.
Chris@4 9
Chris@4 10 bzip2/libbzip2 version 1.0.6 of 6 September 2010
Chris@4 11 Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Chris@4 12
Chris@4 13 Please read the WARNING, DISCLAIMER and PATENTS sections in the
Chris@4 14 README file.
Chris@4 15
Chris@4 16 This program is released under the terms of the license contained
Chris@4 17 in the file LICENSE.
Chris@4 18 ------------------------------------------------------------------ */
Chris@4 19
Chris@4 20
Chris@4 21 /* Place a 1 beside your platform, and 0 elsewhere.
Chris@4 22 Generic 32-bit Unix.
Chris@4 23 Also works on 64-bit Unix boxes.
Chris@4 24 This is the default.
Chris@4 25 */
Chris@4 26 #define BZ_UNIX 1
Chris@4 27
Chris@4 28 /*--
Chris@4 29 Win32, as seen by Jacob Navia's excellent
Chris@4 30 port of (Chris Fraser & David Hanson)'s excellent
Chris@4 31 lcc compiler. Or with MS Visual C.
Chris@4 32 This is selected automatically if compiled by a compiler which
Chris@4 33 defines _WIN32, not including the Cygwin GCC.
Chris@4 34 --*/
Chris@4 35 #define BZ_LCCWIN32 0
Chris@4 36
Chris@4 37 #if defined(_WIN32) && !defined(__CYGWIN__)
Chris@4 38 #undef BZ_LCCWIN32
Chris@4 39 #define BZ_LCCWIN32 1
Chris@4 40 #undef BZ_UNIX
Chris@4 41 #define BZ_UNIX 0
Chris@4 42 #endif
Chris@4 43
Chris@4 44
Chris@4 45 /*---------------------------------------------*/
Chris@4 46 /*--
Chris@4 47 Some stuff for all platforms.
Chris@4 48 --*/
Chris@4 49
Chris@4 50 #include <stdio.h>
Chris@4 51 #include <stdlib.h>
Chris@4 52 #include <string.h>
Chris@4 53 #include <signal.h>
Chris@4 54 #include <math.h>
Chris@4 55 #include <errno.h>
Chris@4 56 #include <ctype.h>
Chris@4 57 #include "bzlib.h"
Chris@4 58
Chris@4 59 #define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); }
Chris@4 60 #define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); }
Chris@4 61 #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
Chris@4 62
Chris@4 63
Chris@4 64 /*---------------------------------------------*/
Chris@4 65 /*--
Chris@4 66 Platform-specific stuff.
Chris@4 67 --*/
Chris@4 68
Chris@4 69 #if BZ_UNIX
Chris@4 70 # include <fcntl.h>
Chris@4 71 # include <sys/types.h>
Chris@4 72 # include <utime.h>
Chris@4 73 # include <unistd.h>
Chris@4 74 # include <sys/stat.h>
Chris@4 75 # include <sys/times.h>
Chris@4 76
Chris@4 77 # define PATH_SEP '/'
Chris@4 78 # define MY_LSTAT lstat
Chris@4 79 # define MY_STAT stat
Chris@4 80 # define MY_S_ISREG S_ISREG
Chris@4 81 # define MY_S_ISDIR S_ISDIR
Chris@4 82
Chris@4 83 # define APPEND_FILESPEC(root, name) \
Chris@4 84 root=snocString((root), (name))
Chris@4 85
Chris@4 86 # define APPEND_FLAG(root, name) \
Chris@4 87 root=snocString((root), (name))
Chris@4 88
Chris@4 89 # define SET_BINARY_MODE(fd) /**/
Chris@4 90
Chris@4 91 # ifdef __GNUC__
Chris@4 92 # define NORETURN __attribute__ ((noreturn))
Chris@4 93 # else
Chris@4 94 # define NORETURN /**/
Chris@4 95 # endif
Chris@4 96
Chris@4 97 # ifdef __DJGPP__
Chris@4 98 # include <io.h>
Chris@4 99 # include <fcntl.h>
Chris@4 100 # undef MY_LSTAT
Chris@4 101 # undef MY_STAT
Chris@4 102 # define MY_LSTAT stat
Chris@4 103 # define MY_STAT stat
Chris@4 104 # undef SET_BINARY_MODE
Chris@4 105 # define SET_BINARY_MODE(fd) \
Chris@4 106 do { \
Chris@4 107 int retVal = setmode ( fileno ( fd ), \
Chris@4 108 O_BINARY ); \
Chris@4 109 ERROR_IF_MINUS_ONE ( retVal ); \
Chris@4 110 } while ( 0 )
Chris@4 111 # endif
Chris@4 112
Chris@4 113 # ifdef __CYGWIN__
Chris@4 114 # include <io.h>
Chris@4 115 # include <fcntl.h>
Chris@4 116 # undef SET_BINARY_MODE
Chris@4 117 # define SET_BINARY_MODE(fd) \
Chris@4 118 do { \
Chris@4 119 int retVal = setmode ( fileno ( fd ), \
Chris@4 120 O_BINARY ); \
Chris@4 121 ERROR_IF_MINUS_ONE ( retVal ); \
Chris@4 122 } while ( 0 )
Chris@4 123 # endif
Chris@4 124 #endif /* BZ_UNIX */
Chris@4 125
Chris@4 126
Chris@4 127
Chris@4 128 #if BZ_LCCWIN32
Chris@4 129 # include <io.h>
Chris@4 130 # include <fcntl.h>
Chris@4 131 # include <sys\stat.h>
Chris@4 132
Chris@4 133 # define NORETURN /**/
Chris@4 134 # define PATH_SEP '\\'
Chris@4 135 # define MY_LSTAT _stat
Chris@4 136 # define MY_STAT _stat
Chris@4 137 # define MY_S_ISREG(x) ((x) & _S_IFREG)
Chris@4 138 # define MY_S_ISDIR(x) ((x) & _S_IFDIR)
Chris@4 139
Chris@4 140 # define APPEND_FLAG(root, name) \
Chris@4 141 root=snocString((root), (name))
Chris@4 142
Chris@4 143 # define APPEND_FILESPEC(root, name) \
Chris@4 144 root = snocString ((root), (name))
Chris@4 145
Chris@4 146 # define SET_BINARY_MODE(fd) \
Chris@4 147 do { \
Chris@4 148 int retVal = setmode ( fileno ( fd ), \
Chris@4 149 O_BINARY ); \
Chris@4 150 ERROR_IF_MINUS_ONE ( retVal ); \
Chris@4 151 } while ( 0 )
Chris@4 152
Chris@4 153 #endif /* BZ_LCCWIN32 */
Chris@4 154
Chris@4 155
Chris@4 156 /*---------------------------------------------*/
Chris@4 157 /*--
Chris@4 158 Some more stuff for all platforms :-)
Chris@4 159 --*/
Chris@4 160
Chris@4 161 typedef char Char;
Chris@4 162 typedef unsigned char Bool;
Chris@4 163 typedef unsigned char UChar;
Chris@4 164 typedef int Int32;
Chris@4 165 typedef unsigned int UInt32;
Chris@4 166 typedef short Int16;
Chris@4 167 typedef unsigned short UInt16;
Chris@4 168
Chris@4 169 #define True ((Bool)1)
Chris@4 170 #define False ((Bool)0)
Chris@4 171
Chris@4 172 /*--
Chris@4 173 IntNative is your platform's `native' int size.
Chris@4 174 Only here to avoid probs with 64-bit platforms.
Chris@4 175 --*/
Chris@4 176 typedef int IntNative;
Chris@4 177
Chris@4 178
Chris@4 179 /*---------------------------------------------------*/
Chris@4 180 /*--- Misc (file handling) data decls ---*/
Chris@4 181 /*---------------------------------------------------*/
Chris@4 182
Chris@4 183 Int32 verbosity;
Chris@4 184 Bool keepInputFiles, smallMode, deleteOutputOnInterrupt;
Chris@4 185 Bool forceOverwrite, testFailsExist, unzFailsExist, noisy;
Chris@4 186 Int32 numFileNames, numFilesProcessed, blockSize100k;
Chris@4 187 Int32 exitValue;
Chris@4 188
Chris@4 189 /*-- source modes; F==file, I==stdin, O==stdout --*/
Chris@4 190 #define SM_I2O 1
Chris@4 191 #define SM_F2O 2
Chris@4 192 #define SM_F2F 3
Chris@4 193
Chris@4 194 /*-- operation modes --*/
Chris@4 195 #define OM_Z 1
Chris@4 196 #define OM_UNZ 2
Chris@4 197 #define OM_TEST 3
Chris@4 198
Chris@4 199 Int32 opMode;
Chris@4 200 Int32 srcMode;
Chris@4 201
Chris@4 202 #define FILE_NAME_LEN 1034
Chris@4 203
Chris@4 204 Int32 longestFileName;
Chris@4 205 Char inName [FILE_NAME_LEN];
Chris@4 206 Char outName[FILE_NAME_LEN];
Chris@4 207 Char tmpName[FILE_NAME_LEN];
Chris@4 208 Char *progName;
Chris@4 209 Char progNameReally[FILE_NAME_LEN];
Chris@4 210 FILE *outputHandleJustInCase;
Chris@4 211 Int32 workFactor;
Chris@4 212
Chris@4 213 static void panic ( const Char* ) NORETURN;
Chris@4 214 static void ioError ( void ) NORETURN;
Chris@4 215 static void outOfMemory ( void ) NORETURN;
Chris@4 216 static void configError ( void ) NORETURN;
Chris@4 217 static void crcError ( void ) NORETURN;
Chris@4 218 static void cleanUpAndFail ( Int32 ) NORETURN;
Chris@4 219 static void compressedStreamEOF ( void ) NORETURN;
Chris@4 220
Chris@4 221 static void copyFileName ( Char*, Char* );
Chris@4 222 static void* myMalloc ( Int32 );
Chris@4 223 static void applySavedFileAttrToOutputFile ( IntNative fd );
Chris@4 224
Chris@4 225
Chris@4 226
Chris@4 227 /*---------------------------------------------------*/
Chris@4 228 /*--- An implementation of 64-bit ints. Sigh. ---*/
Chris@4 229 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
Chris@4 230 /*---------------------------------------------------*/
Chris@4 231
Chris@4 232 typedef
Chris@4 233 struct { UChar b[8]; }
Chris@4 234 UInt64;
Chris@4 235
Chris@4 236
Chris@4 237 static
Chris@4 238 void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
Chris@4 239 {
Chris@4 240 n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
Chris@4 241 n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
Chris@4 242 n->b[5] = (UChar)((hi32 >> 8) & 0xFF);
Chris@4 243 n->b[4] = (UChar) (hi32 & 0xFF);
Chris@4 244 n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
Chris@4 245 n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
Chris@4 246 n->b[1] = (UChar)((lo32 >> 8) & 0xFF);
Chris@4 247 n->b[0] = (UChar) (lo32 & 0xFF);
Chris@4 248 }
Chris@4 249
Chris@4 250
Chris@4 251 static
Chris@4 252 double uInt64_to_double ( UInt64* n )
Chris@4 253 {
Chris@4 254 Int32 i;
Chris@4 255 double base = 1.0;
Chris@4 256 double sum = 0.0;
Chris@4 257 for (i = 0; i < 8; i++) {
Chris@4 258 sum += base * (double)(n->b[i]);
Chris@4 259 base *= 256.0;
Chris@4 260 }
Chris@4 261 return sum;
Chris@4 262 }
Chris@4 263
Chris@4 264
Chris@4 265 static
Chris@4 266 Bool uInt64_isZero ( UInt64* n )
Chris@4 267 {
Chris@4 268 Int32 i;
Chris@4 269 for (i = 0; i < 8; i++)
Chris@4 270 if (n->b[i] != 0) return 0;
Chris@4 271 return 1;
Chris@4 272 }
Chris@4 273
Chris@4 274
Chris@4 275 /* Divide *n by 10, and return the remainder. */
Chris@4 276 static
Chris@4 277 Int32 uInt64_qrm10 ( UInt64* n )
Chris@4 278 {
Chris@4 279 UInt32 rem, tmp;
Chris@4 280 Int32 i;
Chris@4 281 rem = 0;
Chris@4 282 for (i = 7; i >= 0; i--) {
Chris@4 283 tmp = rem * 256 + n->b[i];
Chris@4 284 n->b[i] = tmp / 10;
Chris@4 285 rem = tmp % 10;
Chris@4 286 }
Chris@4 287 return rem;
Chris@4 288 }
Chris@4 289
Chris@4 290
Chris@4 291 /* ... and the Whole Entire Point of all this UInt64 stuff is
Chris@4 292 so that we can supply the following function.
Chris@4 293 */
Chris@4 294 static
Chris@4 295 void uInt64_toAscii ( char* outbuf, UInt64* n )
Chris@4 296 {
Chris@4 297 Int32 i, q;
Chris@4 298 UChar buf[32];
Chris@4 299 Int32 nBuf = 0;
Chris@4 300 UInt64 n_copy = *n;
Chris@4 301 do {
Chris@4 302 q = uInt64_qrm10 ( &n_copy );
Chris@4 303 buf[nBuf] = q + '0';
Chris@4 304 nBuf++;
Chris@4 305 } while (!uInt64_isZero(&n_copy));
Chris@4 306 outbuf[nBuf] = 0;
Chris@4 307 for (i = 0; i < nBuf; i++)
Chris@4 308 outbuf[i] = buf[nBuf-i-1];
Chris@4 309 }
Chris@4 310
Chris@4 311
Chris@4 312 /*---------------------------------------------------*/
Chris@4 313 /*--- Processing of complete files and streams ---*/
Chris@4 314 /*---------------------------------------------------*/
Chris@4 315
Chris@4 316 /*---------------------------------------------*/
Chris@4 317 static
Chris@4 318 Bool myfeof ( FILE* f )
Chris@4 319 {
Chris@4 320 Int32 c = fgetc ( f );
Chris@4 321 if (c == EOF) return True;
Chris@4 322 ungetc ( c, f );
Chris@4 323 return False;
Chris@4 324 }
Chris@4 325
Chris@4 326
Chris@4 327 /*---------------------------------------------*/
Chris@4 328 static
Chris@4 329 void compressStream ( FILE *stream, FILE *zStream )
Chris@4 330 {
Chris@4 331 BZFILE* bzf = NULL;
Chris@4 332 UChar ibuf[5000];
Chris@4 333 Int32 nIbuf;
Chris@4 334 UInt32 nbytes_in_lo32, nbytes_in_hi32;
Chris@4 335 UInt32 nbytes_out_lo32, nbytes_out_hi32;
Chris@4 336 Int32 bzerr, bzerr_dummy, ret;
Chris@4 337
Chris@4 338 SET_BINARY_MODE(stream);
Chris@4 339 SET_BINARY_MODE(zStream);
Chris@4 340
Chris@4 341 if (ferror(stream)) goto errhandler_io;
Chris@4 342 if (ferror(zStream)) goto errhandler_io;
Chris@4 343
Chris@4 344 bzf = BZ2_bzWriteOpen ( &bzerr, zStream,
Chris@4 345 blockSize100k, verbosity, workFactor );
Chris@4 346 if (bzerr != BZ_OK) goto errhandler;
Chris@4 347
Chris@4 348 if (verbosity >= 2) fprintf ( stderr, "\n" );
Chris@4 349
Chris@4 350 while (True) {
Chris@4 351
Chris@4 352 if (myfeof(stream)) break;
Chris@4 353 nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
Chris@4 354 if (ferror(stream)) goto errhandler_io;
Chris@4 355 if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
Chris@4 356 if (bzerr != BZ_OK) goto errhandler;
Chris@4 357
Chris@4 358 }
Chris@4 359
Chris@4 360 BZ2_bzWriteClose64 ( &bzerr, bzf, 0,
Chris@4 361 &nbytes_in_lo32, &nbytes_in_hi32,
Chris@4 362 &nbytes_out_lo32, &nbytes_out_hi32 );
Chris@4 363 if (bzerr != BZ_OK) goto errhandler;
Chris@4 364
Chris@4 365 if (ferror(zStream)) goto errhandler_io;
Chris@4 366 ret = fflush ( zStream );
Chris@4 367 if (ret == EOF) goto errhandler_io;
Chris@4 368 if (zStream != stdout) {
Chris@4 369 Int32 fd = fileno ( zStream );
Chris@4 370 if (fd < 0) goto errhandler_io;
Chris@4 371 applySavedFileAttrToOutputFile ( fd );
Chris@4 372 ret = fclose ( zStream );
Chris@4 373 outputHandleJustInCase = NULL;
Chris@4 374 if (ret == EOF) goto errhandler_io;
Chris@4 375 }
Chris@4 376 outputHandleJustInCase = NULL;
Chris@4 377 if (ferror(stream)) goto errhandler_io;
Chris@4 378 ret = fclose ( stream );
Chris@4 379 if (ret == EOF) goto errhandler_io;
Chris@4 380
Chris@4 381 if (verbosity >= 1) {
Chris@4 382 if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
Chris@4 383 fprintf ( stderr, " no data compressed.\n");
Chris@4 384 } else {
Chris@4 385 Char buf_nin[32], buf_nout[32];
Chris@4 386 UInt64 nbytes_in, nbytes_out;
Chris@4 387 double nbytes_in_d, nbytes_out_d;
Chris@4 388 uInt64_from_UInt32s ( &nbytes_in,
Chris@4 389 nbytes_in_lo32, nbytes_in_hi32 );
Chris@4 390 uInt64_from_UInt32s ( &nbytes_out,
Chris@4 391 nbytes_out_lo32, nbytes_out_hi32 );
Chris@4 392 nbytes_in_d = uInt64_to_double ( &nbytes_in );
Chris@4 393 nbytes_out_d = uInt64_to_double ( &nbytes_out );
Chris@4 394 uInt64_toAscii ( buf_nin, &nbytes_in );
Chris@4 395 uInt64_toAscii ( buf_nout, &nbytes_out );
Chris@4 396 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
Chris@4 397 "%5.2f%% saved, %s in, %s out.\n",
Chris@4 398 nbytes_in_d / nbytes_out_d,
Chris@4 399 (8.0 * nbytes_out_d) / nbytes_in_d,
Chris@4 400 100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
Chris@4 401 buf_nin,
Chris@4 402 buf_nout
Chris@4 403 );
Chris@4 404 }
Chris@4 405 }
Chris@4 406
Chris@4 407 return;
Chris@4 408
Chris@4 409 errhandler:
Chris@4 410 BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1,
Chris@4 411 &nbytes_in_lo32, &nbytes_in_hi32,
Chris@4 412 &nbytes_out_lo32, &nbytes_out_hi32 );
Chris@4 413 switch (bzerr) {
Chris@4 414 case BZ_CONFIG_ERROR:
Chris@4 415 configError(); break;
Chris@4 416 case BZ_MEM_ERROR:
Chris@4 417 outOfMemory (); break;
Chris@4 418 case BZ_IO_ERROR:
Chris@4 419 errhandler_io:
Chris@4 420 ioError(); break;
Chris@4 421 default:
Chris@4 422 panic ( "compress:unexpected error" );
Chris@4 423 }
Chris@4 424
Chris@4 425 panic ( "compress:end" );
Chris@4 426 /*notreached*/
Chris@4 427 }
Chris@4 428
Chris@4 429
Chris@4 430
Chris@4 431 /*---------------------------------------------*/
Chris@4 432 static
Chris@4 433 Bool uncompressStream ( FILE *zStream, FILE *stream )
Chris@4 434 {
Chris@4 435 BZFILE* bzf = NULL;
Chris@4 436 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
Chris@4 437 UChar obuf[5000];
Chris@4 438 UChar unused[BZ_MAX_UNUSED];
Chris@4 439 Int32 nUnused;
Chris@4 440 void* unusedTmpV;
Chris@4 441 UChar* unusedTmp;
Chris@4 442
Chris@4 443 nUnused = 0;
Chris@4 444 streamNo = 0;
Chris@4 445
Chris@4 446 SET_BINARY_MODE(stream);
Chris@4 447 SET_BINARY_MODE(zStream);
Chris@4 448
Chris@4 449 if (ferror(stream)) goto errhandler_io;
Chris@4 450 if (ferror(zStream)) goto errhandler_io;
Chris@4 451
Chris@4 452 while (True) {
Chris@4 453
Chris@4 454 bzf = BZ2_bzReadOpen (
Chris@4 455 &bzerr, zStream, verbosity,
Chris@4 456 (int)smallMode, unused, nUnused
Chris@4 457 );
Chris@4 458 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
Chris@4 459 streamNo++;
Chris@4 460
Chris@4 461 while (bzerr == BZ_OK) {
Chris@4 462 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
Chris@4 463 if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
Chris@4 464 if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
Chris@4 465 fwrite ( obuf, sizeof(UChar), nread, stream );
Chris@4 466 if (ferror(stream)) goto errhandler_io;
Chris@4 467 }
Chris@4 468 if (bzerr != BZ_STREAM_END) goto errhandler;
Chris@4 469
Chris@4 470 BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
Chris@4 471 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
Chris@4 472
Chris@4 473 unusedTmp = (UChar*)unusedTmpV;
Chris@4 474 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
Chris@4 475
Chris@4 476 BZ2_bzReadClose ( &bzerr, bzf );
Chris@4 477 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
Chris@4 478
Chris@4 479 if (nUnused == 0 && myfeof(zStream)) break;
Chris@4 480 }
Chris@4 481
Chris@4 482 closeok:
Chris@4 483 if (ferror(zStream)) goto errhandler_io;
Chris@4 484 if (stream != stdout) {
Chris@4 485 Int32 fd = fileno ( stream );
Chris@4 486 if (fd < 0) goto errhandler_io;
Chris@4 487 applySavedFileAttrToOutputFile ( fd );
Chris@4 488 }
Chris@4 489 ret = fclose ( zStream );
Chris@4 490 if (ret == EOF) goto errhandler_io;
Chris@4 491
Chris@4 492 if (ferror(stream)) goto errhandler_io;
Chris@4 493 ret = fflush ( stream );
Chris@4 494 if (ret != 0) goto errhandler_io;
Chris@4 495 if (stream != stdout) {
Chris@4 496 ret = fclose ( stream );
Chris@4 497 outputHandleJustInCase = NULL;
Chris@4 498 if (ret == EOF) goto errhandler_io;
Chris@4 499 }
Chris@4 500 outputHandleJustInCase = NULL;
Chris@4 501 if (verbosity >= 2) fprintf ( stderr, "\n " );
Chris@4 502 return True;
Chris@4 503
Chris@4 504 trycat:
Chris@4 505 if (forceOverwrite) {
Chris@4 506 rewind(zStream);
Chris@4 507 while (True) {
Chris@4 508 if (myfeof(zStream)) break;
Chris@4 509 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
Chris@4 510 if (ferror(zStream)) goto errhandler_io;
Chris@4 511 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
Chris@4 512 if (ferror(stream)) goto errhandler_io;
Chris@4 513 }
Chris@4 514 goto closeok;
Chris@4 515 }
Chris@4 516
Chris@4 517 errhandler:
Chris@4 518 BZ2_bzReadClose ( &bzerr_dummy, bzf );
Chris@4 519 switch (bzerr) {
Chris@4 520 case BZ_CONFIG_ERROR:
Chris@4 521 configError(); break;
Chris@4 522 case BZ_IO_ERROR:
Chris@4 523 errhandler_io:
Chris@4 524 ioError(); break;
Chris@4 525 case BZ_DATA_ERROR:
Chris@4 526 crcError();
Chris@4 527 case BZ_MEM_ERROR:
Chris@4 528 outOfMemory();
Chris@4 529 case BZ_UNEXPECTED_EOF:
Chris@4 530 compressedStreamEOF();
Chris@4 531 case BZ_DATA_ERROR_MAGIC:
Chris@4 532 if (zStream != stdin) fclose(zStream);
Chris@4 533 if (stream != stdout) fclose(stream);
Chris@4 534 if (streamNo == 1) {
Chris@4 535 return False;
Chris@4 536 } else {
Chris@4 537 if (noisy)
Chris@4 538 fprintf ( stderr,
Chris@4 539 "\n%s: %s: trailing garbage after EOF ignored\n",
Chris@4 540 progName, inName );
Chris@4 541 return True;
Chris@4 542 }
Chris@4 543 default:
Chris@4 544 panic ( "decompress:unexpected error" );
Chris@4 545 }
Chris@4 546
Chris@4 547 panic ( "decompress:end" );
Chris@4 548 return True; /*notreached*/
Chris@4 549 }
Chris@4 550
Chris@4 551
Chris@4 552 /*---------------------------------------------*/
Chris@4 553 static
Chris@4 554 Bool testStream ( FILE *zStream )
Chris@4 555 {
Chris@4 556 BZFILE* bzf = NULL;
Chris@4 557 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
Chris@4 558 UChar obuf[5000];
Chris@4 559 UChar unused[BZ_MAX_UNUSED];
Chris@4 560 Int32 nUnused;
Chris@4 561 void* unusedTmpV;
Chris@4 562 UChar* unusedTmp;
Chris@4 563
Chris@4 564 nUnused = 0;
Chris@4 565 streamNo = 0;
Chris@4 566
Chris@4 567 SET_BINARY_MODE(zStream);
Chris@4 568 if (ferror(zStream)) goto errhandler_io;
Chris@4 569
Chris@4 570 while (True) {
Chris@4 571
Chris@4 572 bzf = BZ2_bzReadOpen (
Chris@4 573 &bzerr, zStream, verbosity,
Chris@4 574 (int)smallMode, unused, nUnused
Chris@4 575 );
Chris@4 576 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
Chris@4 577 streamNo++;
Chris@4 578
Chris@4 579 while (bzerr == BZ_OK) {
Chris@4 580 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
Chris@4 581 if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
Chris@4 582 }
Chris@4 583 if (bzerr != BZ_STREAM_END) goto errhandler;
Chris@4 584
Chris@4 585 BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
Chris@4 586 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
Chris@4 587
Chris@4 588 unusedTmp = (UChar*)unusedTmpV;
Chris@4 589 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
Chris@4 590
Chris@4 591 BZ2_bzReadClose ( &bzerr, bzf );
Chris@4 592 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
Chris@4 593 if (nUnused == 0 && myfeof(zStream)) break;
Chris@4 594
Chris@4 595 }
Chris@4 596
Chris@4 597 if (ferror(zStream)) goto errhandler_io;
Chris@4 598 ret = fclose ( zStream );
Chris@4 599 if (ret == EOF) goto errhandler_io;
Chris@4 600
Chris@4 601 if (verbosity >= 2) fprintf ( stderr, "\n " );
Chris@4 602 return True;
Chris@4 603
Chris@4 604 errhandler:
Chris@4 605 BZ2_bzReadClose ( &bzerr_dummy, bzf );
Chris@4 606 if (verbosity == 0)
Chris@4 607 fprintf ( stderr, "%s: %s: ", progName, inName );
Chris@4 608 switch (bzerr) {
Chris@4 609 case BZ_CONFIG_ERROR:
Chris@4 610 configError(); break;
Chris@4 611 case BZ_IO_ERROR:
Chris@4 612 errhandler_io:
Chris@4 613 ioError(); break;
Chris@4 614 case BZ_DATA_ERROR:
Chris@4 615 fprintf ( stderr,
Chris@4 616 "data integrity (CRC) error in data\n" );
Chris@4 617 return False;
Chris@4 618 case BZ_MEM_ERROR:
Chris@4 619 outOfMemory();
Chris@4 620 case BZ_UNEXPECTED_EOF:
Chris@4 621 fprintf ( stderr,
Chris@4 622 "file ends unexpectedly\n" );
Chris@4 623 return False;
Chris@4 624 case BZ_DATA_ERROR_MAGIC:
Chris@4 625 if (zStream != stdin) fclose(zStream);
Chris@4 626 if (streamNo == 1) {
Chris@4 627 fprintf ( stderr,
Chris@4 628 "bad magic number (file not created by bzip2)\n" );
Chris@4 629 return False;
Chris@4 630 } else {
Chris@4 631 if (noisy)
Chris@4 632 fprintf ( stderr,
Chris@4 633 "trailing garbage after EOF ignored\n" );
Chris@4 634 return True;
Chris@4 635 }
Chris@4 636 default:
Chris@4 637 panic ( "test:unexpected error" );
Chris@4 638 }
Chris@4 639
Chris@4 640 panic ( "test:end" );
Chris@4 641 return True; /*notreached*/
Chris@4 642 }
Chris@4 643
Chris@4 644
Chris@4 645 /*---------------------------------------------------*/
Chris@4 646 /*--- Error [non-] handling grunge ---*/
Chris@4 647 /*---------------------------------------------------*/
Chris@4 648
Chris@4 649 /*---------------------------------------------*/
Chris@4 650 static
Chris@4 651 void setExit ( Int32 v )
Chris@4 652 {
Chris@4 653 if (v > exitValue) exitValue = v;
Chris@4 654 }
Chris@4 655
Chris@4 656
Chris@4 657 /*---------------------------------------------*/
Chris@4 658 static
Chris@4 659 void cadvise ( void )
Chris@4 660 {
Chris@4 661 if (noisy)
Chris@4 662 fprintf (
Chris@4 663 stderr,
Chris@4 664 "\nIt is possible that the compressed file(s) have become corrupted.\n"
Chris@4 665 "You can use the -tvv option to test integrity of such files.\n\n"
Chris@4 666 "You can use the `bzip2recover' program to attempt to recover\n"
Chris@4 667 "data from undamaged sections of corrupted files.\n\n"
Chris@4 668 );
Chris@4 669 }
Chris@4 670
Chris@4 671
Chris@4 672 /*---------------------------------------------*/
Chris@4 673 static
Chris@4 674 void showFileNames ( void )
Chris@4 675 {
Chris@4 676 if (noisy)
Chris@4 677 fprintf (
Chris@4 678 stderr,
Chris@4 679 "\tInput file = %s, output file = %s\n",
Chris@4 680 inName, outName
Chris@4 681 );
Chris@4 682 }
Chris@4 683
Chris@4 684
Chris@4 685 /*---------------------------------------------*/
Chris@4 686 static
Chris@4 687 void cleanUpAndFail ( Int32 ec )
Chris@4 688 {
Chris@4 689 IntNative retVal;
Chris@4 690 struct MY_STAT statBuf;
Chris@4 691
Chris@4 692 if ( srcMode == SM_F2F
Chris@4 693 && opMode != OM_TEST
Chris@4 694 && deleteOutputOnInterrupt ) {
Chris@4 695
Chris@4 696 /* Check whether input file still exists. Delete output file
Chris@4 697 only if input exists to avoid loss of data. Joerg Prante, 5
Chris@4 698 January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean
Chris@4 699 this is less likely to happen. But to be ultra-paranoid, we
Chris@4 700 do the check anyway.) */
Chris@4 701 retVal = MY_STAT ( inName, &statBuf );
Chris@4 702 if (retVal == 0) {
Chris@4 703 if (noisy)
Chris@4 704 fprintf ( stderr,
Chris@4 705 "%s: Deleting output file %s, if it exists.\n",
Chris@4 706 progName, outName );
Chris@4 707 if (outputHandleJustInCase != NULL)
Chris@4 708 fclose ( outputHandleJustInCase );
Chris@4 709 retVal = remove ( outName );
Chris@4 710 if (retVal != 0)
Chris@4 711 fprintf ( stderr,
Chris@4 712 "%s: WARNING: deletion of output file "
Chris@4 713 "(apparently) failed.\n",
Chris@4 714 progName );
Chris@4 715 } else {
Chris@4 716 fprintf ( stderr,
Chris@4 717 "%s: WARNING: deletion of output file suppressed\n",
Chris@4 718 progName );
Chris@4 719 fprintf ( stderr,
Chris@4 720 "%s: since input file no longer exists. Output file\n",
Chris@4 721 progName );
Chris@4 722 fprintf ( stderr,
Chris@4 723 "%s: `%s' may be incomplete.\n",
Chris@4 724 progName, outName );
Chris@4 725 fprintf ( stderr,
Chris@4 726 "%s: I suggest doing an integrity test (bzip2 -tv)"
Chris@4 727 " of it.\n",
Chris@4 728 progName );
Chris@4 729 }
Chris@4 730 }
Chris@4 731
Chris@4 732 if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
Chris@4 733 fprintf ( stderr,
Chris@4 734 "%s: WARNING: some files have not been processed:\n"
Chris@4 735 "%s: %d specified on command line, %d not processed yet.\n\n",
Chris@4 736 progName, progName,
Chris@4 737 numFileNames, numFileNames - numFilesProcessed );
Chris@4 738 }
Chris@4 739 setExit(ec);
Chris@4 740 exit(exitValue);
Chris@4 741 }
Chris@4 742
Chris@4 743
Chris@4 744 /*---------------------------------------------*/
Chris@4 745 static
Chris@4 746 void panic ( const Char* s )
Chris@4 747 {
Chris@4 748 fprintf ( stderr,
Chris@4 749 "\n%s: PANIC -- internal consistency error:\n"
Chris@4 750 "\t%s\n"
Chris@4 751 "\tThis is a BUG. Please report it to me at:\n"
Chris@4 752 "\tjseward@bzip.org\n",
Chris@4 753 progName, s );
Chris@4 754 showFileNames();
Chris@4 755 cleanUpAndFail( 3 );
Chris@4 756 }
Chris@4 757
Chris@4 758
Chris@4 759 /*---------------------------------------------*/
Chris@4 760 static
Chris@4 761 void crcError ( void )
Chris@4 762 {
Chris@4 763 fprintf ( stderr,
Chris@4 764 "\n%s: Data integrity error when decompressing.\n",
Chris@4 765 progName );
Chris@4 766 showFileNames();
Chris@4 767 cadvise();
Chris@4 768 cleanUpAndFail( 2 );
Chris@4 769 }
Chris@4 770
Chris@4 771
Chris@4 772 /*---------------------------------------------*/
Chris@4 773 static
Chris@4 774 void compressedStreamEOF ( void )
Chris@4 775 {
Chris@4 776 if (noisy) {
Chris@4 777 fprintf ( stderr,
Chris@4 778 "\n%s: Compressed file ends unexpectedly;\n\t"
Chris@4 779 "perhaps it is corrupted? *Possible* reason follows.\n",
Chris@4 780 progName );
Chris@4 781 perror ( progName );
Chris@4 782 showFileNames();
Chris@4 783 cadvise();
Chris@4 784 }
Chris@4 785 cleanUpAndFail( 2 );
Chris@4 786 }
Chris@4 787
Chris@4 788
Chris@4 789 /*---------------------------------------------*/
Chris@4 790 static
Chris@4 791 void ioError ( void )
Chris@4 792 {
Chris@4 793 fprintf ( stderr,
Chris@4 794 "\n%s: I/O or other error, bailing out. "
Chris@4 795 "Possible reason follows.\n",
Chris@4 796 progName );
Chris@4 797 perror ( progName );
Chris@4 798 showFileNames();
Chris@4 799 cleanUpAndFail( 1 );
Chris@4 800 }
Chris@4 801
Chris@4 802
Chris@4 803 /*---------------------------------------------*/
Chris@4 804 static
Chris@4 805 void mySignalCatcher ( IntNative n )
Chris@4 806 {
Chris@4 807 fprintf ( stderr,
Chris@4 808 "\n%s: Control-C or similar caught, quitting.\n",
Chris@4 809 progName );
Chris@4 810 cleanUpAndFail(1);
Chris@4 811 }
Chris@4 812
Chris@4 813
Chris@4 814 /*---------------------------------------------*/
Chris@4 815 static
Chris@4 816 void mySIGSEGVorSIGBUScatcher ( IntNative n )
Chris@4 817 {
Chris@4 818 if (opMode == OM_Z)
Chris@4 819 fprintf (
Chris@4 820 stderr,
Chris@4 821 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
Chris@4 822 "\n"
Chris@4 823 " Possible causes are (most likely first):\n"
Chris@4 824 " (1) This computer has unreliable memory or cache hardware\n"
Chris@4 825 " (a surprisingly common problem; try a different machine.)\n"
Chris@4 826 " (2) A bug in the compiler used to create this executable\n"
Chris@4 827 " (unlikely, if you didn't compile bzip2 yourself.)\n"
Chris@4 828 " (3) A real bug in bzip2 -- I hope this should never be the case.\n"
Chris@4 829 " The user's manual, Section 4.3, has more info on (1) and (2).\n"
Chris@4 830 " \n"
Chris@4 831 " If you suspect this is a bug in bzip2, or are unsure about (1)\n"
Chris@4 832 " or (2), feel free to report it to me at: jseward@bzip.org.\n"
Chris@4 833 " Section 4.3 of the user's manual describes the info a useful\n"
Chris@4 834 " bug report should have. If the manual is available on your\n"
Chris@4 835 " system, please try and read it before mailing me. If you don't\n"
Chris@4 836 " have the manual or can't be bothered to read it, mail me anyway.\n"
Chris@4 837 "\n",
Chris@4 838 progName );
Chris@4 839 else
Chris@4 840 fprintf (
Chris@4 841 stderr,
Chris@4 842 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
Chris@4 843 "\n"
Chris@4 844 " Possible causes are (most likely first):\n"
Chris@4 845 " (1) The compressed data is corrupted, and bzip2's usual checks\n"
Chris@4 846 " failed to detect this. Try bzip2 -tvv my_file.bz2.\n"
Chris@4 847 " (2) This computer has unreliable memory or cache hardware\n"
Chris@4 848 " (a surprisingly common problem; try a different machine.)\n"
Chris@4 849 " (3) A bug in the compiler used to create this executable\n"
Chris@4 850 " (unlikely, if you didn't compile bzip2 yourself.)\n"
Chris@4 851 " (4) A real bug in bzip2 -- I hope this should never be the case.\n"
Chris@4 852 " The user's manual, Section 4.3, has more info on (2) and (3).\n"
Chris@4 853 " \n"
Chris@4 854 " If you suspect this is a bug in bzip2, or are unsure about (2)\n"
Chris@4 855 " or (3), feel free to report it to me at: jseward@bzip.org.\n"
Chris@4 856 " Section 4.3 of the user's manual describes the info a useful\n"
Chris@4 857 " bug report should have. If the manual is available on your\n"
Chris@4 858 " system, please try and read it before mailing me. If you don't\n"
Chris@4 859 " have the manual or can't be bothered to read it, mail me anyway.\n"
Chris@4 860 "\n",
Chris@4 861 progName );
Chris@4 862
Chris@4 863 showFileNames();
Chris@4 864 if (opMode == OM_Z)
Chris@4 865 cleanUpAndFail( 3 ); else
Chris@4 866 { cadvise(); cleanUpAndFail( 2 ); }
Chris@4 867 }
Chris@4 868
Chris@4 869
Chris@4 870 /*---------------------------------------------*/
Chris@4 871 static
Chris@4 872 void outOfMemory ( void )
Chris@4 873 {
Chris@4 874 fprintf ( stderr,
Chris@4 875 "\n%s: couldn't allocate enough memory\n",
Chris@4 876 progName );
Chris@4 877 showFileNames();
Chris@4 878 cleanUpAndFail(1);
Chris@4 879 }
Chris@4 880
Chris@4 881
Chris@4 882 /*---------------------------------------------*/
Chris@4 883 static
Chris@4 884 void configError ( void )
Chris@4 885 {
Chris@4 886 fprintf ( stderr,
Chris@4 887 "bzip2: I'm not configured correctly for this platform!\n"
Chris@4 888 "\tI require Int32, Int16 and Char to have sizes\n"
Chris@4 889 "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
Chris@4 890 "\tProbably you can fix this by defining them correctly,\n"
Chris@4 891 "\tand recompiling. Bye!\n" );
Chris@4 892 setExit(3);
Chris@4 893 exit(exitValue);
Chris@4 894 }
Chris@4 895
Chris@4 896
Chris@4 897 /*---------------------------------------------------*/
Chris@4 898 /*--- The main driver machinery ---*/
Chris@4 899 /*---------------------------------------------------*/
Chris@4 900
Chris@4 901 /* All rather crufty. The main problem is that input files
Chris@4 902 are stat()d multiple times before use. This should be
Chris@4 903 cleaned up.
Chris@4 904 */
Chris@4 905
Chris@4 906 /*---------------------------------------------*/
Chris@4 907 static
Chris@4 908 void pad ( Char *s )
Chris@4 909 {
Chris@4 910 Int32 i;
Chris@4 911 if ( (Int32)strlen(s) >= longestFileName ) return;
Chris@4 912 for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
Chris@4 913 fprintf ( stderr, " " );
Chris@4 914 }
Chris@4 915
Chris@4 916
Chris@4 917 /*---------------------------------------------*/
Chris@4 918 static
Chris@4 919 void copyFileName ( Char* to, Char* from )
Chris@4 920 {
Chris@4 921 if ( strlen(from) > FILE_NAME_LEN-10 ) {
Chris@4 922 fprintf (
Chris@4 923 stderr,
Chris@4 924 "bzip2: file name\n`%s'\n"
Chris@4 925 "is suspiciously (more than %d chars) long.\n"
Chris@4 926 "Try using a reasonable file name instead. Sorry! :-)\n",
Chris@4 927 from, FILE_NAME_LEN-10
Chris@4 928 );
Chris@4 929 setExit(1);
Chris@4 930 exit(exitValue);
Chris@4 931 }
Chris@4 932
Chris@4 933 strncpy(to,from,FILE_NAME_LEN-10);
Chris@4 934 to[FILE_NAME_LEN-10]='\0';
Chris@4 935 }
Chris@4 936
Chris@4 937
Chris@4 938 /*---------------------------------------------*/
Chris@4 939 static
Chris@4 940 Bool fileExists ( Char* name )
Chris@4 941 {
Chris@4 942 FILE *tmp = fopen ( name, "rb" );
Chris@4 943 Bool exists = (tmp != NULL);
Chris@4 944 if (tmp != NULL) fclose ( tmp );
Chris@4 945 return exists;
Chris@4 946 }
Chris@4 947
Chris@4 948
Chris@4 949 /*---------------------------------------------*/
Chris@4 950 /* Open an output file safely with O_EXCL and good permissions.
Chris@4 951 This avoids a race condition in versions < 1.0.2, in which
Chris@4 952 the file was first opened and then had its interim permissions
Chris@4 953 set safely. We instead use open() to create the file with
Chris@4 954 the interim permissions required. (--- --- rw-).
Chris@4 955
Chris@4 956 For non-Unix platforms, if we are not worrying about
Chris@4 957 security issues, simple this simply behaves like fopen.
Chris@4 958 */
Chris@4 959 static
Chris@4 960 FILE* fopen_output_safely ( Char* name, const char* mode )
Chris@4 961 {
Chris@4 962 # if BZ_UNIX
Chris@4 963 FILE* fp;
Chris@4 964 IntNative fh;
Chris@4 965 fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
Chris@4 966 if (fh == -1) return NULL;
Chris@4 967 fp = fdopen(fh, mode);
Chris@4 968 if (fp == NULL) close(fh);
Chris@4 969 return fp;
Chris@4 970 # else
Chris@4 971 return fopen(name, mode);
Chris@4 972 # endif
Chris@4 973 }
Chris@4 974
Chris@4 975
Chris@4 976 /*---------------------------------------------*/
Chris@4 977 /*--
Chris@4 978 if in doubt, return True
Chris@4 979 --*/
Chris@4 980 static
Chris@4 981 Bool notAStandardFile ( Char* name )
Chris@4 982 {
Chris@4 983 IntNative i;
Chris@4 984 struct MY_STAT statBuf;
Chris@4 985
Chris@4 986 i = MY_LSTAT ( name, &statBuf );
Chris@4 987 if (i != 0) return True;
Chris@4 988 if (MY_S_ISREG(statBuf.st_mode)) return False;
Chris@4 989 return True;
Chris@4 990 }
Chris@4 991
Chris@4 992
Chris@4 993 /*---------------------------------------------*/
Chris@4 994 /*--
Chris@4 995 rac 11/21/98 see if file has hard links to it
Chris@4 996 --*/
Chris@4 997 static
Chris@4 998 Int32 countHardLinks ( Char* name )
Chris@4 999 {
Chris@4 1000 IntNative i;
Chris@4 1001 struct MY_STAT statBuf;
Chris@4 1002
Chris@4 1003 i = MY_LSTAT ( name, &statBuf );
Chris@4 1004 if (i != 0) return 0;
Chris@4 1005 return (statBuf.st_nlink - 1);
Chris@4 1006 }
Chris@4 1007
Chris@4 1008
Chris@4 1009 /*---------------------------------------------*/
Chris@4 1010 /* Copy modification date, access date, permissions and owner from the
Chris@4 1011 source to destination file. We have to copy this meta-info off
Chris@4 1012 into fileMetaInfo before starting to compress / decompress it,
Chris@4 1013 because doing it afterwards means we get the wrong access time.
Chris@4 1014
Chris@4 1015 To complicate matters, in compress() and decompress() below, the
Chris@4 1016 sequence of tests preceding the call to saveInputFileMetaInfo()
Chris@4 1017 involves calling fileExists(), which in turn establishes its result
Chris@4 1018 by attempting to fopen() the file, and if successful, immediately
Chris@4 1019 fclose()ing it again. So we have to assume that the fopen() call
Chris@4 1020 does not cause the access time field to be updated.
Chris@4 1021
Chris@4 1022 Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
Chris@4 1023 to imply that merely doing open() will not affect the access time.
Chris@4 1024 Therefore we merely need to hope that the C library only does
Chris@4 1025 open() as a result of fopen(), and not any kind of read()-ahead
Chris@4 1026 cleverness.
Chris@4 1027
Chris@4 1028 It sounds pretty fragile to me. Whether this carries across
Chris@4 1029 robustly to arbitrary Unix-like platforms (or even works robustly
Chris@4 1030 on this one, RedHat 7.2) is unknown to me. Nevertheless ...
Chris@4 1031 */
Chris@4 1032 #if BZ_UNIX
Chris@4 1033 static
Chris@4 1034 struct MY_STAT fileMetaInfo;
Chris@4 1035 #endif
Chris@4 1036
Chris@4 1037 static
Chris@4 1038 void saveInputFileMetaInfo ( Char *srcName )
Chris@4 1039 {
Chris@4 1040 # if BZ_UNIX
Chris@4 1041 IntNative retVal;
Chris@4 1042 /* Note use of stat here, not lstat. */
Chris@4 1043 retVal = MY_STAT( srcName, &fileMetaInfo );
Chris@4 1044 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1045 # endif
Chris@4 1046 }
Chris@4 1047
Chris@4 1048
Chris@4 1049 static
Chris@4 1050 void applySavedTimeInfoToOutputFile ( Char *dstName )
Chris@4 1051 {
Chris@4 1052 # if BZ_UNIX
Chris@4 1053 IntNative retVal;
Chris@4 1054 struct utimbuf uTimBuf;
Chris@4 1055
Chris@4 1056 uTimBuf.actime = fileMetaInfo.st_atime;
Chris@4 1057 uTimBuf.modtime = fileMetaInfo.st_mtime;
Chris@4 1058
Chris@4 1059 retVal = utime ( dstName, &uTimBuf );
Chris@4 1060 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1061 # endif
Chris@4 1062 }
Chris@4 1063
Chris@4 1064 static
Chris@4 1065 void applySavedFileAttrToOutputFile ( IntNative fd )
Chris@4 1066 {
Chris@4 1067 # if BZ_UNIX
Chris@4 1068 IntNative retVal;
Chris@4 1069
Chris@4 1070 retVal = fchmod ( fd, fileMetaInfo.st_mode );
Chris@4 1071 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1072
Chris@4 1073 (void) fchown ( fd, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
Chris@4 1074 /* chown() will in many cases return with EPERM, which can
Chris@4 1075 be safely ignored.
Chris@4 1076 */
Chris@4 1077 # endif
Chris@4 1078 }
Chris@4 1079
Chris@4 1080
Chris@4 1081 /*---------------------------------------------*/
Chris@4 1082 static
Chris@4 1083 Bool containsDubiousChars ( Char* name )
Chris@4 1084 {
Chris@4 1085 # if BZ_UNIX
Chris@4 1086 /* On unix, files can contain any characters and the file expansion
Chris@4 1087 * is performed by the shell.
Chris@4 1088 */
Chris@4 1089 return False;
Chris@4 1090 # else /* ! BZ_UNIX */
Chris@4 1091 /* On non-unix (Win* platforms), wildcard characters are not allowed in
Chris@4 1092 * filenames.
Chris@4 1093 */
Chris@4 1094 for (; *name != '\0'; name++)
Chris@4 1095 if (*name == '?' || *name == '*') return True;
Chris@4 1096 return False;
Chris@4 1097 # endif /* BZ_UNIX */
Chris@4 1098 }
Chris@4 1099
Chris@4 1100
Chris@4 1101 /*---------------------------------------------*/
Chris@4 1102 #define BZ_N_SUFFIX_PAIRS 4
Chris@4 1103
Chris@4 1104 const Char* zSuffix[BZ_N_SUFFIX_PAIRS]
Chris@4 1105 = { ".bz2", ".bz", ".tbz2", ".tbz" };
Chris@4 1106 const Char* unzSuffix[BZ_N_SUFFIX_PAIRS]
Chris@4 1107 = { "", "", ".tar", ".tar" };
Chris@4 1108
Chris@4 1109 static
Chris@4 1110 Bool hasSuffix ( Char* s, const Char* suffix )
Chris@4 1111 {
Chris@4 1112 Int32 ns = strlen(s);
Chris@4 1113 Int32 nx = strlen(suffix);
Chris@4 1114 if (ns < nx) return False;
Chris@4 1115 if (strcmp(s + ns - nx, suffix) == 0) return True;
Chris@4 1116 return False;
Chris@4 1117 }
Chris@4 1118
Chris@4 1119 static
Chris@4 1120 Bool mapSuffix ( Char* name,
Chris@4 1121 const Char* oldSuffix,
Chris@4 1122 const Char* newSuffix )
Chris@4 1123 {
Chris@4 1124 if (!hasSuffix(name,oldSuffix)) return False;
Chris@4 1125 name[strlen(name)-strlen(oldSuffix)] = 0;
Chris@4 1126 strcat ( name, newSuffix );
Chris@4 1127 return True;
Chris@4 1128 }
Chris@4 1129
Chris@4 1130
Chris@4 1131 /*---------------------------------------------*/
Chris@4 1132 static
Chris@4 1133 void compress ( Char *name )
Chris@4 1134 {
Chris@4 1135 FILE *inStr;
Chris@4 1136 FILE *outStr;
Chris@4 1137 Int32 n, i;
Chris@4 1138 struct MY_STAT statBuf;
Chris@4 1139
Chris@4 1140 deleteOutputOnInterrupt = False;
Chris@4 1141
Chris@4 1142 if (name == NULL && srcMode != SM_I2O)
Chris@4 1143 panic ( "compress: bad modes\n" );
Chris@4 1144
Chris@4 1145 switch (srcMode) {
Chris@4 1146 case SM_I2O:
Chris@4 1147 copyFileName ( inName, (Char*)"(stdin)" );
Chris@4 1148 copyFileName ( outName, (Char*)"(stdout)" );
Chris@4 1149 break;
Chris@4 1150 case SM_F2F:
Chris@4 1151 copyFileName ( inName, name );
Chris@4 1152 copyFileName ( outName, name );
Chris@4 1153 strcat ( outName, ".bz2" );
Chris@4 1154 break;
Chris@4 1155 case SM_F2O:
Chris@4 1156 copyFileName ( inName, name );
Chris@4 1157 copyFileName ( outName, (Char*)"(stdout)" );
Chris@4 1158 break;
Chris@4 1159 }
Chris@4 1160
Chris@4 1161 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Chris@4 1162 if (noisy)
Chris@4 1163 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Chris@4 1164 progName, inName );
Chris@4 1165 setExit(1);
Chris@4 1166 return;
Chris@4 1167 }
Chris@4 1168 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Chris@4 1169 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Chris@4 1170 progName, inName, strerror(errno) );
Chris@4 1171 setExit(1);
Chris@4 1172 return;
Chris@4 1173 }
Chris@4 1174 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
Chris@4 1175 if (hasSuffix(inName, zSuffix[i])) {
Chris@4 1176 if (noisy)
Chris@4 1177 fprintf ( stderr,
Chris@4 1178 "%s: Input file %s already has %s suffix.\n",
Chris@4 1179 progName, inName, zSuffix[i] );
Chris@4 1180 setExit(1);
Chris@4 1181 return;
Chris@4 1182 }
Chris@4 1183 }
Chris@4 1184 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
Chris@4 1185 MY_STAT(inName, &statBuf);
Chris@4 1186 if ( MY_S_ISDIR(statBuf.st_mode) ) {
Chris@4 1187 fprintf( stderr,
Chris@4 1188 "%s: Input file %s is a directory.\n",
Chris@4 1189 progName,inName);
Chris@4 1190 setExit(1);
Chris@4 1191 return;
Chris@4 1192 }
Chris@4 1193 }
Chris@4 1194 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
Chris@4 1195 if (noisy)
Chris@4 1196 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
Chris@4 1197 progName, inName );
Chris@4 1198 setExit(1);
Chris@4 1199 return;
Chris@4 1200 }
Chris@4 1201 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
Chris@4 1202 if (forceOverwrite) {
Chris@4 1203 remove(outName);
Chris@4 1204 } else {
Chris@4 1205 fprintf ( stderr, "%s: Output file %s already exists.\n",
Chris@4 1206 progName, outName );
Chris@4 1207 setExit(1);
Chris@4 1208 return;
Chris@4 1209 }
Chris@4 1210 }
Chris@4 1211 if ( srcMode == SM_F2F && !forceOverwrite &&
Chris@4 1212 (n=countHardLinks ( inName )) > 0) {
Chris@4 1213 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
Chris@4 1214 progName, inName, n, n > 1 ? "s" : "" );
Chris@4 1215 setExit(1);
Chris@4 1216 return;
Chris@4 1217 }
Chris@4 1218
Chris@4 1219 if ( srcMode == SM_F2F ) {
Chris@4 1220 /* Save the file's meta-info before we open it. Doing it later
Chris@4 1221 means we mess up the access times. */
Chris@4 1222 saveInputFileMetaInfo ( inName );
Chris@4 1223 }
Chris@4 1224
Chris@4 1225 switch ( srcMode ) {
Chris@4 1226
Chris@4 1227 case SM_I2O:
Chris@4 1228 inStr = stdin;
Chris@4 1229 outStr = stdout;
Chris@4 1230 if ( isatty ( fileno ( stdout ) ) ) {
Chris@4 1231 fprintf ( stderr,
Chris@4 1232 "%s: I won't write compressed data to a terminal.\n",
Chris@4 1233 progName );
Chris@4 1234 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Chris@4 1235 progName, progName );
Chris@4 1236 setExit(1);
Chris@4 1237 return;
Chris@4 1238 };
Chris@4 1239 break;
Chris@4 1240
Chris@4 1241 case SM_F2O:
Chris@4 1242 inStr = fopen ( inName, "rb" );
Chris@4 1243 outStr = stdout;
Chris@4 1244 if ( isatty ( fileno ( stdout ) ) ) {
Chris@4 1245 fprintf ( stderr,
Chris@4 1246 "%s: I won't write compressed data to a terminal.\n",
Chris@4 1247 progName );
Chris@4 1248 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Chris@4 1249 progName, progName );
Chris@4 1250 if ( inStr != NULL ) fclose ( inStr );
Chris@4 1251 setExit(1);
Chris@4 1252 return;
Chris@4 1253 };
Chris@4 1254 if ( inStr == NULL ) {
Chris@4 1255 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Chris@4 1256 progName, inName, strerror(errno) );
Chris@4 1257 setExit(1);
Chris@4 1258 return;
Chris@4 1259 };
Chris@4 1260 break;
Chris@4 1261
Chris@4 1262 case SM_F2F:
Chris@4 1263 inStr = fopen ( inName, "rb" );
Chris@4 1264 outStr = fopen_output_safely ( outName, "wb" );
Chris@4 1265 if ( outStr == NULL) {
Chris@4 1266 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
Chris@4 1267 progName, outName, strerror(errno) );
Chris@4 1268 if ( inStr != NULL ) fclose ( inStr );
Chris@4 1269 setExit(1);
Chris@4 1270 return;
Chris@4 1271 }
Chris@4 1272 if ( inStr == NULL ) {
Chris@4 1273 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Chris@4 1274 progName, inName, strerror(errno) );
Chris@4 1275 if ( outStr != NULL ) fclose ( outStr );
Chris@4 1276 setExit(1);
Chris@4 1277 return;
Chris@4 1278 };
Chris@4 1279 break;
Chris@4 1280
Chris@4 1281 default:
Chris@4 1282 panic ( "compress: bad srcMode" );
Chris@4 1283 break;
Chris@4 1284 }
Chris@4 1285
Chris@4 1286 if (verbosity >= 1) {
Chris@4 1287 fprintf ( stderr, " %s: ", inName );
Chris@4 1288 pad ( inName );
Chris@4 1289 fflush ( stderr );
Chris@4 1290 }
Chris@4 1291
Chris@4 1292 /*--- Now the input and output handles are sane. Do the Biz. ---*/
Chris@4 1293 outputHandleJustInCase = outStr;
Chris@4 1294 deleteOutputOnInterrupt = True;
Chris@4 1295 compressStream ( inStr, outStr );
Chris@4 1296 outputHandleJustInCase = NULL;
Chris@4 1297
Chris@4 1298 /*--- If there was an I/O error, we won't get here. ---*/
Chris@4 1299 if ( srcMode == SM_F2F ) {
Chris@4 1300 applySavedTimeInfoToOutputFile ( outName );
Chris@4 1301 deleteOutputOnInterrupt = False;
Chris@4 1302 if ( !keepInputFiles ) {
Chris@4 1303 IntNative retVal = remove ( inName );
Chris@4 1304 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1305 }
Chris@4 1306 }
Chris@4 1307
Chris@4 1308 deleteOutputOnInterrupt = False;
Chris@4 1309 }
Chris@4 1310
Chris@4 1311
Chris@4 1312 /*---------------------------------------------*/
Chris@4 1313 static
Chris@4 1314 void uncompress ( Char *name )
Chris@4 1315 {
Chris@4 1316 FILE *inStr;
Chris@4 1317 FILE *outStr;
Chris@4 1318 Int32 n, i;
Chris@4 1319 Bool magicNumberOK;
Chris@4 1320 Bool cantGuess;
Chris@4 1321 struct MY_STAT statBuf;
Chris@4 1322
Chris@4 1323 deleteOutputOnInterrupt = False;
Chris@4 1324
Chris@4 1325 if (name == NULL && srcMode != SM_I2O)
Chris@4 1326 panic ( "uncompress: bad modes\n" );
Chris@4 1327
Chris@4 1328 cantGuess = False;
Chris@4 1329 switch (srcMode) {
Chris@4 1330 case SM_I2O:
Chris@4 1331 copyFileName ( inName, (Char*)"(stdin)" );
Chris@4 1332 copyFileName ( outName, (Char*)"(stdout)" );
Chris@4 1333 break;
Chris@4 1334 case SM_F2F:
Chris@4 1335 copyFileName ( inName, name );
Chris@4 1336 copyFileName ( outName, name );
Chris@4 1337 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
Chris@4 1338 if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
Chris@4 1339 goto zzz;
Chris@4 1340 cantGuess = True;
Chris@4 1341 strcat ( outName, ".out" );
Chris@4 1342 break;
Chris@4 1343 case SM_F2O:
Chris@4 1344 copyFileName ( inName, name );
Chris@4 1345 copyFileName ( outName, (Char*)"(stdout)" );
Chris@4 1346 break;
Chris@4 1347 }
Chris@4 1348
Chris@4 1349 zzz:
Chris@4 1350 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Chris@4 1351 if (noisy)
Chris@4 1352 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Chris@4 1353 progName, inName );
Chris@4 1354 setExit(1);
Chris@4 1355 return;
Chris@4 1356 }
Chris@4 1357 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Chris@4 1358 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Chris@4 1359 progName, inName, strerror(errno) );
Chris@4 1360 setExit(1);
Chris@4 1361 return;
Chris@4 1362 }
Chris@4 1363 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
Chris@4 1364 MY_STAT(inName, &statBuf);
Chris@4 1365 if ( MY_S_ISDIR(statBuf.st_mode) ) {
Chris@4 1366 fprintf( stderr,
Chris@4 1367 "%s: Input file %s is a directory.\n",
Chris@4 1368 progName,inName);
Chris@4 1369 setExit(1);
Chris@4 1370 return;
Chris@4 1371 }
Chris@4 1372 }
Chris@4 1373 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
Chris@4 1374 if (noisy)
Chris@4 1375 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
Chris@4 1376 progName, inName );
Chris@4 1377 setExit(1);
Chris@4 1378 return;
Chris@4 1379 }
Chris@4 1380 if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
Chris@4 1381 if (noisy)
Chris@4 1382 fprintf ( stderr,
Chris@4 1383 "%s: Can't guess original name for %s -- using %s\n",
Chris@4 1384 progName, inName, outName );
Chris@4 1385 /* just a warning, no return */
Chris@4 1386 }
Chris@4 1387 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
Chris@4 1388 if (forceOverwrite) {
Chris@4 1389 remove(outName);
Chris@4 1390 } else {
Chris@4 1391 fprintf ( stderr, "%s: Output file %s already exists.\n",
Chris@4 1392 progName, outName );
Chris@4 1393 setExit(1);
Chris@4 1394 return;
Chris@4 1395 }
Chris@4 1396 }
Chris@4 1397 if ( srcMode == SM_F2F && !forceOverwrite &&
Chris@4 1398 (n=countHardLinks ( inName ) ) > 0) {
Chris@4 1399 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
Chris@4 1400 progName, inName, n, n > 1 ? "s" : "" );
Chris@4 1401 setExit(1);
Chris@4 1402 return;
Chris@4 1403 }
Chris@4 1404
Chris@4 1405 if ( srcMode == SM_F2F ) {
Chris@4 1406 /* Save the file's meta-info before we open it. Doing it later
Chris@4 1407 means we mess up the access times. */
Chris@4 1408 saveInputFileMetaInfo ( inName );
Chris@4 1409 }
Chris@4 1410
Chris@4 1411 switch ( srcMode ) {
Chris@4 1412
Chris@4 1413 case SM_I2O:
Chris@4 1414 inStr = stdin;
Chris@4 1415 outStr = stdout;
Chris@4 1416 if ( isatty ( fileno ( stdin ) ) ) {
Chris@4 1417 fprintf ( stderr,
Chris@4 1418 "%s: I won't read compressed data from a terminal.\n",
Chris@4 1419 progName );
Chris@4 1420 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Chris@4 1421 progName, progName );
Chris@4 1422 setExit(1);
Chris@4 1423 return;
Chris@4 1424 };
Chris@4 1425 break;
Chris@4 1426
Chris@4 1427 case SM_F2O:
Chris@4 1428 inStr = fopen ( inName, "rb" );
Chris@4 1429 outStr = stdout;
Chris@4 1430 if ( inStr == NULL ) {
Chris@4 1431 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
Chris@4 1432 progName, inName, strerror(errno) );
Chris@4 1433 if ( inStr != NULL ) fclose ( inStr );
Chris@4 1434 setExit(1);
Chris@4 1435 return;
Chris@4 1436 };
Chris@4 1437 break;
Chris@4 1438
Chris@4 1439 case SM_F2F:
Chris@4 1440 inStr = fopen ( inName, "rb" );
Chris@4 1441 outStr = fopen_output_safely ( outName, "wb" );
Chris@4 1442 if ( outStr == NULL) {
Chris@4 1443 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
Chris@4 1444 progName, outName, strerror(errno) );
Chris@4 1445 if ( inStr != NULL ) fclose ( inStr );
Chris@4 1446 setExit(1);
Chris@4 1447 return;
Chris@4 1448 }
Chris@4 1449 if ( inStr == NULL ) {
Chris@4 1450 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Chris@4 1451 progName, inName, strerror(errno) );
Chris@4 1452 if ( outStr != NULL ) fclose ( outStr );
Chris@4 1453 setExit(1);
Chris@4 1454 return;
Chris@4 1455 };
Chris@4 1456 break;
Chris@4 1457
Chris@4 1458 default:
Chris@4 1459 panic ( "uncompress: bad srcMode" );
Chris@4 1460 break;
Chris@4 1461 }
Chris@4 1462
Chris@4 1463 if (verbosity >= 1) {
Chris@4 1464 fprintf ( stderr, " %s: ", inName );
Chris@4 1465 pad ( inName );
Chris@4 1466 fflush ( stderr );
Chris@4 1467 }
Chris@4 1468
Chris@4 1469 /*--- Now the input and output handles are sane. Do the Biz. ---*/
Chris@4 1470 outputHandleJustInCase = outStr;
Chris@4 1471 deleteOutputOnInterrupt = True;
Chris@4 1472 magicNumberOK = uncompressStream ( inStr, outStr );
Chris@4 1473 outputHandleJustInCase = NULL;
Chris@4 1474
Chris@4 1475 /*--- If there was an I/O error, we won't get here. ---*/
Chris@4 1476 if ( magicNumberOK ) {
Chris@4 1477 if ( srcMode == SM_F2F ) {
Chris@4 1478 applySavedTimeInfoToOutputFile ( outName );
Chris@4 1479 deleteOutputOnInterrupt = False;
Chris@4 1480 if ( !keepInputFiles ) {
Chris@4 1481 IntNative retVal = remove ( inName );
Chris@4 1482 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1483 }
Chris@4 1484 }
Chris@4 1485 } else {
Chris@4 1486 unzFailsExist = True;
Chris@4 1487 deleteOutputOnInterrupt = False;
Chris@4 1488 if ( srcMode == SM_F2F ) {
Chris@4 1489 IntNative retVal = remove ( outName );
Chris@4 1490 ERROR_IF_NOT_ZERO ( retVal );
Chris@4 1491 }
Chris@4 1492 }
Chris@4 1493 deleteOutputOnInterrupt = False;
Chris@4 1494
Chris@4 1495 if ( magicNumberOK ) {
Chris@4 1496 if (verbosity >= 1)
Chris@4 1497 fprintf ( stderr, "done\n" );
Chris@4 1498 } else {
Chris@4 1499 setExit(2);
Chris@4 1500 if (verbosity >= 1)
Chris@4 1501 fprintf ( stderr, "not a bzip2 file.\n" ); else
Chris@4 1502 fprintf ( stderr,
Chris@4 1503 "%s: %s is not a bzip2 file.\n",
Chris@4 1504 progName, inName );
Chris@4 1505 }
Chris@4 1506
Chris@4 1507 }
Chris@4 1508
Chris@4 1509
Chris@4 1510 /*---------------------------------------------*/
Chris@4 1511 static
Chris@4 1512 void testf ( Char *name )
Chris@4 1513 {
Chris@4 1514 FILE *inStr;
Chris@4 1515 Bool allOK;
Chris@4 1516 struct MY_STAT statBuf;
Chris@4 1517
Chris@4 1518 deleteOutputOnInterrupt = False;
Chris@4 1519
Chris@4 1520 if (name == NULL && srcMode != SM_I2O)
Chris@4 1521 panic ( "testf: bad modes\n" );
Chris@4 1522
Chris@4 1523 copyFileName ( outName, (Char*)"(none)" );
Chris@4 1524 switch (srcMode) {
Chris@4 1525 case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break;
Chris@4 1526 case SM_F2F: copyFileName ( inName, name ); break;
Chris@4 1527 case SM_F2O: copyFileName ( inName, name ); break;
Chris@4 1528 }
Chris@4 1529
Chris@4 1530 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Chris@4 1531 if (noisy)
Chris@4 1532 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Chris@4 1533 progName, inName );
Chris@4 1534 setExit(1);
Chris@4 1535 return;
Chris@4 1536 }
Chris@4 1537 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Chris@4 1538 fprintf ( stderr, "%s: Can't open input %s: %s.\n",
Chris@4 1539 progName, inName, strerror(errno) );
Chris@4 1540 setExit(1);
Chris@4 1541 return;
Chris@4 1542 }
Chris@4 1543 if ( srcMode != SM_I2O ) {
Chris@4 1544 MY_STAT(inName, &statBuf);
Chris@4 1545 if ( MY_S_ISDIR(statBuf.st_mode) ) {
Chris@4 1546 fprintf( stderr,
Chris@4 1547 "%s: Input file %s is a directory.\n",
Chris@4 1548 progName,inName);
Chris@4 1549 setExit(1);
Chris@4 1550 return;
Chris@4 1551 }
Chris@4 1552 }
Chris@4 1553
Chris@4 1554 switch ( srcMode ) {
Chris@4 1555
Chris@4 1556 case SM_I2O:
Chris@4 1557 if ( isatty ( fileno ( stdin ) ) ) {
Chris@4 1558 fprintf ( stderr,
Chris@4 1559 "%s: I won't read compressed data from a terminal.\n",
Chris@4 1560 progName );
Chris@4 1561 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Chris@4 1562 progName, progName );
Chris@4 1563 setExit(1);
Chris@4 1564 return;
Chris@4 1565 };
Chris@4 1566 inStr = stdin;
Chris@4 1567 break;
Chris@4 1568
Chris@4 1569 case SM_F2O: case SM_F2F:
Chris@4 1570 inStr = fopen ( inName, "rb" );
Chris@4 1571 if ( inStr == NULL ) {
Chris@4 1572 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
Chris@4 1573 progName, inName, strerror(errno) );
Chris@4 1574 setExit(1);
Chris@4 1575 return;
Chris@4 1576 };
Chris@4 1577 break;
Chris@4 1578
Chris@4 1579 default:
Chris@4 1580 panic ( "testf: bad srcMode" );
Chris@4 1581 break;
Chris@4 1582 }
Chris@4 1583
Chris@4 1584 if (verbosity >= 1) {
Chris@4 1585 fprintf ( stderr, " %s: ", inName );
Chris@4 1586 pad ( inName );
Chris@4 1587 fflush ( stderr );
Chris@4 1588 }
Chris@4 1589
Chris@4 1590 /*--- Now the input handle is sane. Do the Biz. ---*/
Chris@4 1591 outputHandleJustInCase = NULL;
Chris@4 1592 allOK = testStream ( inStr );
Chris@4 1593
Chris@4 1594 if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
Chris@4 1595 if (!allOK) testFailsExist = True;
Chris@4 1596 }
Chris@4 1597
Chris@4 1598
Chris@4 1599 /*---------------------------------------------*/
Chris@4 1600 static
Chris@4 1601 void license ( void )
Chris@4 1602 {
Chris@4 1603 fprintf ( stderr,
Chris@4 1604
Chris@4 1605 "bzip2, a block-sorting file compressor. "
Chris@4 1606 "Version %s.\n"
Chris@4 1607 " \n"
Chris@4 1608 " Copyright (C) 1996-2010 by Julian Seward.\n"
Chris@4 1609 " \n"
Chris@4 1610 " This program is free software; you can redistribute it and/or modify\n"
Chris@4 1611 " it under the terms set out in the LICENSE file, which is included\n"
Chris@4 1612 " in the bzip2-1.0.6 source distribution.\n"
Chris@4 1613 " \n"
Chris@4 1614 " This program is distributed in the hope that it will be useful,\n"
Chris@4 1615 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
Chris@4 1616 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
Chris@4 1617 " LICENSE file for more details.\n"
Chris@4 1618 " \n",
Chris@4 1619 BZ2_bzlibVersion()
Chris@4 1620 );
Chris@4 1621 }
Chris@4 1622
Chris@4 1623
Chris@4 1624 /*---------------------------------------------*/
Chris@4 1625 static
Chris@4 1626 void usage ( Char *fullProgName )
Chris@4 1627 {
Chris@4 1628 fprintf (
Chris@4 1629 stderr,
Chris@4 1630 "bzip2, a block-sorting file compressor. "
Chris@4 1631 "Version %s.\n"
Chris@4 1632 "\n usage: %s [flags and input files in any order]\n"
Chris@4 1633 "\n"
Chris@4 1634 " -h --help print this message\n"
Chris@4 1635 " -d --decompress force decompression\n"
Chris@4 1636 " -z --compress force compression\n"
Chris@4 1637 " -k --keep keep (don't delete) input files\n"
Chris@4 1638 " -f --force overwrite existing output files\n"
Chris@4 1639 " -t --test test compressed file integrity\n"
Chris@4 1640 " -c --stdout output to standard out\n"
Chris@4 1641 " -q --quiet suppress noncritical error messages\n"
Chris@4 1642 " -v --verbose be verbose (a 2nd -v gives more)\n"
Chris@4 1643 " -L --license display software version & license\n"
Chris@4 1644 " -V --version display software version & license\n"
Chris@4 1645 " -s --small use less memory (at most 2500k)\n"
Chris@4 1646 " -1 .. -9 set block size to 100k .. 900k\n"
Chris@4 1647 " --fast alias for -1\n"
Chris@4 1648 " --best alias for -9\n"
Chris@4 1649 "\n"
Chris@4 1650 " If invoked as `bzip2', default action is to compress.\n"
Chris@4 1651 " as `bunzip2', default action is to decompress.\n"
Chris@4 1652 " as `bzcat', default action is to decompress to stdout.\n"
Chris@4 1653 "\n"
Chris@4 1654 " If no file names are given, bzip2 compresses or decompresses\n"
Chris@4 1655 " from standard input to standard output. You can combine\n"
Chris@4 1656 " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
Chris@4 1657 # if BZ_UNIX
Chris@4 1658 "\n"
Chris@4 1659 # endif
Chris@4 1660 ,
Chris@4 1661
Chris@4 1662 BZ2_bzlibVersion(),
Chris@4 1663 fullProgName
Chris@4 1664 );
Chris@4 1665 }
Chris@4 1666
Chris@4 1667
Chris@4 1668 /*---------------------------------------------*/
Chris@4 1669 static
Chris@4 1670 void redundant ( Char* flag )
Chris@4 1671 {
Chris@4 1672 fprintf (
Chris@4 1673 stderr,
Chris@4 1674 "%s: %s is redundant in versions 0.9.5 and above\n",
Chris@4 1675 progName, flag );
Chris@4 1676 }
Chris@4 1677
Chris@4 1678
Chris@4 1679 /*---------------------------------------------*/
Chris@4 1680 /*--
Chris@4 1681 All the garbage from here to main() is purely to
Chris@4 1682 implement a linked list of command-line arguments,
Chris@4 1683 into which main() copies argv[1 .. argc-1].
Chris@4 1684
Chris@4 1685 The purpose of this exercise is to facilitate
Chris@4 1686 the expansion of wildcard characters * and ? in
Chris@4 1687 filenames for OSs which don't know how to do it
Chris@4 1688 themselves, like MSDOS, Windows 95 and NT.
Chris@4 1689
Chris@4 1690 The actual Dirty Work is done by the platform-
Chris@4 1691 specific macro APPEND_FILESPEC.
Chris@4 1692 --*/
Chris@4 1693
Chris@4 1694 typedef
Chris@4 1695 struct zzzz {
Chris@4 1696 Char *name;
Chris@4 1697 struct zzzz *link;
Chris@4 1698 }
Chris@4 1699 Cell;
Chris@4 1700
Chris@4 1701
Chris@4 1702 /*---------------------------------------------*/
Chris@4 1703 static
Chris@4 1704 void *myMalloc ( Int32 n )
Chris@4 1705 {
Chris@4 1706 void* p;
Chris@4 1707
Chris@4 1708 p = malloc ( (size_t)n );
Chris@4 1709 if (p == NULL) outOfMemory ();
Chris@4 1710 return p;
Chris@4 1711 }
Chris@4 1712
Chris@4 1713
Chris@4 1714 /*---------------------------------------------*/
Chris@4 1715 static
Chris@4 1716 Cell *mkCell ( void )
Chris@4 1717 {
Chris@4 1718 Cell *c;
Chris@4 1719
Chris@4 1720 c = (Cell*) myMalloc ( sizeof ( Cell ) );
Chris@4 1721 c->name = NULL;
Chris@4 1722 c->link = NULL;
Chris@4 1723 return c;
Chris@4 1724 }
Chris@4 1725
Chris@4 1726
Chris@4 1727 /*---------------------------------------------*/
Chris@4 1728 static
Chris@4 1729 Cell *snocString ( Cell *root, Char *name )
Chris@4 1730 {
Chris@4 1731 if (root == NULL) {
Chris@4 1732 Cell *tmp = mkCell();
Chris@4 1733 tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
Chris@4 1734 strcpy ( tmp->name, name );
Chris@4 1735 return tmp;
Chris@4 1736 } else {
Chris@4 1737 Cell *tmp = root;
Chris@4 1738 while (tmp->link != NULL) tmp = tmp->link;
Chris@4 1739 tmp->link = snocString ( tmp->link, name );
Chris@4 1740 return root;
Chris@4 1741 }
Chris@4 1742 }
Chris@4 1743
Chris@4 1744
Chris@4 1745 /*---------------------------------------------*/
Chris@4 1746 static
Chris@4 1747 void addFlagsFromEnvVar ( Cell** argList, Char* varName )
Chris@4 1748 {
Chris@4 1749 Int32 i, j, k;
Chris@4 1750 Char *envbase, *p;
Chris@4 1751
Chris@4 1752 envbase = getenv(varName);
Chris@4 1753 if (envbase != NULL) {
Chris@4 1754 p = envbase;
Chris@4 1755 i = 0;
Chris@4 1756 while (True) {
Chris@4 1757 if (p[i] == 0) break;
Chris@4 1758 p += i;
Chris@4 1759 i = 0;
Chris@4 1760 while (isspace((Int32)(p[0]))) p++;
Chris@4 1761 while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
Chris@4 1762 if (i > 0) {
Chris@4 1763 k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
Chris@4 1764 for (j = 0; j < k; j++) tmpName[j] = p[j];
Chris@4 1765 tmpName[k] = 0;
Chris@4 1766 APPEND_FLAG(*argList, tmpName);
Chris@4 1767 }
Chris@4 1768 }
Chris@4 1769 }
Chris@4 1770 }
Chris@4 1771
Chris@4 1772
Chris@4 1773 /*---------------------------------------------*/
Chris@4 1774 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
Chris@4 1775
Chris@4 1776 IntNative main ( IntNative argc, Char *argv[] )
Chris@4 1777 {
Chris@4 1778 Int32 i, j;
Chris@4 1779 Char *tmp;
Chris@4 1780 Cell *argList;
Chris@4 1781 Cell *aa;
Chris@4 1782 Bool decode;
Chris@4 1783
Chris@4 1784 /*-- Be really really really paranoid :-) --*/
Chris@4 1785 if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 ||
Chris@4 1786 sizeof(Int16) != 2 || sizeof(UInt16) != 2 ||
Chris@4 1787 sizeof(Char) != 1 || sizeof(UChar) != 1)
Chris@4 1788 configError();
Chris@4 1789
Chris@4 1790 /*-- Initialise --*/
Chris@4 1791 outputHandleJustInCase = NULL;
Chris@4 1792 smallMode = False;
Chris@4 1793 keepInputFiles = False;
Chris@4 1794 forceOverwrite = False;
Chris@4 1795 noisy = True;
Chris@4 1796 verbosity = 0;
Chris@4 1797 blockSize100k = 9;
Chris@4 1798 testFailsExist = False;
Chris@4 1799 unzFailsExist = False;
Chris@4 1800 numFileNames = 0;
Chris@4 1801 numFilesProcessed = 0;
Chris@4 1802 workFactor = 30;
Chris@4 1803 deleteOutputOnInterrupt = False;
Chris@4 1804 exitValue = 0;
Chris@4 1805 i = j = 0; /* avoid bogus warning from egcs-1.1.X */
Chris@4 1806
Chris@4 1807 /*-- Set up signal handlers for mem access errors --*/
Chris@4 1808 signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
Chris@4 1809 # if BZ_UNIX
Chris@4 1810 # ifndef __DJGPP__
Chris@4 1811 signal (SIGBUS, mySIGSEGVorSIGBUScatcher);
Chris@4 1812 # endif
Chris@4 1813 # endif
Chris@4 1814
Chris@4 1815 copyFileName ( inName, (Char*)"(none)" );
Chris@4 1816 copyFileName ( outName, (Char*)"(none)" );
Chris@4 1817
Chris@4 1818 copyFileName ( progNameReally, argv[0] );
Chris@4 1819 progName = &progNameReally[0];
Chris@4 1820 for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
Chris@4 1821 if (*tmp == PATH_SEP) progName = tmp + 1;
Chris@4 1822
Chris@4 1823
Chris@4 1824 /*-- Copy flags from env var BZIP2, and
Chris@4 1825 expand filename wildcards in arg list.
Chris@4 1826 --*/
Chris@4 1827 argList = NULL;
Chris@4 1828 addFlagsFromEnvVar ( &argList, (Char*)"BZIP2" );
Chris@4 1829 addFlagsFromEnvVar ( &argList, (Char*)"BZIP" );
Chris@4 1830 for (i = 1; i <= argc-1; i++)
Chris@4 1831 APPEND_FILESPEC(argList, argv[i]);
Chris@4 1832
Chris@4 1833
Chris@4 1834 /*-- Find the length of the longest filename --*/
Chris@4 1835 longestFileName = 7;
Chris@4 1836 numFileNames = 0;
Chris@4 1837 decode = True;
Chris@4 1838 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 1839 if (ISFLAG("--")) { decode = False; continue; }
Chris@4 1840 if (aa->name[0] == '-' && decode) continue;
Chris@4 1841 numFileNames++;
Chris@4 1842 if (longestFileName < (Int32)strlen(aa->name) )
Chris@4 1843 longestFileName = (Int32)strlen(aa->name);
Chris@4 1844 }
Chris@4 1845
Chris@4 1846
Chris@4 1847 /*-- Determine source modes; flag handling may change this too. --*/
Chris@4 1848 if (numFileNames == 0)
Chris@4 1849 srcMode = SM_I2O; else srcMode = SM_F2F;
Chris@4 1850
Chris@4 1851
Chris@4 1852 /*-- Determine what to do (compress/uncompress/test/cat). --*/
Chris@4 1853 /*-- Note that subsequent flag handling may change this. --*/
Chris@4 1854 opMode = OM_Z;
Chris@4 1855
Chris@4 1856 if ( (strstr ( progName, "unzip" ) != 0) ||
Chris@4 1857 (strstr ( progName, "UNZIP" ) != 0) )
Chris@4 1858 opMode = OM_UNZ;
Chris@4 1859
Chris@4 1860 if ( (strstr ( progName, "z2cat" ) != 0) ||
Chris@4 1861 (strstr ( progName, "Z2CAT" ) != 0) ||
Chris@4 1862 (strstr ( progName, "zcat" ) != 0) ||
Chris@4 1863 (strstr ( progName, "ZCAT" ) != 0) ) {
Chris@4 1864 opMode = OM_UNZ;
Chris@4 1865 srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
Chris@4 1866 }
Chris@4 1867
Chris@4 1868
Chris@4 1869 /*-- Look at the flags. --*/
Chris@4 1870 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 1871 if (ISFLAG("--")) break;
Chris@4 1872 if (aa->name[0] == '-' && aa->name[1] != '-') {
Chris@4 1873 for (j = 1; aa->name[j] != '\0'; j++) {
Chris@4 1874 switch (aa->name[j]) {
Chris@4 1875 case 'c': srcMode = SM_F2O; break;
Chris@4 1876 case 'd': opMode = OM_UNZ; break;
Chris@4 1877 case 'z': opMode = OM_Z; break;
Chris@4 1878 case 'f': forceOverwrite = True; break;
Chris@4 1879 case 't': opMode = OM_TEST; break;
Chris@4 1880 case 'k': keepInputFiles = True; break;
Chris@4 1881 case 's': smallMode = True; break;
Chris@4 1882 case 'q': noisy = False; break;
Chris@4 1883 case '1': blockSize100k = 1; break;
Chris@4 1884 case '2': blockSize100k = 2; break;
Chris@4 1885 case '3': blockSize100k = 3; break;
Chris@4 1886 case '4': blockSize100k = 4; break;
Chris@4 1887 case '5': blockSize100k = 5; break;
Chris@4 1888 case '6': blockSize100k = 6; break;
Chris@4 1889 case '7': blockSize100k = 7; break;
Chris@4 1890 case '8': blockSize100k = 8; break;
Chris@4 1891 case '9': blockSize100k = 9; break;
Chris@4 1892 case 'V':
Chris@4 1893 case 'L': license(); break;
Chris@4 1894 case 'v': verbosity++; break;
Chris@4 1895 case 'h': usage ( progName );
Chris@4 1896 exit ( 0 );
Chris@4 1897 break;
Chris@4 1898 default: fprintf ( stderr, "%s: Bad flag `%s'\n",
Chris@4 1899 progName, aa->name );
Chris@4 1900 usage ( progName );
Chris@4 1901 exit ( 1 );
Chris@4 1902 break;
Chris@4 1903 }
Chris@4 1904 }
Chris@4 1905 }
Chris@4 1906 }
Chris@4 1907
Chris@4 1908 /*-- And again ... --*/
Chris@4 1909 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 1910 if (ISFLAG("--")) break;
Chris@4 1911 if (ISFLAG("--stdout")) srcMode = SM_F2O; else
Chris@4 1912 if (ISFLAG("--decompress")) opMode = OM_UNZ; else
Chris@4 1913 if (ISFLAG("--compress")) opMode = OM_Z; else
Chris@4 1914 if (ISFLAG("--force")) forceOverwrite = True; else
Chris@4 1915 if (ISFLAG("--test")) opMode = OM_TEST; else
Chris@4 1916 if (ISFLAG("--keep")) keepInputFiles = True; else
Chris@4 1917 if (ISFLAG("--small")) smallMode = True; else
Chris@4 1918 if (ISFLAG("--quiet")) noisy = False; else
Chris@4 1919 if (ISFLAG("--version")) license(); else
Chris@4 1920 if (ISFLAG("--license")) license(); else
Chris@4 1921 if (ISFLAG("--exponential")) workFactor = 1; else
Chris@4 1922 if (ISFLAG("--repetitive-best")) redundant(aa->name); else
Chris@4 1923 if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
Chris@4 1924 if (ISFLAG("--fast")) blockSize100k = 1; else
Chris@4 1925 if (ISFLAG("--best")) blockSize100k = 9; else
Chris@4 1926 if (ISFLAG("--verbose")) verbosity++; else
Chris@4 1927 if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); }
Chris@4 1928 else
Chris@4 1929 if (strncmp ( aa->name, "--", 2) == 0) {
Chris@4 1930 fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
Chris@4 1931 usage ( progName );
Chris@4 1932 exit ( 1 );
Chris@4 1933 }
Chris@4 1934 }
Chris@4 1935
Chris@4 1936 if (verbosity > 4) verbosity = 4;
Chris@4 1937 if (opMode == OM_Z && smallMode && blockSize100k > 2)
Chris@4 1938 blockSize100k = 2;
Chris@4 1939
Chris@4 1940 if (opMode == OM_TEST && srcMode == SM_F2O) {
Chris@4 1941 fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
Chris@4 1942 progName );
Chris@4 1943 exit ( 1 );
Chris@4 1944 }
Chris@4 1945
Chris@4 1946 if (srcMode == SM_F2O && numFileNames == 0)
Chris@4 1947 srcMode = SM_I2O;
Chris@4 1948
Chris@4 1949 if (opMode != OM_Z) blockSize100k = 0;
Chris@4 1950
Chris@4 1951 if (srcMode == SM_F2F) {
Chris@4 1952 signal (SIGINT, mySignalCatcher);
Chris@4 1953 signal (SIGTERM, mySignalCatcher);
Chris@4 1954 # if BZ_UNIX
Chris@4 1955 signal (SIGHUP, mySignalCatcher);
Chris@4 1956 # endif
Chris@4 1957 }
Chris@4 1958
Chris@4 1959 if (opMode == OM_Z) {
Chris@4 1960 if (srcMode == SM_I2O) {
Chris@4 1961 compress ( NULL );
Chris@4 1962 } else {
Chris@4 1963 decode = True;
Chris@4 1964 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 1965 if (ISFLAG("--")) { decode = False; continue; }
Chris@4 1966 if (aa->name[0] == '-' && decode) continue;
Chris@4 1967 numFilesProcessed++;
Chris@4 1968 compress ( aa->name );
Chris@4 1969 }
Chris@4 1970 }
Chris@4 1971 }
Chris@4 1972 else
Chris@4 1973
Chris@4 1974 if (opMode == OM_UNZ) {
Chris@4 1975 unzFailsExist = False;
Chris@4 1976 if (srcMode == SM_I2O) {
Chris@4 1977 uncompress ( NULL );
Chris@4 1978 } else {
Chris@4 1979 decode = True;
Chris@4 1980 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 1981 if (ISFLAG("--")) { decode = False; continue; }
Chris@4 1982 if (aa->name[0] == '-' && decode) continue;
Chris@4 1983 numFilesProcessed++;
Chris@4 1984 uncompress ( aa->name );
Chris@4 1985 }
Chris@4 1986 }
Chris@4 1987 if (unzFailsExist) {
Chris@4 1988 setExit(2);
Chris@4 1989 exit(exitValue);
Chris@4 1990 }
Chris@4 1991 }
Chris@4 1992
Chris@4 1993 else {
Chris@4 1994 testFailsExist = False;
Chris@4 1995 if (srcMode == SM_I2O) {
Chris@4 1996 testf ( NULL );
Chris@4 1997 } else {
Chris@4 1998 decode = True;
Chris@4 1999 for (aa = argList; aa != NULL; aa = aa->link) {
Chris@4 2000 if (ISFLAG("--")) { decode = False; continue; }
Chris@4 2001 if (aa->name[0] == '-' && decode) continue;
Chris@4 2002 numFilesProcessed++;
Chris@4 2003 testf ( aa->name );
Chris@4 2004 }
Chris@4 2005 }
Chris@4 2006 if (testFailsExist && noisy) {
Chris@4 2007 fprintf ( stderr,
Chris@4 2008 "\n"
Chris@4 2009 "You can use the `bzip2recover' program to attempt to recover\n"
Chris@4 2010 "data from undamaged sections of corrupted files.\n\n"
Chris@4 2011 );
Chris@4 2012 setExit(2);
Chris@4 2013 exit(exitValue);
Chris@4 2014 }
Chris@4 2015 }
Chris@4 2016
Chris@4 2017 /* Free the argument list memory to mollify leak detectors
Chris@4 2018 (eg) Purify, Checker. Serves no other useful purpose.
Chris@4 2019 */
Chris@4 2020 aa = argList;
Chris@4 2021 while (aa != NULL) {
Chris@4 2022 Cell* aa2 = aa->link;
Chris@4 2023 if (aa->name != NULL) free(aa->name);
Chris@4 2024 free(aa);
Chris@4 2025 aa = aa2;
Chris@4 2026 }
Chris@4 2027
Chris@4 2028 return exitValue;
Chris@4 2029 }
Chris@4 2030
Chris@4 2031
Chris@4 2032 /*-----------------------------------------------------------*/
Chris@4 2033 /*--- end bzip2.c ---*/
Chris@4 2034 /*-----------------------------------------------------------*/