Blame bzip2.c

Packit 71fd91
Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
/*--- A block-sorting, lossless compressor        bzip2.c ---*/
Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* ------------------------------------------------------------------
Packit 71fd91
   This file is part of bzip2/libbzip2, a program and library for
Packit 71fd91
   lossless, block-sorting data compression.
Packit 71fd91
Packit 71fd91
   bzip2/libbzip2 version 1.0.6 of 6 September 2010
Packit 71fd91
   Copyright (C) 1996-2010 Julian Seward <jseward@bzip.org>
Packit 71fd91
Packit 71fd91
   Please read the WARNING, DISCLAIMER and PATENTS sections in the 
Packit 71fd91
   README file.
Packit 71fd91
Packit 71fd91
   This program is released under the terms of the license contained
Packit 71fd91
   in the file LICENSE.
Packit 71fd91
   ------------------------------------------------------------------ */
Packit 71fd91
Packit 71fd91
Packit 71fd91
/* Place a 1 beside your platform, and 0 elsewhere.
Packit 71fd91
   Generic 32-bit Unix.
Packit 71fd91
   Also works on 64-bit Unix boxes.
Packit 71fd91
   This is the default.
Packit 71fd91
*/
Packit 71fd91
#define BZ_UNIX      1
Packit 71fd91
Packit 71fd91
/*--
Packit 71fd91
  Win32, as seen by Jacob Navia's excellent
Packit 71fd91
  port of (Chris Fraser & David Hanson)'s excellent
Packit 71fd91
  lcc compiler.  Or with MS Visual C.
Packit 71fd91
  This is selected automatically if compiled by a compiler which
Packit 71fd91
  defines _WIN32, not including the Cygwin GCC.
Packit 71fd91
--*/
Packit 71fd91
#define BZ_LCCWIN32  0
Packit 71fd91
Packit 71fd91
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit 71fd91
#undef  BZ_LCCWIN32
Packit 71fd91
#define BZ_LCCWIN32 1
Packit 71fd91
#undef  BZ_UNIX
Packit 71fd91
#define BZ_UNIX 0
Packit 71fd91
#endif
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
  Some stuff for all platforms.
Packit 71fd91
--*/
Packit 71fd91
Packit 71fd91
#include <stdio.h>
Packit 71fd91
#include <stdlib.h>
Packit 71fd91
#include <string.h>
Packit 71fd91
#include <signal.h>
Packit 71fd91
#include <math.h>
Packit 71fd91
#include <errno.h>
Packit 71fd91
#include <ctype.h>
Packit 71fd91
#include "bzlib.h"
Packit 71fd91
Packit 71fd91
#define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
Packit 71fd91
#define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
Packit 71fd91
#define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
   Platform-specific stuff.
Packit 71fd91
--*/
Packit 71fd91
Packit 71fd91
#if BZ_UNIX
Packit 71fd91
#   include <fcntl.h>
Packit 71fd91
#   include <sys/types.h>
Packit 71fd91
#   include <utime.h>
Packit 71fd91
#   include <unistd.h>
Packit 71fd91
#   include <sys/stat.h>
Packit 71fd91
#   include <sys/times.h>
Packit 71fd91
Packit 71fd91
#   define PATH_SEP    '/'
Packit 71fd91
#   define MY_LSTAT    lstat
Packit 71fd91
#   define MY_STAT     stat
Packit 71fd91
#   define MY_S_ISREG  S_ISREG
Packit 71fd91
#   define MY_S_ISDIR  S_ISDIR
Packit 71fd91
Packit 71fd91
#   define APPEND_FILESPEC(root, name) \
Packit 71fd91
      root=snocString((root), (name))
Packit 71fd91
Packit 71fd91
#   define APPEND_FLAG(root, name) \
Packit 71fd91
      root=snocString((root), (name))
Packit 71fd91
Packit 71fd91
#   define SET_BINARY_MODE(fd) /**/
Packit 71fd91
Packit 71fd91
#   ifdef __GNUC__
Packit 71fd91
#      define NORETURN __attribute__ ((noreturn))
Packit 71fd91
#   else
Packit 71fd91
#      define NORETURN /**/
Packit 71fd91
#   endif
Packit 71fd91
Packit 71fd91
#   ifdef __DJGPP__
Packit 71fd91
#     include <io.h>
Packit 71fd91
#     include <fcntl.h>
Packit 71fd91
#     undef MY_LSTAT
Packit 71fd91
#     undef MY_STAT
Packit 71fd91
#     define MY_LSTAT stat
Packit 71fd91
#     define MY_STAT stat
Packit 71fd91
#     undef SET_BINARY_MODE
Packit 71fd91
#     define SET_BINARY_MODE(fd)                        \
Packit 71fd91
        do {                                            \
Packit 71fd91
           int retVal = setmode ( fileno ( fd ),        \
Packit 71fd91
                                  O_BINARY );           \
Packit 71fd91
           ERROR_IF_MINUS_ONE ( retVal );               \
Packit 71fd91
        } while ( 0 )
Packit 71fd91
#   endif
Packit 71fd91
Packit 71fd91
#   ifdef __CYGWIN__
Packit 71fd91
#     include <io.h>
Packit 71fd91
#     include <fcntl.h>
Packit 71fd91
#     undef SET_BINARY_MODE
Packit 71fd91
#     define SET_BINARY_MODE(fd)                        \
Packit 71fd91
        do {                                            \
Packit 71fd91
           int retVal = setmode ( fileno ( fd ),        \
Packit 71fd91
                                  O_BINARY );           \
Packit 71fd91
           ERROR_IF_MINUS_ONE ( retVal );               \
Packit 71fd91
        } while ( 0 )
Packit 71fd91
#   endif
Packit 71fd91
#endif /* BZ_UNIX */
Packit 71fd91
Packit 71fd91
Packit 71fd91
Packit 71fd91
#if BZ_LCCWIN32
Packit 71fd91
#   include <io.h>
Packit 71fd91
#   include <fcntl.h>
Packit 71fd91
#   include <sys\stat.h>
Packit 71fd91
Packit 71fd91
#   define NORETURN       /**/
Packit 71fd91
#   define PATH_SEP       '\\'
Packit 71fd91
#   define MY_LSTAT       _stat
Packit 71fd91
#   define MY_STAT        _stat
Packit 71fd91
#   define MY_S_ISREG(x)  ((x) & _S_IFREG)
Packit 71fd91
#   define MY_S_ISDIR(x)  ((x) & _S_IFDIR)
Packit 71fd91
Packit 71fd91
#   define APPEND_FLAG(root, name) \
Packit 71fd91
      root=snocString((root), (name))
Packit 71fd91
Packit 71fd91
#   define APPEND_FILESPEC(root, name)                \
Packit 71fd91
      root = snocString ((root), (name))
Packit 71fd91
Packit 71fd91
#   define SET_BINARY_MODE(fd)                        \
Packit 71fd91
      do {                                            \
Packit 71fd91
         int retVal = setmode ( fileno ( fd ),        \
Packit 71fd91
                                O_BINARY );           \
Packit 71fd91
         ERROR_IF_MINUS_ONE ( retVal );               \
Packit 71fd91
      } while ( 0 )
Packit 71fd91
Packit 71fd91
#endif /* BZ_LCCWIN32 */
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
  Some more stuff for all platforms :-)
Packit 71fd91
--*/
Packit 71fd91
Packit 71fd91
typedef char            Char;
Packit 71fd91
typedef unsigned char   Bool;
Packit 71fd91
typedef unsigned char   UChar;
Packit 71fd91
typedef int             Int32;
Packit 71fd91
typedef unsigned int    UInt32;
Packit 71fd91
typedef short           Int16;
Packit 71fd91
typedef unsigned short  UInt16;
Packit 71fd91
                                       
Packit 71fd91
#define True  ((Bool)1)
Packit 71fd91
#define False ((Bool)0)
Packit 71fd91
Packit 71fd91
/*--
Packit 71fd91
  IntNative is your platform's `native' int size.
Packit 71fd91
  Only here to avoid probs with 64-bit platforms.
Packit 71fd91
--*/
Packit 71fd91
typedef int IntNative;
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- Misc (file handling) data decls             ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
Int32   verbosity;
Packit 71fd91
Bool    keepInputFiles, smallMode, deleteOutputOnInterrupt;
Packit 71fd91
Bool    forceOverwrite, testFailsExist, unzFailsExist, noisy;
Packit 71fd91
Int32   numFileNames, numFilesProcessed, blockSize100k;
Packit 71fd91
Int32   exitValue;
Packit 71fd91
Packit 71fd91
/*-- source modes; F==file, I==stdin, O==stdout --*/
Packit 71fd91
#define SM_I2O           1
Packit 71fd91
#define SM_F2O           2
Packit 71fd91
#define SM_F2F           3
Packit 71fd91
Packit 71fd91
/*-- operation modes --*/
Packit 71fd91
#define OM_Z             1
Packit 71fd91
#define OM_UNZ           2
Packit 71fd91
#define OM_TEST          3
Packit 71fd91
Packit 71fd91
Int32   opMode;
Packit 71fd91
Int32   srcMode;
Packit 71fd91
Packit 71fd91
#define FILE_NAME_LEN 1034
Packit 71fd91
Packit 71fd91
Int32   longestFileName;
Packit 71fd91
Char    inName [FILE_NAME_LEN];
Packit 71fd91
Char    outName[FILE_NAME_LEN];
Packit 71fd91
Char    tmpName[FILE_NAME_LEN];
Packit 71fd91
Char    *progName;
Packit 71fd91
Char    progNameReally[FILE_NAME_LEN];
Packit 71fd91
FILE    *outputHandleJustInCase;
Packit 71fd91
Int32   workFactor;
Packit 71fd91
Packit 71fd91
static void    panic                 ( const Char* ) NORETURN;
Packit 71fd91
static void    ioError               ( void )        NORETURN;
Packit 71fd91
static void    outOfMemory           ( void )        NORETURN;
Packit 71fd91
static void    configError           ( void )        NORETURN;
Packit 71fd91
static void    crcError              ( void )        NORETURN;
Packit 71fd91
static void    cleanUpAndFail        ( Int32 )       NORETURN;
Packit 71fd91
static void    compressedStreamEOF   ( void )        NORETURN;
Packit 71fd91
Packit 71fd91
static void    copyFileName ( Char*, Char* );
Packit 71fd91
static void*   myMalloc     ( Int32 );
Packit 71fd91
static void    applySavedFileAttrToOutputFile ( IntNative fd );
Packit 71fd91
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- An implementation of 64-bit ints.  Sigh.    ---*/
Packit 71fd91
/*--- Roll on widespread deployment of ANSI C9X ! ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
typedef
Packit 71fd91
   struct { UChar b[8]; } 
Packit 71fd91
   UInt64;
Packit 71fd91
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
Packit 71fd91
{
Packit 71fd91
   n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
Packit 71fd91
   n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
Packit 71fd91
   n->b[5] = (UChar)((hi32 >> 8)  & 0xFF);
Packit 71fd91
   n->b[4] = (UChar) (hi32        & 0xFF);
Packit 71fd91
   n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
Packit 71fd91
   n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
Packit 71fd91
   n->b[1] = (UChar)((lo32 >> 8)  & 0xFF);
Packit 71fd91
   n->b[0] = (UChar) (lo32        & 0xFF);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
double uInt64_to_double ( UInt64* n )
Packit 71fd91
{
Packit 71fd91
   Int32  i;
Packit 71fd91
   double base = 1.0;
Packit 71fd91
   double sum  = 0.0;
Packit 71fd91
   for (i = 0; i < 8; i++) {
Packit 71fd91
      sum  += base * (double)(n->b[i]);
Packit 71fd91
      base *= 256.0;
Packit 71fd91
   }
Packit 71fd91
   return sum;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
static
Packit 71fd91
Bool uInt64_isZero ( UInt64* n )
Packit 71fd91
{
Packit 71fd91
   Int32 i;
Packit 71fd91
   for (i = 0; i < 8; i++)
Packit 71fd91
      if (n->b[i] != 0) return 0;
Packit 71fd91
   return 1;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/* Divide *n by 10, and return the remainder.  */
