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