~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to win32/3rdparty/bzip2/bzip2.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

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