xref: /dragonfly/contrib/bzip2/bzip2.c (revision 86954436)
171e7ee59SPeter Avalos 
271e7ee59SPeter Avalos /*-----------------------------------------------------------*/
371e7ee59SPeter Avalos /*--- A block-sorting, lossless compressor        bzip2.c ---*/
471e7ee59SPeter Avalos /*-----------------------------------------------------------*/
571e7ee59SPeter Avalos 
671e7ee59SPeter Avalos /* ------------------------------------------------------------------
771e7ee59SPeter Avalos    This file is part of bzip2/libbzip2, a program and library for
871e7ee59SPeter Avalos    lossless, block-sorting data compression.
971e7ee59SPeter Avalos 
10*86954436SDaniel Fojt    bzip2/libbzip2 version 1.0.8 of 13 July 2019
11*86954436SDaniel Fojt    Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
1271e7ee59SPeter Avalos 
1371e7ee59SPeter Avalos    Please read the WARNING, DISCLAIMER and PATENTS sections in the
1471e7ee59SPeter Avalos    README file.
1571e7ee59SPeter Avalos 
1671e7ee59SPeter Avalos    This program is released under the terms of the license contained
1771e7ee59SPeter Avalos    in the file LICENSE.
1871e7ee59SPeter Avalos    ------------------------------------------------------------------ */
1971e7ee59SPeter Avalos 
2071e7ee59SPeter Avalos 
2171e7ee59SPeter Avalos /* Place a 1 beside your platform, and 0 elsewhere.
2271e7ee59SPeter Avalos    Generic 32-bit Unix.
2371e7ee59SPeter Avalos    Also works on 64-bit Unix boxes.
2471e7ee59SPeter Avalos    This is the default.
2571e7ee59SPeter Avalos */
2671e7ee59SPeter Avalos #define BZ_UNIX      1
2771e7ee59SPeter Avalos 
2871e7ee59SPeter Avalos /*--
2971e7ee59SPeter Avalos   Win32, as seen by Jacob Navia's excellent
3071e7ee59SPeter Avalos   port of (Chris Fraser & David Hanson)'s excellent
3171e7ee59SPeter Avalos   lcc compiler.  Or with MS Visual C.
3271e7ee59SPeter Avalos   This is selected automatically if compiled by a compiler which
3371e7ee59SPeter Avalos   defines _WIN32, not including the Cygwin GCC.
3471e7ee59SPeter Avalos --*/
3571e7ee59SPeter Avalos #define BZ_LCCWIN32  0
3671e7ee59SPeter Avalos 
3771e7ee59SPeter Avalos #if defined(_WIN32) && !defined(__CYGWIN__)
3871e7ee59SPeter Avalos #undef  BZ_LCCWIN32
3971e7ee59SPeter Avalos #define BZ_LCCWIN32 1
4071e7ee59SPeter Avalos #undef  BZ_UNIX
4171e7ee59SPeter Avalos #define BZ_UNIX 0
4271e7ee59SPeter Avalos #endif
4371e7ee59SPeter Avalos 
4471e7ee59SPeter Avalos 
4571e7ee59SPeter Avalos /*---------------------------------------------*/
4671e7ee59SPeter Avalos /*--
4771e7ee59SPeter Avalos   Some stuff for all platforms.
4871e7ee59SPeter Avalos --*/
4971e7ee59SPeter Avalos 
5071e7ee59SPeter Avalos #include <stdio.h>
5171e7ee59SPeter Avalos #include <stdlib.h>
5271e7ee59SPeter Avalos #include <string.h>
5371e7ee59SPeter Avalos #include <signal.h>
5471e7ee59SPeter Avalos #include <math.h>
5571e7ee59SPeter Avalos #include <errno.h>
5671e7ee59SPeter Avalos #include <ctype.h>
5771e7ee59SPeter Avalos #include "bzlib.h"
5871e7ee59SPeter Avalos 
5971e7ee59SPeter Avalos #define ERROR_IF_EOF(i)       { if ((i) == EOF)  ioError(); }
6071e7ee59SPeter Avalos #define ERROR_IF_NOT_ZERO(i)  { if ((i) != 0)    ioError(); }
6171e7ee59SPeter Avalos #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
6271e7ee59SPeter Avalos 
6371e7ee59SPeter Avalos 
6471e7ee59SPeter Avalos /*---------------------------------------------*/
6571e7ee59SPeter Avalos /*--
6671e7ee59SPeter Avalos    Platform-specific stuff.
6771e7ee59SPeter Avalos --*/
6871e7ee59SPeter Avalos 
6971e7ee59SPeter Avalos #if BZ_UNIX
7071e7ee59SPeter Avalos #   include <fcntl.h>
7171e7ee59SPeter Avalos #   include <sys/types.h>
7271e7ee59SPeter Avalos #   include <utime.h>
7371e7ee59SPeter Avalos #   include <unistd.h>
7471e7ee59SPeter Avalos #   include <sys/stat.h>
7571e7ee59SPeter Avalos #   include <sys/times.h>
7671e7ee59SPeter Avalos 
7771e7ee59SPeter Avalos #   define PATH_SEP    '/'
7871e7ee59SPeter Avalos #   define MY_LSTAT    lstat
7971e7ee59SPeter Avalos #   define MY_STAT     stat
8071e7ee59SPeter Avalos #   define MY_S_ISREG  S_ISREG
8171e7ee59SPeter Avalos #   define MY_S_ISDIR  S_ISDIR
8271e7ee59SPeter Avalos 
8371e7ee59SPeter Avalos #   define APPEND_FILESPEC(root, name) \
8471e7ee59SPeter Avalos       root=snocString((root), (name))
8571e7ee59SPeter Avalos 
8671e7ee59SPeter Avalos #   define APPEND_FLAG(root, name) \
8771e7ee59SPeter Avalos       root=snocString((root), (name))
8871e7ee59SPeter Avalos 
8971e7ee59SPeter Avalos #   define SET_BINARY_MODE(fd) /**/
9071e7ee59SPeter Avalos 
9171e7ee59SPeter Avalos #   ifdef __GNUC__
9271e7ee59SPeter Avalos #      define NORETURN __attribute__ ((noreturn))
9371e7ee59SPeter Avalos #   else
9471e7ee59SPeter Avalos #      define NORETURN /**/
9571e7ee59SPeter Avalos #   endif
9671e7ee59SPeter Avalos 
9771e7ee59SPeter Avalos #   ifdef __DJGPP__
9871e7ee59SPeter Avalos #     include <io.h>
9971e7ee59SPeter Avalos #     include <fcntl.h>
10071e7ee59SPeter Avalos #     undef MY_LSTAT
10171e7ee59SPeter Avalos #     undef MY_STAT
10271e7ee59SPeter Avalos #     define MY_LSTAT stat
10371e7ee59SPeter Avalos #     define MY_STAT stat
10471e7ee59SPeter Avalos #     undef SET_BINARY_MODE
10571e7ee59SPeter Avalos #     define SET_BINARY_MODE(fd)                        \
10671e7ee59SPeter Avalos         do {                                            \
10771e7ee59SPeter Avalos            int retVal = setmode ( fileno ( fd ),        \
10871e7ee59SPeter Avalos                                   O_BINARY );           \
10971e7ee59SPeter Avalos            ERROR_IF_MINUS_ONE ( retVal );               \
11071e7ee59SPeter Avalos         } while ( 0 )
11171e7ee59SPeter Avalos #   endif
11271e7ee59SPeter Avalos 
11371e7ee59SPeter Avalos #   ifdef __CYGWIN__
11471e7ee59SPeter Avalos #     include <io.h>
11571e7ee59SPeter Avalos #     include <fcntl.h>
11671e7ee59SPeter Avalos #     undef SET_BINARY_MODE
11771e7ee59SPeter Avalos #     define SET_BINARY_MODE(fd)                        \
11871e7ee59SPeter Avalos         do {                                            \
11971e7ee59SPeter Avalos            int retVal = setmode ( fileno ( fd ),        \
12071e7ee59SPeter Avalos                                   O_BINARY );           \
12171e7ee59SPeter Avalos            ERROR_IF_MINUS_ONE ( retVal );               \
12271e7ee59SPeter Avalos         } while ( 0 )
12371e7ee59SPeter Avalos #   endif
12471e7ee59SPeter Avalos #endif /* BZ_UNIX */
12571e7ee59SPeter Avalos 
12671e7ee59SPeter Avalos 
12771e7ee59SPeter Avalos 
12871e7ee59SPeter Avalos #if BZ_LCCWIN32
12971e7ee59SPeter Avalos #   include <io.h>
13071e7ee59SPeter Avalos #   include <fcntl.h>
131*86954436SDaniel Fojt #   include <sys/stat.h>
13271e7ee59SPeter Avalos 
13371e7ee59SPeter Avalos #   define NORETURN       /**/
13471e7ee59SPeter Avalos #   define PATH_SEP       '\\'
135*86954436SDaniel Fojt #   define MY_LSTAT       _stati64
136*86954436SDaniel Fojt #   define MY_STAT        _stati64
13771e7ee59SPeter Avalos #   define MY_S_ISREG(x)  ((x) & _S_IFREG)
13871e7ee59SPeter Avalos #   define MY_S_ISDIR(x)  ((x) & _S_IFDIR)
13971e7ee59SPeter Avalos 
14071e7ee59SPeter Avalos #   define APPEND_FLAG(root, name) \
14171e7ee59SPeter Avalos       root=snocString((root), (name))
14271e7ee59SPeter Avalos 
14371e7ee59SPeter Avalos #   define APPEND_FILESPEC(root, name)                \
14471e7ee59SPeter Avalos       root = snocString ((root), (name))
14571e7ee59SPeter Avalos 
14671e7ee59SPeter Avalos #   define SET_BINARY_MODE(fd)                        \
14771e7ee59SPeter Avalos       do {                                            \
14871e7ee59SPeter Avalos          int retVal = setmode ( fileno ( fd ),        \
14971e7ee59SPeter Avalos                                 O_BINARY );           \
15071e7ee59SPeter Avalos          ERROR_IF_MINUS_ONE ( retVal );               \
15171e7ee59SPeter Avalos       } while ( 0 )
15271e7ee59SPeter Avalos 
15371e7ee59SPeter Avalos #endif /* BZ_LCCWIN32 */
15471e7ee59SPeter Avalos 
15571e7ee59SPeter Avalos 
15671e7ee59SPeter Avalos /*---------------------------------------------*/
15771e7ee59SPeter Avalos /*--
15871e7ee59SPeter Avalos   Some more stuff for all platforms :-)
15971e7ee59SPeter Avalos --*/
16071e7ee59SPeter Avalos 
16171e7ee59SPeter Avalos typedef char            Char;
16271e7ee59SPeter Avalos typedef unsigned char   Bool;
16371e7ee59SPeter Avalos typedef unsigned char   UChar;
16471e7ee59SPeter Avalos typedef int             Int32;
16571e7ee59SPeter Avalos typedef unsigned int    UInt32;
16671e7ee59SPeter Avalos typedef short           Int16;
16771e7ee59SPeter Avalos typedef unsigned short  UInt16;
16871e7ee59SPeter Avalos 
16971e7ee59SPeter Avalos #define True  ((Bool)1)
17071e7ee59SPeter Avalos #define False ((Bool)0)
17171e7ee59SPeter Avalos 
17271e7ee59SPeter Avalos /*--
17371e7ee59SPeter Avalos   IntNative is your platform's `native' int size.
17471e7ee59SPeter Avalos   Only here to avoid probs with 64-bit platforms.
17571e7ee59SPeter Avalos --*/
17671e7ee59SPeter Avalos typedef int IntNative;
17771e7ee59SPeter Avalos 
17871e7ee59SPeter Avalos 
17971e7ee59SPeter Avalos /*---------------------------------------------------*/
18071e7ee59SPeter Avalos /*--- Misc (file handling) data decls             ---*/
18171e7ee59SPeter Avalos /*---------------------------------------------------*/
18271e7ee59SPeter Avalos 
18371e7ee59SPeter Avalos Int32   verbosity;
18471e7ee59SPeter Avalos Bool    keepInputFiles, smallMode, deleteOutputOnInterrupt;
18571e7ee59SPeter Avalos Bool    forceOverwrite, testFailsExist, unzFailsExist, noisy;
18671e7ee59SPeter Avalos Int32   numFileNames, numFilesProcessed, blockSize100k;
18771e7ee59SPeter Avalos Int32   exitValue;
18871e7ee59SPeter Avalos 
18971e7ee59SPeter Avalos /*-- source modes; F==file, I==stdin, O==stdout --*/
19071e7ee59SPeter Avalos #define SM_I2O           1
19171e7ee59SPeter Avalos #define SM_F2O           2
19271e7ee59SPeter Avalos #define SM_F2F           3
19371e7ee59SPeter Avalos 
19471e7ee59SPeter Avalos /*-- operation modes --*/
19571e7ee59SPeter Avalos #define OM_Z             1
19671e7ee59SPeter Avalos #define OM_UNZ           2
19771e7ee59SPeter Avalos #define OM_TEST          3
19871e7ee59SPeter Avalos 
19971e7ee59SPeter Avalos Int32   opMode;
20071e7ee59SPeter Avalos Int32   srcMode;
20171e7ee59SPeter Avalos 
20271e7ee59SPeter Avalos #define FILE_NAME_LEN 1034
20371e7ee59SPeter Avalos 
20471e7ee59SPeter Avalos Int32   longestFileName;
20571e7ee59SPeter Avalos Char    inName [FILE_NAME_LEN];
20671e7ee59SPeter Avalos Char    outName[FILE_NAME_LEN];
20771e7ee59SPeter Avalos Char    tmpName[FILE_NAME_LEN];
20871e7ee59SPeter Avalos Char    *progName;
20971e7ee59SPeter Avalos Char    progNameReally[FILE_NAME_LEN];
21071e7ee59SPeter Avalos FILE    *outputHandleJustInCase;
21171e7ee59SPeter Avalos Int32   workFactor;
21271e7ee59SPeter Avalos 
21371e7ee59SPeter Avalos static void    panic                 ( const Char* ) NORETURN;
21471e7ee59SPeter Avalos static void    ioError               ( void )        NORETURN;
21571e7ee59SPeter Avalos static void    outOfMemory           ( void )        NORETURN;
21671e7ee59SPeter Avalos static void    configError           ( void )        NORETURN;
21771e7ee59SPeter Avalos static void    crcError              ( void )        NORETURN;
21871e7ee59SPeter Avalos static void    cleanUpAndFail        ( Int32 )       NORETURN;
21971e7ee59SPeter Avalos static void    compressedStreamEOF   ( void )        NORETURN;
22071e7ee59SPeter Avalos 
22171e7ee59SPeter Avalos static void    copyFileName ( Char*, Char* );
22271e7ee59SPeter Avalos static void*   myMalloc     ( Int32 );
22371e7ee59SPeter Avalos static void    applySavedFileAttrToOutputFile ( IntNative fd );
22471e7ee59SPeter Avalos 
22571e7ee59SPeter Avalos 
22671e7ee59SPeter Avalos 
22771e7ee59SPeter Avalos /*---------------------------------------------------*/
22871e7ee59SPeter Avalos /*--- An implementation of 64-bit ints.  Sigh.    ---*/
22971e7ee59SPeter Avalos /*--- Roll on widespread deployment of ANSI C9X ! ---*/
23071e7ee59SPeter Avalos /*---------------------------------------------------*/
23171e7ee59SPeter Avalos 
23271e7ee59SPeter Avalos typedef
23371e7ee59SPeter Avalos    struct { UChar b[8]; }
23471e7ee59SPeter Avalos    UInt64;
23571e7ee59SPeter Avalos 
23671e7ee59SPeter Avalos 
23771e7ee59SPeter Avalos static
uInt64_from_UInt32s(UInt64 * n,UInt32 lo32,UInt32 hi32)23871e7ee59SPeter Avalos void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
23971e7ee59SPeter Avalos {
24071e7ee59SPeter Avalos    n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
24171e7ee59SPeter Avalos    n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
24271e7ee59SPeter Avalos    n->b[5] = (UChar)((hi32 >> 8)  & 0xFF);
24371e7ee59SPeter Avalos    n->b[4] = (UChar) (hi32        & 0xFF);
24471e7ee59SPeter Avalos    n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
24571e7ee59SPeter Avalos    n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
24671e7ee59SPeter Avalos    n->b[1] = (UChar)((lo32 >> 8)  & 0xFF);
24771e7ee59SPeter Avalos    n->b[0] = (UChar) (lo32        & 0xFF);
24871e7ee59SPeter Avalos }
24971e7ee59SPeter Avalos 
25071e7ee59SPeter Avalos 
25171e7ee59SPeter Avalos static
uInt64_to_double(UInt64 * n)25271e7ee59SPeter Avalos double uInt64_to_double ( UInt64* n )
25371e7ee59SPeter Avalos {
25471e7ee59SPeter Avalos    Int32  i;
25571e7ee59SPeter Avalos    double base = 1.0;
25671e7ee59SPeter Avalos    double sum  = 0.0;
25771e7ee59SPeter Avalos    for (i = 0; i < 8; i++) {
25871e7ee59SPeter Avalos       sum  += base * (double)(n->b[i]);
25971e7ee59SPeter Avalos       base *= 256.0;
26071e7ee59SPeter Avalos    }
26171e7ee59SPeter Avalos    return sum;
26271e7ee59SPeter Avalos }
26371e7ee59SPeter Avalos 
26471e7ee59SPeter Avalos 
26571e7ee59SPeter Avalos static
uInt64_isZero(UInt64 * n)26671e7ee59SPeter Avalos Bool uInt64_isZero ( UInt64* n )
26771e7ee59SPeter Avalos {
26871e7ee59SPeter Avalos    Int32 i;
26971e7ee59SPeter Avalos    for (i = 0; i < 8; i++)
27071e7ee59SPeter Avalos       if (n->b[i] != 0) return 0;
27171e7ee59SPeter Avalos    return 1;
27271e7ee59SPeter Avalos }
27371e7ee59SPeter Avalos 
27471e7ee59SPeter Avalos 
27571e7ee59SPeter Avalos /* Divide *n by 10, and return the remainder.  */
27671e7ee59SPeter Avalos static
uInt64_qrm10(UInt64 * n)27771e7ee59SPeter Avalos Int32 uInt64_qrm10 ( UInt64* n )
27871e7ee59SPeter Avalos {
27971e7ee59SPeter Avalos    UInt32 rem, tmp;
28071e7ee59SPeter Avalos    Int32  i;
28171e7ee59SPeter Avalos    rem = 0;
28271e7ee59SPeter Avalos    for (i = 7; i >= 0; i--) {
28371e7ee59SPeter Avalos       tmp = rem * 256 + n->b[i];
28471e7ee59SPeter Avalos       n->b[i] = tmp / 10;
28571e7ee59SPeter Avalos       rem = tmp % 10;
28671e7ee59SPeter Avalos    }
28771e7ee59SPeter Avalos    return rem;
28871e7ee59SPeter Avalos }
28971e7ee59SPeter Avalos 
29071e7ee59SPeter Avalos 
29171e7ee59SPeter Avalos /* ... and the Whole Entire Point of all this UInt64 stuff is
29271e7ee59SPeter Avalos    so that we can supply the following function.
29371e7ee59SPeter Avalos */
29471e7ee59SPeter Avalos static
uInt64_toAscii(char * outbuf,UInt64 * n)29571e7ee59SPeter Avalos void uInt64_toAscii ( char* outbuf, UInt64* n )
29671e7ee59SPeter Avalos {
29771e7ee59SPeter Avalos    Int32  i, q;
29871e7ee59SPeter Avalos    UChar  buf[32];
29971e7ee59SPeter Avalos    Int32  nBuf   = 0;
30071e7ee59SPeter Avalos    UInt64 n_copy = *n;
30171e7ee59SPeter Avalos    do {
30271e7ee59SPeter Avalos       q = uInt64_qrm10 ( &n_copy );
30371e7ee59SPeter Avalos       buf[nBuf] = q + '0';
30471e7ee59SPeter Avalos       nBuf++;
30571e7ee59SPeter Avalos    } while (!uInt64_isZero(&n_copy));
30671e7ee59SPeter Avalos    outbuf[nBuf] = 0;
30771e7ee59SPeter Avalos    for (i = 0; i < nBuf; i++)
30871e7ee59SPeter Avalos       outbuf[i] = buf[nBuf-i-1];
30971e7ee59SPeter Avalos }
31071e7ee59SPeter Avalos 
31171e7ee59SPeter Avalos 
31271e7ee59SPeter Avalos /*---------------------------------------------------*/
31371e7ee59SPeter Avalos /*--- Processing of complete files and streams    ---*/
31471e7ee59SPeter Avalos /*---------------------------------------------------*/
31571e7ee59SPeter Avalos 
31671e7ee59SPeter Avalos /*---------------------------------------------*/
31771e7ee59SPeter Avalos static
myfeof(FILE * f)31871e7ee59SPeter Avalos Bool myfeof ( FILE* f )
31971e7ee59SPeter Avalos {
32071e7ee59SPeter Avalos    Int32 c = fgetc ( f );
32171e7ee59SPeter Avalos    if (c == EOF) return True;
32271e7ee59SPeter Avalos    ungetc ( c, f );
32371e7ee59SPeter Avalos    return False;
32471e7ee59SPeter Avalos }
32571e7ee59SPeter Avalos 
32671e7ee59SPeter Avalos 
32771e7ee59SPeter Avalos /*---------------------------------------------*/
32871e7ee59SPeter Avalos static
compressStream(FILE * stream,FILE * zStream)32971e7ee59SPeter Avalos void compressStream ( FILE *stream, FILE *zStream )
33071e7ee59SPeter Avalos {
33171e7ee59SPeter Avalos    BZFILE* bzf = NULL;
33271e7ee59SPeter Avalos    UChar   ibuf[5000];
33371e7ee59SPeter Avalos    Int32   nIbuf;
33471e7ee59SPeter Avalos    UInt32  nbytes_in_lo32, nbytes_in_hi32;
33571e7ee59SPeter Avalos    UInt32  nbytes_out_lo32, nbytes_out_hi32;
33671e7ee59SPeter Avalos    Int32   bzerr, bzerr_dummy, ret;
33771e7ee59SPeter Avalos 
33871e7ee59SPeter Avalos    SET_BINARY_MODE(stream);
33971e7ee59SPeter Avalos    SET_BINARY_MODE(zStream);
34071e7ee59SPeter Avalos 
34171e7ee59SPeter Avalos    if (ferror(stream)) goto errhandler_io;
34271e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
34371e7ee59SPeter Avalos 
34471e7ee59SPeter Avalos    bzf = BZ2_bzWriteOpen ( &bzerr, zStream,
34571e7ee59SPeter Avalos                            blockSize100k, verbosity, workFactor );
34671e7ee59SPeter Avalos    if (bzerr != BZ_OK) goto errhandler;
34771e7ee59SPeter Avalos 
34871e7ee59SPeter Avalos    if (verbosity >= 2) fprintf ( stderr, "\n" );
34971e7ee59SPeter Avalos 
35071e7ee59SPeter Avalos    while (True) {
35171e7ee59SPeter Avalos 
35271e7ee59SPeter Avalos       if (myfeof(stream)) break;
35371e7ee59SPeter Avalos       nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
35471e7ee59SPeter Avalos       if (ferror(stream)) goto errhandler_io;
35571e7ee59SPeter Avalos       if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
35671e7ee59SPeter Avalos       if (bzerr != BZ_OK) goto errhandler;
35771e7ee59SPeter Avalos 
35871e7ee59SPeter Avalos    }
35971e7ee59SPeter Avalos 
36071e7ee59SPeter Avalos    BZ2_bzWriteClose64 ( &bzerr, bzf, 0,
36171e7ee59SPeter Avalos                         &nbytes_in_lo32, &nbytes_in_hi32,
36271e7ee59SPeter Avalos                         &nbytes_out_lo32, &nbytes_out_hi32 );
36371e7ee59SPeter Avalos    if (bzerr != BZ_OK) goto errhandler;
36471e7ee59SPeter Avalos 
36571e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
36671e7ee59SPeter Avalos    ret = fflush ( zStream );
36771e7ee59SPeter Avalos    if (ret == EOF) goto errhandler_io;
36871e7ee59SPeter Avalos    if (zStream != stdout) {
36971e7ee59SPeter Avalos       Int32 fd = fileno ( zStream );
37071e7ee59SPeter Avalos       if (fd < 0) goto errhandler_io;
37171e7ee59SPeter Avalos       applySavedFileAttrToOutputFile ( fd );
37271e7ee59SPeter Avalos       ret = fclose ( zStream );
37371e7ee59SPeter Avalos       outputHandleJustInCase = NULL;
37471e7ee59SPeter Avalos       if (ret == EOF) goto errhandler_io;
37571e7ee59SPeter Avalos    }
37671e7ee59SPeter Avalos    outputHandleJustInCase = NULL;
37771e7ee59SPeter Avalos    if (ferror(stream)) goto errhandler_io;
37871e7ee59SPeter Avalos    ret = fclose ( stream );
37971e7ee59SPeter Avalos    if (ret == EOF) goto errhandler_io;
38071e7ee59SPeter Avalos 
38171e7ee59SPeter Avalos    if (verbosity >= 1) {
38271e7ee59SPeter Avalos       if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
38371e7ee59SPeter Avalos 	 fprintf ( stderr, " no data compressed.\n");
38471e7ee59SPeter Avalos       } else {
38571e7ee59SPeter Avalos 	 Char   buf_nin[32], buf_nout[32];
38671e7ee59SPeter Avalos 	 UInt64 nbytes_in,   nbytes_out;
38771e7ee59SPeter Avalos 	 double nbytes_in_d, nbytes_out_d;
38871e7ee59SPeter Avalos 	 uInt64_from_UInt32s ( &nbytes_in,
38971e7ee59SPeter Avalos 			       nbytes_in_lo32, nbytes_in_hi32 );
39071e7ee59SPeter Avalos 	 uInt64_from_UInt32s ( &nbytes_out,
39171e7ee59SPeter Avalos 			       nbytes_out_lo32, nbytes_out_hi32 );
39271e7ee59SPeter Avalos 	 nbytes_in_d  = uInt64_to_double ( &nbytes_in );
39371e7ee59SPeter Avalos 	 nbytes_out_d = uInt64_to_double ( &nbytes_out );
39471e7ee59SPeter Avalos 	 uInt64_toAscii ( buf_nin, &nbytes_in );
39571e7ee59SPeter Avalos 	 uInt64_toAscii ( buf_nout, &nbytes_out );
39671e7ee59SPeter Avalos 	 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
39771e7ee59SPeter Avalos 		   "%5.2f%% saved, %s in, %s out.\n",
39871e7ee59SPeter Avalos 		   nbytes_in_d / nbytes_out_d,
39971e7ee59SPeter Avalos 		   (8.0 * nbytes_out_d) / nbytes_in_d,
40071e7ee59SPeter Avalos 		   100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
40171e7ee59SPeter Avalos 		   buf_nin,
40271e7ee59SPeter Avalos 		   buf_nout
40371e7ee59SPeter Avalos 		 );
40471e7ee59SPeter Avalos       }
40571e7ee59SPeter Avalos    }
40671e7ee59SPeter Avalos 
40771e7ee59SPeter Avalos    return;
40871e7ee59SPeter Avalos 
40971e7ee59SPeter Avalos    errhandler:
41071e7ee59SPeter Avalos    BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1,
41171e7ee59SPeter Avalos                         &nbytes_in_lo32, &nbytes_in_hi32,
41271e7ee59SPeter Avalos                         &nbytes_out_lo32, &nbytes_out_hi32 );
41371e7ee59SPeter Avalos    switch (bzerr) {
41471e7ee59SPeter Avalos       case BZ_CONFIG_ERROR:
41571e7ee59SPeter Avalos          configError(); break;
41671e7ee59SPeter Avalos       case BZ_MEM_ERROR:
41771e7ee59SPeter Avalos          outOfMemory (); break;
41871e7ee59SPeter Avalos       case BZ_IO_ERROR:
41971e7ee59SPeter Avalos          errhandler_io:
42071e7ee59SPeter Avalos          ioError(); break;
42171e7ee59SPeter Avalos       default:
42271e7ee59SPeter Avalos          panic ( "compress:unexpected error" );
42371e7ee59SPeter Avalos    }
42471e7ee59SPeter Avalos 
42571e7ee59SPeter Avalos    panic ( "compress:end" );
42671e7ee59SPeter Avalos    /*notreached*/
42771e7ee59SPeter Avalos }
42871e7ee59SPeter Avalos 
42971e7ee59SPeter Avalos 
43071e7ee59SPeter Avalos 
43171e7ee59SPeter Avalos /*---------------------------------------------*/
43271e7ee59SPeter Avalos static
uncompressStream(FILE * zStream,FILE * stream)43371e7ee59SPeter Avalos Bool uncompressStream ( FILE *zStream, FILE *stream )
43471e7ee59SPeter Avalos {
43571e7ee59SPeter Avalos    BZFILE* bzf = NULL;
43671e7ee59SPeter Avalos    Int32   bzerr, bzerr_dummy, ret, nread, streamNo, i;
43771e7ee59SPeter Avalos    UChar   obuf[5000];
43871e7ee59SPeter Avalos    UChar   unused[BZ_MAX_UNUSED];
43971e7ee59SPeter Avalos    Int32   nUnused;
44071e7ee59SPeter Avalos    void*   unusedTmpV;
44171e7ee59SPeter Avalos    UChar*  unusedTmp;
44271e7ee59SPeter Avalos 
44371e7ee59SPeter Avalos    nUnused = 0;
44471e7ee59SPeter Avalos    streamNo = 0;
44571e7ee59SPeter Avalos 
44671e7ee59SPeter Avalos    SET_BINARY_MODE(stream);
44771e7ee59SPeter Avalos    SET_BINARY_MODE(zStream);
44871e7ee59SPeter Avalos 
44971e7ee59SPeter Avalos    if (ferror(stream)) goto errhandler_io;
45071e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
45171e7ee59SPeter Avalos 
45271e7ee59SPeter Avalos    while (True) {
45371e7ee59SPeter Avalos 
45471e7ee59SPeter Avalos       bzf = BZ2_bzReadOpen (
45571e7ee59SPeter Avalos                &bzerr, zStream, verbosity,
45671e7ee59SPeter Avalos                (int)smallMode, unused, nUnused
45771e7ee59SPeter Avalos             );
45871e7ee59SPeter Avalos       if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
45971e7ee59SPeter Avalos       streamNo++;
46071e7ee59SPeter Avalos 
46171e7ee59SPeter Avalos       while (bzerr == BZ_OK) {
46271e7ee59SPeter Avalos          nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
46371e7ee59SPeter Avalos          if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
46471e7ee59SPeter Avalos          if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
46571e7ee59SPeter Avalos             fwrite ( obuf, sizeof(UChar), nread, stream );
46671e7ee59SPeter Avalos          if (ferror(stream)) goto errhandler_io;
46771e7ee59SPeter Avalos       }
46871e7ee59SPeter Avalos       if (bzerr != BZ_STREAM_END) goto errhandler;
46971e7ee59SPeter Avalos 
47071e7ee59SPeter Avalos       BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
47171e7ee59SPeter Avalos       if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
47271e7ee59SPeter Avalos 
47371e7ee59SPeter Avalos       unusedTmp = (UChar*)unusedTmpV;
47471e7ee59SPeter Avalos       for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
47571e7ee59SPeter Avalos 
47671e7ee59SPeter Avalos       BZ2_bzReadClose ( &bzerr, bzf );
47771e7ee59SPeter Avalos       if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
47871e7ee59SPeter Avalos 
47971e7ee59SPeter Avalos       if (nUnused == 0 && myfeof(zStream)) break;
48071e7ee59SPeter Avalos    }
48171e7ee59SPeter Avalos 
48271e7ee59SPeter Avalos    closeok:
48371e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
48471e7ee59SPeter Avalos    if (stream != stdout) {
48571e7ee59SPeter Avalos       Int32 fd = fileno ( stream );
48671e7ee59SPeter Avalos       if (fd < 0) goto errhandler_io;
48771e7ee59SPeter Avalos       applySavedFileAttrToOutputFile ( fd );
48871e7ee59SPeter Avalos    }
48971e7ee59SPeter Avalos    ret = fclose ( zStream );
49071e7ee59SPeter Avalos    if (ret == EOF) goto errhandler_io;
49171e7ee59SPeter Avalos 
49271e7ee59SPeter Avalos    if (ferror(stream)) goto errhandler_io;
49371e7ee59SPeter Avalos    ret = fflush ( stream );
49471e7ee59SPeter Avalos    if (ret != 0) goto errhandler_io;
49571e7ee59SPeter Avalos    if (stream != stdout) {
49671e7ee59SPeter Avalos       ret = fclose ( stream );
49771e7ee59SPeter Avalos       outputHandleJustInCase = NULL;
49871e7ee59SPeter Avalos       if (ret == EOF) goto errhandler_io;
49971e7ee59SPeter Avalos    }
50071e7ee59SPeter Avalos    outputHandleJustInCase = NULL;
50171e7ee59SPeter Avalos    if (verbosity >= 2) fprintf ( stderr, "\n    " );
50271e7ee59SPeter Avalos    return True;
50371e7ee59SPeter Avalos 
50471e7ee59SPeter Avalos    trycat:
50571e7ee59SPeter Avalos    if (forceOverwrite) {
50671e7ee59SPeter Avalos       rewind(zStream);
50771e7ee59SPeter Avalos       while (True) {
50871e7ee59SPeter Avalos       	 if (myfeof(zStream)) break;
50971e7ee59SPeter Avalos       	 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
51071e7ee59SPeter Avalos       	 if (ferror(zStream)) goto errhandler_io;
51171e7ee59SPeter Avalos       	 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
51271e7ee59SPeter Avalos       	 if (ferror(stream)) goto errhandler_io;
51371e7ee59SPeter Avalos       }
51471e7ee59SPeter Avalos       goto closeok;
51571e7ee59SPeter Avalos    }
51671e7ee59SPeter Avalos 
51771e7ee59SPeter Avalos    errhandler:
51871e7ee59SPeter Avalos    BZ2_bzReadClose ( &bzerr_dummy, bzf );
51971e7ee59SPeter Avalos    switch (bzerr) {
52071e7ee59SPeter Avalos       case BZ_CONFIG_ERROR:
52171e7ee59SPeter Avalos          configError(); break;
52271e7ee59SPeter Avalos       case BZ_IO_ERROR:
52371e7ee59SPeter Avalos          errhandler_io:
52471e7ee59SPeter Avalos          ioError(); break;
52571e7ee59SPeter Avalos       case BZ_DATA_ERROR:
52671e7ee59SPeter Avalos          crcError();
52771e7ee59SPeter Avalos       case BZ_MEM_ERROR:
52871e7ee59SPeter Avalos          outOfMemory();
52971e7ee59SPeter Avalos       case BZ_UNEXPECTED_EOF:
53071e7ee59SPeter Avalos          compressedStreamEOF();
53171e7ee59SPeter Avalos       case BZ_DATA_ERROR_MAGIC:
53271e7ee59SPeter Avalos          if (zStream != stdin) fclose(zStream);
53371e7ee59SPeter Avalos          if (stream != stdout) fclose(stream);
53471e7ee59SPeter Avalos          if (streamNo == 1) {
53571e7ee59SPeter Avalos             return False;
53671e7ee59SPeter Avalos          } else {
53771e7ee59SPeter Avalos             if (noisy)
53871e7ee59SPeter Avalos             fprintf ( stderr,
53971e7ee59SPeter Avalos                       "\n%s: %s: trailing garbage after EOF ignored\n",
54071e7ee59SPeter Avalos                       progName, inName );
54171e7ee59SPeter Avalos             return True;
54271e7ee59SPeter Avalos          }
54371e7ee59SPeter Avalos       default:
54471e7ee59SPeter Avalos          panic ( "decompress:unexpected error" );
54571e7ee59SPeter Avalos    }
54671e7ee59SPeter Avalos 
54771e7ee59SPeter Avalos    panic ( "decompress:end" );
54871e7ee59SPeter Avalos    return True; /*notreached*/
54971e7ee59SPeter Avalos }
55071e7ee59SPeter Avalos 
55171e7ee59SPeter Avalos 
55271e7ee59SPeter Avalos /*---------------------------------------------*/
55371e7ee59SPeter Avalos static
testStream(FILE * zStream)55471e7ee59SPeter Avalos Bool testStream ( FILE *zStream )
55571e7ee59SPeter Avalos {
55671e7ee59SPeter Avalos    BZFILE* bzf = NULL;
557*86954436SDaniel Fojt    Int32   bzerr, bzerr_dummy, ret, streamNo, i;
55871e7ee59SPeter Avalos    UChar   obuf[5000];
55971e7ee59SPeter Avalos    UChar   unused[BZ_MAX_UNUSED];
56071e7ee59SPeter Avalos    Int32   nUnused;
56171e7ee59SPeter Avalos    void*   unusedTmpV;
56271e7ee59SPeter Avalos    UChar*  unusedTmp;
56371e7ee59SPeter Avalos 
56471e7ee59SPeter Avalos    nUnused = 0;
56571e7ee59SPeter Avalos    streamNo = 0;
56671e7ee59SPeter Avalos 
56771e7ee59SPeter Avalos    SET_BINARY_MODE(zStream);
56871e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
56971e7ee59SPeter Avalos 
57071e7ee59SPeter Avalos    while (True) {
57171e7ee59SPeter Avalos 
57271e7ee59SPeter Avalos       bzf = BZ2_bzReadOpen (
57371e7ee59SPeter Avalos                &bzerr, zStream, verbosity,
57471e7ee59SPeter Avalos                (int)smallMode, unused, nUnused
57571e7ee59SPeter Avalos             );
57671e7ee59SPeter Avalos       if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
57771e7ee59SPeter Avalos       streamNo++;
57871e7ee59SPeter Avalos 
57971e7ee59SPeter Avalos       while (bzerr == BZ_OK) {
580*86954436SDaniel Fojt          BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
58171e7ee59SPeter Avalos          if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
58271e7ee59SPeter Avalos       }
58371e7ee59SPeter Avalos       if (bzerr != BZ_STREAM_END) goto errhandler;
58471e7ee59SPeter Avalos 
58571e7ee59SPeter Avalos       BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
58671e7ee59SPeter Avalos       if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
58771e7ee59SPeter Avalos 
58871e7ee59SPeter Avalos       unusedTmp = (UChar*)unusedTmpV;
58971e7ee59SPeter Avalos       for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
59071e7ee59SPeter Avalos 
59171e7ee59SPeter Avalos       BZ2_bzReadClose ( &bzerr, bzf );
59271e7ee59SPeter Avalos       if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
59371e7ee59SPeter Avalos       if (nUnused == 0 && myfeof(zStream)) break;
59471e7ee59SPeter Avalos 
59571e7ee59SPeter Avalos    }
59671e7ee59SPeter Avalos 
59771e7ee59SPeter Avalos    if (ferror(zStream)) goto errhandler_io;
59871e7ee59SPeter Avalos    ret = fclose ( zStream );
59971e7ee59SPeter Avalos    if (ret == EOF) goto errhandler_io;
60071e7ee59SPeter Avalos 
60171e7ee59SPeter Avalos    if (verbosity >= 2) fprintf ( stderr, "\n    " );
60271e7ee59SPeter Avalos    return True;
60371e7ee59SPeter Avalos 
60471e7ee59SPeter Avalos    errhandler:
60571e7ee59SPeter Avalos    BZ2_bzReadClose ( &bzerr_dummy, bzf );
60671e7ee59SPeter Avalos    if (verbosity == 0)
60771e7ee59SPeter Avalos       fprintf ( stderr, "%s: %s: ", progName, inName );
60871e7ee59SPeter Avalos    switch (bzerr) {
60971e7ee59SPeter Avalos       case BZ_CONFIG_ERROR:
61071e7ee59SPeter Avalos          configError(); break;
61171e7ee59SPeter Avalos       case BZ_IO_ERROR:
61271e7ee59SPeter Avalos          errhandler_io:
61371e7ee59SPeter Avalos          ioError(); break;
61471e7ee59SPeter Avalos       case BZ_DATA_ERROR:
61571e7ee59SPeter Avalos          fprintf ( stderr,
61671e7ee59SPeter Avalos                    "data integrity (CRC) error in data\n" );
61771e7ee59SPeter Avalos          return False;
61871e7ee59SPeter Avalos       case BZ_MEM_ERROR:
61971e7ee59SPeter Avalos          outOfMemory();
62071e7ee59SPeter Avalos       case BZ_UNEXPECTED_EOF:
62171e7ee59SPeter Avalos          fprintf ( stderr,
62271e7ee59SPeter Avalos                    "file ends unexpectedly\n" );
62371e7ee59SPeter Avalos          return False;
62471e7ee59SPeter Avalos       case BZ_DATA_ERROR_MAGIC:
62571e7ee59SPeter Avalos          if (zStream != stdin) fclose(zStream);
62671e7ee59SPeter Avalos          if (streamNo == 1) {
62771e7ee59SPeter Avalos           fprintf ( stderr,
62871e7ee59SPeter Avalos                     "bad magic number (file not created by bzip2)\n" );
62971e7ee59SPeter Avalos             return False;
63071e7ee59SPeter Avalos          } else {
63171e7ee59SPeter Avalos             if (noisy)
63271e7ee59SPeter Avalos             fprintf ( stderr,
63371e7ee59SPeter Avalos                       "trailing garbage after EOF ignored\n" );
63471e7ee59SPeter Avalos             return True;
63571e7ee59SPeter Avalos          }
63671e7ee59SPeter Avalos       default:
63771e7ee59SPeter Avalos          panic ( "test:unexpected error" );
63871e7ee59SPeter Avalos    }
63971e7ee59SPeter Avalos 
64071e7ee59SPeter Avalos    panic ( "test:end" );
64171e7ee59SPeter Avalos    return True; /*notreached*/
64271e7ee59SPeter Avalos }
64371e7ee59SPeter Avalos 
64471e7ee59SPeter Avalos 
64571e7ee59SPeter Avalos /*---------------------------------------------------*/
64671e7ee59SPeter Avalos /*--- Error [non-] handling grunge                ---*/
64771e7ee59SPeter Avalos /*---------------------------------------------------*/
64871e7ee59SPeter Avalos 
64971e7ee59SPeter Avalos /*---------------------------------------------*/
65071e7ee59SPeter Avalos static
setExit(Int32 v)65171e7ee59SPeter Avalos void setExit ( Int32 v )
65271e7ee59SPeter Avalos {
65371e7ee59SPeter Avalos    if (v > exitValue) exitValue = v;
65471e7ee59SPeter Avalos }
65571e7ee59SPeter Avalos 
65671e7ee59SPeter Avalos 
65771e7ee59SPeter Avalos /*---------------------------------------------*/
65871e7ee59SPeter Avalos static
cadvise(void)65971e7ee59SPeter Avalos void cadvise ( void )
66071e7ee59SPeter Avalos {
66171e7ee59SPeter Avalos    if (noisy)
66271e7ee59SPeter Avalos    fprintf (
66371e7ee59SPeter Avalos       stderr,
66471e7ee59SPeter Avalos       "\nIt is possible that the compressed file(s) have become corrupted.\n"
66571e7ee59SPeter Avalos         "You can use the -tvv option to test integrity of such files.\n\n"
66671e7ee59SPeter Avalos         "You can use the `bzip2recover' program to attempt to recover\n"
66771e7ee59SPeter Avalos         "data from undamaged sections of corrupted files.\n\n"
66871e7ee59SPeter Avalos     );
66971e7ee59SPeter Avalos }
67071e7ee59SPeter Avalos 
67171e7ee59SPeter Avalos 
67271e7ee59SPeter Avalos /*---------------------------------------------*/
67371e7ee59SPeter Avalos static
showFileNames(void)67471e7ee59SPeter Avalos void showFileNames ( void )
67571e7ee59SPeter Avalos {
67671e7ee59SPeter Avalos    if (noisy)
67771e7ee59SPeter Avalos    fprintf (
67871e7ee59SPeter Avalos       stderr,
67971e7ee59SPeter Avalos       "\tInput file = %s, output file = %s\n",
68071e7ee59SPeter Avalos       inName, outName
68171e7ee59SPeter Avalos    );
68271e7ee59SPeter Avalos }
68371e7ee59SPeter Avalos 
68471e7ee59SPeter Avalos 
68571e7ee59SPeter Avalos /*---------------------------------------------*/
68671e7ee59SPeter Avalos static
cleanUpAndFail(Int32 ec)68771e7ee59SPeter Avalos void cleanUpAndFail ( Int32 ec )
68871e7ee59SPeter Avalos {
68971e7ee59SPeter Avalos    IntNative      retVal;
69071e7ee59SPeter Avalos    struct MY_STAT statBuf;
69171e7ee59SPeter Avalos 
69271e7ee59SPeter Avalos    if ( srcMode == SM_F2F
69371e7ee59SPeter Avalos         && opMode != OM_TEST
69471e7ee59SPeter Avalos         && deleteOutputOnInterrupt ) {
69571e7ee59SPeter Avalos 
69671e7ee59SPeter Avalos       /* Check whether input file still exists.  Delete output file
69771e7ee59SPeter Avalos          only if input exists to avoid loss of data.  Joerg Prante, 5
69871e7ee59SPeter Avalos          January 2002.  (JRS 06-Jan-2002: other changes in 1.0.2 mean
69971e7ee59SPeter Avalos          this is less likely to happen.  But to be ultra-paranoid, we
70071e7ee59SPeter Avalos          do the check anyway.)  */
70171e7ee59SPeter Avalos       retVal = MY_STAT ( inName, &statBuf );
70271e7ee59SPeter Avalos       if (retVal == 0) {
70371e7ee59SPeter Avalos          if (noisy)
70471e7ee59SPeter Avalos             fprintf ( stderr,
70571e7ee59SPeter Avalos                       "%s: Deleting output file %s, if it exists.\n",
70671e7ee59SPeter Avalos                       progName, outName );
70771e7ee59SPeter Avalos          if (outputHandleJustInCase != NULL)
70871e7ee59SPeter Avalos             fclose ( outputHandleJustInCase );
70971e7ee59SPeter Avalos          retVal = remove ( outName );
71071e7ee59SPeter Avalos          if (retVal != 0)
71171e7ee59SPeter Avalos             fprintf ( stderr,
71271e7ee59SPeter Avalos                       "%s: WARNING: deletion of output file "
71371e7ee59SPeter Avalos                       "(apparently) failed.\n",
71471e7ee59SPeter Avalos                       progName );
71571e7ee59SPeter Avalos       } else {
71671e7ee59SPeter Avalos          fprintf ( stderr,
71771e7ee59SPeter Avalos                    "%s: WARNING: deletion of output file suppressed\n",
71871e7ee59SPeter Avalos                     progName );
71971e7ee59SPeter Avalos          fprintf ( stderr,
72071e7ee59SPeter Avalos                    "%s:    since input file no longer exists.  Output file\n",
72171e7ee59SPeter Avalos                    progName );
72271e7ee59SPeter Avalos          fprintf ( stderr,
72371e7ee59SPeter Avalos                    "%s:    `%s' may be incomplete.\n",
72471e7ee59SPeter Avalos                    progName, outName );
72571e7ee59SPeter Avalos          fprintf ( stderr,
72671e7ee59SPeter Avalos                    "%s:    I suggest doing an integrity test (bzip2 -tv)"
72771e7ee59SPeter Avalos                    " of it.\n",
72871e7ee59SPeter Avalos                    progName );
72971e7ee59SPeter Avalos       }
73071e7ee59SPeter Avalos    }
73171e7ee59SPeter Avalos 
73271e7ee59SPeter Avalos    if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
73371e7ee59SPeter Avalos       fprintf ( stderr,
73471e7ee59SPeter Avalos                 "%s: WARNING: some files have not been processed:\n"
73571e7ee59SPeter Avalos                 "%s:    %d specified on command line, %d not processed yet.\n\n",
73671e7ee59SPeter Avalos                 progName, progName,
73771e7ee59SPeter Avalos                 numFileNames, numFileNames - numFilesProcessed );
73871e7ee59SPeter Avalos    }
73971e7ee59SPeter Avalos    setExit(ec);
74071e7ee59SPeter Avalos    exit(exitValue);
74171e7ee59SPeter Avalos }
74271e7ee59SPeter Avalos 
74371e7ee59SPeter Avalos 
74471e7ee59SPeter Avalos /*---------------------------------------------*/
74571e7ee59SPeter Avalos static
panic(const Char * s)74671e7ee59SPeter Avalos void panic ( const Char* s )
74771e7ee59SPeter Avalos {
74871e7ee59SPeter Avalos    fprintf ( stderr,
74971e7ee59SPeter Avalos              "\n%s: PANIC -- internal consistency error:\n"
75071e7ee59SPeter Avalos              "\t%s\n"
751*86954436SDaniel Fojt              "\tThis is a BUG.  Please report it to:\n"
752*86954436SDaniel Fojt              "\tbzip2-devel@sourceware.org\n",
75371e7ee59SPeter Avalos              progName, s );
75471e7ee59SPeter Avalos    showFileNames();
75571e7ee59SPeter Avalos    cleanUpAndFail( 3 );
75671e7ee59SPeter Avalos }
75771e7ee59SPeter Avalos 
75871e7ee59SPeter Avalos 
75971e7ee59SPeter Avalos /*---------------------------------------------*/
76071e7ee59SPeter Avalos static
crcError(void)76171e7ee59SPeter Avalos void crcError ( void )
76271e7ee59SPeter Avalos {
76371e7ee59SPeter Avalos    fprintf ( stderr,
76471e7ee59SPeter Avalos              "\n%s: Data integrity error when decompressing.\n",
76571e7ee59SPeter Avalos              progName );
76671e7ee59SPeter Avalos    showFileNames();
76771e7ee59SPeter Avalos    cadvise();
76871e7ee59SPeter Avalos    cleanUpAndFail( 2 );
76971e7ee59SPeter Avalos }
77071e7ee59SPeter Avalos 
77171e7ee59SPeter Avalos 
77271e7ee59SPeter Avalos /*---------------------------------------------*/
77371e7ee59SPeter Avalos static
compressedStreamEOF(void)77471e7ee59SPeter Avalos void compressedStreamEOF ( void )
77571e7ee59SPeter Avalos {
77671e7ee59SPeter Avalos   if (noisy) {
77771e7ee59SPeter Avalos     fprintf ( stderr,
77871e7ee59SPeter Avalos 	      "\n%s: Compressed file ends unexpectedly;\n\t"
77971e7ee59SPeter Avalos 	      "perhaps it is corrupted?  *Possible* reason follows.\n",
78071e7ee59SPeter Avalos 	      progName );
78171e7ee59SPeter Avalos     perror ( progName );
78271e7ee59SPeter Avalos     showFileNames();
78371e7ee59SPeter Avalos     cadvise();
78471e7ee59SPeter Avalos   }
78571e7ee59SPeter Avalos   cleanUpAndFail( 2 );
78671e7ee59SPeter Avalos }
78771e7ee59SPeter Avalos 
78871e7ee59SPeter Avalos 
78971e7ee59SPeter Avalos /*---------------------------------------------*/
79071e7ee59SPeter Avalos static
ioError(void)79171e7ee59SPeter Avalos void ioError ( void )
79271e7ee59SPeter Avalos {
79371e7ee59SPeter Avalos    fprintf ( stderr,
79471e7ee59SPeter Avalos              "\n%s: I/O or other error, bailing out.  "
79571e7ee59SPeter Avalos              "Possible reason follows.\n",
79671e7ee59SPeter Avalos              progName );
79771e7ee59SPeter Avalos    perror ( progName );
79871e7ee59SPeter Avalos    showFileNames();
79971e7ee59SPeter Avalos    cleanUpAndFail( 1 );
80071e7ee59SPeter Avalos }
80171e7ee59SPeter Avalos 
80271e7ee59SPeter Avalos 
80371e7ee59SPeter Avalos /*---------------------------------------------*/
80471e7ee59SPeter Avalos static
mySignalCatcher(IntNative n)80571e7ee59SPeter Avalos void mySignalCatcher ( IntNative n )
80671e7ee59SPeter Avalos {
80771e7ee59SPeter Avalos    fprintf ( stderr,
80871e7ee59SPeter Avalos              "\n%s: Control-C or similar caught, quitting.\n",
80971e7ee59SPeter Avalos              progName );
81071e7ee59SPeter Avalos    cleanUpAndFail(1);
81171e7ee59SPeter Avalos }
81271e7ee59SPeter Avalos 
81371e7ee59SPeter Avalos 
81471e7ee59SPeter Avalos /*---------------------------------------------*/
81571e7ee59SPeter Avalos static
mySIGSEGVorSIGBUScatcher(IntNative n)81671e7ee59SPeter Avalos void mySIGSEGVorSIGBUScatcher ( IntNative n )
81771e7ee59SPeter Avalos {
81871e7ee59SPeter Avalos    if (opMode == OM_Z)
81971e7ee59SPeter Avalos       fprintf (
82071e7ee59SPeter Avalos       stderr,
82171e7ee59SPeter Avalos       "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
82271e7ee59SPeter Avalos       "\n"
82371e7ee59SPeter Avalos       "   Possible causes are (most likely first):\n"
82471e7ee59SPeter Avalos       "   (1) This computer has unreliable memory or cache hardware\n"
82571e7ee59SPeter Avalos       "       (a surprisingly common problem; try a different machine.)\n"
82671e7ee59SPeter Avalos       "   (2) A bug in the compiler used to create this executable\n"
82771e7ee59SPeter Avalos       "       (unlikely, if you didn't compile bzip2 yourself.)\n"
82871e7ee59SPeter Avalos       "   (3) A real bug in bzip2 -- I hope this should never be the case.\n"
82971e7ee59SPeter Avalos       "   The user's manual, Section 4.3, has more info on (1) and (2).\n"
83071e7ee59SPeter Avalos       "   \n"
83171e7ee59SPeter Avalos       "   If you suspect this is a bug in bzip2, or are unsure about (1)\n"
832*86954436SDaniel Fojt       "   or (2), feel free to report it to: bzip2-devel@sourceware.org.\n"
83371e7ee59SPeter Avalos       "   Section 4.3 of the user's manual describes the info a useful\n"
83471e7ee59SPeter Avalos       "   bug report should have.  If the manual is available on your\n"
83571e7ee59SPeter Avalos       "   system, please try and read it before mailing me.  If you don't\n"
83671e7ee59SPeter Avalos       "   have the manual or can't be bothered to read it, mail me anyway.\n"
83771e7ee59SPeter Avalos       "\n",
83871e7ee59SPeter Avalos       progName );
83971e7ee59SPeter Avalos       else
84071e7ee59SPeter Avalos       fprintf (
84171e7ee59SPeter Avalos       stderr,
84271e7ee59SPeter Avalos       "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
84371e7ee59SPeter Avalos       "\n"
84471e7ee59SPeter Avalos       "   Possible causes are (most likely first):\n"
84571e7ee59SPeter Avalos       "   (1) The compressed data is corrupted, and bzip2's usual checks\n"
84671e7ee59SPeter Avalos       "       failed to detect this.  Try bzip2 -tvv my_file.bz2.\n"
84771e7ee59SPeter Avalos       "   (2) This computer has unreliable memory or cache hardware\n"
84871e7ee59SPeter Avalos       "       (a surprisingly common problem; try a different machine.)\n"
84971e7ee59SPeter Avalos       "   (3) A bug in the compiler used to create this executable\n"
85071e7ee59SPeter Avalos       "       (unlikely, if you didn't compile bzip2 yourself.)\n"
85171e7ee59SPeter Avalos       "   (4) A real bug in bzip2 -- I hope this should never be the case.\n"
85271e7ee59SPeter Avalos       "   The user's manual, Section 4.3, has more info on (2) and (3).\n"
85371e7ee59SPeter Avalos       "   \n"
85471e7ee59SPeter Avalos       "   If you suspect this is a bug in bzip2, or are unsure about (2)\n"
855*86954436SDaniel Fojt       "   or (3), feel free to report it to: bzip2-devel@sourceware.org.\n"
85671e7ee59SPeter Avalos       "   Section 4.3 of the user's manual describes the info a useful\n"
85771e7ee59SPeter Avalos       "   bug report should have.  If the manual is available on your\n"
85871e7ee59SPeter Avalos       "   system, please try and read it before mailing me.  If you don't\n"
85971e7ee59SPeter Avalos       "   have the manual or can't be bothered to read it, mail me anyway.\n"
86071e7ee59SPeter Avalos       "\n",
86171e7ee59SPeter Avalos       progName );
86271e7ee59SPeter Avalos 
86371e7ee59SPeter Avalos    showFileNames();
86471e7ee59SPeter Avalos    if (opMode == OM_Z)
86571e7ee59SPeter Avalos       cleanUpAndFail( 3 ); else
86671e7ee59SPeter Avalos       { cadvise(); cleanUpAndFail( 2 ); }
86771e7ee59SPeter Avalos }
86871e7ee59SPeter Avalos 
86971e7ee59SPeter Avalos 
87071e7ee59SPeter Avalos /*---------------------------------------------*/
87171e7ee59SPeter Avalos static
outOfMemory(void)87271e7ee59SPeter Avalos void outOfMemory ( void )
87371e7ee59SPeter Avalos {
87471e7ee59SPeter Avalos    fprintf ( stderr,
87571e7ee59SPeter Avalos              "\n%s: couldn't allocate enough memory\n",
87671e7ee59SPeter Avalos              progName );
87771e7ee59SPeter Avalos    showFileNames();
87871e7ee59SPeter Avalos    cleanUpAndFail(1);
87971e7ee59SPeter Avalos }
88071e7ee59SPeter Avalos 
88171e7ee59SPeter Avalos 
88271e7ee59SPeter Avalos /*---------------------------------------------*/
88371e7ee59SPeter Avalos static
configError(void)88471e7ee59SPeter Avalos void configError ( void )
88571e7ee59SPeter Avalos {
88671e7ee59SPeter Avalos    fprintf ( stderr,
88771e7ee59SPeter Avalos              "bzip2: I'm not configured correctly for this platform!\n"
88871e7ee59SPeter Avalos              "\tI require Int32, Int16 and Char to have sizes\n"
88971e7ee59SPeter Avalos              "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
89071e7ee59SPeter Avalos              "\tProbably you can fix this by defining them correctly,\n"
89171e7ee59SPeter Avalos              "\tand recompiling.  Bye!\n" );
89271e7ee59SPeter Avalos    setExit(3);
89371e7ee59SPeter Avalos    exit(exitValue);
89471e7ee59SPeter Avalos }
89571e7ee59SPeter Avalos 
89671e7ee59SPeter Avalos 
89771e7ee59SPeter Avalos /*---------------------------------------------------*/
89871e7ee59SPeter Avalos /*--- The main driver machinery                   ---*/
89971e7ee59SPeter Avalos /*---------------------------------------------------*/
90071e7ee59SPeter Avalos 
90171e7ee59SPeter Avalos /* All rather crufty.  The main problem is that input files
90271e7ee59SPeter Avalos    are stat()d multiple times before use.  This should be
90371e7ee59SPeter Avalos    cleaned up.
90471e7ee59SPeter Avalos */
90571e7ee59SPeter Avalos 
90671e7ee59SPeter Avalos /*---------------------------------------------*/
90771e7ee59SPeter Avalos static
pad(Char * s)90871e7ee59SPeter Avalos void pad ( Char *s )
90971e7ee59SPeter Avalos {
91071e7ee59SPeter Avalos    Int32 i;
91171e7ee59SPeter Avalos    if ( (Int32)strlen(s) >= longestFileName ) return;
91271e7ee59SPeter Avalos    for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
91371e7ee59SPeter Avalos       fprintf ( stderr, " " );
91471e7ee59SPeter Avalos }
91571e7ee59SPeter Avalos 
91671e7ee59SPeter Avalos 
91771e7ee59SPeter Avalos /*---------------------------------------------*/
91871e7ee59SPeter Avalos static
copyFileName(Char * to,Char * from)91971e7ee59SPeter Avalos void copyFileName ( Char* to, Char* from )
92071e7ee59SPeter Avalos {
92171e7ee59SPeter Avalos    if ( strlen(from) > FILE_NAME_LEN-10 )  {
92271e7ee59SPeter Avalos       fprintf (
92371e7ee59SPeter Avalos          stderr,
92471e7ee59SPeter Avalos          "bzip2: file name\n`%s'\n"
92571e7ee59SPeter Avalos          "is suspiciously (more than %d chars) long.\n"
92671e7ee59SPeter Avalos          "Try using a reasonable file name instead.  Sorry! :-)\n",
92771e7ee59SPeter Avalos          from, FILE_NAME_LEN-10
92871e7ee59SPeter Avalos       );
92971e7ee59SPeter Avalos       setExit(1);
93071e7ee59SPeter Avalos       exit(exitValue);
93171e7ee59SPeter Avalos    }
93271e7ee59SPeter Avalos 
93371e7ee59SPeter Avalos   strncpy(to,from,FILE_NAME_LEN-10);
93471e7ee59SPeter Avalos   to[FILE_NAME_LEN-10]='\0';
93571e7ee59SPeter Avalos }
93671e7ee59SPeter Avalos 
93771e7ee59SPeter Avalos 
93871e7ee59SPeter Avalos /*---------------------------------------------*/
93971e7ee59SPeter Avalos static
fileExists(Char * name)94071e7ee59SPeter Avalos Bool fileExists ( Char* name )
94171e7ee59SPeter Avalos {
94271e7ee59SPeter Avalos    FILE *tmp   = fopen ( name, "rb" );
94371e7ee59SPeter Avalos    Bool exists = (tmp != NULL);
94471e7ee59SPeter Avalos    if (tmp != NULL) fclose ( tmp );
94571e7ee59SPeter Avalos    return exists;
94671e7ee59SPeter Avalos }
94771e7ee59SPeter Avalos 
94871e7ee59SPeter Avalos 
94971e7ee59SPeter Avalos /*---------------------------------------------*/
95071e7ee59SPeter Avalos /* Open an output file safely with O_EXCL and good permissions.
95171e7ee59SPeter Avalos    This avoids a race condition in versions < 1.0.2, in which
95271e7ee59SPeter Avalos    the file was first opened and then had its interim permissions
95371e7ee59SPeter Avalos    set safely.  We instead use open() to create the file with
95471e7ee59SPeter Avalos    the interim permissions required. (--- --- rw-).
95571e7ee59SPeter Avalos 
95671e7ee59SPeter Avalos    For non-Unix platforms, if we are not worrying about
95771e7ee59SPeter Avalos    security issues, simple this simply behaves like fopen.
95871e7ee59SPeter Avalos */
95971e7ee59SPeter Avalos static
fopen_output_safely(Char * name,const char * mode)96071e7ee59SPeter Avalos FILE* fopen_output_safely ( Char* name, const char* mode )
96171e7ee59SPeter Avalos {
96271e7ee59SPeter Avalos #  if BZ_UNIX
96371e7ee59SPeter Avalos    FILE*     fp;
96471e7ee59SPeter Avalos    IntNative fh;
96571e7ee59SPeter Avalos    fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
96671e7ee59SPeter Avalos    if (fh == -1) return NULL;
96771e7ee59SPeter Avalos    fp = fdopen(fh, mode);
96871e7ee59SPeter Avalos    if (fp == NULL) close(fh);
96971e7ee59SPeter Avalos    return fp;
97071e7ee59SPeter Avalos #  else
97171e7ee59SPeter Avalos    return fopen(name, mode);
97271e7ee59SPeter Avalos #  endif
97371e7ee59SPeter Avalos }
97471e7ee59SPeter Avalos 
97571e7ee59SPeter Avalos 
97671e7ee59SPeter Avalos /*---------------------------------------------*/
97771e7ee59SPeter Avalos /*--
97871e7ee59SPeter Avalos   if in doubt, return True
97971e7ee59SPeter Avalos --*/
98071e7ee59SPeter Avalos static
notAStandardFile(Char * name)98171e7ee59SPeter Avalos Bool notAStandardFile ( Char* name )
98271e7ee59SPeter Avalos {
98371e7ee59SPeter Avalos    IntNative      i;
98471e7ee59SPeter Avalos    struct MY_STAT statBuf;
98571e7ee59SPeter Avalos 
98671e7ee59SPeter Avalos    i = MY_LSTAT ( name, &statBuf );
98771e7ee59SPeter Avalos    if (i != 0) return True;
98871e7ee59SPeter Avalos    if (MY_S_ISREG(statBuf.st_mode)) return False;
98971e7ee59SPeter Avalos    return True;
99071e7ee59SPeter Avalos }
99171e7ee59SPeter Avalos 
99271e7ee59SPeter Avalos 
99371e7ee59SPeter Avalos /*---------------------------------------------*/
99471e7ee59SPeter Avalos /*--
99571e7ee59SPeter Avalos   rac 11/21/98 see if file has hard links to it
99671e7ee59SPeter Avalos --*/
99771e7ee59SPeter Avalos static
countHardLinks(Char * name)99871e7ee59SPeter Avalos Int32 countHardLinks ( Char* name )
99971e7ee59SPeter Avalos {
100071e7ee59SPeter Avalos    IntNative      i;
100171e7ee59SPeter Avalos    struct MY_STAT statBuf;
100271e7ee59SPeter Avalos 
100371e7ee59SPeter Avalos    i = MY_LSTAT ( name, &statBuf );
100471e7ee59SPeter Avalos    if (i != 0) return 0;
100571e7ee59SPeter Avalos    return (statBuf.st_nlink - 1);
100671e7ee59SPeter Avalos }
100771e7ee59SPeter Avalos 
100871e7ee59SPeter Avalos 
100971e7ee59SPeter Avalos /*---------------------------------------------*/
101071e7ee59SPeter Avalos /* Copy modification date, access date, permissions and owner from the
101171e7ee59SPeter Avalos    source to destination file.  We have to copy this meta-info off
101271e7ee59SPeter Avalos    into fileMetaInfo before starting to compress / decompress it,
101371e7ee59SPeter Avalos    because doing it afterwards means we get the wrong access time.
101471e7ee59SPeter Avalos 
101571e7ee59SPeter Avalos    To complicate matters, in compress() and decompress() below, the
101671e7ee59SPeter Avalos    sequence of tests preceding the call to saveInputFileMetaInfo()
101771e7ee59SPeter Avalos    involves calling fileExists(), which in turn establishes its result
101871e7ee59SPeter Avalos    by attempting to fopen() the file, and if successful, immediately
101971e7ee59SPeter Avalos    fclose()ing it again.  So we have to assume that the fopen() call
102071e7ee59SPeter Avalos    does not cause the access time field to be updated.
102171e7ee59SPeter Avalos 
102271e7ee59SPeter Avalos    Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
102371e7ee59SPeter Avalos    to imply that merely doing open() will not affect the access time.
102471e7ee59SPeter Avalos    Therefore we merely need to hope that the C library only does
102571e7ee59SPeter Avalos    open() as a result of fopen(), and not any kind of read()-ahead
102671e7ee59SPeter Avalos    cleverness.
102771e7ee59SPeter Avalos 
102871e7ee59SPeter Avalos    It sounds pretty fragile to me.  Whether this carries across
102971e7ee59SPeter Avalos    robustly to arbitrary Unix-like platforms (or even works robustly
103071e7ee59SPeter Avalos    on this one, RedHat 7.2) is unknown to me.  Nevertheless ...
103171e7ee59SPeter Avalos */
103271e7ee59SPeter Avalos #if BZ_UNIX
103371e7ee59SPeter Avalos static
103471e7ee59SPeter Avalos struct MY_STAT fileMetaInfo;
103571e7ee59SPeter Avalos #endif
103671e7ee59SPeter Avalos 
103771e7ee59SPeter Avalos static
saveInputFileMetaInfo(Char * srcName)103871e7ee59SPeter Avalos void saveInputFileMetaInfo ( Char *srcName )
103971e7ee59SPeter Avalos {
104071e7ee59SPeter Avalos #  if BZ_UNIX
104171e7ee59SPeter Avalos    IntNative retVal;
104271e7ee59SPeter Avalos    /* Note use of stat here, not lstat. */
104371e7ee59SPeter Avalos    retVal = MY_STAT( srcName, &fileMetaInfo );
104471e7ee59SPeter Avalos    ERROR_IF_NOT_ZERO ( retVal );
104571e7ee59SPeter Avalos #  endif
104671e7ee59SPeter Avalos }
104771e7ee59SPeter Avalos 
104871e7ee59SPeter Avalos 
104971e7ee59SPeter Avalos static
applySavedTimeInfoToOutputFile(Char * dstName)105071e7ee59SPeter Avalos void applySavedTimeInfoToOutputFile ( Char *dstName )
105171e7ee59SPeter Avalos {
105271e7ee59SPeter Avalos #  if BZ_UNIX
105371e7ee59SPeter Avalos    IntNative      retVal;
105471e7ee59SPeter Avalos    struct utimbuf uTimBuf;
105571e7ee59SPeter Avalos 
105671e7ee59SPeter Avalos    uTimBuf.actime = fileMetaInfo.st_atime;
105771e7ee59SPeter Avalos    uTimBuf.modtime = fileMetaInfo.st_mtime;
105871e7ee59SPeter Avalos 
105971e7ee59SPeter Avalos    retVal = utime ( dstName, &uTimBuf );
106071e7ee59SPeter Avalos    ERROR_IF_NOT_ZERO ( retVal );
106171e7ee59SPeter Avalos #  endif
106271e7ee59SPeter Avalos }
106371e7ee59SPeter Avalos 
106471e7ee59SPeter Avalos static
applySavedFileAttrToOutputFile(IntNative fd)106571e7ee59SPeter Avalos void applySavedFileAttrToOutputFile ( IntNative fd )
106671e7ee59SPeter Avalos {
106771e7ee59SPeter Avalos #  if BZ_UNIX
106871e7ee59SPeter Avalos    IntNative retVal;
106971e7ee59SPeter Avalos 
107071e7ee59SPeter Avalos    retVal = fchmod ( fd, fileMetaInfo.st_mode );
107171e7ee59SPeter Avalos    ERROR_IF_NOT_ZERO ( retVal );
107271e7ee59SPeter Avalos 
107371e7ee59SPeter Avalos    (void) fchown ( fd, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
107471e7ee59SPeter Avalos    /* chown() will in many cases return with EPERM, which can
107571e7ee59SPeter Avalos       be safely ignored.
107671e7ee59SPeter Avalos    */
107771e7ee59SPeter Avalos #  endif
107871e7ee59SPeter Avalos }
107971e7ee59SPeter Avalos 
108071e7ee59SPeter Avalos 
108171e7ee59SPeter Avalos /*---------------------------------------------*/
108271e7ee59SPeter Avalos static
containsDubiousChars(Char * name)108371e7ee59SPeter Avalos Bool containsDubiousChars ( Char* name )
108471e7ee59SPeter Avalos {
108571e7ee59SPeter Avalos #  if BZ_UNIX
108671e7ee59SPeter Avalos    /* On unix, files can contain any characters and the file expansion
108771e7ee59SPeter Avalos     * is performed by the shell.
108871e7ee59SPeter Avalos     */
108971e7ee59SPeter Avalos    return False;
109071e7ee59SPeter Avalos #  else /* ! BZ_UNIX */
109171e7ee59SPeter Avalos    /* On non-unix (Win* platforms), wildcard characters are not allowed in
109271e7ee59SPeter Avalos     * filenames.
109371e7ee59SPeter Avalos     */
109471e7ee59SPeter Avalos    for (; *name != '\0'; name++)
109571e7ee59SPeter Avalos       if (*name == '?' || *name == '*') return True;
109671e7ee59SPeter Avalos    return False;
109771e7ee59SPeter Avalos #  endif /* BZ_UNIX */
109871e7ee59SPeter Avalos }
109971e7ee59SPeter Avalos 
110071e7ee59SPeter Avalos 
110171e7ee59SPeter Avalos /*---------------------------------------------*/
110271e7ee59SPeter Avalos #define BZ_N_SUFFIX_PAIRS 4
110371e7ee59SPeter Avalos 
110471e7ee59SPeter Avalos const Char* zSuffix[BZ_N_SUFFIX_PAIRS]
110571e7ee59SPeter Avalos    = { ".bz2", ".bz", ".tbz2", ".tbz" };
110671e7ee59SPeter Avalos const Char* unzSuffix[BZ_N_SUFFIX_PAIRS]
110771e7ee59SPeter Avalos    = { "", "", ".tar", ".tar" };
110871e7ee59SPeter Avalos 
110971e7ee59SPeter Avalos static
hasSuffix(Char * s,const Char * suffix)111071e7ee59SPeter Avalos Bool hasSuffix ( Char* s, const Char* suffix )
111171e7ee59SPeter Avalos {
111271e7ee59SPeter Avalos    Int32 ns = strlen(s);
111371e7ee59SPeter Avalos    Int32 nx = strlen(suffix);
111471e7ee59SPeter Avalos    if (ns < nx) return False;
111571e7ee59SPeter Avalos    if (strcmp(s + ns - nx, suffix) == 0) return True;
111671e7ee59SPeter Avalos    return False;
111771e7ee59SPeter Avalos }
111871e7ee59SPeter Avalos 
111971e7ee59SPeter Avalos static
mapSuffix(Char * name,const Char * oldSuffix,const Char * newSuffix)112071e7ee59SPeter Avalos Bool mapSuffix ( Char* name,
112171e7ee59SPeter Avalos                  const Char* oldSuffix,
112271e7ee59SPeter Avalos                  const Char* newSuffix )
112371e7ee59SPeter Avalos {
112471e7ee59SPeter Avalos    if (!hasSuffix(name,oldSuffix)) return False;
112571e7ee59SPeter Avalos    name[strlen(name)-strlen(oldSuffix)] = 0;
112671e7ee59SPeter Avalos    strcat ( name, newSuffix );
112771e7ee59SPeter Avalos    return True;
112871e7ee59SPeter Avalos }
112971e7ee59SPeter Avalos 
113071e7ee59SPeter Avalos 
113171e7ee59SPeter Avalos /*---------------------------------------------*/
113271e7ee59SPeter Avalos static
compress(Char * name)113371e7ee59SPeter Avalos void compress ( Char *name )
113471e7ee59SPeter Avalos {
113571e7ee59SPeter Avalos    FILE  *inStr;
113671e7ee59SPeter Avalos    FILE  *outStr;
113771e7ee59SPeter Avalos    Int32 n, i;
113871e7ee59SPeter Avalos    struct MY_STAT statBuf;
113971e7ee59SPeter Avalos 
114071e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
114171e7ee59SPeter Avalos 
114271e7ee59SPeter Avalos    if (name == NULL && srcMode != SM_I2O)
114371e7ee59SPeter Avalos       panic ( "compress: bad modes\n" );
114471e7ee59SPeter Avalos 
114571e7ee59SPeter Avalos    switch (srcMode) {
114671e7ee59SPeter Avalos       case SM_I2O:
114771e7ee59SPeter Avalos          copyFileName ( inName, (Char*)"(stdin)" );
114871e7ee59SPeter Avalos          copyFileName ( outName, (Char*)"(stdout)" );
114971e7ee59SPeter Avalos          break;
115071e7ee59SPeter Avalos       case SM_F2F:
115171e7ee59SPeter Avalos          copyFileName ( inName, name );
115271e7ee59SPeter Avalos          copyFileName ( outName, name );
115371e7ee59SPeter Avalos          strcat ( outName, ".bz2" );
115471e7ee59SPeter Avalos          break;
115571e7ee59SPeter Avalos       case SM_F2O:
115671e7ee59SPeter Avalos          copyFileName ( inName, name );
115771e7ee59SPeter Avalos          copyFileName ( outName, (Char*)"(stdout)" );
115871e7ee59SPeter Avalos          break;
115971e7ee59SPeter Avalos    }
116071e7ee59SPeter Avalos 
116171e7ee59SPeter Avalos    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
116271e7ee59SPeter Avalos       if (noisy)
116371e7ee59SPeter Avalos       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
116471e7ee59SPeter Avalos                 progName, inName );
116571e7ee59SPeter Avalos       setExit(1);
116671e7ee59SPeter Avalos       return;
116771e7ee59SPeter Avalos    }
116871e7ee59SPeter Avalos    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
116971e7ee59SPeter Avalos       fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
117071e7ee59SPeter Avalos                 progName, inName, strerror(errno) );
117171e7ee59SPeter Avalos       setExit(1);
117271e7ee59SPeter Avalos       return;
117371e7ee59SPeter Avalos    }
117471e7ee59SPeter Avalos    for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
117571e7ee59SPeter Avalos       if (hasSuffix(inName, zSuffix[i])) {
117671e7ee59SPeter Avalos          if (noisy)
117771e7ee59SPeter Avalos          fprintf ( stderr,
117871e7ee59SPeter Avalos                    "%s: Input file %s already has %s suffix.\n",
117971e7ee59SPeter Avalos                    progName, inName, zSuffix[i] );
118071e7ee59SPeter Avalos          setExit(1);
118171e7ee59SPeter Avalos          return;
118271e7ee59SPeter Avalos       }
118371e7ee59SPeter Avalos    }
118471e7ee59SPeter Avalos    if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
118571e7ee59SPeter Avalos       MY_STAT(inName, &statBuf);
118671e7ee59SPeter Avalos       if ( MY_S_ISDIR(statBuf.st_mode) ) {
118771e7ee59SPeter Avalos          fprintf( stderr,
118871e7ee59SPeter Avalos                   "%s: Input file %s is a directory.\n",
118971e7ee59SPeter Avalos                   progName,inName);
119071e7ee59SPeter Avalos          setExit(1);
119171e7ee59SPeter Avalos          return;
119271e7ee59SPeter Avalos       }
119371e7ee59SPeter Avalos    }
119471e7ee59SPeter Avalos    if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
119571e7ee59SPeter Avalos       if (noisy)
119671e7ee59SPeter Avalos       fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
119771e7ee59SPeter Avalos                 progName, inName );
119871e7ee59SPeter Avalos       setExit(1);
119971e7ee59SPeter Avalos       return;
120071e7ee59SPeter Avalos    }
120171e7ee59SPeter Avalos    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
120271e7ee59SPeter Avalos       if (forceOverwrite) {
120371e7ee59SPeter Avalos 	 remove(outName);
120471e7ee59SPeter Avalos       } else {
120571e7ee59SPeter Avalos 	 fprintf ( stderr, "%s: Output file %s already exists.\n",
120671e7ee59SPeter Avalos 		   progName, outName );
120771e7ee59SPeter Avalos 	 setExit(1);
120871e7ee59SPeter Avalos 	 return;
120971e7ee59SPeter Avalos       }
121071e7ee59SPeter Avalos    }
121171e7ee59SPeter Avalos    if ( srcMode == SM_F2F && !forceOverwrite &&
121271e7ee59SPeter Avalos         (n=countHardLinks ( inName )) > 0) {
121371e7ee59SPeter Avalos       fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
121471e7ee59SPeter Avalos                 progName, inName, n, n > 1 ? "s" : "" );
121571e7ee59SPeter Avalos       setExit(1);
121671e7ee59SPeter Avalos       return;
121771e7ee59SPeter Avalos    }
121871e7ee59SPeter Avalos 
121971e7ee59SPeter Avalos    if ( srcMode == SM_F2F ) {
122071e7ee59SPeter Avalos       /* Save the file's meta-info before we open it.  Doing it later
122171e7ee59SPeter Avalos          means we mess up the access times. */
122271e7ee59SPeter Avalos       saveInputFileMetaInfo ( inName );
122371e7ee59SPeter Avalos    }
122471e7ee59SPeter Avalos 
122571e7ee59SPeter Avalos    switch ( srcMode ) {
122671e7ee59SPeter Avalos 
122771e7ee59SPeter Avalos       case SM_I2O:
122871e7ee59SPeter Avalos          inStr = stdin;
122971e7ee59SPeter Avalos          outStr = stdout;
123071e7ee59SPeter Avalos          if ( isatty ( fileno ( stdout ) ) ) {
123171e7ee59SPeter Avalos             fprintf ( stderr,
123271e7ee59SPeter Avalos                       "%s: I won't write compressed data to a terminal.\n",
123371e7ee59SPeter Avalos                       progName );
123471e7ee59SPeter Avalos             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
123571e7ee59SPeter Avalos                               progName, progName );
123671e7ee59SPeter Avalos             setExit(1);
123771e7ee59SPeter Avalos             return;
123871e7ee59SPeter Avalos          };
123971e7ee59SPeter Avalos          break;
124071e7ee59SPeter Avalos 
124171e7ee59SPeter Avalos       case SM_F2O:
124271e7ee59SPeter Avalos          inStr = fopen ( inName, "rb" );
124371e7ee59SPeter Avalos          outStr = stdout;
124471e7ee59SPeter Avalos          if ( isatty ( fileno ( stdout ) ) ) {
124571e7ee59SPeter Avalos             fprintf ( stderr,
124671e7ee59SPeter Avalos                       "%s: I won't write compressed data to a terminal.\n",
124771e7ee59SPeter Avalos                       progName );
124871e7ee59SPeter Avalos             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
124971e7ee59SPeter Avalos                               progName, progName );
125071e7ee59SPeter Avalos             if ( inStr != NULL ) fclose ( inStr );
125171e7ee59SPeter Avalos             setExit(1);
125271e7ee59SPeter Avalos             return;
125371e7ee59SPeter Avalos          };
125471e7ee59SPeter Avalos          if ( inStr == NULL ) {
125571e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
125671e7ee59SPeter Avalos                       progName, inName, strerror(errno) );
125771e7ee59SPeter Avalos             setExit(1);
125871e7ee59SPeter Avalos             return;
125971e7ee59SPeter Avalos          };
126071e7ee59SPeter Avalos          break;
126171e7ee59SPeter Avalos 
126271e7ee59SPeter Avalos       case SM_F2F:
126371e7ee59SPeter Avalos          inStr = fopen ( inName, "rb" );
126471e7ee59SPeter Avalos          outStr = fopen_output_safely ( outName, "wb" );
126571e7ee59SPeter Avalos          if ( outStr == NULL) {
126671e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
126771e7ee59SPeter Avalos                       progName, outName, strerror(errno) );
126871e7ee59SPeter Avalos             if ( inStr != NULL ) fclose ( inStr );
126971e7ee59SPeter Avalos             setExit(1);
127071e7ee59SPeter Avalos             return;
127171e7ee59SPeter Avalos          }
127271e7ee59SPeter Avalos          if ( inStr == NULL ) {
127371e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
127471e7ee59SPeter Avalos                       progName, inName, strerror(errno) );
127571e7ee59SPeter Avalos             if ( outStr != NULL ) fclose ( outStr );
127671e7ee59SPeter Avalos             setExit(1);
127771e7ee59SPeter Avalos             return;
127871e7ee59SPeter Avalos          };
127971e7ee59SPeter Avalos          break;
128071e7ee59SPeter Avalos 
128171e7ee59SPeter Avalos       default:
128271e7ee59SPeter Avalos          panic ( "compress: bad srcMode" );
128371e7ee59SPeter Avalos          break;
128471e7ee59SPeter Avalos    }
128571e7ee59SPeter Avalos 
128671e7ee59SPeter Avalos    if (verbosity >= 1) {
128771e7ee59SPeter Avalos       fprintf ( stderr,  "  %s: ", inName );
128871e7ee59SPeter Avalos       pad ( inName );
128971e7ee59SPeter Avalos       fflush ( stderr );
129071e7ee59SPeter Avalos    }
129171e7ee59SPeter Avalos 
129271e7ee59SPeter Avalos    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
129371e7ee59SPeter Avalos    outputHandleJustInCase = outStr;
129471e7ee59SPeter Avalos    deleteOutputOnInterrupt = True;
129571e7ee59SPeter Avalos    compressStream ( inStr, outStr );
129671e7ee59SPeter Avalos    outputHandleJustInCase = NULL;
129771e7ee59SPeter Avalos 
129871e7ee59SPeter Avalos    /*--- If there was an I/O error, we won't get here. ---*/
129971e7ee59SPeter Avalos    if ( srcMode == SM_F2F ) {
130071e7ee59SPeter Avalos       applySavedTimeInfoToOutputFile ( outName );
130171e7ee59SPeter Avalos       deleteOutputOnInterrupt = False;
130271e7ee59SPeter Avalos       if ( !keepInputFiles ) {
130371e7ee59SPeter Avalos          IntNative retVal = remove ( inName );
130471e7ee59SPeter Avalos          ERROR_IF_NOT_ZERO ( retVal );
130571e7ee59SPeter Avalos       }
130671e7ee59SPeter Avalos    }
130771e7ee59SPeter Avalos 
130871e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
130971e7ee59SPeter Avalos }
131071e7ee59SPeter Avalos 
131171e7ee59SPeter Avalos 
131271e7ee59SPeter Avalos /*---------------------------------------------*/
131371e7ee59SPeter Avalos static
uncompress(Char * name)131471e7ee59SPeter Avalos void uncompress ( Char *name )
131571e7ee59SPeter Avalos {
131671e7ee59SPeter Avalos    FILE  *inStr;
131771e7ee59SPeter Avalos    FILE  *outStr;
131871e7ee59SPeter Avalos    Int32 n, i;
131971e7ee59SPeter Avalos    Bool  magicNumberOK;
132071e7ee59SPeter Avalos    Bool  cantGuess;
132171e7ee59SPeter Avalos    struct MY_STAT statBuf;
132271e7ee59SPeter Avalos 
132371e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
132471e7ee59SPeter Avalos 
132571e7ee59SPeter Avalos    if (name == NULL && srcMode != SM_I2O)
132671e7ee59SPeter Avalos       panic ( "uncompress: bad modes\n" );
132771e7ee59SPeter Avalos 
132871e7ee59SPeter Avalos    cantGuess = False;
132971e7ee59SPeter Avalos    switch (srcMode) {
133071e7ee59SPeter Avalos       case SM_I2O:
133171e7ee59SPeter Avalos          copyFileName ( inName, (Char*)"(stdin)" );
133271e7ee59SPeter Avalos          copyFileName ( outName, (Char*)"(stdout)" );
133371e7ee59SPeter Avalos          break;
133471e7ee59SPeter Avalos       case SM_F2F:
133571e7ee59SPeter Avalos          copyFileName ( inName, name );
133671e7ee59SPeter Avalos          copyFileName ( outName, name );
133771e7ee59SPeter Avalos          for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
133871e7ee59SPeter Avalos             if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
133971e7ee59SPeter Avalos                goto zzz;
134071e7ee59SPeter Avalos          cantGuess = True;
134171e7ee59SPeter Avalos          strcat ( outName, ".out" );
134271e7ee59SPeter Avalos          break;
134371e7ee59SPeter Avalos       case SM_F2O:
134471e7ee59SPeter Avalos          copyFileName ( inName, name );
134571e7ee59SPeter Avalos          copyFileName ( outName, (Char*)"(stdout)" );
134671e7ee59SPeter Avalos          break;
134771e7ee59SPeter Avalos    }
134871e7ee59SPeter Avalos 
134971e7ee59SPeter Avalos    zzz:
135071e7ee59SPeter Avalos    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
135171e7ee59SPeter Avalos       if (noisy)
135271e7ee59SPeter Avalos       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
135371e7ee59SPeter Avalos                 progName, inName );
135471e7ee59SPeter Avalos       setExit(1);
135571e7ee59SPeter Avalos       return;
135671e7ee59SPeter Avalos    }
135771e7ee59SPeter Avalos    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
135871e7ee59SPeter Avalos       fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
135971e7ee59SPeter Avalos                 progName, inName, strerror(errno) );
136071e7ee59SPeter Avalos       setExit(1);
136171e7ee59SPeter Avalos       return;
136271e7ee59SPeter Avalos    }
136371e7ee59SPeter Avalos    if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
136471e7ee59SPeter Avalos       MY_STAT(inName, &statBuf);
136571e7ee59SPeter Avalos       if ( MY_S_ISDIR(statBuf.st_mode) ) {
136671e7ee59SPeter Avalos          fprintf( stderr,
136771e7ee59SPeter Avalos                   "%s: Input file %s is a directory.\n",
136871e7ee59SPeter Avalos                   progName,inName);
136971e7ee59SPeter Avalos          setExit(1);
137071e7ee59SPeter Avalos          return;
137171e7ee59SPeter Avalos       }
137271e7ee59SPeter Avalos    }
137371e7ee59SPeter Avalos    if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
137471e7ee59SPeter Avalos       if (noisy)
137571e7ee59SPeter Avalos       fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
137671e7ee59SPeter Avalos                 progName, inName );
137771e7ee59SPeter Avalos       setExit(1);
137871e7ee59SPeter Avalos       return;
137971e7ee59SPeter Avalos    }
138071e7ee59SPeter Avalos    if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
138171e7ee59SPeter Avalos       if (noisy)
138271e7ee59SPeter Avalos       fprintf ( stderr,
138371e7ee59SPeter Avalos                 "%s: Can't guess original name for %s -- using %s\n",
138471e7ee59SPeter Avalos                 progName, inName, outName );
138571e7ee59SPeter Avalos       /* just a warning, no return */
138671e7ee59SPeter Avalos    }
138771e7ee59SPeter Avalos    if ( srcMode == SM_F2F && fileExists ( outName ) ) {
138871e7ee59SPeter Avalos       if (forceOverwrite) {
138971e7ee59SPeter Avalos 	remove(outName);
139071e7ee59SPeter Avalos       } else {
139171e7ee59SPeter Avalos         fprintf ( stderr, "%s: Output file %s already exists.\n",
139271e7ee59SPeter Avalos                   progName, outName );
139371e7ee59SPeter Avalos         setExit(1);
139471e7ee59SPeter Avalos         return;
139571e7ee59SPeter Avalos       }
139671e7ee59SPeter Avalos    }
139771e7ee59SPeter Avalos    if ( srcMode == SM_F2F && !forceOverwrite &&
139871e7ee59SPeter Avalos         (n=countHardLinks ( inName ) ) > 0) {
139971e7ee59SPeter Avalos       fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
140071e7ee59SPeter Avalos                 progName, inName, n, n > 1 ? "s" : "" );
140171e7ee59SPeter Avalos       setExit(1);
140271e7ee59SPeter Avalos       return;
140371e7ee59SPeter Avalos    }
140471e7ee59SPeter Avalos 
140571e7ee59SPeter Avalos    if ( srcMode == SM_F2F ) {
140671e7ee59SPeter Avalos       /* Save the file's meta-info before we open it.  Doing it later
140771e7ee59SPeter Avalos          means we mess up the access times. */
140871e7ee59SPeter Avalos       saveInputFileMetaInfo ( inName );
140971e7ee59SPeter Avalos    }
141071e7ee59SPeter Avalos 
141171e7ee59SPeter Avalos    switch ( srcMode ) {
141271e7ee59SPeter Avalos 
141371e7ee59SPeter Avalos       case SM_I2O:
141471e7ee59SPeter Avalos          inStr = stdin;
141571e7ee59SPeter Avalos          outStr = stdout;
141671e7ee59SPeter Avalos          if ( isatty ( fileno ( stdin ) ) ) {
141771e7ee59SPeter Avalos             fprintf ( stderr,
141871e7ee59SPeter Avalos                       "%s: I won't read compressed data from a terminal.\n",
141971e7ee59SPeter Avalos                       progName );
142071e7ee59SPeter Avalos             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
142171e7ee59SPeter Avalos                               progName, progName );
142271e7ee59SPeter Avalos             setExit(1);
142371e7ee59SPeter Avalos             return;
142471e7ee59SPeter Avalos          };
142571e7ee59SPeter Avalos          break;
142671e7ee59SPeter Avalos 
142771e7ee59SPeter Avalos       case SM_F2O:
142871e7ee59SPeter Avalos          inStr = fopen ( inName, "rb" );
142971e7ee59SPeter Avalos          outStr = stdout;
143071e7ee59SPeter Avalos          if ( inStr == NULL ) {
143171e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
143271e7ee59SPeter Avalos                       progName, inName, strerror(errno) );
143371e7ee59SPeter Avalos             if ( inStr != NULL ) fclose ( inStr );
143471e7ee59SPeter Avalos             setExit(1);
143571e7ee59SPeter Avalos             return;
143671e7ee59SPeter Avalos          };
143771e7ee59SPeter Avalos          break;
143871e7ee59SPeter Avalos 
143971e7ee59SPeter Avalos       case SM_F2F:
144071e7ee59SPeter Avalos          inStr = fopen ( inName, "rb" );
144171e7ee59SPeter Avalos          outStr = fopen_output_safely ( outName, "wb" );
144271e7ee59SPeter Avalos          if ( outStr == NULL) {
144371e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
144471e7ee59SPeter Avalos                       progName, outName, strerror(errno) );
144571e7ee59SPeter Avalos             if ( inStr != NULL ) fclose ( inStr );
144671e7ee59SPeter Avalos             setExit(1);
144771e7ee59SPeter Avalos             return;
144871e7ee59SPeter Avalos          }
144971e7ee59SPeter Avalos          if ( inStr == NULL ) {
145071e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
145171e7ee59SPeter Avalos                       progName, inName, strerror(errno) );
145271e7ee59SPeter Avalos             if ( outStr != NULL ) fclose ( outStr );
145371e7ee59SPeter Avalos             setExit(1);
145471e7ee59SPeter Avalos             return;
145571e7ee59SPeter Avalos          };
145671e7ee59SPeter Avalos          break;
145771e7ee59SPeter Avalos 
145871e7ee59SPeter Avalos       default:
145971e7ee59SPeter Avalos          panic ( "uncompress: bad srcMode" );
146071e7ee59SPeter Avalos          break;
146171e7ee59SPeter Avalos    }
146271e7ee59SPeter Avalos 
146371e7ee59SPeter Avalos    if (verbosity >= 1) {
146471e7ee59SPeter Avalos       fprintf ( stderr, "  %s: ", inName );
146571e7ee59SPeter Avalos       pad ( inName );
146671e7ee59SPeter Avalos       fflush ( stderr );
146771e7ee59SPeter Avalos    }
146871e7ee59SPeter Avalos 
146971e7ee59SPeter Avalos    /*--- Now the input and output handles are sane.  Do the Biz. ---*/
147071e7ee59SPeter Avalos    outputHandleJustInCase = outStr;
147171e7ee59SPeter Avalos    deleteOutputOnInterrupt = True;
147271e7ee59SPeter Avalos    magicNumberOK = uncompressStream ( inStr, outStr );
147371e7ee59SPeter Avalos    outputHandleJustInCase = NULL;
147471e7ee59SPeter Avalos 
147571e7ee59SPeter Avalos    /*--- If there was an I/O error, we won't get here. ---*/
147671e7ee59SPeter Avalos    if ( magicNumberOK ) {
147771e7ee59SPeter Avalos       if ( srcMode == SM_F2F ) {
147871e7ee59SPeter Avalos          applySavedTimeInfoToOutputFile ( outName );
147971e7ee59SPeter Avalos          deleteOutputOnInterrupt = False;
148071e7ee59SPeter Avalos          if ( !keepInputFiles ) {
148171e7ee59SPeter Avalos             IntNative retVal = remove ( inName );
148271e7ee59SPeter Avalos             ERROR_IF_NOT_ZERO ( retVal );
148371e7ee59SPeter Avalos          }
148471e7ee59SPeter Avalos       }
148571e7ee59SPeter Avalos    } else {
148671e7ee59SPeter Avalos       unzFailsExist = True;
148771e7ee59SPeter Avalos       deleteOutputOnInterrupt = False;
148871e7ee59SPeter Avalos       if ( srcMode == SM_F2F ) {
148971e7ee59SPeter Avalos          IntNative retVal = remove ( outName );
149071e7ee59SPeter Avalos          ERROR_IF_NOT_ZERO ( retVal );
149171e7ee59SPeter Avalos       }
149271e7ee59SPeter Avalos    }
149371e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
149471e7ee59SPeter Avalos 
149571e7ee59SPeter Avalos    if ( magicNumberOK ) {
149671e7ee59SPeter Avalos       if (verbosity >= 1)
149771e7ee59SPeter Avalos          fprintf ( stderr, "done\n" );
149871e7ee59SPeter Avalos    } else {
149971e7ee59SPeter Avalos       setExit(2);
150071e7ee59SPeter Avalos       if (verbosity >= 1)
150171e7ee59SPeter Avalos          fprintf ( stderr, "not a bzip2 file.\n" ); else
150271e7ee59SPeter Avalos          fprintf ( stderr,
150371e7ee59SPeter Avalos                    "%s: %s is not a bzip2 file.\n",
150471e7ee59SPeter Avalos                    progName, inName );
150571e7ee59SPeter Avalos    }
150671e7ee59SPeter Avalos 
150771e7ee59SPeter Avalos }
150871e7ee59SPeter Avalos 
150971e7ee59SPeter Avalos 
151071e7ee59SPeter Avalos /*---------------------------------------------*/
151171e7ee59SPeter Avalos static
testf(Char * name)151271e7ee59SPeter Avalos void testf ( Char *name )
151371e7ee59SPeter Avalos {
151471e7ee59SPeter Avalos    FILE *inStr;
151571e7ee59SPeter Avalos    Bool allOK;
151671e7ee59SPeter Avalos    struct MY_STAT statBuf;
151771e7ee59SPeter Avalos 
151871e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
151971e7ee59SPeter Avalos 
152071e7ee59SPeter Avalos    if (name == NULL && srcMode != SM_I2O)
152171e7ee59SPeter Avalos       panic ( "testf: bad modes\n" );
152271e7ee59SPeter Avalos 
152371e7ee59SPeter Avalos    copyFileName ( outName, (Char*)"(none)" );
152471e7ee59SPeter Avalos    switch (srcMode) {
152571e7ee59SPeter Avalos       case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break;
152671e7ee59SPeter Avalos       case SM_F2F: copyFileName ( inName, name ); break;
152771e7ee59SPeter Avalos       case SM_F2O: copyFileName ( inName, name ); break;
152871e7ee59SPeter Avalos    }
152971e7ee59SPeter Avalos 
153071e7ee59SPeter Avalos    if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
153171e7ee59SPeter Avalos       if (noisy)
153271e7ee59SPeter Avalos       fprintf ( stderr, "%s: There are no files matching `%s'.\n",
153371e7ee59SPeter Avalos                 progName, inName );
153471e7ee59SPeter Avalos       setExit(1);
153571e7ee59SPeter Avalos       return;
153671e7ee59SPeter Avalos    }
153771e7ee59SPeter Avalos    if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
153871e7ee59SPeter Avalos       fprintf ( stderr, "%s: Can't open input %s: %s.\n",
153971e7ee59SPeter Avalos                 progName, inName, strerror(errno) );
154071e7ee59SPeter Avalos       setExit(1);
154171e7ee59SPeter Avalos       return;
154271e7ee59SPeter Avalos    }
154371e7ee59SPeter Avalos    if ( srcMode != SM_I2O ) {
154471e7ee59SPeter Avalos       MY_STAT(inName, &statBuf);
154571e7ee59SPeter Avalos       if ( MY_S_ISDIR(statBuf.st_mode) ) {
154671e7ee59SPeter Avalos          fprintf( stderr,
154771e7ee59SPeter Avalos                   "%s: Input file %s is a directory.\n",
154871e7ee59SPeter Avalos                   progName,inName);
154971e7ee59SPeter Avalos          setExit(1);
155071e7ee59SPeter Avalos          return;
155171e7ee59SPeter Avalos       }
155271e7ee59SPeter Avalos    }
155371e7ee59SPeter Avalos 
155471e7ee59SPeter Avalos    switch ( srcMode ) {
155571e7ee59SPeter Avalos 
155671e7ee59SPeter Avalos       case SM_I2O:
155771e7ee59SPeter Avalos          if ( isatty ( fileno ( stdin ) ) ) {
155871e7ee59SPeter Avalos             fprintf ( stderr,
155971e7ee59SPeter Avalos                       "%s: I won't read compressed data from a terminal.\n",
156071e7ee59SPeter Avalos                       progName );
156171e7ee59SPeter Avalos             fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
156271e7ee59SPeter Avalos                               progName, progName );
156371e7ee59SPeter Avalos             setExit(1);
156471e7ee59SPeter Avalos             return;
156571e7ee59SPeter Avalos          };
156671e7ee59SPeter Avalos          inStr = stdin;
156771e7ee59SPeter Avalos          break;
156871e7ee59SPeter Avalos 
156971e7ee59SPeter Avalos       case SM_F2O: case SM_F2F:
157071e7ee59SPeter Avalos          inStr = fopen ( inName, "rb" );
157171e7ee59SPeter Avalos          if ( inStr == NULL ) {
157271e7ee59SPeter Avalos             fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
157371e7ee59SPeter Avalos                       progName, inName, strerror(errno) );
157471e7ee59SPeter Avalos             setExit(1);
157571e7ee59SPeter Avalos             return;
157671e7ee59SPeter Avalos          };
157771e7ee59SPeter Avalos          break;
157871e7ee59SPeter Avalos 
157971e7ee59SPeter Avalos       default:
158071e7ee59SPeter Avalos          panic ( "testf: bad srcMode" );
158171e7ee59SPeter Avalos          break;
158271e7ee59SPeter Avalos    }
158371e7ee59SPeter Avalos 
158471e7ee59SPeter Avalos    if (verbosity >= 1) {
158571e7ee59SPeter Avalos       fprintf ( stderr, "  %s: ", inName );
158671e7ee59SPeter Avalos       pad ( inName );
158771e7ee59SPeter Avalos       fflush ( stderr );
158871e7ee59SPeter Avalos    }
158971e7ee59SPeter Avalos 
159071e7ee59SPeter Avalos    /*--- Now the input handle is sane.  Do the Biz. ---*/
159171e7ee59SPeter Avalos    outputHandleJustInCase = NULL;
159271e7ee59SPeter Avalos    allOK = testStream ( inStr );
159371e7ee59SPeter Avalos 
159471e7ee59SPeter Avalos    if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
159571e7ee59SPeter Avalos    if (!allOK) testFailsExist = True;
159671e7ee59SPeter Avalos }
159771e7ee59SPeter Avalos 
159871e7ee59SPeter Avalos 
159971e7ee59SPeter Avalos /*---------------------------------------------*/
160071e7ee59SPeter Avalos static
license(void)160171e7ee59SPeter Avalos void license ( void )
160271e7ee59SPeter Avalos {
160371e7ee59SPeter Avalos    fprintf ( stderr,
160471e7ee59SPeter Avalos 
160571e7ee59SPeter Avalos     "bzip2, a block-sorting file compressor.  "
160671e7ee59SPeter Avalos     "Version %s.\n"
160771e7ee59SPeter Avalos     "   \n"
1608*86954436SDaniel Fojt     "   Copyright (C) 1996-2019 by Julian Seward.\n"
160971e7ee59SPeter Avalos     "   \n"
161071e7ee59SPeter Avalos     "   This program is free software; you can redistribute it and/or modify\n"
161171e7ee59SPeter Avalos     "   it under the terms set out in the LICENSE file, which is included\n"
1612*86954436SDaniel Fojt     "   in the bzip2 source distribution.\n"
161371e7ee59SPeter Avalos     "   \n"
161471e7ee59SPeter Avalos     "   This program is distributed in the hope that it will be useful,\n"
161571e7ee59SPeter Avalos     "   but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
161671e7ee59SPeter Avalos     "   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
161771e7ee59SPeter Avalos     "   LICENSE file for more details.\n"
161871e7ee59SPeter Avalos     "   \n",
161971e7ee59SPeter Avalos     BZ2_bzlibVersion()
162071e7ee59SPeter Avalos    );
162171e7ee59SPeter Avalos }
162271e7ee59SPeter Avalos 
162371e7ee59SPeter Avalos 
162471e7ee59SPeter Avalos /*---------------------------------------------*/
162571e7ee59SPeter Avalos static
usage(Char * fullProgName)162671e7ee59SPeter Avalos void usage ( Char *fullProgName )
162771e7ee59SPeter Avalos {
162871e7ee59SPeter Avalos    fprintf (
162971e7ee59SPeter Avalos       stderr,
163071e7ee59SPeter Avalos       "bzip2, a block-sorting file compressor.  "
163171e7ee59SPeter Avalos       "Version %s.\n"
163271e7ee59SPeter Avalos       "\n   usage: %s [flags and input files in any order]\n"
163371e7ee59SPeter Avalos       "\n"
163471e7ee59SPeter Avalos       "   -h --help           print this message\n"
163571e7ee59SPeter Avalos       "   -d --decompress     force decompression\n"
163671e7ee59SPeter Avalos       "   -z --compress       force compression\n"
163771e7ee59SPeter Avalos       "   -k --keep           keep (don't delete) input files\n"
163871e7ee59SPeter Avalos       "   -f --force          overwrite existing output files\n"
163971e7ee59SPeter Avalos       "   -t --test           test compressed file integrity\n"
164071e7ee59SPeter Avalos       "   -c --stdout         output to standard out\n"
164171e7ee59SPeter Avalos       "   -q --quiet          suppress noncritical error messages\n"
164271e7ee59SPeter Avalos       "   -v --verbose        be verbose (a 2nd -v gives more)\n"
164371e7ee59SPeter Avalos       "   -L --license        display software version & license\n"
164471e7ee59SPeter Avalos       "   -V --version        display software version & license\n"
164571e7ee59SPeter Avalos       "   -s --small          use less memory (at most 2500k)\n"
164671e7ee59SPeter Avalos       "   -1 .. -9            set block size to 100k .. 900k\n"
164771e7ee59SPeter Avalos       "   --fast              alias for -1\n"
164871e7ee59SPeter Avalos       "   --best              alias for -9\n"
164971e7ee59SPeter Avalos       "\n"
165071e7ee59SPeter Avalos       "   If invoked as `bzip2', default action is to compress.\n"
165171e7ee59SPeter Avalos       "              as `bunzip2',  default action is to decompress.\n"
165271e7ee59SPeter Avalos       "              as `bzcat', default action is to decompress to stdout.\n"
165371e7ee59SPeter Avalos       "\n"
165471e7ee59SPeter Avalos       "   If no file names are given, bzip2 compresses or decompresses\n"
165571e7ee59SPeter Avalos       "   from standard input to standard output.  You can combine\n"
165671e7ee59SPeter Avalos       "   short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
165771e7ee59SPeter Avalos #     if BZ_UNIX
165871e7ee59SPeter Avalos       "\n"
165971e7ee59SPeter Avalos #     endif
166071e7ee59SPeter Avalos       ,
166171e7ee59SPeter Avalos 
166271e7ee59SPeter Avalos       BZ2_bzlibVersion(),
166371e7ee59SPeter Avalos       fullProgName
166471e7ee59SPeter Avalos    );
166571e7ee59SPeter Avalos }
166671e7ee59SPeter Avalos 
166771e7ee59SPeter Avalos 
166871e7ee59SPeter Avalos /*---------------------------------------------*/
166971e7ee59SPeter Avalos static
redundant(Char * flag)167071e7ee59SPeter Avalos void redundant ( Char* flag )
167171e7ee59SPeter Avalos {
167271e7ee59SPeter Avalos    fprintf (
167371e7ee59SPeter Avalos       stderr,
167471e7ee59SPeter Avalos       "%s: %s is redundant in versions 0.9.5 and above\n",
167571e7ee59SPeter Avalos       progName, flag );
167671e7ee59SPeter Avalos }
167771e7ee59SPeter Avalos 
167871e7ee59SPeter Avalos 
167971e7ee59SPeter Avalos /*---------------------------------------------*/
168071e7ee59SPeter Avalos /*--
168171e7ee59SPeter Avalos   All the garbage from here to main() is purely to
168271e7ee59SPeter Avalos   implement a linked list of command-line arguments,
168371e7ee59SPeter Avalos   into which main() copies argv[1 .. argc-1].
168471e7ee59SPeter Avalos 
168571e7ee59SPeter Avalos   The purpose of this exercise is to facilitate
168671e7ee59SPeter Avalos   the expansion of wildcard characters * and ? in
168771e7ee59SPeter Avalos   filenames for OSs which don't know how to do it
168871e7ee59SPeter Avalos   themselves, like MSDOS, Windows 95 and NT.
168971e7ee59SPeter Avalos 
169071e7ee59SPeter Avalos   The actual Dirty Work is done by the platform-
169171e7ee59SPeter Avalos   specific macro APPEND_FILESPEC.
169271e7ee59SPeter Avalos --*/
169371e7ee59SPeter Avalos 
169471e7ee59SPeter Avalos typedef
169571e7ee59SPeter Avalos    struct zzzz {
169671e7ee59SPeter Avalos       Char        *name;
169771e7ee59SPeter Avalos       struct zzzz *link;
169871e7ee59SPeter Avalos    }
169971e7ee59SPeter Avalos    Cell;
170071e7ee59SPeter Avalos 
170171e7ee59SPeter Avalos 
170271e7ee59SPeter Avalos /*---------------------------------------------*/
170371e7ee59SPeter Avalos static
myMalloc(Int32 n)170471e7ee59SPeter Avalos void *myMalloc ( Int32 n )
170571e7ee59SPeter Avalos {
170671e7ee59SPeter Avalos    void* p;
170771e7ee59SPeter Avalos 
170871e7ee59SPeter Avalos    p = malloc ( (size_t)n );
170971e7ee59SPeter Avalos    if (p == NULL) outOfMemory ();
171071e7ee59SPeter Avalos    return p;
171171e7ee59SPeter Avalos }
171271e7ee59SPeter Avalos 
171371e7ee59SPeter Avalos 
171471e7ee59SPeter Avalos /*---------------------------------------------*/
171571e7ee59SPeter Avalos static
mkCell(void)171671e7ee59SPeter Avalos Cell *mkCell ( void )
171771e7ee59SPeter Avalos {
171871e7ee59SPeter Avalos    Cell *c;
171971e7ee59SPeter Avalos 
172071e7ee59SPeter Avalos    c = (Cell*) myMalloc ( sizeof ( Cell ) );
172171e7ee59SPeter Avalos    c->name = NULL;
172271e7ee59SPeter Avalos    c->link = NULL;
172371e7ee59SPeter Avalos    return c;
172471e7ee59SPeter Avalos }
172571e7ee59SPeter Avalos 
172671e7ee59SPeter Avalos 
172771e7ee59SPeter Avalos /*---------------------------------------------*/
172871e7ee59SPeter Avalos static
snocString(Cell * root,Char * name)172971e7ee59SPeter Avalos Cell *snocString ( Cell *root, Char *name )
173071e7ee59SPeter Avalos {
173171e7ee59SPeter Avalos    if (root == NULL) {
173271e7ee59SPeter Avalos       Cell *tmp = mkCell();
173371e7ee59SPeter Avalos       tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
173471e7ee59SPeter Avalos       strcpy ( tmp->name, name );
173571e7ee59SPeter Avalos       return tmp;
173671e7ee59SPeter Avalos    } else {
173771e7ee59SPeter Avalos       Cell *tmp = root;
173871e7ee59SPeter Avalos       while (tmp->link != NULL) tmp = tmp->link;
173971e7ee59SPeter Avalos       tmp->link = snocString ( tmp->link, name );
174071e7ee59SPeter Avalos       return root;
174171e7ee59SPeter Avalos    }
174271e7ee59SPeter Avalos }
174371e7ee59SPeter Avalos 
174471e7ee59SPeter Avalos 
174571e7ee59SPeter Avalos /*---------------------------------------------*/
174671e7ee59SPeter Avalos static
addFlagsFromEnvVar(Cell ** argList,Char * varName)174771e7ee59SPeter Avalos void addFlagsFromEnvVar ( Cell** argList, Char* varName )
174871e7ee59SPeter Avalos {
174971e7ee59SPeter Avalos    Int32 i, j, k;
175071e7ee59SPeter Avalos    Char *envbase, *p;
175171e7ee59SPeter Avalos 
175271e7ee59SPeter Avalos    envbase = getenv(varName);
175371e7ee59SPeter Avalos    if (envbase != NULL) {
175471e7ee59SPeter Avalos       p = envbase;
175571e7ee59SPeter Avalos       i = 0;
175671e7ee59SPeter Avalos       while (True) {
175771e7ee59SPeter Avalos          if (p[i] == 0) break;
175871e7ee59SPeter Avalos          p += i;
175971e7ee59SPeter Avalos          i = 0;
176071e7ee59SPeter Avalos          while (isspace((Int32)(p[0]))) p++;
176171e7ee59SPeter Avalos          while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
176271e7ee59SPeter Avalos          if (i > 0) {
176371e7ee59SPeter Avalos             k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
176471e7ee59SPeter Avalos             for (j = 0; j < k; j++) tmpName[j] = p[j];
176571e7ee59SPeter Avalos             tmpName[k] = 0;
176671e7ee59SPeter Avalos             APPEND_FLAG(*argList, tmpName);
176771e7ee59SPeter Avalos          }
176871e7ee59SPeter Avalos       }
176971e7ee59SPeter Avalos    }
177071e7ee59SPeter Avalos }
177171e7ee59SPeter Avalos 
177271e7ee59SPeter Avalos 
177371e7ee59SPeter Avalos /*---------------------------------------------*/
177471e7ee59SPeter Avalos #define ISFLAG(s) (strcmp(aa->name, (s))==0)
177571e7ee59SPeter Avalos 
main(IntNative argc,Char * argv[])177671e7ee59SPeter Avalos IntNative main ( IntNative argc, Char *argv[] )
177771e7ee59SPeter Avalos {
177871e7ee59SPeter Avalos    Int32  i, j;
177971e7ee59SPeter Avalos    Char   *tmp;
178071e7ee59SPeter Avalos    Cell   *argList;
178171e7ee59SPeter Avalos    Cell   *aa;
178271e7ee59SPeter Avalos    Bool   decode;
178371e7ee59SPeter Avalos 
178471e7ee59SPeter Avalos    /*-- Be really really really paranoid :-) --*/
178571e7ee59SPeter Avalos    if (sizeof(Int32) != 4 || sizeof(UInt32) != 4  ||
178671e7ee59SPeter Avalos        sizeof(Int16) != 2 || sizeof(UInt16) != 2  ||
178771e7ee59SPeter Avalos        sizeof(Char)  != 1 || sizeof(UChar)  != 1)
178871e7ee59SPeter Avalos       configError();
178971e7ee59SPeter Avalos 
179071e7ee59SPeter Avalos    /*-- Initialise --*/
179171e7ee59SPeter Avalos    outputHandleJustInCase  = NULL;
179271e7ee59SPeter Avalos    smallMode               = False;
179371e7ee59SPeter Avalos    keepInputFiles          = False;
179471e7ee59SPeter Avalos    forceOverwrite          = False;
179571e7ee59SPeter Avalos    noisy                   = True;
179671e7ee59SPeter Avalos    verbosity               = 0;
179771e7ee59SPeter Avalos    blockSize100k           = 9;
179871e7ee59SPeter Avalos    testFailsExist          = False;
179971e7ee59SPeter Avalos    unzFailsExist           = False;
180071e7ee59SPeter Avalos    numFileNames            = 0;
180171e7ee59SPeter Avalos    numFilesProcessed       = 0;
180271e7ee59SPeter Avalos    workFactor              = 30;
180371e7ee59SPeter Avalos    deleteOutputOnInterrupt = False;
180471e7ee59SPeter Avalos    exitValue               = 0;
180571e7ee59SPeter Avalos    i = j = 0; /* avoid bogus warning from egcs-1.1.X */
180671e7ee59SPeter Avalos 
180771e7ee59SPeter Avalos    /*-- Set up signal handlers for mem access errors --*/
180871e7ee59SPeter Avalos    signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
180971e7ee59SPeter Avalos #  if BZ_UNIX
181071e7ee59SPeter Avalos #  ifndef __DJGPP__
181171e7ee59SPeter Avalos    signal (SIGBUS,  mySIGSEGVorSIGBUScatcher);
181271e7ee59SPeter Avalos #  endif
181371e7ee59SPeter Avalos #  endif
181471e7ee59SPeter Avalos 
181571e7ee59SPeter Avalos    copyFileName ( inName,  (Char*)"(none)" );
181671e7ee59SPeter Avalos    copyFileName ( outName, (Char*)"(none)" );
181771e7ee59SPeter Avalos 
181871e7ee59SPeter Avalos    copyFileName ( progNameReally, argv[0] );
181971e7ee59SPeter Avalos    progName = &progNameReally[0];
182071e7ee59SPeter Avalos    for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
182171e7ee59SPeter Avalos       if (*tmp == PATH_SEP) progName = tmp + 1;
182271e7ee59SPeter Avalos 
182371e7ee59SPeter Avalos 
182471e7ee59SPeter Avalos    /*-- Copy flags from env var BZIP2, and
182571e7ee59SPeter Avalos         expand filename wildcards in arg list.
182671e7ee59SPeter Avalos    --*/
182771e7ee59SPeter Avalos    argList = NULL;
182871e7ee59SPeter Avalos    addFlagsFromEnvVar ( &argList,  (Char*)"BZIP2" );
182971e7ee59SPeter Avalos    addFlagsFromEnvVar ( &argList,  (Char*)"BZIP" );
183071e7ee59SPeter Avalos    for (i = 1; i <= argc-1; i++)
183171e7ee59SPeter Avalos       APPEND_FILESPEC(argList, argv[i]);
183271e7ee59SPeter Avalos 
183371e7ee59SPeter Avalos 
183471e7ee59SPeter Avalos    /*-- Find the length of the longest filename --*/
183571e7ee59SPeter Avalos    longestFileName = 7;
183671e7ee59SPeter Avalos    numFileNames    = 0;
183771e7ee59SPeter Avalos    decode          = True;
183871e7ee59SPeter Avalos    for (aa = argList; aa != NULL; aa = aa->link) {
183971e7ee59SPeter Avalos       if (ISFLAG("--")) { decode = False; continue; }
184071e7ee59SPeter Avalos       if (aa->name[0] == '-' && decode) continue;
184171e7ee59SPeter Avalos       numFileNames++;
184271e7ee59SPeter Avalos       if (longestFileName < (Int32)strlen(aa->name) )
184371e7ee59SPeter Avalos          longestFileName = (Int32)strlen(aa->name);
184471e7ee59SPeter Avalos    }
184571e7ee59SPeter Avalos 
184671e7ee59SPeter Avalos 
184771e7ee59SPeter Avalos    /*-- Determine source modes; flag handling may change this too. --*/
184871e7ee59SPeter Avalos    if (numFileNames == 0)
184971e7ee59SPeter Avalos       srcMode = SM_I2O; else srcMode = SM_F2F;
185071e7ee59SPeter Avalos 
185171e7ee59SPeter Avalos 
185271e7ee59SPeter Avalos    /*-- Determine what to do (compress/uncompress/test/cat). --*/
185371e7ee59SPeter Avalos    /*-- Note that subsequent flag handling may change this. --*/
185471e7ee59SPeter Avalos    opMode = OM_Z;
185571e7ee59SPeter Avalos 
185671e7ee59SPeter Avalos    if ( (strstr ( progName, "unzip" ) != 0) ||
185771e7ee59SPeter Avalos         (strstr ( progName, "UNZIP" ) != 0) )
185871e7ee59SPeter Avalos       opMode = OM_UNZ;
185971e7ee59SPeter Avalos 
186071e7ee59SPeter Avalos    if ( (strstr ( progName, "z2cat" ) != 0) ||
186171e7ee59SPeter Avalos         (strstr ( progName, "Z2CAT" ) != 0) ||
186271e7ee59SPeter Avalos         (strstr ( progName, "zcat" ) != 0)  ||
186371e7ee59SPeter Avalos         (strstr ( progName, "ZCAT" ) != 0) )  {
186471e7ee59SPeter Avalos       opMode = OM_UNZ;
186571e7ee59SPeter Avalos       srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
186671e7ee59SPeter Avalos    }
186771e7ee59SPeter Avalos 
186871e7ee59SPeter Avalos 
186971e7ee59SPeter Avalos    /*-- Look at the flags. --*/
187071e7ee59SPeter Avalos    for (aa = argList; aa != NULL; aa = aa->link) {
187171e7ee59SPeter Avalos       if (ISFLAG("--")) break;
187271e7ee59SPeter Avalos       if (aa->name[0] == '-' && aa->name[1] != '-') {
187371e7ee59SPeter Avalos          for (j = 1; aa->name[j] != '\0'; j++) {
187471e7ee59SPeter Avalos             switch (aa->name[j]) {
187571e7ee59SPeter Avalos                case 'c': srcMode          = SM_F2O; break;
187671e7ee59SPeter Avalos                case 'd': opMode           = OM_UNZ; break;
187771e7ee59SPeter Avalos                case 'z': opMode           = OM_Z; break;
187871e7ee59SPeter Avalos                case 'f': forceOverwrite   = True; break;
187971e7ee59SPeter Avalos                case 't': opMode           = OM_TEST; break;
188071e7ee59SPeter Avalos                case 'k': keepInputFiles   = True; break;
188171e7ee59SPeter Avalos                case 's': smallMode        = True; break;
188271e7ee59SPeter Avalos                case 'q': noisy            = False; break;
188371e7ee59SPeter Avalos                case '1': blockSize100k    = 1; break;
188471e7ee59SPeter Avalos                case '2': blockSize100k    = 2; break;
188571e7ee59SPeter Avalos                case '3': blockSize100k    = 3; break;
188671e7ee59SPeter Avalos                case '4': blockSize100k    = 4; break;
188771e7ee59SPeter Avalos                case '5': blockSize100k    = 5; break;
188871e7ee59SPeter Avalos                case '6': blockSize100k    = 6; break;
188971e7ee59SPeter Avalos                case '7': blockSize100k    = 7; break;
189071e7ee59SPeter Avalos                case '8': blockSize100k    = 8; break;
189171e7ee59SPeter Avalos                case '9': blockSize100k    = 9; break;
189271e7ee59SPeter Avalos                case 'V':
189371e7ee59SPeter Avalos                case 'L': license();            break;
189471e7ee59SPeter Avalos                case 'v': verbosity++; break;
189571e7ee59SPeter Avalos                case 'h': usage ( progName );
189671e7ee59SPeter Avalos                          exit ( 0 );
189771e7ee59SPeter Avalos                          break;
189871e7ee59SPeter Avalos                default:  fprintf ( stderr, "%s: Bad flag `%s'\n",
189971e7ee59SPeter Avalos                                    progName, aa->name );
190071e7ee59SPeter Avalos                          usage ( progName );
190171e7ee59SPeter Avalos                          exit ( 1 );
190271e7ee59SPeter Avalos                          break;
190371e7ee59SPeter Avalos             }
190471e7ee59SPeter Avalos          }
190571e7ee59SPeter Avalos       }
190671e7ee59SPeter Avalos    }
190771e7ee59SPeter Avalos 
190871e7ee59SPeter Avalos    /*-- And again ... --*/
190971e7ee59SPeter Avalos    for (aa = argList; aa != NULL; aa = aa->link) {
191071e7ee59SPeter Avalos       if (ISFLAG("--")) break;
191171e7ee59SPeter Avalos       if (ISFLAG("--stdout"))            srcMode          = SM_F2O;  else
191271e7ee59SPeter Avalos       if (ISFLAG("--decompress"))        opMode           = OM_UNZ;  else
191371e7ee59SPeter Avalos       if (ISFLAG("--compress"))          opMode           = OM_Z;    else
191471e7ee59SPeter Avalos       if (ISFLAG("--force"))             forceOverwrite   = True;    else
191571e7ee59SPeter Avalos       if (ISFLAG("--test"))              opMode           = OM_TEST; else
191671e7ee59SPeter Avalos       if (ISFLAG("--keep"))              keepInputFiles   = True;    else
191771e7ee59SPeter Avalos       if (ISFLAG("--small"))             smallMode        = True;    else
191871e7ee59SPeter Avalos       if (ISFLAG("--quiet"))             noisy            = False;   else
191971e7ee59SPeter Avalos       if (ISFLAG("--version"))           license();                  else
192071e7ee59SPeter Avalos       if (ISFLAG("--license"))           license();                  else
192171e7ee59SPeter Avalos       if (ISFLAG("--exponential"))       workFactor = 1;             else
192271e7ee59SPeter Avalos       if (ISFLAG("--repetitive-best"))   redundant(aa->name);        else
192371e7ee59SPeter Avalos       if (ISFLAG("--repetitive-fast"))   redundant(aa->name);        else
192471e7ee59SPeter Avalos       if (ISFLAG("--fast"))              blockSize100k = 1;          else
192571e7ee59SPeter Avalos       if (ISFLAG("--best"))              blockSize100k = 9;          else
192671e7ee59SPeter Avalos       if (ISFLAG("--verbose"))           verbosity++;                else
192771e7ee59SPeter Avalos       if (ISFLAG("--help"))              { usage ( progName ); exit ( 0 ); }
192871e7ee59SPeter Avalos          else
192971e7ee59SPeter Avalos          if (strncmp ( aa->name, "--", 2) == 0) {
193071e7ee59SPeter Avalos             fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
193171e7ee59SPeter Avalos             usage ( progName );
193271e7ee59SPeter Avalos             exit ( 1 );
193371e7ee59SPeter Avalos          }
193471e7ee59SPeter Avalos    }
193571e7ee59SPeter Avalos 
193671e7ee59SPeter Avalos    if (verbosity > 4) verbosity = 4;
193771e7ee59SPeter Avalos    if (opMode == OM_Z && smallMode && blockSize100k > 2)
193871e7ee59SPeter Avalos       blockSize100k = 2;
193971e7ee59SPeter Avalos 
194071e7ee59SPeter Avalos    if (opMode == OM_TEST && srcMode == SM_F2O) {
194171e7ee59SPeter Avalos       fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
194271e7ee59SPeter Avalos                 progName );
194371e7ee59SPeter Avalos       exit ( 1 );
194471e7ee59SPeter Avalos    }
194571e7ee59SPeter Avalos 
194671e7ee59SPeter Avalos    if (srcMode == SM_F2O && numFileNames == 0)
194771e7ee59SPeter Avalos       srcMode = SM_I2O;
194871e7ee59SPeter Avalos 
194971e7ee59SPeter Avalos    if (opMode != OM_Z) blockSize100k = 0;
195071e7ee59SPeter Avalos 
195171e7ee59SPeter Avalos    if (srcMode == SM_F2F) {
195271e7ee59SPeter Avalos       signal (SIGINT,  mySignalCatcher);
195371e7ee59SPeter Avalos       signal (SIGTERM, mySignalCatcher);
195471e7ee59SPeter Avalos #     if BZ_UNIX
195571e7ee59SPeter Avalos       signal (SIGHUP,  mySignalCatcher);
195671e7ee59SPeter Avalos #     endif
195771e7ee59SPeter Avalos    }
195871e7ee59SPeter Avalos 
195971e7ee59SPeter Avalos    if (opMode == OM_Z) {
196071e7ee59SPeter Avalos      if (srcMode == SM_I2O) {
196171e7ee59SPeter Avalos         compress ( NULL );
196271e7ee59SPeter Avalos      } else {
196371e7ee59SPeter Avalos         decode = True;
196471e7ee59SPeter Avalos         for (aa = argList; aa != NULL; aa = aa->link) {
196571e7ee59SPeter Avalos            if (ISFLAG("--")) { decode = False; continue; }
196671e7ee59SPeter Avalos            if (aa->name[0] == '-' && decode) continue;
196771e7ee59SPeter Avalos            numFilesProcessed++;
196871e7ee59SPeter Avalos            compress ( aa->name );
196971e7ee59SPeter Avalos         }
197071e7ee59SPeter Avalos      }
197171e7ee59SPeter Avalos    }
197271e7ee59SPeter Avalos    else
197371e7ee59SPeter Avalos 
197471e7ee59SPeter Avalos    if (opMode == OM_UNZ) {
197571e7ee59SPeter Avalos       unzFailsExist = False;
197671e7ee59SPeter Avalos       if (srcMode == SM_I2O) {
197771e7ee59SPeter Avalos          uncompress ( NULL );
197871e7ee59SPeter Avalos       } else {
197971e7ee59SPeter Avalos          decode = True;
198071e7ee59SPeter Avalos          for (aa = argList; aa != NULL; aa = aa->link) {
198171e7ee59SPeter Avalos             if (ISFLAG("--")) { decode = False; continue; }
198271e7ee59SPeter Avalos             if (aa->name[0] == '-' && decode) continue;
198371e7ee59SPeter Avalos             numFilesProcessed++;
198471e7ee59SPeter Avalos             uncompress ( aa->name );
198571e7ee59SPeter Avalos          }
198671e7ee59SPeter Avalos       }
198771e7ee59SPeter Avalos       if (unzFailsExist) {
198871e7ee59SPeter Avalos          setExit(2);
198971e7ee59SPeter Avalos          exit(exitValue);
199071e7ee59SPeter Avalos       }
199171e7ee59SPeter Avalos    }
199271e7ee59SPeter Avalos 
199371e7ee59SPeter Avalos    else {
199471e7ee59SPeter Avalos       testFailsExist = False;
199571e7ee59SPeter Avalos       if (srcMode == SM_I2O) {
199671e7ee59SPeter Avalos          testf ( NULL );
199771e7ee59SPeter Avalos       } else {
199871e7ee59SPeter Avalos          decode = True;
199971e7ee59SPeter Avalos          for (aa = argList; aa != NULL; aa = aa->link) {
200071e7ee59SPeter Avalos 	    if (ISFLAG("--")) { decode = False; continue; }
200171e7ee59SPeter Avalos             if (aa->name[0] == '-' && decode) continue;
200271e7ee59SPeter Avalos             numFilesProcessed++;
200371e7ee59SPeter Avalos             testf ( aa->name );
200471e7ee59SPeter Avalos 	 }
200571e7ee59SPeter Avalos       }
2006*86954436SDaniel Fojt       if (testFailsExist) {
2007*86954436SDaniel Fojt 	 if (noisy) {
200871e7ee59SPeter Avalos             fprintf ( stderr,
200971e7ee59SPeter Avalos                "\n"
201071e7ee59SPeter Avalos                "You can use the `bzip2recover' program to attempt to recover\n"
201171e7ee59SPeter Avalos                "data from undamaged sections of corrupted files.\n\n"
201271e7ee59SPeter Avalos             );
2013*86954436SDaniel Fojt 	 }
201471e7ee59SPeter Avalos          setExit(2);
201571e7ee59SPeter Avalos          exit(exitValue);
201671e7ee59SPeter Avalos       }
201771e7ee59SPeter Avalos    }
201871e7ee59SPeter Avalos 
201971e7ee59SPeter Avalos    /* Free the argument list memory to mollify leak detectors
202071e7ee59SPeter Avalos       (eg) Purify, Checker.  Serves no other useful purpose.
202171e7ee59SPeter Avalos    */
202271e7ee59SPeter Avalos    aa = argList;
202371e7ee59SPeter Avalos    while (aa != NULL) {
202471e7ee59SPeter Avalos       Cell* aa2 = aa->link;
202571e7ee59SPeter Avalos       if (aa->name != NULL) free(aa->name);
202671e7ee59SPeter Avalos       free(aa);
202771e7ee59SPeter Avalos       aa = aa2;
202871e7ee59SPeter Avalos    }
202971e7ee59SPeter Avalos 
203071e7ee59SPeter Avalos    return exitValue;
203171e7ee59SPeter Avalos }
203271e7ee59SPeter Avalos 
203371e7ee59SPeter Avalos 
203471e7ee59SPeter Avalos /*-----------------------------------------------------------*/
203571e7ee59SPeter Avalos /*--- end                                         bzip2.c ---*/
203671e7ee59SPeter Avalos /*-----------------------------------------------------------*/
2037