annotate src/bzip2-1.0.6/bzip2.c @ 169:223a55898ab9 tip default

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