Packit 71fd91
static 
Packit 71fd91
Int32 uInt64_qrm10 ( UInt64* n )
Packit 71fd91
{
Packit 71fd91
   UInt32 rem, tmp;
Packit 71fd91
   Int32  i;
Packit 71fd91
   rem = 0;
Packit 71fd91
   for (i = 7; i >= 0; i--) {
Packit 71fd91
      tmp = rem * 256 + n->b[i];
Packit 71fd91
      n->b[i] = tmp / 10;
Packit 71fd91
      rem = tmp % 10;
Packit 71fd91
   }
Packit 71fd91
   return rem;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/* ... and the Whole Entire Point of all this UInt64 stuff is
Packit 71fd91
   so that we can supply the following function.
Packit 71fd91
*/
Packit 71fd91
static
Packit 71fd91
void uInt64_toAscii ( char* outbuf, UInt64* n )
Packit 71fd91
{
Packit 71fd91
   Int32  i, q;
Packit 71fd91
   UChar  buf[32];
Packit 71fd91
   Int32  nBuf   = 0;
Packit 71fd91
   UInt64 n_copy = *n;
Packit 71fd91
   do {
Packit 71fd91
      q = uInt64_qrm10 ( &n_copy );
Packit 71fd91
      buf[nBuf] = q + '0';
Packit 71fd91
      nBuf++;
Packit 71fd91
   } while (!uInt64_isZero(&n_copy));
Packit 71fd91
   outbuf[nBuf] = 0;
Packit 71fd91
   for (i = 0; i < nBuf; i++) 
Packit 71fd91
      outbuf[i] = buf[nBuf-i-1];
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- Processing of complete files and streams    ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Bool myfeof ( FILE* f )
Packit 71fd91
{
Packit 71fd91
   Int32 c = fgetc ( f );
Packit 71fd91
   if (c == EOF) return True;
Packit 71fd91
   ungetc ( c, f );
Packit 71fd91
   return False;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void compressStream ( FILE *stream, FILE *zStream )
Packit 71fd91
{
Packit 71fd91
   BZFILE* bzf = NULL;
Packit 71fd91
   UChar   ibuf[5000];
Packit 71fd91
   Int32   nIbuf;
Packit 71fd91
   UInt32  nbytes_in_lo32, nbytes_in_hi32;
Packit 71fd91
   UInt32  nbytes_out_lo32, nbytes_out_hi32;
Packit 71fd91
   Int32   bzerr, bzerr_dummy, ret;
Packit 71fd91
Packit 71fd91
   SET_BINARY_MODE(stream);
Packit 71fd91
   SET_BINARY_MODE(zStream);
Packit 71fd91
Packit 71fd91
   if (ferror(stream)) goto errhandler_io;
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   bzf = BZ2_bzWriteOpen ( &bzerr, zStream, 
Packit 71fd91
                           blockSize100k, verbosity, workFactor );   
Packit 71fd91
   if (bzerr != BZ_OK) goto errhandler;
Packit 71fd91
Packit 71fd91
   if (verbosity >= 2) fprintf ( stderr, "\n" );
Packit 71fd91
Packit 71fd91
   while (True) {
Packit 71fd91
Packit 71fd91
      if (myfeof(stream)) break;
Packit 71fd91
      nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
Packit 71fd91
      if (ferror(stream)) goto errhandler_io;
Packit 71fd91
      if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
Packit 71fd91
      if (bzerr != BZ_OK) goto errhandler;
Packit 71fd91
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   BZ2_bzWriteClose64 ( &bzerr, bzf, 0, 
Packit 71fd91
                        &nbytes_in_lo32, &nbytes_in_hi32,
Packit 71fd91
                        &nbytes_out_lo32, &nbytes_out_hi32 );
Packit 71fd91
   if (bzerr != BZ_OK) goto errhandler;
Packit 71fd91
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
   ret = fflush ( zStream );
Packit 71fd91
   if (ret == EOF) goto errhandler_io;
Packit 71fd91
   if (zStream != stdout) {
Packit 71fd91
      Int32 fd = fileno ( zStream );
Packit 71fd91
      if (fd < 0) goto errhandler_io;
Packit 71fd91
      applySavedFileAttrToOutputFile ( fd );
Packit 71fd91
      ret = fclose ( zStream );
Packit 71fd91
      outputHandleJustInCase = NULL;
Packit 71fd91
      if (ret == EOF) goto errhandler_io;
Packit 71fd91
   }
Packit 71fd91
   outputHandleJustInCase = NULL;
Packit 71fd91
   if (ferror(stream)) goto errhandler_io;
Packit 71fd91
   ret = fclose ( stream );
Packit 71fd91
   if (ret == EOF) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   if (verbosity >= 1) {
Packit 71fd91
      if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
Packit 71fd91
	 fprintf ( stderr, " no data compressed.\n");
Packit 71fd91
      } else {
Packit 71fd91
	 Char   buf_nin[32], buf_nout[32];
Packit 71fd91
	 UInt64 nbytes_in,   nbytes_out;
Packit 71fd91
	 double nbytes_in_d, nbytes_out_d;
Packit 71fd91
	 uInt64_from_UInt32s ( &nbytes_in, 
Packit 71fd91
			       nbytes_in_lo32, nbytes_in_hi32 );
Packit 71fd91
	 uInt64_from_UInt32s ( &nbytes_out, 
Packit 71fd91
			       nbytes_out_lo32, nbytes_out_hi32 );
Packit 71fd91
	 nbytes_in_d  = uInt64_to_double ( &nbytes_in );
Packit 71fd91
	 nbytes_out_d = uInt64_to_double ( &nbytes_out );
Packit 71fd91
	 uInt64_toAscii ( buf_nin, &nbytes_in );
Packit 71fd91
	 uInt64_toAscii ( buf_nout, &nbytes_out );
Packit 71fd91
	 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
Packit 71fd91
		   "%5.2f%% saved, %s in, %s out.\n",
Packit 71fd91
		   nbytes_in_d / nbytes_out_d,
Packit 71fd91
		   (8.0 * nbytes_out_d) / nbytes_in_d,
Packit 71fd91
		   100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
Packit 71fd91
		   buf_nin,
Packit 71fd91
		   buf_nout
Packit 71fd91
		 );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   return;
Packit 71fd91
Packit 71fd91
   errhandler:
Packit 71fd91
   BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1, 
Packit 71fd91
                        &nbytes_in_lo32, &nbytes_in_hi32,
Packit 71fd91
                        &nbytes_out_lo32, &nbytes_out_hi32 );
Packit 71fd91
   switch (bzerr) {
Packit 71fd91
      case BZ_CONFIG_ERROR:
Packit 71fd91
         configError(); break;
Packit 71fd91
      case BZ_MEM_ERROR:
Packit 71fd91
         outOfMemory (); break;
Packit 71fd91
      case BZ_IO_ERROR:
Packit 71fd91
         errhandler_io:
Packit 71fd91
         ioError(); break;
Packit 71fd91
      default:
Packit 71fd91
         panic ( "compress:unexpected error" );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   panic ( "compress:end" );
Packit 71fd91
   /*notreached*/
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Bool uncompressStream ( FILE *zStream, FILE *stream )
Packit 71fd91
{
Packit 71fd91
   BZFILE* bzf = NULL;
Packit 71fd91
   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
Packit 71fd91
   UChar   obuf[5000];
Packit 71fd91
   UChar   unused[BZ_MAX_UNUSED];
Packit 71fd91
   Int32   nUnused;
Packit 71fd91
   void*   unusedTmpV;
Packit 71fd91
   UChar*  unusedTmp;
Packit 71fd91
Packit 71fd91
   nUnused = 0;
Packit 71fd91
   streamNo = 0;
Packit 71fd91
Packit 71fd91
   SET_BINARY_MODE(stream);
Packit 71fd91
   SET_BINARY_MODE(zStream);
Packit 71fd91
Packit 71fd91
   if (ferror(stream)) goto errhandler_io;
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   while (True) {
Packit 71fd91
Packit 71fd91
      bzf = BZ2_bzReadOpen ( 
Packit 71fd91
               &bzerr, zStream, verbosity, 
Packit 71fd91
               (int)smallMode, unused, nUnused
Packit 71fd91
            );
Packit 71fd91
      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
Packit 71fd91
      streamNo++;
Packit 71fd91
Packit 71fd91
      while (bzerr == BZ_OK) {
Packit 71fd91
         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
Packit 71fd91
         if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
Packit 71fd91
         if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
Packit 71fd91
            fwrite ( obuf, sizeof(UChar), nread, stream );
Packit 71fd91
         if (ferror(stream)) goto errhandler_io;
Packit 71fd91
      }
Packit 71fd91
      if (bzerr != BZ_STREAM_END) goto errhandler;
Packit 71fd91
Packit 71fd91
      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
Packit 71fd91
      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
Packit 71fd91
Packit 71fd91
      unusedTmp = (UChar*)unusedTmpV;
Packit 71fd91
      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
Packit 71fd91
Packit 71fd91
      BZ2_bzReadClose ( &bzerr, bzf );
Packit 71fd91
      if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
Packit 71fd91
Packit 71fd91
      if (nUnused == 0 && myfeof(zStream)) break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   closeok:
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
   if (stream != stdout) {
Packit 71fd91
      Int32 fd = fileno ( stream );
Packit 71fd91
      if (fd < 0) goto errhandler_io;
Packit 71fd91
      applySavedFileAttrToOutputFile ( fd );
Packit 71fd91
   }
Packit 71fd91
   ret = fclose ( zStream );
Packit 71fd91
   if (ret == EOF) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   if (ferror(stream)) goto errhandler_io;
Packit 71fd91
   ret = fflush ( stream );
Packit 71fd91
   if (ret != 0) goto errhandler_io;
Packit 71fd91
   if (stream != stdout) {
Packit 71fd91
      ret = fclose ( stream );
Packit 71fd91
      outputHandleJustInCase = NULL;
Packit 71fd91
      if (ret == EOF) goto errhandler_io;
Packit 71fd91
   }
Packit 71fd91
   outputHandleJustInCase = NULL;
Packit 71fd91
   if (verbosity >= 2) fprintf ( stderr, "\n    " );
Packit 71fd91
   return True;
Packit 71fd91
Packit 71fd91
   trycat: 
Packit 71fd91
   if (forceOverwrite) {
Packit 71fd91
      rewind(zStream);
Packit 71fd91
      while (True) {
Packit 71fd91
      	 if (myfeof(zStream)) break;
Packit 71fd91
      	 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
Packit 71fd91
      	 if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
      	 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
Packit 71fd91
      	 if (ferror(stream)) goto errhandler_io;
Packit 71fd91
      }
Packit 71fd91
      goto closeok;
Packit 71fd91
   }
Packit 71fd91
  
Packit 71fd91
   errhandler:
Packit 71fd91
   BZ2_bzReadClose ( &bzerr_dummy, bzf );
Packit 71fd91
   switch (bzerr) {
Packit 71fd91
      case BZ_CONFIG_ERROR:
Packit 71fd91
         configError(); break;
Packit 71fd91
      case BZ_IO_ERROR:
Packit 71fd91
         errhandler_io:
Packit 71fd91
         ioError(); break;
Packit 71fd91
      case BZ_DATA_ERROR:
Packit 71fd91
         crcError();
Packit 71fd91
      case BZ_MEM_ERROR:
Packit 71fd91
         outOfMemory();
Packit 71fd91
      case BZ_UNEXPECTED_EOF:
Packit 71fd91
         compressedStreamEOF();
Packit 71fd91
      case BZ_DATA_ERROR_MAGIC:
Packit 71fd91
         if (zStream != stdin) fclose(zStream);
Packit 71fd91
         if (stream != stdout) fclose(stream);
Packit 71fd91
         if (streamNo == 1) {
Packit 71fd91
            return False;
Packit 71fd91
         } else {
Packit 71fd91
            if (noisy)
Packit 71fd91
            fprintf ( stderr, 
Packit 71fd91
                      "\n%s: %s: trailing garbage after EOF ignored\n",
Packit 71fd91
                      progName, inName );
Packit 71fd91
            return True;       
Packit 71fd91
         }
Packit 71fd91
      default:
Packit 71fd91
         panic ( "decompress:unexpected error" );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   panic ( "decompress:end" );
Packit 71fd91
   return True; /*notreached*/
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Bool testStream ( FILE *zStream )
Packit 71fd91
{
Packit 71fd91
   BZFILE* bzf = NULL;
Packit 71fd91
   Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
Packit 71fd91
   UChar   obuf[5000];
Packit 71fd91
   UChar   unused[BZ_MAX_UNUSED];
Packit 71fd91
   Int32   nUnused;
Packit 71fd91
   void*   unusedTmpV;
Packit 71fd91
   UChar*  unusedTmp;
Packit 71fd91
Packit 71fd91
   nUnused = 0;
Packit 71fd91
   streamNo = 0;
Packit 71fd91
Packit 71fd91
   SET_BINARY_MODE(zStream);
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   while (True) {
Packit 71fd91
Packit 71fd91
      bzf = BZ2_bzReadOpen ( 
Packit 71fd91
               &bzerr, zStream, verbosity, 
Packit 71fd91
               (int)smallMode, unused, nUnused
Packit 71fd91
            );
Packit 71fd91
      if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
Packit 71fd91
      streamNo++;
Packit 71fd91
Packit 71fd91
      while (bzerr == BZ_OK) {
Packit 71fd91
         nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
Packit 71fd91
         if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
Packit 71fd91
      }
Packit 71fd91
      if (bzerr != BZ_STREAM_END) goto errhandler;
Packit 71fd91
Packit 71fd91
      BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
Packit 71fd91
      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
Packit 71fd91
Packit 71fd91
      unusedTmp = (UChar*)unusedTmpV;
Packit 71fd91
      for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
Packit 71fd91
Packit 71fd91
      BZ2_bzReadClose ( &bzerr, bzf );
Packit 71fd91
      if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
Packit 71fd91
      if (nUnused == 0 && myfeof(zStream)) break;
Packit 71fd91
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (ferror(zStream)) goto errhandler_io;
Packit 71fd91
   ret = fclose ( zStream );
Packit 71fd91
   if (ret == EOF) goto errhandler_io;
Packit 71fd91
Packit 71fd91
   if (verbosity >= 2) fprintf ( stderr, "\n    " );
Packit 71fd91
   return True;
Packit 71fd91
Packit 71fd91
   errhandler:
Packit 71fd91
   BZ2_bzReadClose ( &bzerr_dummy, bzf );
Packit 71fd91
   if (verbosity == 0) 
Packit 71fd91
      fprintf ( stderr, "%s: %s: ", progName, inName );
Packit 71fd91
   switch (bzerr) {
Packit 71fd91
      case BZ_CONFIG_ERROR:
Packit 71fd91
         configError(); break;
Packit 71fd91
      case BZ_IO_ERROR:
Packit 71fd91
         errhandler_io:
Packit 71fd91
         ioError(); break;
Packit 71fd91
      case BZ_DATA_ERROR:
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "data integrity (CRC) error in data\n" );
Packit 71fd91
         return False;
Packit 71fd91
      case BZ_MEM_ERROR:
Packit 71fd91
         outOfMemory();
Packit 71fd91
      case BZ_UNEXPECTED_EOF:
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "file ends unexpectedly\n" );
Packit 71fd91
         return False;
Packit 71fd91
      case BZ_DATA_ERROR_MAGIC:
Packit 71fd91
         if (zStream != stdin) fclose(zStream);
Packit 71fd91
         if (streamNo == 1) {
Packit 71fd91
          fprintf ( stderr, 
Packit 71fd91
                    "bad magic number (file not created by bzip2)\n" );
Packit 71fd91
            return False;
Packit 71fd91
         } else {
Packit 71fd91
            if (noisy)
Packit 71fd91
            fprintf ( stderr, 
Packit 71fd91
                      "trailing garbage after EOF ignored\n" );
Packit 71fd91
            return True;       
Packit 71fd91
         }
Packit 71fd91
      default:
Packit 71fd91
         panic ( "test:unexpected error" );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   panic ( "test:end" );
Packit 71fd91
   return True; /*notreached*/
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- Error [non-] handling grunge                ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static
Packit 71fd91
void setExit ( Int32 v )
Packit 71fd91
{
Packit 71fd91
   if (v > exitValue) exitValue = v;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void cadvise ( void )
Packit 71fd91
{
Packit 71fd91
   if (noisy)
Packit 71fd91
   fprintf (
Packit 71fd91
      stderr,
Packit 71fd91
      "\nIt is possible that the compressed file(s) have become corrupted.\n"
Packit 71fd91
        "You can use the -tvv option to test integrity of such files.\n\n"
Packit 71fd91
        "You can use the `bzip2recover' program to attempt to recover\n"
Packit 71fd91
        "data from undamaged sections of corrupted files.\n\n"
Packit 71fd91
    );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void showFileNames ( void )
Packit 71fd91
{
Packit 71fd91
   if (noisy)
Packit 71fd91
   fprintf (
Packit 71fd91
      stderr,
Packit 71fd91
      "\tInput file = %s, output file = %s\n",
Packit 71fd91
      inName, outName 
Packit 71fd91
   );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void cleanUpAndFail ( Int32 ec )
Packit 71fd91
{
Packit 71fd91
   IntNative      retVal;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   if ( srcMode == SM_F2F 
Packit 71fd91
        && opMode != OM_TEST
Packit 71fd91
        && deleteOutputOnInterrupt ) {
Packit 71fd91
Packit 71fd91
      /* Check whether input file still exists.  Delete output file
Packit 71fd91
         only if input exists to avoid loss of data.  Joerg Prante, 5
Packit 71fd91
         January 2002.  (JRS 06-Jan-2002: other changes in 1.0.2 mean
Packit 71fd91
         this is less likely to happen.  But to be ultra-paranoid, we
Packit 71fd91
         do the check anyway.)  */
Packit 71fd91
      retVal = MY_STAT ( inName, &statBuf );
Packit 71fd91
      if (retVal == 0) {
Packit 71fd91
         if (noisy)
Packit 71fd91
            fprintf ( stderr, 
Packit 71fd91
                      "%s: Deleting output file %s, if it exists.\n",
Packit 71fd91
                      progName, outName );
Packit 71fd91
         if (outputHandleJustInCase != NULL)
Packit 71fd91
            fclose ( outputHandleJustInCase );
Packit 71fd91
         retVal = remove ( outName );
Packit 71fd91
         if (retVal != 0)
Packit 71fd91
            fprintf ( stderr,
Packit 71fd91
                      "%s: WARNING: deletion of output file "
Packit 71fd91
                      "(apparently) failed.\n",
Packit 71fd91
                      progName );
Packit 71fd91
      } else {
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "%s: WARNING: deletion of output file suppressed\n",
Packit 71fd91
                    progName );
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "%s:    since input file no longer exists.  Output file\n",
Packit 71fd91
                   progName );
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "%s:    `%s' may be incomplete.\n",
Packit 71fd91
                   progName, outName );
Packit 71fd91
         fprintf ( stderr, 
Packit 71fd91
                   "%s:    I suggest doing an integrity test (bzip2 -tv)"
Packit 71fd91
                   " of it.\n",
Packit 71fd91
                   progName );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
Packit 71fd91
      fprintf ( stderr, 
Packit 71fd91
                "%s: WARNING: some files have not been processed:\n"
Packit 71fd91
                "%s:    %d specified on command line, %d not processed yet.\n\n",
Packit 71fd91
                progName, progName,
Packit 71fd91
                numFileNames, numFileNames - numFilesProcessed );
Packit 71fd91
   }
Packit 71fd91
   setExit(ec);
Packit 71fd91
   exit(exitValue);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void panic ( const Char* s )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "\n%s: PANIC -- internal consistency error:\n"
Packit 71fd91
             "\t%s\n"
Packit 71fd91
             "\tThis is a BUG.  Please report it to me at:\n"
Packit 71fd91
             "\tjseward@bzip.org\n",
Packit 71fd91
             progName, s );
Packit 71fd91
   showFileNames();
Packit 71fd91
   cleanUpAndFail( 3 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void crcError ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "\n%s: Data integrity error when decompressing.\n",
Packit 71fd91
             progName );
Packit 71fd91
   showFileNames();
Packit 71fd91
   cadvise();
Packit 71fd91
   cleanUpAndFail( 2 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void compressedStreamEOF ( void )
Packit 71fd91
{
Packit 71fd91
  if (noisy) {
Packit 71fd91
    fprintf ( stderr,
Packit 71fd91
	      "\n%s: Compressed file ends unexpectedly;\n\t"
Packit 71fd91
	      "perhaps it is corrupted?  *Possible* reason follows.\n",
Packit 71fd91
	      progName );
Packit 71fd91
    perror ( progName );
Packit 71fd91
    showFileNames();
Packit 71fd91
    cadvise();
Packit 71fd91
  }
Packit 71fd91
  cleanUpAndFail( 2 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void ioError ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "\n%s: I/O or other error, bailing out.  "
Packit 71fd91
             "Possible reason follows.\n",
Packit 71fd91
             progName );
Packit 71fd91
   perror ( progName );
Packit 71fd91
   showFileNames();
Packit 71fd91
   cleanUpAndFail( 1 );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void mySignalCatcher ( IntNative n )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "\n%s: Control-C or similar caught, quitting.\n",
Packit 71fd91
             progName );
Packit 71fd91
   cleanUpAndFail(1);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void mySIGSEGVorSIGBUScatcher ( IntNative n )
Packit 71fd91
{
Packit 71fd91
   if (opMode == OM_Z)
Packit 71fd91
      fprintf ( 
Packit 71fd91
      stderr,
Packit 71fd91
      "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
Packit 71fd91
      "\n"
Packit 71fd91
      "   Possible causes are (most likely first):\n"
Packit 71fd91
      "   (1) This computer has unreliable memory or cache hardware\n"
Packit 71fd91
      "       (a surprisingly common problem; try a different machine.)\n"
Packit 71fd91
      "   (2) A bug in the compiler used to create this executable\n"
Packit 71fd91
      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
Packit 71fd91
      "   (3) A real bug in bzip2 -- I hope this should never be the case.\n"
Packit 71fd91
      "   The user's manual, Section 4.3, has more info on (1) and (2).\n"
Packit 71fd91
      "   \n"
Packit 71fd91
      "   If you suspect this is a bug in bzip2, or are unsure about (1)\n"
Packit 71fd91
      "   or (2), feel free to report it to me at: jseward@bzip.org.\n"
Packit 71fd91
      "   Section 4.3 of the user's manual describes the info a useful\n"
Packit 71fd91
      "   bug report should have.  If the manual is available on your\n"
Packit 71fd91
      "   system, please try and read it before mailing me.  If you don't\n"
Packit 71fd91
      "   have the manual or can't be bothered to read it, mail me anyway.\n"
Packit 71fd91
      "\n",
Packit 71fd91
      progName );
Packit 71fd91
      else
Packit 71fd91
      fprintf ( 
Packit 71fd91
      stderr,
Packit 71fd91
      "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
Packit 71fd91
      "\n"
Packit 71fd91
      "   Possible causes are (most likely first):\n"
Packit 71fd91
      "   (1) The compressed data is corrupted, and bzip2's usual checks\n"
Packit 71fd91
      "       failed to detect this.  Try bzip2 -tvv my_file.bz2.\n"
Packit 71fd91
      "   (2) This computer has unreliable memory or cache hardware\n"
Packit 71fd91
      "       (a surprisingly common problem; try a different machine.)\n"
Packit 71fd91
      "   (3) A bug in the compiler used to create this executable\n"
Packit 71fd91
      "       (unlikely, if you didn't compile bzip2 yourself.)\n"
Packit 71fd91
      "   (4) A real bug in bzip2 -- I hope this should never be the case.\n"
Packit 71fd91
      "   The user's manual, Section 4.3, has more info on (2) and (3).\n"
Packit 71fd91
      "   \n"
Packit 71fd91
      "   If you suspect this is a bug in bzip2, or are unsure about (2)\n"
Packit 71fd91
      "   or (3), feel free to report it to me at: jseward@bzip.org.\n"
Packit 71fd91
      "   Section 4.3 of the user's manual describes the info a useful\n"
Packit 71fd91
      "   bug report should have.  If the manual is available on your\n"
Packit 71fd91
      "   system, please try and read it before mailing me.  If you don't\n"
Packit 71fd91
      "   have the manual or can't be bothered to read it, mail me anyway.\n"
Packit 71fd91
      "\n",
Packit 71fd91
      progName );
Packit 71fd91
Packit 71fd91
   showFileNames();
Packit 71fd91
   if (opMode == OM_Z)
Packit 71fd91
      cleanUpAndFail( 3 ); else
Packit 71fd91
      { cadvise(); cleanUpAndFail( 2 ); }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void outOfMemory ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "\n%s: couldn't allocate enough memory\n",
Packit 71fd91
             progName );
Packit 71fd91
   showFileNames();
Packit 71fd91
   cleanUpAndFail(1);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void configError ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
             "bzip2: I'm not configured correctly for this platform!\n"
Packit 71fd91
             "\tI require Int32, Int16 and Char to have sizes\n"
Packit 71fd91
             "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
Packit 71fd91
             "\tProbably you can fix this by defining them correctly,\n"
Packit 71fd91
             "\tand recompiling.  Bye!\n" );
Packit 71fd91
   setExit(3);
Packit 71fd91
   exit(exitValue);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
/*--- The main driver machinery                   ---*/
Packit 71fd91
/*---------------------------------------------------*/
Packit 71fd91
Packit 71fd91
/* All rather crufty.  The main problem is that input files
Packit 71fd91
   are stat()d multiple times before use.  This should be
Packit 71fd91
   cleaned up. 
Packit 71fd91
*/
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void pad ( Char *s )
Packit 71fd91
{
Packit 71fd91
   Int32 i;
Packit 71fd91
   if ( (Int32)strlen(s) >= longestFileName ) return;
Packit 71fd91
   for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
Packit 71fd91
      fprintf ( stderr, " " );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void copyFileName ( Char* to, Char* from ) 
Packit 71fd91
{
Packit 71fd91
   if ( strlen(from) > FILE_NAME_LEN-10 )  {
Packit 71fd91
      fprintf (
Packit 71fd91
         stderr,
Packit 71fd91
         "bzip2: file name\n`%s'\n"
Packit 71fd91
         "is suspiciously (more than %d chars) long.\n"
Packit 71fd91
         "Try using a reasonable file name instead.  Sorry! :-)\n",
Packit 71fd91
         from, FILE_NAME_LEN-10
Packit 71fd91
      );
Packit 71fd91
      setExit(1);
Packit 71fd91
      exit(exitValue);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
  strncpy(to,from,FILE_NAME_LEN-10);
Packit 71fd91
  to[FILE_NAME_LEN-10]='\0';
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Bool fileExists ( Char* name )
Packit 71fd91
{
Packit 71fd91
   FILE *tmp   = fopen ( name, "rb" );
Packit 71fd91
   Bool exists = (tmp != NULL);
Packit 71fd91
   if (tmp != NULL) fclose ( tmp );
Packit 71fd91
   return exists;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/* Open an output file safely with O_EXCL and good permissions.
Packit 71fd91
   This avoids a race condition in versions < 1.0.2, in which
Packit 71fd91
   the file was first opened and then had its interim permissions
Packit 71fd91
   set safely.  We instead use open() to create the file with
Packit 71fd91
   the interim permissions required. (--- --- rw-).
Packit 71fd91
Packit 71fd91
   For non-Unix platforms, if we are not worrying about
Packit 71fd91
   security issues, simple this simply behaves like fopen.
Packit 71fd91
*/
Packit 71fd91
static
Packit 71fd91
FILE* fopen_output_safely ( Char* name, const char* mode )
Packit 71fd91
{
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
   FILE*     fp;
Packit 71fd91
   IntNative fh;
Packit 71fd91
   fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
Packit 71fd91
   if (fh == -1) return NULL;
Packit 71fd91
   fp = fdopen(fh, mode);
Packit 71fd91
   if (fp == NULL) close(fh);
Packit 71fd91
   return fp;
Packit 71fd91
#  else
Packit 71fd91
   return fopen(name, mode);
Packit 71fd91
#  endif
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
  if in doubt, return True
Packit 71fd91
--*/
Packit 71fd91
static 
Packit 71fd91
Bool notAStandardFile ( Char* name )
Packit 71fd91
{
Packit 71fd91
   IntNative      i;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   i = MY_LSTAT ( name, &statBuf );
Packit 71fd91
   if (i != 0) return True;
Packit 71fd91
   if (MY_S_ISREG(statBuf.st_mode)) return False;
Packit 71fd91
   return True;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
  rac 11/21/98 see if file has hard links to it
Packit 71fd91
--*/
Packit 71fd91
static 
Packit 71fd91
Int32 countHardLinks ( Char* name )
Packit 71fd91
{  
Packit 71fd91
   IntNative      i;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   i = MY_LSTAT ( name, &statBuf );
Packit 71fd91
   if (i != 0) return 0;
Packit 71fd91
   return (statBuf.st_nlink - 1);
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/* Copy modification date, access date, permissions and owner from the
Packit 71fd91
   source to destination file.  We have to copy this meta-info off
Packit 71fd91
   into fileMetaInfo before starting to compress / decompress it,
Packit 71fd91
   because doing it afterwards means we get the wrong access time.
Packit 71fd91
Packit 71fd91
   To complicate matters, in compress() and decompress() below, the
Packit 71fd91
   sequence of tests preceding the call to saveInputFileMetaInfo()
Packit 71fd91
   involves calling fileExists(), which in turn establishes its result
Packit 71fd91
   by attempting to fopen() the file, and if successful, immediately
Packit 71fd91
   fclose()ing it again.  So we have to assume that the fopen() call
Packit 71fd91
   does not cause the access time field to be updated.
Packit 71fd91
Packit 71fd91
   Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
Packit 71fd91
   to imply that merely doing open() will not affect the access time.
Packit 71fd91
   Therefore we merely need to hope that the C library only does
Packit 71fd91
   open() as a result of fopen(), and not any kind of read()-ahead
Packit 71fd91
   cleverness.
Packit 71fd91
Packit 71fd91
   It sounds pretty fragile to me.  Whether this carries across
Packit 71fd91
   robustly to arbitrary Unix-like platforms (or even works robustly
Packit 71fd91
   on this one, RedHat 7.2) is unknown to me.  Nevertheless ...  
Packit 71fd91
*/
Packit 71fd91
#if BZ_UNIX
Packit 71fd91
static 
Packit 71fd91
struct MY_STAT fileMetaInfo;
Packit 71fd91
#endif
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
void saveInputFileMetaInfo ( Char *srcName )
Packit 71fd91
{
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
   IntNative retVal;
Packit 71fd91
   /* Note use of stat here, not lstat. */
Packit 71fd91
   retVal = MY_STAT( srcName, &fileMetaInfo );
Packit 71fd91
   ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
#  endif
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
void applySavedTimeInfoToOutputFile ( Char *dstName )
Packit 71fd91
{
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
   IntNative      retVal;
Packit 71fd91
   struct utimbuf uTimBuf;
Packit 71fd91
Packit 71fd91
   uTimBuf.actime = fileMetaInfo.st_atime;
Packit 71fd91
   uTimBuf.modtime = fileMetaInfo.st_mtime;
Packit 71fd91
Packit 71fd91
   retVal = utime ( dstName, &uTimBuf );
Packit 71fd91
   ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
#  endif
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
void applySavedFileAttrToOutputFile ( IntNative fd )
Packit 71fd91
{
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
   IntNative retVal;
Packit 71fd91
Packit 71fd91
   retVal = fchmod ( fd, fileMetaInfo.st_mode );
Packit 71fd91
   ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
Packit 71fd91
   (void) fchown ( fd, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
Packit 71fd91
   /* chown() will in many cases return with EPERM, which can
Packit 71fd91
      be safely ignored.
Packit 71fd91
   */
Packit 71fd91
#  endif
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Bool containsDubiousChars ( Char* name )
Packit 71fd91
{
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
   /* On unix, files can contain any characters and the file expansion
Packit 71fd91
    * is performed by the shell.
Packit 71fd91
    */
Packit 71fd91
   return False;
Packit 71fd91
#  else /* ! BZ_UNIX */
Packit 71fd91
   /* On non-unix (Win* platforms), wildcard characters are not allowed in 
Packit 71fd91
    * filenames.
Packit 71fd91
    */
Packit 71fd91
   for (; *name != '\0'; name++)
Packit 71fd91
      if (*name == '?' || *name == '*') return True;
Packit 71fd91
   return False;
Packit 71fd91
#  endif /* BZ_UNIX */
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
#define BZ_N_SUFFIX_PAIRS 4
Packit 71fd91
Packit 71fd91
const Char* zSuffix[BZ_N_SUFFIX_PAIRS] 
Packit 71fd91
   = { ".bz2", ".bz", ".tbz2", ".tbz" };
Packit 71fd91
const Char* unzSuffix[BZ_N_SUFFIX_PAIRS] 
Packit 71fd91
   = { "", "", ".tar", ".tar" };
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
Bool hasSuffix ( Char* s, const Char* suffix )
Packit 71fd91
{
Packit 71fd91
   Int32 ns = strlen(s);
Packit 71fd91
   Int32 nx = strlen(suffix);
Packit 71fd91
   if (ns < nx) return False;
Packit 71fd91
   if (strcmp(s + ns - nx, suffix) == 0) return True;
Packit 71fd91
   return False;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
static 
Packit 71fd91
Bool mapSuffix ( Char* name, 
Packit 71fd91
                 const Char* oldSuffix, 
Packit 71fd91
                 const Char* newSuffix )
Packit 71fd91
{
Packit 71fd91
   if (!hasSuffix(name,oldSuffix)) return False;
Packit 71fd91
   name[strlen(name)-strlen(oldSuffix)] = 0;
Packit 71fd91
   strcat ( name, newSuffix );
Packit 71fd91
   return True;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void compress ( Char *name )
Packit 71fd91
{
Packit 71fd91
   FILE  *inStr;
Packit 71fd91
   FILE  *outStr;
Packit 71fd91
   Int32 n, i;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
Packit 71fd91
   if (name == NULL && srcMode != SM_I2O)
Packit 71fd91
      panic ( "compress: bad modes\n" );
Packit 71fd91
Packit 71fd91
   switch (srcMode) {
Packit 71fd91
      case SM_I2O: 
Packit 71fd91
         copyFileName ( inName, (Char*)"(stdin)" );
Packit 71fd91
         copyFileName ( outName, (Char*)"(stdout)" ); 
Packit 71fd91
         break;
Packit 71fd91
      case SM_F2F: 
Packit 71fd91
         copyFileName ( inName, name );
Packit 71fd91
         copyFileName ( outName, name );
Packit 71fd91
         strcat ( outName, ".bz2" ); 
Packit 71fd91
         break;
Packit 71fd91
      case SM_F2O: 
Packit 71fd91
         copyFileName ( inName, name );
Packit 71fd91
         copyFileName ( outName, (Char*)"(stdout)" ); 
Packit 71fd91
         break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Packit 71fd91
                progName, inName );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Packit 71fd91
      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Packit 71fd91
                progName, inName, strerror(errno) );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
Packit 71fd91
      if (hasSuffix(inName, zSuffix[i])) {
Packit 71fd91
         if (noisy)
Packit 71fd91
         fprintf ( stderr, 
Packit 71fd91
                   "%s: Input file %s already has %s suffix.\n",
Packit 71fd91
                   progName, inName, zSuffix[i] );
Packit 71fd91
         setExit(1);
Packit 71fd91
         return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
Packit 71fd91
      MY_STAT(inName, &statBuf);
Packit 71fd91
      if ( MY_S_ISDIR(statBuf.st_mode) ) {
Packit 71fd91
         fprintf( stderr,
Packit 71fd91
                  "%s: Input file %s is a directory.\n",
Packit 71fd91
                  progName,inName);
Packit 71fd91
         setExit(1);
Packit 71fd91
         return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
Packit 71fd91
                progName, inName );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
Packit 71fd91
      if (forceOverwrite) {
Packit 71fd91
	 remove(outName);
Packit 71fd91
      } else {
Packit 71fd91
	 fprintf ( stderr, "%s: Output file %s already exists.\n",
Packit 71fd91
		   progName, outName );
Packit 71fd91
	 setExit(1);
Packit 71fd91
	 return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F && !forceOverwrite &&
Packit 71fd91
        (n=countHardLinks ( inName )) > 0) {
Packit 71fd91
      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
Packit 71fd91
                progName, inName, n, n > 1 ? "s" : "" );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if ( srcMode == SM_F2F ) {
Packit 71fd91
      /* Save the file's meta-info before we open it.  Doing it later
Packit 71fd91
         means we mess up the access times. */
Packit 71fd91
      saveInputFileMetaInfo ( inName );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   switch ( srcMode ) {
Packit 71fd91
Packit 71fd91
      case SM_I2O:
Packit 71fd91
         inStr = stdin;
Packit 71fd91
         outStr = stdout;
Packit 71fd91
         if ( isatty ( fileno ( stdout ) ) ) {
Packit 71fd91
            fprintf ( stderr,
Packit 71fd91
                      "%s: I won't write compressed data to a terminal.\n",
Packit 71fd91
                      progName );
Packit 71fd91
            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Packit 71fd91
                              progName, progName );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      case SM_F2O:
Packit 71fd91
         inStr = fopen ( inName, "rb" );
Packit 71fd91
         outStr = stdout;
Packit 71fd91
         if ( isatty ( fileno ( stdout ) ) ) {
Packit 71fd91
            fprintf ( stderr,
Packit 71fd91
                      "%s: I won't write compressed data to a terminal.\n",
Packit 71fd91
                      progName );
Packit 71fd91
            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Packit 71fd91
                              progName, progName );
Packit 71fd91
            if ( inStr != NULL ) fclose ( inStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         if ( inStr == NULL ) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Packit 71fd91
                      progName, inName, strerror(errno) );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      case SM_F2F:
Packit 71fd91
         inStr = fopen ( inName, "rb" );
Packit 71fd91
         outStr = fopen_output_safely ( outName, "wb" );
Packit 71fd91
         if ( outStr == NULL) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
Packit 71fd91
                      progName, outName, strerror(errno) );
Packit 71fd91
            if ( inStr != NULL ) fclose ( inStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         }
Packit 71fd91
         if ( inStr == NULL ) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Packit 71fd91
                      progName, inName, strerror(errno) );
Packit 71fd91
            if ( outStr != NULL ) fclose ( outStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      default:
Packit 71fd91
         panic ( "compress: bad srcMode" );
Packit 71fd91
         break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verbosity >= 1) {
Packit 71fd91
      fprintf ( stderr,  "  %s: ", inName );
Packit 71fd91
      pad ( inName );
Packit 71fd91
      fflush ( stderr );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
Packit 71fd91
   outputHandleJustInCase = outStr;
Packit 71fd91
   deleteOutputOnInterrupt = True;
Packit 71fd91
   compressStream ( inStr, outStr );
Packit 71fd91
   outputHandleJustInCase = NULL;
Packit 71fd91
Packit 71fd91
   /*--- If there was an I/O error, we won't get here. ---*/
Packit 71fd91
   if ( srcMode == SM_F2F ) {
Packit 71fd91
      applySavedTimeInfoToOutputFile ( outName );
Packit 71fd91
      deleteOutputOnInterrupt = False;
Packit 71fd91
      if ( !keepInputFiles ) {
Packit 71fd91
         IntNative retVal = remove ( inName );
Packit 71fd91
         ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void uncompress ( Char *name )
Packit 71fd91
{
Packit 71fd91
   FILE  *inStr;
Packit 71fd91
   FILE  *outStr;
Packit 71fd91
   Int32 n, i;
Packit 71fd91
   Bool  magicNumberOK;
Packit 71fd91
   Bool  cantGuess;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
Packit 71fd91
   if (name == NULL && srcMode != SM_I2O)
Packit 71fd91
      panic ( "uncompress: bad modes\n" );
Packit 71fd91
Packit 71fd91
   cantGuess = False;
Packit 71fd91
   switch (srcMode) {
Packit 71fd91
      case SM_I2O: 
Packit 71fd91
         copyFileName ( inName, (Char*)"(stdin)" );
Packit 71fd91
         copyFileName ( outName, (Char*)"(stdout)" ); 
Packit 71fd91
         break;
Packit 71fd91
      case SM_F2F: 
Packit 71fd91
         copyFileName ( inName, name );
Packit 71fd91
         copyFileName ( outName, name );
Packit 71fd91
         for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
Packit 71fd91
            if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
Packit 71fd91
               goto zzz; 
Packit 71fd91
         cantGuess = True;
Packit 71fd91
         strcat ( outName, ".out" );
Packit 71fd91
         break;
Packit 71fd91
      case SM_F2O: 
Packit 71fd91
         copyFileName ( inName, name );
Packit 71fd91
         copyFileName ( outName, (Char*)"(stdout)" ); 
Packit 71fd91
         break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   zzz:
Packit 71fd91
   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Packit 71fd91
                progName, inName );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Packit 71fd91
      fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Packit 71fd91
                progName, inName, strerror(errno) );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
Packit 71fd91
      MY_STAT(inName, &statBuf);
Packit 71fd91
      if ( MY_S_ISDIR(statBuf.st_mode) ) {
Packit 71fd91
         fprintf( stderr,
Packit 71fd91
                  "%s: Input file %s is a directory.\n",
Packit 71fd91
                  progName,inName);
Packit 71fd91
         setExit(1);
Packit 71fd91
         return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
Packit 71fd91
                progName, inName );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, 
Packit 71fd91
                "%s: Can't guess original name for %s -- using %s\n",
Packit 71fd91
                progName, inName, outName );
Packit 71fd91
      /* just a warning, no return */
Packit 71fd91
   }   
Packit 71fd91
   if ( srcMode == SM_F2F && fileExists ( outName ) ) {
Packit 71fd91
      if (forceOverwrite) {
Packit 71fd91
	remove(outName);
Packit 71fd91
      } else {
Packit 71fd91
        fprintf ( stderr, "%s: Output file %s already exists.\n",
Packit 71fd91
                  progName, outName );
Packit 71fd91
        setExit(1);
Packit 71fd91
        return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode == SM_F2F && !forceOverwrite &&
Packit 71fd91
        (n=countHardLinks ( inName ) ) > 0) {
Packit 71fd91
      fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
Packit 71fd91
                progName, inName, n, n > 1 ? "s" : "" );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if ( srcMode == SM_F2F ) {
Packit 71fd91
      /* Save the file's meta-info before we open it.  Doing it later
Packit 71fd91
         means we mess up the access times. */
Packit 71fd91
      saveInputFileMetaInfo ( inName );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   switch ( srcMode ) {
Packit 71fd91
Packit 71fd91
      case SM_I2O:
Packit 71fd91
         inStr = stdin;
Packit 71fd91
         outStr = stdout;
Packit 71fd91
         if ( isatty ( fileno ( stdin ) ) ) {
Packit 71fd91
            fprintf ( stderr,
Packit 71fd91
                      "%s: I won't read compressed data from a terminal.\n",
Packit 71fd91
                      progName );
Packit 71fd91
            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Packit 71fd91
                              progName, progName );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      case SM_F2O:
Packit 71fd91
         inStr = fopen ( inName, "rb" );
Packit 71fd91
         outStr = stdout;
Packit 71fd91
         if ( inStr == NULL ) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
Packit 71fd91
                      progName, inName, strerror(errno) );
Packit 71fd91
            if ( inStr != NULL ) fclose ( inStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      case SM_F2F:
Packit 71fd91
         inStr = fopen ( inName, "rb" );
Packit 71fd91
         outStr = fopen_output_safely ( outName, "wb" );
Packit 71fd91
         if ( outStr == NULL) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
Packit 71fd91
                      progName, outName, strerror(errno) );
Packit 71fd91
            if ( inStr != NULL ) fclose ( inStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         }
Packit 71fd91
         if ( inStr == NULL ) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
Packit 71fd91
                      progName, inName, strerror(errno) );
Packit 71fd91
            if ( outStr != NULL ) fclose ( outStr );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      default:
Packit 71fd91
         panic ( "uncompress: bad srcMode" );
Packit 71fd91
         break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verbosity >= 1) {
Packit 71fd91
      fprintf ( stderr, "  %s: ", inName );
Packit 71fd91
      pad ( inName );
Packit 71fd91
      fflush ( stderr );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*--- Now the input and output handles are sane.  Do the Biz. ---*/
Packit 71fd91
   outputHandleJustInCase = outStr;
Packit 71fd91
   deleteOutputOnInterrupt = True;
Packit 71fd91
   magicNumberOK = uncompressStream ( inStr, outStr );
Packit 71fd91
   outputHandleJustInCase = NULL;
Packit 71fd91
Packit 71fd91
   /*--- If there was an I/O error, we won't get here. ---*/
Packit 71fd91
   if ( magicNumberOK ) {
Packit 71fd91
      if ( srcMode == SM_F2F ) {
Packit 71fd91
         applySavedTimeInfoToOutputFile ( outName );
Packit 71fd91
         deleteOutputOnInterrupt = False;
Packit 71fd91
         if ( !keepInputFiles ) {
Packit 71fd91
            IntNative retVal = remove ( inName );
Packit 71fd91
            ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
   } else {
Packit 71fd91
      unzFailsExist = True;
Packit 71fd91
      deleteOutputOnInterrupt = False;
Packit 71fd91
      if ( srcMode == SM_F2F ) {
Packit 71fd91
         IntNative retVal = remove ( outName );
Packit 71fd91
         ERROR_IF_NOT_ZERO ( retVal );
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
Packit 71fd91
   if ( magicNumberOK ) {
Packit 71fd91
      if (verbosity >= 1)
Packit 71fd91
         fprintf ( stderr, "done\n" );
Packit 71fd91
   } else {
Packit 71fd91
      setExit(2);
Packit 71fd91
      if (verbosity >= 1)
Packit 71fd91
         fprintf ( stderr, "not a bzip2 file.\n" ); else
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
                   "%s: %s is not a bzip2 file.\n",
Packit 71fd91
                   progName, inName );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void testf ( Char *name )
Packit 71fd91
{
Packit 71fd91
   FILE *inStr;
Packit 71fd91
   Bool allOK;
Packit 71fd91
   struct MY_STAT statBuf;
Packit 71fd91
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
Packit 71fd91
   if (name == NULL && srcMode != SM_I2O)
Packit 71fd91
      panic ( "testf: bad modes\n" );
Packit 71fd91
Packit 71fd91
   copyFileName ( outName, (Char*)"(none)" );
Packit 71fd91
   switch (srcMode) {
Packit 71fd91
      case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break;
Packit 71fd91
      case SM_F2F: copyFileName ( inName, name ); break;
Packit 71fd91
      case SM_F2O: copyFileName ( inName, name ); break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
Packit 71fd91
      if (noisy)
Packit 71fd91
      fprintf ( stderr, "%s: There are no files matching `%s'.\n",
Packit 71fd91
                progName, inName );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
Packit 71fd91
      fprintf ( stderr, "%s: Can't open input %s: %s.\n",
Packit 71fd91
                progName, inName, strerror(errno) );
Packit 71fd91
      setExit(1);
Packit 71fd91
      return;
Packit 71fd91
   }
Packit 71fd91
   if ( srcMode != SM_I2O ) {
Packit 71fd91
      MY_STAT(inName, &statBuf);
Packit 71fd91
      if ( MY_S_ISDIR(statBuf.st_mode) ) {
Packit 71fd91
         fprintf( stderr,
Packit 71fd91
                  "%s: Input file %s is a directory.\n",
Packit 71fd91
                  progName,inName);
Packit 71fd91
         setExit(1);
Packit 71fd91
         return;
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   switch ( srcMode ) {
Packit 71fd91
Packit 71fd91
      case SM_I2O:
Packit 71fd91
         if ( isatty ( fileno ( stdin ) ) ) {
Packit 71fd91
            fprintf ( stderr,
Packit 71fd91
                      "%s: I won't read compressed data from a terminal.\n",
Packit 71fd91
                      progName );
Packit 71fd91
            fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
Packit 71fd91
                              progName, progName );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         inStr = stdin;
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      case SM_F2O: case SM_F2F:
Packit 71fd91
         inStr = fopen ( inName, "rb" );
Packit 71fd91
         if ( inStr == NULL ) {
Packit 71fd91
            fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
Packit 71fd91
                      progName, inName, strerror(errno) );
Packit 71fd91
            setExit(1);
Packit 71fd91
            return;
Packit 71fd91
         };
Packit 71fd91
         break;
Packit 71fd91
Packit 71fd91
      default:
Packit 71fd91
         panic ( "testf: bad srcMode" );
Packit 71fd91
         break;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verbosity >= 1) {
Packit 71fd91
      fprintf ( stderr, "  %s: ", inName );
Packit 71fd91
      pad ( inName );
Packit 71fd91
      fflush ( stderr );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /*--- Now the input handle is sane.  Do the Biz. ---*/
Packit 71fd91
   outputHandleJustInCase = NULL;
Packit 71fd91
   allOK = testStream ( inStr );
Packit 71fd91
Packit 71fd91
   if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
Packit 71fd91
   if (!allOK) testFailsExist = True;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void license ( void )
Packit 71fd91
{
Packit 71fd91
   fprintf ( stderr,
Packit 71fd91
Packit 71fd91
    "bzip2, a block-sorting file compressor.  "
Packit 71fd91
    "Version %s.\n"
Packit 71fd91
    "   \n"
Packit 71fd91
    "   Copyright (C) 1996-2010 by Julian Seward.\n"
Packit 71fd91
    "   \n"
Packit 71fd91
    "   This program is free software; you can redistribute it and/or modify\n"
Packit 71fd91
    "   it under the terms set out in the LICENSE file, which is included\n"
Packit 71fd91
    "   in the bzip2-1.0.6 source distribution.\n"
Packit 71fd91
    "   \n"
Packit 71fd91
    "   This program is distributed in the hope that it will be useful,\n"
Packit 71fd91
    "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
Packit 71fd91
    "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
Packit 71fd91
    "   LICENSE file for more details.\n"
Packit 71fd91
    "   \n",
Packit 71fd91
    BZ2_bzlibVersion()
Packit 71fd91
   );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void usage ( Char *fullProgName )
Packit 71fd91
{
Packit 71fd91
   fprintf (
Packit 71fd91
      stderr,
Packit 71fd91
      "bzip2, a block-sorting file compressor.  "
Packit 71fd91
      "Version %s.\n"
Packit 71fd91
      "\n   usage: %s [flags and input files in any order]\n"
Packit 71fd91
      "\n"
Packit 71fd91
      "   -h --help           print this message\n"
Packit 71fd91
      "   -d --decompress     force decompression\n"
Packit 71fd91
      "   -z --compress       force compression\n"
Packit 71fd91
      "   -k --keep           keep (don't delete) input files\n"
Packit 71fd91
      "   -f --force          overwrite existing output files\n"
Packit 71fd91
      "   -t --test           test compressed file integrity\n"
Packit 71fd91
      "   -c --stdout         output to standard out\n"
Packit 71fd91
      "   -q --quiet          suppress noncritical error messages\n"
Packit 71fd91
      "   -v --verbose        be verbose (a 2nd -v gives more)\n"
Packit 71fd91
      "   -L --license        display software version & license\n"
Packit 71fd91
      "   -V --version        display software version & license\n"
Packit 71fd91
      "   -s --small          use less memory (at most 2500k)\n"
Packit 71fd91
      "   -1 .. -9            set block size to 100k .. 900k\n"
Packit 71fd91
      "   --fast              alias for -1\n"
Packit 71fd91
      "   --best              alias for -9\n"
Packit 71fd91
      "\n"
Packit 71fd91
      "   If invoked as `bzip2', default action is to compress.\n"
Packit 71fd91
      "              as `bunzip2',  default action is to decompress.\n"
Packit 71fd91
      "              as `bzcat', default action is to decompress to stdout.\n"
Packit 71fd91
      "\n"
Packit 71fd91
      "   If no file names are given, bzip2 compresses or decompresses\n"
Packit 71fd91
      "   from standard input to standard output.  You can combine\n"
Packit 71fd91
      "   short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
Packit 71fd91
#     if BZ_UNIX
Packit 71fd91
      "\n"
Packit 71fd91
#     endif
Packit 71fd91
      ,
Packit 71fd91
Packit 71fd91
      BZ2_bzlibVersion(),
Packit 71fd91
      fullProgName
Packit 71fd91
   );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void redundant ( Char* flag )
Packit 71fd91
{
Packit 71fd91
   fprintf ( 
Packit 71fd91
      stderr, 
Packit 71fd91
      "%s: %s is redundant in versions 0.9.5 and above\n",
Packit 71fd91
      progName, flag );
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
/*--
Packit 71fd91
  All the garbage from here to main() is purely to
Packit 71fd91
  implement a linked list of command-line arguments,
Packit 71fd91
  into which main() copies argv[1 .. argc-1].
Packit 71fd91
Packit 71fd91
  The purpose of this exercise is to facilitate 
Packit 71fd91
  the expansion of wildcard characters * and ? in 
Packit 71fd91
  filenames for OSs which don't know how to do it
Packit 71fd91
  themselves, like MSDOS, Windows 95 and NT.
Packit 71fd91
Packit 71fd91
  The actual Dirty Work is done by the platform-
Packit 71fd91
  specific macro APPEND_FILESPEC.
Packit 71fd91
--*/
Packit 71fd91
Packit 71fd91
typedef
Packit 71fd91
   struct zzzz {
Packit 71fd91
      Char        *name;
Packit 71fd91
      struct zzzz *link;
Packit 71fd91
   }
Packit 71fd91
   Cell;
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void *myMalloc ( Int32 n )
Packit 71fd91
{
Packit 71fd91
   void* p;
Packit 71fd91
Packit 71fd91
   p = malloc ( (size_t)n );
Packit 71fd91
   if (p == NULL) outOfMemory ();
Packit 71fd91
   return p;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Cell *mkCell ( void )
Packit 71fd91
{
Packit 71fd91
   Cell *c;
Packit 71fd91
Packit 71fd91
   c = (Cell*) myMalloc ( sizeof ( Cell ) );
Packit 71fd91
   c->name = NULL;
Packit 71fd91
   c->link = NULL;
Packit 71fd91
   return c;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
Cell *snocString ( Cell *root, Char *name )
Packit 71fd91
{
Packit 71fd91
   if (root == NULL) {
Packit 71fd91
      Cell *tmp = mkCell();
Packit 71fd91
      tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
Packit 71fd91
      strcpy ( tmp->name, name );
Packit 71fd91
      return tmp;
Packit 71fd91
   } else {
Packit 71fd91
      Cell *tmp = root;
Packit 71fd91
      while (tmp->link != NULL) tmp = tmp->link;
Packit 71fd91
      tmp->link = snocString ( tmp->link, name );
Packit 71fd91
      return root;
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
static 
Packit 71fd91
void addFlagsFromEnvVar ( Cell** argList, Char* varName ) 
Packit 71fd91
{
Packit 71fd91
   Int32 i, j, k;
Packit 71fd91
   Char *envbase, *p;
Packit 71fd91
Packit 71fd91
   envbase = getenv(varName);
Packit 71fd91
   if (envbase != NULL) {
Packit 71fd91
      p = envbase;
Packit 71fd91
      i = 0;
Packit 71fd91
      while (True) {
Packit 71fd91
         if (p[i] == 0) break;
Packit 71fd91
         p += i;
Packit 71fd91
         i = 0;
Packit 71fd91
         while (isspace((Int32)(p[0]))) p++;
Packit 71fd91
         while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
Packit 71fd91
         if (i > 0) {
Packit 71fd91
            k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
Packit 71fd91
            for (j = 0; j < k; j++) tmpName[j] = p[j];
Packit 71fd91
            tmpName[k] = 0;
Packit 71fd91
            APPEND_FLAG(*argList, tmpName);
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*---------------------------------------------*/
Packit 71fd91
#define ISFLAG(s) (strcmp(aa->name, (s))==0)
Packit 71fd91
Packit 71fd91
IntNative main ( IntNative argc, Char *argv[] )
Packit 71fd91
{
Packit 71fd91
   Int32  i, j;
Packit 71fd91
   Char   *tmp;
Packit 71fd91
   Cell   *argList;
Packit 71fd91
   Cell   *aa;
Packit 71fd91
   Bool   decode;
Packit 71fd91
Packit 71fd91
   /*-- Be really really really paranoid :-) --*/
Packit 71fd91
   if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
Packit 71fd91
       sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
Packit 71fd91
       sizeof(Char)  != 1 || sizeof(UChar)  != 1)
Packit 71fd91
      configError();
Packit 71fd91
Packit 71fd91
   /*-- Initialise --*/
Packit 71fd91
   outputHandleJustInCase  = NULL;
Packit 71fd91
   smallMode               = False;
Packit 71fd91
   keepInputFiles          = False;
Packit 71fd91
   forceOverwrite          = False;
Packit 71fd91
   noisy                   = True;
Packit 71fd91
   verbosity               = 0;
Packit 71fd91
   blockSize100k           = 9;
Packit 71fd91
   testFailsExist          = False;
Packit 71fd91
   unzFailsExist           = False;
Packit 71fd91
   numFileNames            = 0;
Packit 71fd91
   numFilesProcessed       = 0;
Packit 71fd91
   workFactor              = 30;
Packit 71fd91
   deleteOutputOnInterrupt = False;
Packit 71fd91
   exitValue               = 0;
Packit 71fd91
   i = j = 0; /* avoid bogus warning from egcs-1.1.X */
Packit 71fd91
Packit 71fd91
   /*-- Set up signal handlers for mem access errors --*/
Packit 71fd91
   signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
Packit 71fd91
#  if BZ_UNIX
Packit 71fd91
#  ifndef __DJGPP__
Packit 71fd91
   signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
Packit 71fd91
#  endif
Packit 71fd91
#  endif
Packit 71fd91
Packit 71fd91
   copyFileName ( inName,  (Char*)"(none)" );
Packit 71fd91
   copyFileName ( outName, (Char*)"(none)" );
Packit 71fd91
Packit 71fd91
   copyFileName ( progNameReally, argv[0] );
Packit 71fd91
   progName = &progNameReally[0];
Packit 71fd91
   for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
Packit 71fd91
      if (*tmp == PATH_SEP) progName = tmp + 1;
Packit 71fd91
Packit 71fd91
Packit 71fd91
   /*-- Copy flags from env var BZIP2, and 
Packit 71fd91
        expand filename wildcards in arg list.
Packit 71fd91
   --*/
Packit 71fd91
   argList = NULL;
Packit 71fd91
   addFlagsFromEnvVar ( &argList,  (Char*)"BZIP2" );
Packit 71fd91
   addFlagsFromEnvVar ( &argList,  (Char*)"BZIP" );
Packit 71fd91
   for (i = 1; i <= argc-1; i++)
Packit 71fd91
      APPEND_FILESPEC(argList, argv[i]);
Packit 71fd91
Packit 71fd91
Packit 71fd91
   /*-- Find the length of the longest filename --*/
Packit 71fd91
   longestFileName = 7;
Packit 71fd91
   numFileNames    = 0;
Packit 71fd91
   decode          = True;
Packit 71fd91
   for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
      if (ISFLAG("--")) { decode = False; continue; }
Packit 71fd91
      if (aa->name[0] == '-' && decode) continue;
Packit 71fd91
      numFileNames++;
Packit 71fd91
      if (longestFileName < (Int32)strlen(aa->name) )
Packit 71fd91
         longestFileName = (Int32)strlen(aa->name);
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
Packit 71fd91
   /*-- Determine source modes; flag handling may change this too. --*/
Packit 71fd91
   if (numFileNames == 0)
Packit 71fd91
      srcMode = SM_I2O; else srcMode = SM_F2F;
Packit 71fd91
Packit 71fd91
Packit 71fd91
   /*-- Determine what to do (compress/uncompress/test/cat). --*/
Packit 71fd91
   /*-- Note that subsequent flag handling may change this. --*/
Packit 71fd91
   opMode = OM_Z;
Packit 71fd91
Packit 71fd91
   if ( (strstr ( progName, "unzip" ) != 0) ||
Packit 71fd91
        (strstr ( progName, "UNZIP" ) != 0) )
Packit 71fd91
      opMode = OM_UNZ;
Packit 71fd91
Packit 71fd91
   if ( (strstr ( progName, "z2cat" ) != 0) ||
Packit 71fd91
        (strstr ( progName, "Z2CAT" ) != 0) ||
Packit 71fd91
        (strstr ( progName, "zcat" ) != 0)  ||
Packit 71fd91
        (strstr ( progName, "ZCAT" ) != 0) )  {
Packit 71fd91
      opMode = OM_UNZ;
Packit 71fd91
      srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
Packit 71fd91
   /*-- Look at the flags. --*/
Packit 71fd91
   for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
      if (ISFLAG("--")) break;
Packit 71fd91
      if (aa->name[0] == '-' && aa->name[1] != '-') {
Packit 71fd91
         for (j = 1; aa->name[j] != '\0'; j++) {
Packit 71fd91
            switch (aa->name[j]) {
Packit 71fd91
               case 'c': srcMode          = SM_F2O; break;
Packit 71fd91
               case 'd': opMode           = OM_UNZ; break;
Packit 71fd91
               case 'z': opMode           = OM_Z; break;
Packit 71fd91
               case 'f': forceOverwrite   = True; break;
Packit 71fd91
               case 't': opMode           = OM_TEST; break;
Packit 71fd91
               case 'k': keepInputFiles   = True; break;
Packit 71fd91
               case 's': smallMode        = True; break;
Packit 71fd91
               case 'q': noisy            = False; break;
Packit 71fd91
               case '1': blockSize100k    = 1; break;
Packit 71fd91
               case '2': blockSize100k    = 2; break;
Packit 71fd91
               case '3': blockSize100k    = 3; break;
Packit 71fd91
               case '4': blockSize100k    = 4; break;
Packit 71fd91
               case '5': blockSize100k    = 5; break;
Packit 71fd91
               case '6': blockSize100k    = 6; break;
Packit 71fd91
               case '7': blockSize100k    = 7; break;
Packit 71fd91
               case '8': blockSize100k    = 8; break;
Packit 71fd91
               case '9': blockSize100k    = 9; break;
Packit 71fd91
               case 'V':
Packit 71fd91
               case 'L': license();            break;
Packit 71fd91
               case 'v': verbosity++; break;
Packit 71fd91
               case 'h': usage ( progName );
Packit 71fd91
                         exit ( 0 );
Packit 71fd91
                         break;
Packit 71fd91
               default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
Packit 71fd91
                                   progName, aa->name );
Packit 71fd91
                         usage ( progName );
Packit 71fd91
                         exit ( 1 );
Packit 71fd91
                         break;
Packit 71fd91
            }
Packit 71fd91
         }
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
   
Packit 71fd91
   /*-- And again ... --*/
Packit 71fd91
   for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
      if (ISFLAG("--")) break;
Packit 71fd91
      if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
Packit 71fd91
      if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
Packit 71fd91
      if (ISFLAG("--compress"))          opMode           = OM_Z;    else
Packit 71fd91
      if (ISFLAG("--force"))             forceOverwrite   = True;    else
Packit 71fd91
      if (ISFLAG("--test"))              opMode           = OM_TEST; else
Packit 71fd91
      if (ISFLAG("--keep"))              keepInputFiles   = True;    else
Packit 71fd91
      if (ISFLAG("--small"))             smallMode        = True;    else
Packit 71fd91
      if (ISFLAG("--quiet"))             noisy            = False;   else
Packit 71fd91
      if (ISFLAG("--version"))           license();                  else
Packit 71fd91
      if (ISFLAG("--license"))           license();                  else
Packit 71fd91
      if (ISFLAG("--exponential"))       workFactor = 1;             else 
Packit 71fd91
      if (ISFLAG("--repetitive-best"))   redundant(aa->name);        else
Packit 71fd91
      if (ISFLAG("--repetitive-fast"))   redundant(aa->name);        else
Packit 71fd91
      if (ISFLAG("--fast"))              blockSize100k = 1;          else
Packit 71fd91
      if (ISFLAG("--best"))              blockSize100k = 9;          else
Packit 71fd91
      if (ISFLAG("--verbose"))           verbosity++;                else
Packit 71fd91
      if (ISFLAG("--help"))              { usage ( progName ); exit ( 0 ); }
Packit 71fd91
         else
Packit 71fd91
         if (strncmp ( aa->name, "--", 2) == 0) {
Packit 71fd91
            fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
Packit 71fd91
            usage ( progName );
Packit 71fd91
            exit ( 1 );
Packit 71fd91
         }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (verbosity > 4) verbosity = 4;
Packit 71fd91
   if (opMode == OM_Z && smallMode && blockSize100k > 2) 
Packit 71fd91
      blockSize100k = 2;
Packit 71fd91
Packit 71fd91
   if (opMode == OM_TEST && srcMode == SM_F2O) {
Packit 71fd91
      fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
Packit 71fd91
                progName );
Packit 71fd91
      exit ( 1 );
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (srcMode == SM_F2O && numFileNames == 0)
Packit 71fd91
      srcMode = SM_I2O;
Packit 71fd91
Packit 71fd91
   if (opMode != OM_Z) blockSize100k = 0;
Packit 71fd91
Packit 71fd91
   if (srcMode == SM_F2F) {
Packit 71fd91
      signal (SIGINT,  mySignalCatcher);
Packit 71fd91
      signal (SIGTERM, mySignalCatcher);
Packit 71fd91
#     if BZ_UNIX
Packit 71fd91
      signal (SIGHUP,  mySignalCatcher);
Packit 71fd91
#     endif
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   if (opMode == OM_Z) {
Packit 71fd91
     if (srcMode == SM_I2O) {
Packit 71fd91
        compress ( NULL );
Packit 71fd91
     } else {
Packit 71fd91
        decode = True;
Packit 71fd91
        for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
           if (ISFLAG("--")) { decode = False; continue; }
Packit 71fd91
           if (aa->name[0] == '-' && decode) continue;
Packit 71fd91
           numFilesProcessed++;
Packit 71fd91
           compress ( aa->name );
Packit 71fd91
        }
Packit 71fd91
     }
Packit 71fd91
   } 
Packit 71fd91
   else
Packit 71fd91
Packit 71fd91
   if (opMode == OM_UNZ) {
Packit 71fd91
      unzFailsExist = False;
Packit 71fd91
      if (srcMode == SM_I2O) {
Packit 71fd91
         uncompress ( NULL );
Packit 71fd91
      } else {
Packit 71fd91
         decode = True;
Packit 71fd91
         for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
            if (ISFLAG("--")) { decode = False; continue; }
Packit 71fd91
            if (aa->name[0] == '-' && decode) continue;
Packit 71fd91
            numFilesProcessed++;
Packit 71fd91
            uncompress ( aa->name );
Packit 71fd91
         }      
Packit 71fd91
      }
Packit 71fd91
      if (unzFailsExist) { 
Packit 71fd91
         setExit(2); 
Packit 71fd91
         exit(exitValue);
Packit 71fd91
      }
Packit 71fd91
   } 
Packit 71fd91
Packit 71fd91
   else {
Packit 71fd91
      testFailsExist = False;
Packit 71fd91
      if (srcMode == SM_I2O) {
Packit 71fd91
         testf ( NULL );
Packit 71fd91
      } else {
Packit 71fd91
         decode = True;
Packit 71fd91
         for (aa = argList; aa != NULL; aa = aa->link) {
Packit 71fd91
	    if (ISFLAG("--")) { decode = False; continue; }
Packit 71fd91
            if (aa->name[0] == '-' && decode) continue;
Packit 71fd91
            numFilesProcessed++;
Packit 71fd91
            testf ( aa->name );
Packit 71fd91
	 }
Packit 71fd91
      }
Packit 71fd91
      if (testFailsExist && noisy) {
Packit 71fd91
         fprintf ( stderr,
Packit 71fd91
           "\n"
Packit 71fd91
           "You can use the `bzip2recover' program to attempt to recover\n"
Packit 71fd91
           "data from undamaged sections of corrupted files.\n\n"
Packit 71fd91
         );
Packit 71fd91
         setExit(2);
Packit 71fd91
         exit(exitValue);
Packit 71fd91
      }
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   /* Free the argument list memory to mollify leak detectors 
Packit 71fd91
      (eg) Purify, Checker.  Serves no other useful purpose.
Packit 71fd91
   */
Packit 71fd91
   aa = argList;
Packit 71fd91
   while (aa != NULL) {
Packit 71fd91
      Cell* aa2 = aa->link;
Packit 71fd91
      if (aa->name != NULL) free(aa->name);
Packit 71fd91
      free(aa);
Packit 71fd91
      aa = aa2;
Packit 71fd91
   }
Packit 71fd91
Packit 71fd91
   return exitValue;
Packit 71fd91
}
Packit 71fd91
Packit 71fd91
Packit 71fd91
/*-----------------------------------------------------------*/
Packit 71fd91
/*--- end                                         bzip2.c ---*/
Packit 71fd91
/*-----------------------------------------------------------*/