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