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