Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmbzip2/bzip2.c
3150 views
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.8 of 13 July 2019
11
Copyright (C) 1996-2019 Julian Seward <[email protected]>
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 _stati64
136
# define MY_STAT _stati64
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, 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
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:\n"
752
"\[email protected]\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: [email protected].\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: [email protected].\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-2019 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 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) {
2007
if (noisy) {
2008
fprintf ( stderr,
2009
"\n"
2010
"You can use the `bzip2recover' program to attempt to recover\n"
2011
"data from undamaged sections of corrupted files.\n\n"
2012
);
2013
}
2014
setExit(2);
2015
exit(exitValue);
2016
}
2017
}
2018
2019
/* Free the argument list memory to mollify leak detectors
2020
(eg) Purify, Checker. Serves no other useful purpose.
2021
*/
2022
aa = argList;
2023
while (aa != NULL) {
2024
Cell* aa2 = aa->link;
2025
if (aa->name != NULL) free(aa->name);
2026
free(aa);
2027
aa = aa2;
2028
}
2029
2030
return exitValue;
2031
}
2032
2033
2034
/*-----------------------------------------------------------*/
2035
/*--- end bzip2.c ---*/
2036
/*-----------------------------------------------------------*/
2037
2038