src/util/compress/bzip2/bzip2.c

Go to the documentation of this file.
00001 
00002 /*-----------------------------------------------------------*/
00003 /*--- A block-sorting, lossless compressor        bzip2.c ---*/
00004 /*-----------------------------------------------------------*/
00005 
00006 /*--
00007   This file is a part of bzip2 and/or libbzip2, a program and
00008   library for lossless, block-sorting data compression.
00009 
00010   Copyright (C) 1996-2002 Julian R Seward.  All rights reserved.
00011 
00012   Redistribution and use in source and binary forms, with or without
00013   modification, are permitted provided that the following conditions
00014   are met:
00015 
00016   1. Redistributions of source code must retain the above copyright
00017      notice, this list of conditions and the following disclaimer.
00018 
00019   2. The origin of this software must not be misrepresented; you must 
00020      not claim that you wrote the original software.  If you use this 
00021      software in a product, an acknowledgment in the product 
00022      documentation would be appreciated but is not required.
00023 
00024   3. Altered source versions must be plainly marked as such, and must
00025      not be misrepresented as being the original software.
00026 
00027   4. The name of the author may not be used to endorse or promote 
00028      products derived from this software without specific prior written 
00029      permission.
00030 
00031   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
00032   OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00033   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00034   ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00035   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00036   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
00037   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00038   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00039   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00040   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00041   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00042 
00043   Julian Seward, Cambridge, UK.
00044   jseward@acm.org
00045   bzip2/libbzip2 version 1.0 of 21 March 2000
00046 
00047   This program is based on (at least) the work of:
00048      Mike Burrows
00049      David Wheeler
00050      Peter Fenwick
00051      Alistair Moffat
00052      Radford Neal
00053      Ian H. Witten
00054      Robert Sedgewick
00055      Jon L. Bentley
00056 
00057   For more information on these sources, see the manual.
00058 --*/
00059 
00060 
00061 /*----------------------------------------------------*/
00062 /*--- IMPORTANT                                    ---*/
00063 /*----------------------------------------------------*/
00064 
00065 /*--
00066    WARNING:
00067       This program and library (attempts to) compress data by 
00068       performing several non-trivial transformations on it.  
00069       Unless you are 100% familiar with *all* the algorithms 
00070       contained herein, and with the consequences of modifying them, 
00071       you should NOT meddle with the compression or decompression 
00072       machinery.  Incorrect changes can and very likely *will* 
00073       lead to disasterous loss of data.
00074 
00075    DISCLAIMER:
00076       I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
00077       USE OF THIS PROGRAM, HOWSOEVER CAUSED.
00078 
00079       Every compression of a file implies an assumption that the
00080       compressed file can be decompressed to reproduce the original.
00081       Great efforts in design, coding and testing have been made to
00082       ensure that this program works correctly.  However, the
00083       complexity of the algorithms, and, in particular, the presence
00084       of various special cases in the code which occur with very low
00085       but non-zero probability make it impossible to rule out the
00086       possibility of bugs remaining in the program.  DO NOT COMPRESS
00087       ANY DATA WITH THIS PROGRAM AND/OR LIBRARY UNLESS YOU ARE PREPARED 
00088       TO ACCEPT THE POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL 
00089       NOT BE RECOVERABLE.
00090 
00091       That is not to say this program is inherently unreliable.
00092       Indeed, I very much hope the opposite is true.  bzip2/libbzip2
00093       has been carefully constructed and extensively tested.
00094 
00095    PATENTS:
00096       To the best of my knowledge, bzip2/libbzip2 does not use any 
00097       patented algorithms.  However, I do not have the resources 
00098       available to carry out a full patent search.  Therefore I cannot 
00099       give any guarantee of the above statement.
00100 --*/
00101 
00102 
00103 
00104 /*----------------------------------------------------*/
00105 /*--- and now for something much more pleasant :-) ---*/
00106 /*----------------------------------------------------*/
00107 
00108 /*---------------------------------------------*/
00109 /*--
00110   Place a 1 beside your platform, and 0 elsewhere.
00111 --*/
00112 
00113 /*--
00114   Generic 32-bit Unix.
00115   Also works on 64-bit Unix boxes.
00116   This is the default.
00117 --*/
00118 #define BZ_UNIX      1
00119 
00120 /*--
00121   Win32, as seen by Jacob Navia's excellent
00122   port of (Chris Fraser & David Hanson)'s excellent
00123   lcc compiler.  Or with MS Visual C.
00124   This is selected automatically if compiled by a compiler which
00125   defines _WIN32, not including the Cygwin GCC.
00126 --*/
00127 #define BZ_LCCWIN32  0
00128 
00129 #if defined(_WIN32) && !defined(__CYGWIN__)
00130 #undef  BZ_LCCWIN32
00131 #define BZ_LCCWIN32 1
00132 #undef  BZ_UNIX
00133 #define BZ_UNIX 0
00134 #endif
00135 
00136 
00137 /*---------------------------------------------*/
00138 /*--
00139   Some stuff for all platforms.
00140 --*/
00141 
00142 #include <stdio.h>
00143 #include <stdlib.h>
00144 #include <string.h>
00145 #include <signal.h>
00146 #include <math.h>
00147 #include <errno.h>
00148 #include <ctype.h>
00149 #include "bzlib.h"
00150 
00151 #define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
00152 #define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
00153 #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
00154 
00155 
00156 /*---------------------------------------------*/
00157 /*--
00158    Platform-specific stuff.
00159 --*/
00160 
00161 #if BZ_UNIX
00162 #   include <fcntl.h>
00163 #   include <sys/types.h>
00164 #   include <utime.h>
00165 #   include <unistd.h>
00166 #   include <sys/stat.h>
00167 #   include <sys/times.h>
00168 
00169 #   define PATH_SEP    '/'
00170 #   define MY_LSTAT    lstat
00171 #   define MY_STAT     stat
00172 #   define MY_S_ISREG  S_ISREG
00173 #   define MY_S_ISDIR  S_ISDIR
00174 
00175 #   define APPEND_FILESPEC(root, name) \
00176       root=snocString((root), (name))
00177 
00178 #   define APPEND_FLAG(root, name) \
00179       root=snocString((root), (name))
00180 
00181 #   define SET_BINARY_MODE(fd) /**/
00182 
00183 #   ifdef __GNUC__
00184 #      define NORETURN __attribute__ ((noreturn))
00185 #   else
00186 #      define NORETURN /**/
00187 #   endif
00188 
00189 #   ifdef __DJGPP__
00190 #     include <io.h>
00191 #     include <fcntl.h>
00192 #     undef MY_LSTAT
00193 #     undef MY_STAT
00194 #     define MY_LSTAT stat
00195 #     define MY_STAT stat
00196 #     undef SET_BINARY_MODE
00197 #     define SET_BINARY_MODE(fd)                        \
00198         do {                                            \
00199            int retVal = setmode ( fileno ( fd ),        \
00200                                   O_BINARY );           \
00201            ERROR_IF_MINUS_ONE ( retVal );               \
00202         } while ( 0 )
00203 #   endif
00204 
00205 #   ifdef __CYGWIN__
00206 #     include <io.h>
00207 #     include <fcntl.h>
00208 #     undef SET_BINARY_MODE
00209 #     define SET_BINARY_MODE(fd)                        \
00210         do {                                            \
00211            int retVal = setmode ( fileno ( fd ),        \
00212                                   O_BINARY );           \
00213            ERROR_IF_MINUS_ONE ( retVal );               \
00214         } while ( 0 )
00215 #   endif
00216 #endif /* BZ_UNIX */
00217 
00218 
00219 
00220 #if BZ_LCCWIN32
00221 #   include <io.h>
00222 #   include <fcntl.h>
00223 #   include <sys\stat.h>
00224 
00225 #   define NORETURN       /**/
00226 #   define PATH_SEP       '\\'
00227 #   define MY_LSTAT       _stat
00228 #   define MY_STAT        _stat
00229 #   define MY_S_ISREG(x)  ((x) & _S_IFREG)
00230 #   define MY_S_ISDIR(x)  ((x) & _S_IFDIR)
00231 
00232 #   define APPEND_FLAG(root, name) \
00233       root=snocString((root), (name))
00234 
00235 #   define APPEND_FILESPEC(root, name)                \
00236       root = snocString ((root), (name))
00237 
00238 #   define SET_BINARY_MODE(fd)                        \
00239       do {                                            \
00240          int retVal = setmode ( fileno ( fd ),        \
00241                                 O_BINARY );           \
00242          ERROR_IF_MINUS_ONE ( retVal );               \
00243       } while ( 0 )
00244 
00245 #endif /* BZ_LCCWIN32 */
00246 
00247 
00248 /*---------------------------------------------*/
00249 /*--
00250   Some more stuff for all platforms :-)
00251 --*/
00252 
00253 typedef char            Char;
00254 typedef unsigned char   Bool;
00255 typedef unsigned char   UChar;
00256 typedef int             Int32;
00257 typedef unsigned int    UInt32;
00258 typedef short           Int16;
00259 typedef unsigned short  UInt16;
00260                                        
00261 #define True  ((Bool)1)
00262 #define False ((Bool)0)
00263 
00264 /*--
00265   IntNative is your platform's `native' int size.
00266   Only here to avoid probs with 64-bit platforms.
00267 --*/
00268 typedef int IntNative;
00269 
00270 
00271 /*---------------------------------------------------*/
00272 /*--- Misc (file handling) data decls             ---*/
00273 /*---------------------------------------------------*/
00274 
00275 Int32   verbosity;
00276 Bool    keepInputFiles, smallMode, deleteOutputOnInterrupt;
00277 Bool    forceOverwrite, testFailsExist, unzFailsExist, noisy;
00278 Int32   numFileNames, numFilesProcessed, blockSize100k;
00279 Int32   exitValue;
00280 
00281 /*-- source modes; F==file, I==stdin, O==stdout --*/
00282 #define SM_I2O           1
00283 #define SM_F2O           2
00284 #define SM_F2F           3
00285 
00286 /*-- operation modes --*/
00287 #define OM_Z             1
00288 #define OM_UNZ           2
00289 #define OM_TEST          3
00290 
00291 Int32   opMode;
00292 Int32   srcMode;
00293 
00294 #define FILE_NAME_LEN 1034
00295 
00296 Int32   longestFileName;
00297 Char    inName [FILE_NAME_LEN];
00298 Char    outName[FILE_NAME_LEN];
00299 Char    tmpName[FILE_NAME_LEN];
00300 Char    *progName;
00301 Char    progNameReally[FILE_NAME_LEN];
00302 FILE    *outputHandleJustInCase;
00303 Int32   workFactor;
00304 
00305 static void    panic                 ( Char* )   NORETURN;
00306 static void    ioError               ( void )    NORETURN;
00307 static void    outOfMemory           ( void )    NORETURN;
00308 static void    configError           ( void )    NORETURN;
00309 static void    crcError              ( void )    NORETURN;
00310 static void    cleanUpAndFail        ( Int32 )   NORETURN;
00311 static void    compressedStreamEOF   ( void )    NORETURN;
00312 
00313 static void    copyFileName ( Char*, Char* );
00314 static void*   myMalloc     ( Int32 );
00315 
00316 
00317 
00318 /*---------------------------------------------------*/
00319 /*--- An implementation of 64-bit ints.  Sigh.    ---*/
00320 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
00321 /*---------------------------------------------------*/
00322 
00323 typedef
00324    struct { UChar b[8]; } 
00325    UInt64;
00326 
00327 
00328 static
00329 void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
00330 {
00331    n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
00332    n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
00333    n->b[5] = (UChar)((hi32 >> 8)  & 0xFF);
00334    n->b[4] = (UChar) (hi32        & 0xFF);
00335    n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
00336    n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
00337    n->b[1] = (UChar)((lo32 >> 8)  & 0xFF);
00338    n->b[0] = (UChar) (lo32        & 0xFF);
00339 }
00340 
00341 
00342 static
00343 double uInt64_to_double ( UInt64* n )
00344 {
00345    Int32  i;
00346    double base = 1.0;
00347    double sum  = 0.0;
00348    for (i = 0; i < 8; i++) {
00349       sum  += base * (double)(n->b[i]);
00350       base *= 256.0;
00351    }
00352    return sum;
00353 }
00354 
00355 
00356 static
00357 Bool uInt64_isZero ( UInt64* n )
00358 {
00359    Int32 i;
00360    for (i = 0; i < 8; i++)
00361       if (n->b[i] != 0) return 0;
00362    return 1;
00363 }
00364 
00365 
00366 /* Divide *n by 10, and return the remainder.  */
00367 static 
00368 Int32 uInt64_qrm10 ( UInt64* n )
00369 {
00370    UInt32 rem, tmp;
00371    Int32  i;
00372    rem = 0;
00373    for (i = 7; i >= 0; i--) {
00374       tmp = rem * 256 + n->b[i];
00375       n->b[i] = tmp / 10;
00376       rem = tmp % 10;
00377    }
00378    return rem;
00379 }
00380 
00381 
00382 /* ... and the Whole Entire Point of all this UInt64 stuff is
00383    so that we can supply the following function.
00384 */
00385 static
00386 void uInt64_toAscii ( char* outbuf, UInt64* n )
00387 {
00388    Int32  i, q;
00389    UChar  buf[32];
00390    Int32  nBuf   = 0;
00391    UInt64 n_copy = *n;
00392    do {
00393       q = uInt64_qrm10 ( &n_copy );
00394       buf[nBuf] = q + '0';
00395       nBuf++;
00396    } while (!uInt64_isZero(&n_copy));
00397    outbuf[nBuf] = 0;
00398    for (i = 0; i < nBuf; i++) 
00399       outbuf[i] = buf[nBuf-i-1];
00400 }
00401 
00402 
00403 /*---------------------------------------------------*/
00404 /*--- Processing of complete files and streams    ---*/
00405 /*---------------------------------------------------*/
00406 
00407 /*---------------------------------------------*/
00408 static 
00409 Bool myfeof ( FILE* f )
00410 {
00411    Int32 c = fgetc ( f );
00412    if (c == EOF) return True;
00413    ungetc ( c, f );
00414    return False;
00415 }
00416 
00417 
00418 /*---------------------------------------------*/
00419 static 
00420 void compressStream ( FILE *stream, FILE *zStream )
00421 {
00422    BZFILE* bzf = NULL;
00423    UChar   ibuf[5000];
00424    Int32   nIbuf;
00425    UInt32  nbytes_in_lo32, nbytes_in_hi32;
00426    UInt32  nbytes_out_lo32, nbytes_out_hi32;
00427    Int32   bzerr, bzerr_dummy, ret;
00428 
00429    SET_BINARY_MODE(stream);
00430    SET_BINARY_MODE(zStream);
00431 
00432    if (ferror(stream)) goto errhandler_io;
00433    if (ferror(zStream)) goto errhandler_io;
00434 
00435    bzf = BZ2_bzWriteOpen ( &bzerr, zStream, 
00436                            blockSize100k, verbosity, workFactor );   
00437    if (bzerr != BZ_OK) goto errhandler;
00438 
00439    if (verbosity >= 2) fprintf ( stderr, "\n" );
00440 
00441    while (True) {
00442 
00443       if (myfeof(stream)) break;
00444       nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
00445       if (ferror(stream)) goto errhandler_io;
00446       if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
00447       if (bzerr != BZ_OK) goto errhandler;
00448 
00449    }
00450 
00451    BZ2_bzWriteClose64 ( &bzerr, bzf, 0, 
00452                         &nbytes_in_lo32, &nbytes_in_hi32,
00453                         &nbytes_out_lo32, &nbytes_out_hi32 );
00454    if (bzerr != BZ_OK) goto errhandler;
00455 
00456    if (ferror(zStream)) goto errhandler_io;
00457    ret = fflush ( zStream );
00458    if (ret == EOF) goto errhandler_io;
00459    if (zStream != stdout) {
00460       ret = fclose ( zStream );
00461       outputHandleJustInCase = NULL;
00462       if (ret == EOF) goto errhandler_io;
00463    }
00464    outputHandleJustInCase = NULL;
00465    if (ferror(stream)) goto errhandler_io;
00466    ret = fclose ( stream );
00467    if (ret == EOF) goto errhandler_io;
00468 
00469    if (verbosity >= 1) {
00470       if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
00471      fprintf ( stderr, " no data compressed.\n");
00472       } else {
00473      Char   buf_nin[32], buf_nout[32];
00474      UInt64 nbytes_in,   nbytes_out;
00475      double nbytes_in_d, nbytes_out_d;
00476      uInt64_from_UInt32s ( &nbytes_in, 
00477                    nbytes_in_lo32, nbytes_in_hi32 );
00478      uInt64_from_UInt32s ( &nbytes_out, 
00479                    nbytes_out_lo32, nbytes_out_hi32 );
00480      nbytes_in_d  = uInt64_to_double ( &nbytes_in );
00481      nbytes_out_d = uInt64_to_double ( &nbytes_out );
00482      uInt64_toAscii ( buf_nin, &nbytes_in );
00483      uInt64_toAscii ( buf_nout, &nbytes_out );
00484      fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
00485            "%5.2f%% saved, %s in, %s out.\n",
00486            nbytes_in_d / nbytes_out_d,
00487            (8.0 * nbytes_out_d) / nbytes_in_d,
00488            100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
00489            buf_nin,
00490            buf_nout
00491          );
00492       }
00493    }
00494 
00495    return;
00496 
00497    errhandler:
00498    BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, 
00499                         &nbytes_in_lo32, &nbytes_in_hi32,
00500                         &nbytes_out_lo32, &nbytes_out_hi32 );
00501    switch (bzerr) {
00502       case BZ_CONFIG_ERROR:
00503          configError(); break;
00504       case BZ_MEM_ERROR:
00505          outOfMemory (); break;
00506       case BZ_IO_ERROR:
00507          errhandler_io:
00508          ioError(); break;
00509       default:
00510          panic ( "compress:unexpected error" );
00511    }
00512 
00513    panic ( "compress:end" );
00514    /*notreached*/
00515 }
00516 
00517 
00518 
00519 /*---------------------------------------------*/
00520 static 
00521 Bool uncompressStream ( FILE *zStream, FILE *stream )
00522 {
00523    BZFILE* bzf = NULL;
00524    Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
00525    UChar   obuf[5000];
00526    UChar   unused[BZ_MAX_UNUSED];
00527    Int32   nUnused;
00528    UChar*  unusedTmp;
00529 
00530    nUnused = 0;
00531    streamNo = 0;
00532 
00533    SET_BINARY_MODE(stream);
00534    SET_BINARY_MODE(zStream);
00535 
00536    if (ferror(stream)) goto errhandler_io;
00537    if (ferror(zStream)) goto errhandler_io;
00538 
00539    while (True) {
00540 
00541       bzf = BZ2_bzReadOpen ( 
00542                &bzerr, zStream, verbosity, 
00543                (int)smallMode, unused, nUnused
00544             );
00545       if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
00546       streamNo++;
00547 
00548       while (bzerr == BZ_OK) {
00549          nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
00550          if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
00551          if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
00552             fwrite ( obuf, sizeof(UChar), nread, stream );
00553          if (ferror(stream)) goto errhandler_io;
00554       }
00555       if (bzerr != BZ_STREAM_END) goto errhandler;
00556 
00557       BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused );
00558       if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
00559 
00560       for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
00561 
00562       BZ2_bzReadClose ( &bzerr, bzf );
00563       if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
00564 
00565       if (nUnused == 0 && myfeof(zStream)) break;
00566    }
00567 
00568    closeok:
00569    if (ferror(zStream)) goto errhandler_io;
00570    ret = fclose ( zStream );
00571    if (ret == EOF) goto errhandler_io;
00572 
00573    if (ferror(stream)) goto errhandler_io;
00574    ret = fflush ( stream );
00575    if (ret != 0) goto errhandler_io;
00576    if (stream != stdout) {
00577       ret = fclose ( stream );
00578       outputHandleJustInCase = NULL;
00579       if (ret == EOF) goto errhandler_io;
00580    }
00581    outputHandleJustInCase = NULL;
00582    if (verbosity >= 2) fprintf ( stderr, "\n    " );
00583    return True;
00584 
00585    trycat: 
00586    if (forceOverwrite) {
00587       rewind(zStream);
00588       while (True) {
00589          if (myfeof(zStream)) break;
00590          nread = fread ( obuf, sizeof(UChar), 5000, zStream );
00591          if (ferror(zStream)) goto errhandler_io;
00592          if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
00593          if (ferror(stream)) goto errhandler_io;
00594       }
00595       goto closeok;
00596    }
00597   
00598    errhandler:
00599    BZ2_bzReadClose ( &bzerr_dummy, bzf );
00600    switch (bzerr) {
00601       case BZ_CONFIG_ERROR:
00602          configError(); break;
00603       case BZ_IO_ERROR:
00604          errhandler_io:
00605          ioError(); break;
00606       case BZ_DATA_ERROR:
00607          crcError();
00608       case BZ_MEM_ERROR:
00609          outOfMemory();
00610       case BZ_UNEXPECTED_EOF:
00611          compressedStreamEOF();
00612       case BZ_DATA_ERROR_MAGIC:
00613          if (zStream != stdin) fclose(zStream);
00614          if (stream != stdout) fclose(stream);
00615          if (streamNo == 1) {
00616             return False;
00617          } else {
00618             if (noisy)
00619             fprintf ( stderr, 
00620                       "\n%s: %s: trailing garbage after EOF ignored\n",
00621                       progName, inName );
00622             return True;       
00623          }
00624       default:
00625          panic ( "decompress:unexpected error" );
00626    }
00627 
00628    panic ( "decompress:end" );
00629    return True; /*notreached*/
00630 }
00631 
00632 
00633 /*---------------------------------------------*/
00634 static 
00635 Bool testStream ( FILE *zStream )
00636 {
00637    BZFILE* bzf = NULL;
00638    Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
00639    UChar   obuf[5000];
00640    UChar   unused[BZ_MAX_UNUSED];
00641    Int32   nUnused;
00642    UChar*  unusedTmp;
00643 
00644    nUnused = 0;
00645    streamNo = 0;
00646 
00647    SET_BINARY_MODE(zStream);
00648    if (ferror(zStream)) goto errhandler_io;
00649 
00650    while (True) {
00651 
00652       bzf = BZ2_bzReadOpen ( 
00653                &bzerr, zStream, verbosity, 
00654                (int)smallMode, unused, nUnused
00655             );
00656       if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
00657       streamNo++;
00658 
00659       while (bzerr == BZ_OK) {
00660          nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
00661          if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
00662       }
00663       if (bzerr != BZ_STREAM_END) goto errhandler;
00664 
00665       BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused );
00666       if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
00667 
00668       for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
00669 
00670       BZ2_bzReadClose ( &bzerr, bzf );
00671       if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
00672       if (nUnused == 0 && myfeof(zStream)) break;
00673 
00674    }
00675 
00676    if (ferror(zStream)) goto errhandler_io;
00677    ret = fclose ( zStream );
00678    if (ret == EOF) goto errhandler_io;
00679 
00680    if (verbosity >= 2) fprintf ( stderr, "\n    " );
00681    return True;
00682 
00683    errhandler:
00684    BZ2_bzReadClose ( &bzerr_dummy, bzf );
00685    if (verbosity == 0) 
00686       fprintf ( stderr, "%s: %s: ", progName, inName );
00687    switch (bzerr) {
00688       case BZ_CONFIG_ERROR:
00689          configError(); break;
00690       case BZ_IO_ERROR:
00691          errhandler_io:
00692          ioError(); break;
00693       case BZ_DATA_ERROR:
00694          fprintf ( stderr,
00695                    "data integrity (CRC) error in data\n" );
00696          return False;
00697       case BZ_MEM_ERROR:
00698          outOfMemory();
00699       case BZ_UNEXPECTED_EOF:
00700          fprintf ( stderr,
00701                    "file ends unexpectedly\n" );
00702          return False;
00703       case BZ_DATA_ERROR_MAGIC:
00704          if (zStream != stdin) fclose(zStream);
00705          if (streamNo == 1) {
00706           fprintf ( stderr, 
00707                     "bad magic number (file not created by bzip2)\n" );
00708             return False;
00709          } else {
00710             if (noisy)
00711             fprintf ( stderr, 
00712                       "trailing garbage after EOF ignored\n" );
00713             return True;       
00714          }
00715       default:
00716          panic ( "test:unexpected error" );
00717    }
00718 
00719    panic ( "test:end" );
00720    return True; /*notreached*/
00721 }
00722 
00723 
00724 /*---------------------------------------------------*/
00725 /*--- Error [non-] handling grunge                ---*/
00726 /*---------------------------------------------------*/
00727 
00728 /*---------------------------------------------*/
00729 static
00730 void setExit ( Int32 v )
00731 {
00732    if (v > exitValue) exitValue = v;
00733 }
00734 
00735 
00736 /*---------------------------------------------*/
00737 static 
00738 void cadvise ( void )
00739 {
00740    if (noisy)
00741    fprintf (
00742       stderr,
00743       "\nIt is possible that the compressed file(s) have become corrupted.\n"
00744         "You can use the -tvv option to test integrity of such files.\n\n"
00745         "You can use the `bzip2recover' program to attempt to recover\n"
00746         "data from undamaged sections of corrupted files.\n\n"
00747     );
00748 }
00749 
00750 
00751 /*---------------------------------------------*/
00752 static 
00753 void showFileNames ( void )
00754 {
00755    if (noisy)
00756    fprintf (
00757       stderr,
00758       "\tInput file = %s, output file = %s\n",
00759       inName, outName 
00760    );
00761 }
00762 
00763 
00764 /*---------------------------------------------*/
00765 static 
00766 void cleanUpAndFail ( Int32 ec )
00767 {
00768    IntNative      retVal;
00769    struct MY_STAT statBuf;
00770 
00771    if ( srcMode == SM_F2F 
00772         && opMode != OM_TEST
00773         && deleteOutputOnInterrupt ) {
00774 
00775       /* Check whether input file still exists.  Delete output file
00776          only if input exists to avoid loss of data.  Joerg Prante, 5
00777          January 2002.  (JRS 06-Jan-2002: other changes in 1.0.2 mean
00778          this is less likely to happen.  But to be ultra-paranoid, we
00779          do the check anyway.)  */
00780       retVal = MY_STAT ( inName, &statBuf );
00781       if (retVal == 0) {
00782          if (noisy)
00783             fprintf ( stderr, 
00784                       "%s: Deleting output file %s, if it exists.\n",
00785                       progName, outName );
00786          if (outputHandleJustInCase != NULL)
00787             fclose ( outputHandleJustInCase );
00788          retVal = remove ( outName );
00789          if (retVal != 0)
00790             fprintf ( stderr,
00791                       "%s: WARNING: deletion of output file "
00792                       "(apparently) failed.\n",
00793                       progName );
00794       } else {
00795          fprintf ( stderr,
00796                    "%s: WARNING: deletion of output file suppressed\n",
00797                     progName );
00798          fprintf ( stderr,
00799                    "%s:    since input file no longer exists.  Output file\n",
00800                    progName );
00801          fprintf ( stderr,
00802                    "%s:    `%s' may be incomplete.\n",
00803                    progName, outName );
00804          fprintf ( stderr, 
00805                    "%s:    I suggest doing an integrity test (bzip2 -tv)"
00806                    " of it.\n",
00807                    progName );
00808       }
00809    }
00810 
00811    if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
00812       fprintf ( stderr, 
00813                 "%s: WARNING: some files have not been processed:\n"
00814                 "%s:    %d specified on command line, %d not processed yet.\n\n",
00815                 progName, progName,
00816                 numFileNames, numFileNames - numFilesProcessed );
00817    }
00818    setExit(ec);
00819    exit(exitValue);
00820 }
00821 
00822 
00823 /*---------------------------------------------*/
00824 static 
00825 void panic ( Char* s )
00826 {
00827    fprintf ( stderr,
00828              "\n%s: PANIC -- internal consistency error:\n"
00829              "\t%s\n"
00830              "\tThis is a BUG.  Please report it to me at:\n"
00831              "\tjseward@acm.org\n",
00832              progName, s );
00833    showFileNames();
00834    cleanUpAndFail( 3 );
00835 }
00836 
00837 
00838 /*---------------------------------------------*/
00839 static 
00840 void crcError ( void )
00841 {
00842    fprintf ( stderr,
00843              "\n%s: Data integrity error when decompressing.\n",
00844              progName );
00845    showFileNames();
00846    cadvise();
00847    cleanUpAndFail( 2 );
00848 }
00849 
00850 
00851 /*---------------------------------------------*/
00852 static 
00853 void compressedStreamEOF ( void )
00854 {
00855   if (noisy) {
00856     fprintf ( stderr,
00857           "\n%s: Compressed file ends unexpectedly;\n\t"
00858           "perhaps it is corrupted?  *Possible* reason follows.\n",
00859           progName );
00860     perror ( progName );
00861     showFileNames();
00862     cadvise();
00863   }
00864   cleanUpAndFail( 2 );
00865 }
00866 
00867 
00868 /*---------------------------------------------*/
00869 static 
00870 void ioError ( void )
00871 {
00872    fprintf ( stderr,
00873              "\n%s: I/O or other error, bailing out.  "
00874              "Possible reason follows.\n",
00875              progName );
00876    perror ( progName );
00877    showFileNames();
00878    cleanUpAndFail( 1 );
00879 }
00880 
00881 
00882 /*---------------------------------------------*/
00883 static 
00884 void mySignalCatcher ( IntNative n )
00885 {
00886    fprintf ( stderr,
00887              "\n%s: Control-C or similar caught, quitting.\n",
00888              progName );
00889    cleanUpAndFail(1);
00890 }
00891 
00892 
00893 /*---------------------------------------------*/
00894 static 
00895 void mySIGSEGVorSIGBUScatcher ( IntNative n )
00896 {
00897    if (opMode == OM_Z)
00898       fprintf ( 
00899       stderr,
00900       "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
00901       "\n"
00902       "   Possible causes are (most likely first):\n"
00903       "   (1) This computer has unreliable memory or cache hardware\n"
00904       "       (a surprisingly common problem; try a different machine.)\n"
00905       "   (2) A bug in the compiler used to create this executable\n"
00906       "       (unlikely, if you didn't compile bzip2 yourself.)\n"
00907       "   (3) A real bug in bzip2 -- I hope this should never be the case.\n"
00908       "   The user's manual, Section 4.3, has more info on (1) and (2).\n"
00909       "   \n"
00910       "   If you suspect this is a bug in bzip2, or are unsure about (1)\n"
00911       "   or (2), feel free to report it to me at: jseward@acm.org.\n"
00912       "   Section 4.3 of the user's manual describes the info a useful\n"
00913       "   bug report should have.  If the manual is available on your\n"
00914       "   system, please try and read it before mailing me.  If you don't\n"
00915       "   have the manual or can't be bothered to read it, mail me anyway.\n"
00916       "\n",
00917       progName );
00918       else
00919       fprintf ( 
00920       stderr,
00921       "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
00922       "\n"
00923       "   Possible causes are (most likely first):\n"
00924       "   (1) The compressed data is corrupted, and bzip2's usual checks\n"
00925       "       failed to detect this.  Try bzip2 -tvv my_file.bz2.\n"
00926       "   (2) This computer has unreliable memory or cache hardware\n"
00927       "       (a surprisingly common problem; try a different machine.)\n"
00928       "   (3) A bug in the compiler used to create this executable\n"
00929       "       (unlikely, if you didn't compile bzip2 yourself.)\n"
00930       "   (4) A real bug in bzip2 -- I hope this should never be the case.\n"
00931       "   The user's manual, Section 4.3, has more info on (2) and (3).\n"
00932       "   \n"
00933       "   If you suspect this is a bug in bzip2, or are unsure about (2)\n"
00934       "   or (3), feel free to report it to me at: jseward@acm.org.\n"
00935       "   Section 4.3 of the user's manual describes the info a useful\n"
00936       "   bug report should have.  If the manual is available on your\n"
00937       "   system, please try and read it before mailing me.  If you don't\n"
00938       "   have the manual or can't be bothered to read it, mail me anyway.\n"
00939       "\n",
00940       progName );
00941 
00942    showFileNames();
00943    if (opMode == OM_Z)
00944       cleanUpAndFail( 3 ); else
00945       { cadvise(); cleanUpAndFail( 2 ); }
00946 }
00947 
00948 
00949 /*---------------------------------------------*/
00950 static 
00951 void outOfMemory ( void )
00952 {
00953    fprintf ( stderr,
00954              "\n%s: couldn't allocate enough memory\n",
00955              progName );
00956    showFileNames();
00957    cleanUpAndFail(1);
00958 }
00959 
00960 
00961 /*---------------------------------------------*/
00962 static 
00963 void configError ( void )
00964 {
00965    fprintf ( stderr,
00966              "bzip2: I'm not configured correctly for this platform!\n"
00967              "\tI require Int32, Int16 and Char to have sizes\n"
00968              "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
00969              "\tProbably you can fix this by defining them correctly,\n"
00970              "\tand recompiling.  Bye!\n" );
00971    setExit(3);
00972    exit(exitValue);
00973 }
00974 
00975 
00976 /*---------------------------------------------------*/
00977 /*--- The main driver machinery                   ---*/
00978 /*---------------------------------------------------*/
00979 
00980 /* All rather crufty.  The main problem is that input files
00981    are stat()d multiple times before use.  This should be
00982    cleaned up. 
00983 */
00984 
00985 /*---------------------------------------------*/
00986 static 
00987 void pad ( Char *s )
00988 {
00989    Int32 i;
00990    if ( (Int32)strlen(s) >= longestFileName ) return;
00991    for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
00992       fprintf ( stderr, " " );
00993 }
00994 
00995 
00996 /*---------------------------------------------*/
00997 static 
00998 void copyFileName ( Char* to, Char* from ) 
00999 {
01000    if ( strlen(from) > FILE_NAME_LEN-10 )  {
01001       fprintf (
01002          stderr,
01003          "bzip2: file name\n`%s'\n"
01004          "is suspiciously (more than %d chars) long.\n"
01005          "Try using a reasonable file name instead.  Sorry! :-)\n",
01006          from, FILE_NAME_LEN-10
01007       );
01008       setExit(1);
01009       exit(exitValue);
01010    }
01011 
01012   strncpy(to,from,FILE_NAME_LEN-10);
01013   to[FILE_NAME_LEN-10]='\0';
01014 }
01015 
01016 
01017 /*---------------------------------------------*/
01018 static 
01019 Bool fileExists ( Char* name )
01020 {
01021    FILE *tmp   = fopen ( name, "rb" );
01022    Bool exists = (tmp != NULL);
01023    if (tmp != NULL) fclose ( tmp );
01024    return exists;
01025 }
01026 
01027 
01028 /*---------------------------------------------*/
01029 /* Open an output file safely with O_EXCL and good permissions.
01030    This avoids a race condition in versions < 1.0.2, in which
01031    the file was first opened and then had its interim permissions
01032    set safely.  We instead use open() to create the file with
01033    the interim permissions required. (--- --- rw-).
01034 
01035    For non-Unix platforms, if we are not worrying about
01036    security issues, simple this simply behaves like fopen.
01037 */
01038 FILE* fopen_output_safely ( Char* name, const char* mode )
01039 {
01040 #  if BZ_UNIX
01041    FILE*     fp;
01042    IntNative fh;
01043    fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
01044    if (fh == -1) return NULL;
01045    fp = fdopen(fh, mode);
01046    if (fp == NULL) close(fh);
01047    return fp;
01048 #  else
01049    return fopen(name, mode);
01050 #  endif
01051 }
01052 
01053 
01054 /*---------------------------------------------*/
01055 /*--
01056   if in doubt, return True
01057 --*/
01058 static 
01059 Bool notAStandardFile ( Char* name )
01060 {
01061    IntNative      i;
01062    struct MY_STAT statBuf;
01063 
01064    i = MY_LSTAT ( name, &statBuf );
01065    if (i != 0) return True;
01066    if (MY_S_ISREG(statBuf.st_mode)) return False;
01067    return True;
01068 }
01069 
01070 
01071 /*---------------------------------------------*/
01072 /*--
01073   rac 11/21/98 see if file has hard links to it
01074 --*/
01075 static 
01076 Int32 countHardLinks ( Char* name )
01077 {  
01078    IntNative      i;
01079    struct MY_STAT statBuf;
01080 
01081    i = MY_LSTAT ( name, &statBuf );
01082    if (i != 0) return 0;
01083    return (statBuf.st_nlink - 1);
01084 }
01085 
01086 
01087 /*---------------------------------------------*/
01088 /* Copy modification date, access date, permissions and owner from the
01089    source to destination file.  We have to copy this meta-info off
01090    into fileMetaInfo before starting to compress / decompress it,
01091    because doing it afterwards means we get the wrong access time.
01092 
01093    To complicate matters, in compress() and decompress() below, the
01094    sequence of tests preceding the call to saveInputFileMetaInfo()
01095    involves calling fileExists(), which in turn establishes its result
01096    by attempting to fopen() the file, and if successful, immediately
01097    fclose()ing it again.  So we have to assume that the fopen() call
01098    does not cause the access time field to be updated.
01099 
01100    Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
01101    to imply that merely doing open() will not affect the access time.
01102    Therefore we merely need to hope that the C library only does
01103    open() as a result of fopen(), and not any kind of read()-ahead
01104    cleverness.
01105 
01106    It sounds pretty fragile to me.  Whether this carries across
01107    robustly to arbitrary Unix-like platforms (or even works robustly
01108    on this one, RedHat 7.2) is unknown to me.  Nevertheless ...  
01109 */
01110 #if BZ_UNIX
01111 static 
01112 struct MY_STAT fileMetaInfo;
01113 #endif
01114 
01115 static 
01116 void saveInputFileMetaInfo ( Char *srcName )
01117 {
01118 #  if BZ_UNIX
01119    IntNative retVal;
01120    /* Note use of stat here, not lstat. */
01121    retVal = MY_STAT( srcName, &fileMetaInfo );
01122    ERROR_IF_NOT_ZERO ( retVal );
01123 #  endif
01124 }
01125 
01126 
01127 static 
01128 void applySavedMetaInfoToOutputFile ( Char *dstName )
01129 {
01130 #  if BZ_UNIX
01131    IntNative      retVal;
01132    struct utimbuf uTimBuf;
01133 
01134    uTimBuf.actime = fileMetaInfo.st_atime;
01135    uTimBuf.modtime = fileMetaInfo.st_mtime;
01136 
01137    retVal = chmod ( dstName, fileMetaInfo.st_mode );
01138    ERROR_IF_NOT_ZERO ( retVal );
01139 
01140    retVal = utime ( dstName, &uTimBuf );
01141    ERROR_IF_NOT_ZERO ( retVal );
01142 
01143    retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
01144    /* chown() will in many cases return with EPERM, which can
01145       be safely ignored.
01146    */
01147 #  endif
01148 }
01149 
01150 
01151 /*---------------------------------------------*/
01152 static 
01153 Bool containsDubiousChars ( Char* name )
01154 {
01155 #  if BZ_UNIX
01156    /* On unix, files can contain any characters and the file expansion
01157     * is performed by the shell.
01158     */
01159    return False;
01160 #  else /* ! BZ_UNIX */
01161    /* On non-unix (Win* platforms), wildcard characters are not allowed in 
01162     * filenames.
01163     */
01164    for (; *name != '\0'; name++)
01165       if (*name == '?' || *name == '*') return True;
01166    return False;
01167 #  endif /* BZ_UNIX */
01168 }
01169 
01170 
01171 /*---------------------------------------------*/
01172 #define BZ_N_SUFFIX_PAIRS 4
01173 
01174 Char* zSuffix[BZ_N_SUFFIX_PAIRS] 
01175    = { ".bz2", ".bz", ".tbz2", ".tbz" };
01176 Char* unzSuffix[BZ_N_SUFFIX_PAIRS] 
01177    = { "", "", ".tar", ".tar" };
01178 
01179 static 
01180 Bool hasSuffix ( Char* s, Char* suffix )
01181 {
01182    Int32 ns = strlen(s);
01183    Int32 nx = strlen(suffix);
01184    if (ns < nx) return False;
01185    if (strcmp(s + ns - nx, suffix) == 0) return True;
01186    return False;
01187 }
01188 
01189 static 
01190 Bool mapSuffix ( Char* name, 
01191                  Char* oldSuffix, Char* newSuffix )
01192 {
01193    if (!hasSuffix(name,oldSuffix)) return False;
01194    name[strlen(name)-strlen(oldSuffix)] = 0;
01195    strcat ( name, newSuffix );
01196    return True;
01197 }
01198 
01199 
01200 /*---------------------------------------------*/
01201 static 
01202 void compress ( Char *name )
01203 {
01204    FILE  *inStr;
01205    FILE  *outStr;
01206    Int32 n, i;
01207    struct MY_STAT statBuf;
01208 
01209    deleteOutputOnInterrupt = False;
01210 
01211    if (name == NULL && srcMode != SM_I2O)
01212       panic ( "compress: bad modes\n" );
01213 
01214    switch (srcMode) {
01215       case SM_I2O: 
01216          copyFileName ( inName, "(stdin)" );
01217          copyFileName ( outName, "(stdout)" ); 
01218          break;
01219       case SM_F2F: 
01220          copyFileName ( inName, name );
01221          copyFileName ( outName, name );
01222          strcat ( outName, ".bz2" ); 
01223          break;
01224       case SM_F2O: 
01225          copyFileName ( inName, name );
01226          copyFileName ( outName, "(stdout)" ); 
01227          break;
01228    }
01229 
01230    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
01231       if (noisy)
01232       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
01233                 progName, inName );
01234       setExit(1);
01235       return;
01236    }
01237    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
01238       fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
01239                 progName, inName, strerror(errno) );
01240       setExit(1);
01241       return;
01242    }
01243    for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
01244       if (hasSuffix(inName, zSuffix[i])) {
01245          if (noisy)
01246          fprintf ( stderr, 
01247                    "%s: Input file %s already has %s suffix.\n",
01248                    progName, inName, zSuffix[i] );
01249          setExit(1);
01250          return;
01251       }
01252    }
01253    if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
01254       MY_STAT(inName, &statBuf);
01255       if ( MY_S_ISDIR(statBuf.st_mode) ) {
01256          fprintf( stderr,
01257                   "%s: Input file %s is a directory.\n",
01258                   progName,inName);
01259          setExit(1);
01260          return;
01261       }
01262    }
01263    if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
01264       if (noisy)
01265       fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
01266                 progName, inName );
01267       setExit(1);
01268       return;
01269    }
01270    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
01271       if (forceOverwrite) {
01272      remove(outName);
01273       } else {
01274      fprintf ( stderr, "%s: Output file %s already exists.\n",
01275            progName, outName );
01276      setExit(1);
01277      return;
01278       }
01279    }
01280    if ( srcMode == SM_F2F && !forceOverwrite &&
01281         (n=countHardLinks ( inName )) > 0) {
01282       fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
01283                 progName, inName, n, n > 1 ? "s" : "" );
01284       setExit(1);
01285       return;
01286    }
01287 
01288    if ( srcMode == SM_F2F ) {
01289       /* Save the file's meta-info before we open it.  Doing it later
01290          means we mess up the access times. */
01291       saveInputFileMetaInfo ( inName );
01292    }
01293 
01294    switch ( srcMode ) {
01295 
01296       case SM_I2O:
01297          inStr = stdin;
01298          outStr = stdout;
01299          if ( isatty ( fileno ( stdout ) ) ) {
01300             fprintf ( stderr,
01301                       "%s: I won't write compressed data to a terminal.\n",
01302                       progName );
01303             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
01304                               progName, progName );
01305             setExit(1);
01306             return;
01307          };
01308          break;
01309 
01310       case SM_F2O:
01311          inStr = fopen ( inName, "rb" );
01312          outStr = stdout;
01313          if ( isatty ( fileno ( stdout ) ) ) {
01314             fprintf ( stderr,
01315                       "%s: I won't write compressed data to a terminal.\n",
01316                       progName );
01317             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
01318                               progName, progName );
01319             if ( inStr != NULL ) fclose ( inStr );
01320             setExit(1);
01321             return;
01322          };
01323          if ( inStr == NULL ) {
01324             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
01325                       progName, inName, strerror(errno) );
01326             setExit(1);
01327             return;
01328          };
01329          break;
01330 
01331       case SM_F2F:
01332          inStr = fopen ( inName, "rb" );
01333          outStr = fopen_output_safely ( outName, "wb" );
01334          if ( outStr == NULL) {
01335             fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
01336                       progName, outName, strerror(errno) );
01337             if ( inStr != NULL ) fclose ( inStr );
01338             setExit(1);
01339             return;
01340          }
01341          if ( inStr == NULL ) {
01342             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
01343                       progName, inName, strerror(errno) );
01344             if ( outStr != NULL ) fclose ( outStr );
01345             setExit(1);
01346             return;
01347          };
01348          break;
01349 
01350       default:
01351          panic ( "compress: bad srcMode" );
01352          break;
01353    }
01354 
01355    if (verbosity >= 1) {
01356       fprintf ( stderr,  "  %s: ", inName );
01357       pad ( inName );
01358       fflush ( stderr );
01359    }
01360 
01361    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
01362    outputHandleJustInCase = outStr;
01363    deleteOutputOnInterrupt = True;
01364    compressStream ( inStr, outStr );
01365    outputHandleJustInCase = NULL;
01366 
01367    /*--- If there was an I/O error, we won't get here. ---*/
01368    if ( srcMode == SM_F2F ) {
01369       applySavedMetaInfoToOutputFile ( outName );
01370       deleteOutputOnInterrupt = False;
01371       if ( !keepInputFiles ) {
01372          IntNative retVal = remove ( inName );
01373          ERROR_IF_NOT_ZERO ( retVal );
01374       }
01375    }
01376 
01377    deleteOutputOnInterrupt = False;
01378 }
01379 
01380 
01381 /*---------------------------------------------*/
01382 static 
01383 void uncompress ( Char *name )
01384 {
01385    FILE  *inStr;
01386    FILE  *outStr;
01387    Int32 n, i;
01388    Bool  magicNumberOK;
01389    Bool  cantGuess;
01390    struct MY_STAT statBuf;
01391 
01392    deleteOutputOnInterrupt = False;
01393 
01394    if (name == NULL && srcMode != SM_I2O)
01395       panic ( "uncompress: bad modes\n" );
01396 
01397    cantGuess = False;
01398    switch (srcMode) {
01399       case SM_I2O: 
01400          copyFileName ( inName, "(stdin)" );
01401          copyFileName ( outName, "(stdout)" ); 
01402          break;
01403       case SM_F2F: 
01404          copyFileName ( inName, name );
01405          copyFileName ( outName, name );
01406          for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
01407             if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
01408                goto zzz; 
01409          cantGuess = True;
01410          strcat ( outName, ".out" );
01411          break;
01412       case SM_F2O: 
01413          copyFileName ( inName, name );
01414          copyFileName ( outName, "(stdout)" ); 
01415          break;
01416    }
01417 
01418    zzz:
01419    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
01420       if (noisy)
01421       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
01422                 progName, inName );
01423       setExit(1);
01424       return;
01425    }
01426    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
01427       fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
01428                 progName, inName, strerror(errno) );
01429       setExit(1);
01430       return;
01431    }
01432    if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
01433       MY_STAT(inName, &statBuf);
01434       if ( MY_S_ISDIR(statBuf.st_mode) ) {
01435          fprintf( stderr,
01436                   "%s: Input file %s is a directory.\n",
01437                   progName,inName);
01438          setExit(1);
01439          return;
01440       }
01441    }
01442    if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
01443       if (noisy)
01444       fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
01445                 progName, inName );
01446       setExit(1);
01447       return;
01448    }
01449    if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
01450       if (noisy)
01451       fprintf ( stderr, 
01452                 "%s: Can't guess original name for %s -- using %s\n",
01453                 progName, inName, outName );
01454       /* just a warning, no return */
01455    }   
01456    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
01457       if (forceOverwrite) {
01458     remove(outName);
01459       } else {
01460         fprintf ( stderr, "%s: Output file %s already exists.\n",
01461                   progName, outName );
01462         setExit(1);
01463         return;
01464       }
01465    }
01466    if ( srcMode == SM_F2F && !forceOverwrite &&
01467         (n=countHardLinks ( inName ) ) > 0) {
01468       fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
01469                 progName, inName, n, n > 1 ? "s" : "" );
01470       setExit(1);
01471       return;
01472    }
01473 
01474    if ( srcMode == SM_F2F ) {
01475       /* Save the file's meta-info before we open it.  Doing it later
01476          means we mess up the access times. */
01477       saveInputFileMetaInfo ( inName );
01478    }
01479 
01480    switch ( srcMode ) {
01481 
01482       case SM_I2O:
01483          inStr = stdin;
01484          outStr = stdout;
01485          if ( isatty ( fileno ( stdin ) ) ) {
01486             fprintf ( stderr,
01487                       "%s: I won't read compressed data from a terminal.\n",
01488                       progName );
01489             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
01490                               progName, progName );
01491             setExit(1);
01492             return;
01493          };
01494          break;
01495 
01496       case SM_F2O:
01497          inStr = fopen ( inName, "rb" );
01498          outStr = stdout;
01499          if ( inStr == NULL ) {
01500             fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
01501                       progName, inName, strerror(errno) );
01502             if ( inStr != NULL ) fclose ( inStr );
01503             setExit(1);
01504             return;
01505          };
01506          break;
01507 
01508       case SM_F2F:
01509          inStr = fopen ( inName, "rb" );
01510          outStr = fopen_output_safely ( outName, "wb" );
01511          if ( outStr == NULL) {
01512             fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
01513                       progName, outName, strerror(errno) );
01514             if ( inStr != NULL ) fclose ( inStr );
01515             setExit(1);
01516             return;
01517          }
01518          if ( inStr == NULL ) {
01519             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
01520                       progName, inName, strerror(errno) );
01521             if ( outStr != NULL ) fclose ( outStr );
01522             setExit(1);
01523             return;
01524          };
01525          break;
01526 
01527       default:
01528          panic ( "uncompress: bad srcMode" );
01529          break;
01530    }
01531 
01532    if (verbosity >= 1) {
01533       fprintf ( stderr, "  %s: ", inName );
01534       pad ( inName );
01535       fflush ( stderr );
01536    }
01537 
01538    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
01539    outputHandleJustInCase = outStr;
01540    deleteOutputOnInterrupt = True;
01541    magicNumberOK = uncompressStream ( inStr, outStr );
01542    outputHandleJustInCase = NULL;
01543 
01544    /*--- If there was an I/O error, we won't get here. ---*/
01545    if ( magicNumberOK ) {
01546       if ( srcMode == SM_F2F ) {
01547          applySavedMetaInfoToOutputFile ( outName );
01548          deleteOutputOnInterrupt = False;
01549          if ( !keepInputFiles ) {
01550             IntNative retVal = remove ( inName );
01551             ERROR_IF_NOT_ZERO ( retVal );
01552          }
01553       }
01554    } else {
01555       unzFailsExist = True;
01556       deleteOutputOnInterrupt = False;
01557       if ( srcMode == SM_F2F ) {
01558          IntNative retVal = remove ( outName );
01559          ERROR_IF_NOT_ZERO ( retVal );
01560       }
01561    }
01562    deleteOutputOnInterrupt = False;
01563 
01564    if ( magicNumberOK ) {
01565       if (verbosity >= 1)
01566          fprintf ( stderr, "done\n" );
01567    } else {
01568       setExit(2);
01569       if (verbosity >= 1)
01570          fprintf ( stderr, "not a bzip2 file.\n" ); else
01571          fprintf ( stderr,
01572                    "%s: %s is not a bzip2 file.\n",
01573                    progName, inName );
01574    }
01575 
01576 }
01577 
01578 
01579 /*---------------------------------------------*/
01580 static 
01581 void testf ( Char *name )
01582 {
01583    FILE *inStr;
01584    Bool allOK;
01585    struct MY_STAT statBuf;
01586 
01587    deleteOutputOnInterrupt = False;
01588 
01589    if (name == NULL && srcMode != SM_I2O)
01590       panic ( "testf: bad modes\n" );
01591 
01592    copyFileName ( outName, "(none)" );
01593    switch (srcMode) {
01594       case SM_I2O: copyFileName ( inName, "(stdin)" ); break;
01595       case SM_F2F: copyFileName ( inName, name ); break;
01596       case SM_F2O: copyFileName ( inName, name ); break;
01597    }
01598 
01599    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
01600       if (noisy)
01601       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
01602                 progName, inName );
01603       setExit(1);
01604       return;
01605    }
01606    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
01607       fprintf ( stderr, "%s: Can't open input %s: %s.\n",
01608                 progName, inName, strerror(errno) );
01609       setExit(1);
01610       return;
01611    }
01612    if ( srcMode != SM_I2O ) {
01613       MY_STAT(inName, &statBuf);
01614       if ( MY_S_ISDIR(statBuf.st_mode) ) {
01615          fprintf( stderr,
01616                   "%s: Input file %s is a directory.\n",
01617                   progName,inName);
01618          setExit(1);
01619          return;
01620       }
01621    }
01622 
01623    switch ( srcMode ) {
01624 
01625       case SM_I2O:
01626          if ( isatty ( fileno ( stdin ) ) ) {
01627             fprintf ( stderr,
01628                       "%s: I won't read compressed data from a terminal.\n",
01629                       progName );
01630             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
01631                               progName, progName );
01632             setExit(1);
01633             return;
01634          };
01635          inStr = stdin;
01636          break;
01637 
01638       case SM_F2O: case SM_F2F:
01639          inStr = fopen ( inName, "rb" );
01640          if ( inStr == NULL ) {
01641             fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
01642                       progName, inName, strerror(errno) );
01643             setExit(1);
01644             return;
01645          };
01646          break;
01647 
01648       default:
01649          panic ( "testf: bad srcMode" );
01650          break;
01651    }
01652 
01653    if (verbosity >= 1) {
01654       fprintf ( stderr, "  %s: ", inName );
01655       pad ( inName );
01656       fflush ( stderr );
01657    }
01658 
01659    /*--- Now the input handle is sane.  Do the Biz. ---*/
01660    outputHandleJustInCase = NULL;
01661    allOK = testStream ( inStr );
01662 
01663    if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
01664    if (!allOK) testFailsExist = True;
01665 }
01666 
01667 
01668 /*---------------------------------------------*/
01669 static 
01670 void license ( void )
01671 {
01672    fprintf ( stderr,
01673 
01674     "bzip2, a block-sorting file compressor.  "
01675     "Version %s.\n"
01676     "   \n"
01677     "   Copyright (C) 1996-2002 by Julian Seward.\n"
01678     "   \n"
01679     "   This program is free software; you can redistribute it and/or modify\n"
01680     "   it under the terms set out in the LICENSE file, which is included\n"
01681     "   in the bzip2-1.0 source distribution.\n"
01682     "   \n"
01683     "   This program is distributed in the hope that it will be useful,\n"
01684     "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
01685     "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
01686     "   LICENSE file for more details.\n"
01687     "   \n",
01688     BZ2_bzlibVersion()
01689    );
01690 }
01691 
01692 
01693 /*---------------------------------------------*/
01694 static 
01695 void usage ( Char *fullProgName )
01696 {
01697    fprintf (
01698       stderr,
01699       "bzip2, a block-sorting file compressor.  "
01700       "Version %s.\n"
01701       "\n   usage: %s [flags and input files in any order]\n"
01702       "\n"
01703       "   -h --help           print this message\n"
01704       "   -d --decompress     force decompression\n"
01705       "   -z --compress       force compression\n"
01706       "   -k --keep           keep (don't delete) input files\n"
01707       "   -f --force          overwrite existing output files\n"
01708       "   -t --test           test compressed file integrity\n"
01709       "   -c --stdout         output to standard out\n"
01710       "   -q --quiet          suppress noncritical error messages\n"
01711       "   -v --verbose        be verbose (a 2nd -v gives more)\n"
01712       "   -L --license        display software version & license\n"
01713       "   -V --version        display software version & license\n"
01714       "   -s --small          use less memory (at most 2500k)\n"
01715       "   -1 .. -9            set block size to 100k .. 900k\n"
01716       "   --fast              alias for -1\n"
01717       "   --best              alias for -9\n"
01718       "\n"
01719       "   If invoked as `bzip2', default action is to compress.\n"
01720       "              as `bunzip2',  default action is to decompress.\n"
01721       "              as `bzcat', default action is to decompress to stdout.\n"
01722       "\n"
01723       "   If no file names are given, bzip2 compresses or decompresses\n"
01724       "   from standard input to standard output.  You can combine\n"
01725       "   short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
01726 #     if BZ_UNIX
01727       "\n"
01728 #     endif
01729       ,
01730 
01731       BZ2_bzlibVersion(),
01732       fullProgName
01733    );
01734 }
01735 
01736 
01737 /*---------------------------------------------*/
01738 static 
01739 void redundant ( Char* flag )
01740 {
01741    fprintf ( 
01742       stderr, 
01743       "%s: %s is redundant in versions 0.9.5 and above\n",
01744       progName, flag );
01745 }
01746 
01747 
01748 /*---------------------------------------------*/
01749 /*--
01750   All the garbage from here to main() is purely to
01751   implement a linked list of command-line arguments,
01752   into which main() copies argv[1 .. argc-1].
01753 
01754   The purpose of this exercise is to facilitate 
01755   the expansion of wildcard characters * and ? in 
01756   filenames for OSs which don't know how to do it
01757   themselves, like MSDOS, Windows 95 and NT.
01758 
01759   The actual Dirty Work is done by the platform-
01760   specific macro APPEND_FILESPEC.
01761 --*/
01762 
01763 typedef
01764    struct zzzz {
01765       Char        *name;
01766       struct zzzz *link;
01767    }
01768    Cell;
01769 
01770 
01771 /*---------------------------------------------*/
01772 static 
01773 void *myMalloc ( Int32 n )
01774 {
01775    void* p;
01776 
01777    p = malloc ( (size_t)n );
01778    if (p == NULL) outOfMemory ();
01779    return p;
01780 }
01781 
01782 
01783 /*---------------------------------------------*/
01784 static 
01785 Cell *mkCell ( void )
01786 {
01787    Cell *c;
01788 
01789    c = (Cell*) myMalloc ( sizeof ( Cell ) );
01790    c->name = NULL;
01791    c->link = NULL;
01792    return c;
01793 }
01794 
01795 
01796 /*---------------------------------------------*/
01797 static 
01798 Cell *snocString ( Cell *root, Char *name )
01799 {
01800    if (root == NULL) {
01801       Cell *tmp = mkCell();
01802       tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
01803       strcpy ( tmp->name, name );
01804       return tmp;
01805    } else {
01806       Cell *tmp = root;
01807       while (tmp->link != NULL) tmp = tmp->link;
01808       tmp->link = snocString ( tmp->link, name );
01809       return root;
01810    }
01811 }
01812 
01813 
01814 /*---------------------------------------------*/
01815 static 
01816 void addFlagsFromEnvVar ( Cell** argList, Char* varName ) 
01817 {
01818    Int32 i, j, k;
01819    Char *envbase, *p;
01820 
01821    envbase = getenv(varName);
01822    if (envbase != NULL) {
01823       p = envbase;
01824       i = 0;
01825       while (True) {
01826          if (p[i] == 0) break;
01827          p += i;
01828          i = 0;
01829          while (isspace((Int32)(p[0]))) p++;
01830          while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
01831          if (i > 0) {
01832             k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
01833             for (j = 0; j < k; j++) tmpName[j] = p[j];
01834             tmpName[k] = 0;
01835             APPEND_FLAG(*argList, tmpName);
01836          }
01837       }
01838    }
01839 }
01840 
01841 
01842 /*---------------------------------------------*/
01843 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
01844 
01845 IntNative main ( IntNative argc, Char *argv[] )
01846 {
01847    Int32  i, j;
01848    Char   *tmp;
01849    Cell   *argList;
01850    Cell   *aa;
01851    Bool   decode;
01852 
01853    /*-- Be really really really paranoid :-) --*/
01854    if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
01855        sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
01856        sizeof(Char)  != 1 || sizeof(UChar)  != 1)
01857       configError();
01858 
01859    /*-- Initialise --*/
01860    outputHandleJustInCase  = NULL;
01861    smallMode               = False;
01862    keepInputFiles          = False;
01863    forceOverwrite          = False;
01864    noisy                   = True;
01865    verbosity               = 0;
01866    blockSize100k           = 9;
01867    testFailsExist          = False;
01868    unzFailsExist           = False;
01869    numFileNames            = 0;
01870    numFilesProcessed       = 0;
01871    workFactor              = 30;
01872    deleteOutputOnInterrupt = False;
01873    exitValue               = 0;
01874    i = j = 0; /* avoid bogus warning from egcs-1.1.X */
01875 
01876    /*-- Set up signal handlers for mem access errors --*/
01877    signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
01878 #  if BZ_UNIX
01879 #  ifndef __DJGPP__
01880    signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
01881 #  endif
01882 #  endif
01883 
01884    copyFileName ( inName,  "(none)" );
01885    copyFileName ( outName, "(none)" );
01886 
01887    copyFileName ( progNameReally, argv[0] );
01888    progName = &progNameReally[0];
01889    for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
01890       if (*tmp == PATH_SEP) progName = tmp + 1;
01891 
01892 
01893    /*-- Copy flags from env var BZIP2, and 
01894         expand filename wildcards in arg list.
01895    --*/
01896    argList = NULL;
01897    addFlagsFromEnvVar ( &argList,  "BZIP2" );
01898    addFlagsFromEnvVar ( &argList,  "BZIP" );
01899    for (i = 1; i <= argc-1; i++)
01900       APPEND_FILESPEC(argList, argv[i]);
01901 
01902 
01903    /*-- Find the length of the longest filename --*/
01904    longestFileName = 7;
01905    numFileNames    = 0;
01906    decode          = True;
01907    for (aa = argList; aa != NULL; aa = aa->link) {
01908       if (ISFLAG("--")) { decode = False; continue; }
01909       if (aa->name[0] == '-' && decode) continue;
01910       numFileNames++;
01911       if (longestFileName < (Int32)strlen(aa->name) )
01912          longestFileName = (Int32)strlen(aa->name);
01913    }
01914 
01915 
01916    /*-- Determine source modes; flag handling may change this too. --*/
01917    if (numFileNames == 0)
01918       srcMode = SM_I2O; else srcMode = SM_F2F;
01919 
01920 
01921    /*-- Determine what to do (compress/uncompress/test/cat). --*/
01922    /*-- Note that subsequent flag handling may change this. --*/
01923    opMode = OM_Z;
01924 
01925    if ( (strstr ( progName, "unzip" ) != 0) ||
01926         (strstr ( progName, "UNZIP" ) != 0) )
01927       opMode = OM_UNZ;
01928 
01929    if ( (strstr ( progName, "z2cat" ) != 0) ||
01930         (strstr ( progName, "Z2CAT" ) != 0) ||
01931         (strstr ( progName, "zcat" ) != 0)  ||
01932         (strstr ( progName, "ZCAT" ) != 0) )  {
01933       opMode = OM_UNZ;
01934       srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
01935    }
01936 
01937 
01938    /*-- Look at the flags. --*/
01939    for (aa = argList; aa != NULL; aa = aa->link) {
01940       if (ISFLAG("--")) break;
01941       if (aa->name[0] == '-' && aa->name[1] != '-') {
01942          for (j = 1; aa->name[j] != '\0'; j++) {
01943             switch (aa->name[j]) {
01944                case 'c': srcMode          = SM_F2O; break;
01945                case 'd': opMode           = OM_UNZ; break;
01946                case 'z': opMode           = OM_Z; break;
01947                case 'f': forceOverwrite   = True; break;
01948                case 't': opMode           = OM_TEST; break;
01949                case 'k': keepInputFiles   = True; break;
01950                case 's': smallMode        = True; break;
01951                case 'q': noisy            = False; break;
01952                case '1': blockSize100k    = 1; break;
01953                case '2': blockSize100k    = 2; break;
01954                case '3': blockSize100k    = 3; break;
01955                case '4': blockSize100k    = 4; break;
01956                case '5': blockSize100k    = 5; break;
01957                case '6': blockSize100k    = 6; break;
01958                case '7': blockSize100k    = 7; break;
01959                case '8': blockSize100k    = 8; break;
01960                case '9': blockSize100k    = 9; break;
01961                case 'V':
01962                case 'L': license();            break;
01963                case 'v': verbosity++; break;
01964                case 'h': usage ( progName );
01965                          exit ( 0 );
01966                          break;
01967                default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
01968                                    progName, aa->name );
01969                          usage ( progName );
01970                          exit ( 1 );
01971                          break;
01972             }
01973          }
01974       }
01975    }
01976    
01977    /*-- And again ... --*/
01978    for (aa = argList; aa != NULL; aa = aa->link) {
01979       if (ISFLAG("--")) break;
01980       if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
01981       if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
01982       if (ISFLAG("--compress"))          opMode           = OM_Z;    else
01983       if (ISFLAG("--force"))             forceOverwrite   = True;    else
01984       if (ISFLAG("--test"))              opMode           = OM_TEST; else
01985       if (ISFLAG("--keep"))              keepInputFiles   = True;    else
01986       if (ISFLAG("--small"))             smallMode        = True;    else
01987       if (ISFLAG("--quiet"))             noisy            = False;   else
01988       if (ISFLAG("--version"))           license();                  else
01989       if (ISFLAG("--license"))           license();                  else
01990       if (ISFLAG("--exponential"))       workFactor = 1;             else 
01991       if (ISFLAG("--repetitive-best"))   redundant(aa->name);        else
01992       if (ISFLAG("--repetitive-fast"))   redundant(aa->name);        else
01993       if (ISFLAG("--fast"))              blockSize100k = 1;          else
01994       if (ISFLAG("--best"))              blockSize100k = 9;          else
01995       if (ISFLAG("--verbose"))           verbosity++;                else
01996       if (ISFLAG("--help"))              { usage ( progName ); exit ( 0 ); }
01997          else
01998          if (strncmp ( aa->name, "--", 2) == 0) {
01999             fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
02000             usage ( progName );
02001             exit ( 1 );
02002          }
02003    }
02004 
02005    if (verbosity > 4) verbosity = 4;
02006    if (opMode == OM_Z && smallMode && blockSize100k > 2) 
02007       blockSize100k = 2;
02008 
02009    if (opMode == OM_TEST && srcMode == SM_F2O) {
02010       fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
02011                 progName );
02012       exit ( 1 );
02013    }
02014 
02015    if (srcMode == SM_F2O && numFileNames == 0)
02016       srcMode = SM_I2O;
02017 
02018    if (opMode != OM_Z) blockSize100k = 0;
02019 
02020    if (srcMode == SM_F2F) {
02021       signal (SIGINT,  mySignalCatcher);
02022       signal (SIGTERM, mySignalCatcher);
02023 #     if BZ_UNIX
02024       signal (SIGHUP,  mySignalCatcher);
02025 #     endif
02026    }
02027 
02028    if (opMode == OM_Z) {
02029      if (srcMode == SM_I2O) {
02030         compress ( NULL );
02031      } else {
02032         decode = True;
02033         for (aa = argList; aa != NULL; aa = aa->link) {
02034            if (ISFLAG("--")) { decode = False; continue; }
02035            if (aa->name[0] == '-' && decode) continue;
02036            numFilesProcessed++;
02037            compress ( aa->name );
02038         }
02039      }
02040    } 
02041    else
02042 
02043    if (opMode == OM_UNZ) {
02044       unzFailsExist = False;
02045       if (srcMode == SM_I2O) {
02046          uncompress ( NULL );
02047       } else {
02048          decode = True;
02049          for (aa = argList; aa != NULL; aa = aa->link) {
02050             if (ISFLAG("--")) { decode = False; continue; }
02051             if (aa->name[0] == '-' && decode) continue;
02052             numFilesProcessed++;
02053             uncompress ( aa->name );
02054          }      
02055       }
02056       if (unzFailsExist) { 
02057          setExit(2); 
02058          exit(exitValue);
02059       }
02060    } 
02061 
02062    else {
02063       testFailsExist = False;
02064       if (srcMode == SM_I2O) {
02065          testf ( NULL );
02066       } else {
02067          decode = True;
02068          for (aa = argList; aa != NULL; aa = aa->link) {
02069         if (ISFLAG("--")) { decode = False; continue; }
02070             if (aa->name[0] == '-' && decode) continue;
02071             numFilesProcessed++;
02072             testf ( aa->name );
02073      }
02074       }
02075       if (testFailsExist && noisy) {
02076          fprintf ( stderr,
02077            "\n"
02078            "You can use the `bzip2recover' program to attempt to recover\n"
02079            "data from undamaged sections of corrupted files.\n\n"
02080          );
02081          setExit(2);
02082          exit(exitValue);
02083       }
02084    }
02085 
02086    /* Free the argument list memory to mollify leak detectors 
02087       (eg) Purify, Checker.  Serves no other useful purpose.
02088    */
02089    aa = argList;
02090    while (aa != NULL) {
02091       Cell* aa2 = aa->link;
02092       if (aa->name != NULL) free(aa->name);
02093       free(aa);
02094       aa = aa2;
02095    }
02096 
02097    return exitValue;
02098 }
02099 
02100 
02101 /*-----------------------------------------------------------*/
02102 /*--- end                                         bzip2.c ---*/
02103 /*-----------------------------------------------------------*/
02104 
02105 

Generated on Wed Dec 9 05:25:36 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:18:14 2009 by modify_doxy.py rev. 173732