ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

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

Generated on Fri May 25 2012 04:31:59 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.