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