1 /* $NetBSD: bzip2.c,v 1.8 2009/04/11 11:10:43 lukem Exp $ */
4 /*-----------------------------------------------------------*/
5 /*--- A block-sorting, lossless compressor bzip2.c ---*/
6 /*-----------------------------------------------------------*/
8 /* ------------------------------------------------------------------
9 This file is part of bzip2/libbzip2, a program and library for
10 lossless, block-sorting data compression.
12 bzip2/libbzip2 version 1.0.5 of 10 December 2007
13 Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
15 Please read the WARNING, DISCLAIMER and PATENTS sections in the
18 This program is released under the terms of the license contained
20 ------------------------------------------------------------------ */
23 /* Place a 1 beside your platform, and 0 elsewhere.
25 Also works on 64-bit Unix boxes.
31 Win32, as seen by Jacob Navia's excellent
32 port of (Chris Fraser & David Hanson)'s excellent
33 lcc compiler. Or with MS Visual C.
34 This is selected automatically if compiled by a compiler which
35 defines _WIN32, not including the Cygwin GCC.
39 #if defined(_WIN32) && !defined(__CYGWIN__)
47 /*---------------------------------------------*/
49 Some stuff for all platforms.
61 #define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); }
62 #define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); }
63 #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
66 /*---------------------------------------------*/
68 Platform-specific stuff.
73 # include <sys/types.h>
76 # include <sys/stat.h>
77 # include <sys/times.h>
80 # define MY_LSTAT lstat
82 # define MY_S_ISREG S_ISREG
83 # define MY_S_ISDIR S_ISDIR
85 # define APPEND_FILESPEC(root, name) \
86 root=snocString((root), (name))
88 # define APPEND_FLAG(root, name) \
89 root=snocString((root), (name))
91 # define SET_BINARY_MODE(fd) /**/
94 # define NORETURN __attribute__ ((noreturn))
96 # define NORETURN /**/
104 # define MY_LSTAT stat
105 # define MY_STAT stat
106 # undef SET_BINARY_MODE
107 # define SET_BINARY_MODE(fd) \
109 int retVal = setmode ( fileno ( fd ), \
111 ERROR_IF_MINUS_ONE ( retVal ); \
118 # undef SET_BINARY_MODE
119 # define SET_BINARY_MODE(fd) \
121 int retVal = setmode ( fileno ( fd ), \
123 ERROR_IF_MINUS_ONE ( retVal ); \
133 # include <sys\stat.h>
135 # define NORETURN /**/
136 # define PATH_SEP '\\'
137 # define MY_LSTAT _stat
138 # define MY_STAT _stat
139 # define MY_S_ISREG(x) ((x) & _S_IFREG)
140 # define MY_S_ISDIR(x) ((x) & _S_IFDIR)
142 # define APPEND_FLAG(root, name) \
143 root=snocString((root), (name))
145 # define APPEND_FILESPEC(root, name) \
146 root = snocString ((root), (name))
148 # define SET_BINARY_MODE(fd) \
150 int retVal = setmode ( fileno ( fd ), \
152 ERROR_IF_MINUS_ONE ( retVal ); \
155 #endif /* BZ_LCCWIN32 */
158 /*---------------------------------------------*/
160 Some more stuff for all platforms :-)
164 typedef unsigned char Bool
;
165 typedef unsigned char UChar
;
167 typedef unsigned int UInt32
;
169 typedef unsigned short UInt16
;
171 #define True ((Bool)1)
172 #define False ((Bool)0)
175 IntNative is your platform's `native' int size.
176 Only here to avoid probs with 64-bit platforms.
178 typedef int IntNative
;
181 /*---------------------------------------------------*/
182 /*--- Misc (file handling) data decls ---*/
183 /*---------------------------------------------------*/
186 Bool keepInputFiles
, smallMode
, deleteOutputOnInterrupt
;
187 Bool forceOverwrite
, testFailsExist
, unzFailsExist
, noisy
;
188 Int32 numFileNames
, numFilesProcessed
, blockSize100k
;
191 /*-- source modes; F==file, I==stdin, O==stdout --*/
196 /*-- operation modes --*/
204 #define FILE_NAME_LEN 1034
206 Int32 longestFileName
;
207 Char inName
[FILE_NAME_LEN
];
208 Char outName
[FILE_NAME_LEN
];
209 Char tmpName
[FILE_NAME_LEN
];
211 Char progNameReally
[FILE_NAME_LEN
];
212 FILE *outputHandleJustInCase
;
215 static void panic ( const Char
* ) NORETURN
;
216 static void ioError ( void ) NORETURN
;
217 static void outOfMemory ( void ) NORETURN
;
218 static void configError ( void ) NORETURN
;
219 static void crcError ( void ) NORETURN
;
220 static void cleanUpAndFail ( Int32
) NORETURN
;
221 static void compressedStreamEOF ( void ) NORETURN
;
223 static void copyFileName ( Char
*, const Char
* );
224 static void* myMalloc ( Int32
);
225 static void applySavedFileAttrToOutputFile ( IntNative fd
);
228 static FILE* fopen_output_safely ( Char
*, const char* );
230 /*---------------------------------------------------*/
231 /*--- An implementation of 64-bit ints. Sigh. ---*/
232 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
233 /*---------------------------------------------------*/
236 struct { UChar b
[8]; }
241 void uInt64_from_UInt32s ( UInt64
* n
, UInt32 lo32
, UInt32 hi32
)
243 n
->b
[7] = (UChar
)((hi32
>> 24) & 0xFF);
244 n
->b
[6] = (UChar
)((hi32
>> 16) & 0xFF);
245 n
->b
[5] = (UChar
)((hi32
>> 8) & 0xFF);
246 n
->b
[4] = (UChar
) (hi32
& 0xFF);
247 n
->b
[3] = (UChar
)((lo32
>> 24) & 0xFF);
248 n
->b
[2] = (UChar
)((lo32
>> 16) & 0xFF);
249 n
->b
[1] = (UChar
)((lo32
>> 8) & 0xFF);
250 n
->b
[0] = (UChar
) (lo32
& 0xFF);
255 double uInt64_to_double ( UInt64
* n
)
260 for (i
= 0; i
< 8; i
++) {
261 sum
+= base
* (double)(n
->b
[i
]);
269 Bool
uInt64_isZero ( UInt64
* n
)
272 for (i
= 0; i
< 8; i
++)
273 if (n
->b
[i
] != 0) return 0;
278 /* Divide *n by 10, and return the remainder. */
280 Int32
uInt64_qrm10 ( UInt64
* n
)
285 for (i
= 7; i
>= 0; i
--) {
286 tmp
= rem
* 256 + n
->b
[i
];
294 /* ... and the Whole Entire Point of all this UInt64 stuff is
295 so that we can supply the following function.
298 void uInt64_toAscii ( char* outbuf
, UInt64
* n
)
305 q
= uInt64_qrm10 ( &n_copy
);
308 } while (!uInt64_isZero(&n_copy
));
310 for (i
= 0; i
< nBuf
; i
++)
311 outbuf
[i
] = buf
[nBuf
-i
-1];
315 /*---------------------------------------------------*/
316 /*--- Processing of complete files and streams ---*/
317 /*---------------------------------------------------*/
319 /*---------------------------------------------*/
321 Bool
myfeof ( FILE* f
)
323 Int32 c
= fgetc ( f
);
324 if (c
== EOF
) return True
;
330 /*---------------------------------------------*/
332 void compressStream ( FILE *stream
, FILE *zStream
)
337 UInt32 nbytes_in_lo32
, nbytes_in_hi32
;
338 UInt32 nbytes_out_lo32
, nbytes_out_hi32
;
339 Int32 bzerr
, bzerr_dummy
, ret
;
341 SET_BINARY_MODE(stream
);
342 SET_BINARY_MODE(zStream
);
344 if (ferror(stream
)) goto errhandler_io
;
345 if (ferror(zStream
)) goto errhandler_io
;
347 bzf
= BZ2_bzWriteOpen ( &bzerr
, zStream
,
348 blockSize100k
, verbosity
, workFactor
);
349 if (bzerr
!= BZ_OK
) goto errhandler
;
351 if (verbosity
>= 2) fprintf ( stderr
, "\n" );
355 if (myfeof(stream
)) break;
356 nIbuf
= fread ( ibuf
, sizeof(UChar
), 5000, stream
);
357 if (ferror(stream
)) goto errhandler_io
;
358 if (nIbuf
> 0) BZ2_bzWrite ( &bzerr
, bzf
, (void*)ibuf
, nIbuf
);
359 if (bzerr
!= BZ_OK
) goto errhandler
;
363 BZ2_bzWriteClose64 ( &bzerr
, bzf
, 0,
364 &nbytes_in_lo32
, &nbytes_in_hi32
,
365 &nbytes_out_lo32
, &nbytes_out_hi32
);
366 if (bzerr
!= BZ_OK
) goto errhandler
;
368 if (ferror(zStream
)) goto errhandler_io
;
369 ret
= fflush ( zStream
);
370 if (ret
== EOF
) goto errhandler_io
;
371 if (zStream
!= stdout
) {
372 Int32 fd
= fileno ( zStream
);
373 if (fd
< 0) goto errhandler_io
;
374 applySavedFileAttrToOutputFile ( fd
);
375 ret
= fclose ( zStream
);
376 outputHandleJustInCase
= NULL
;
377 if (ret
== EOF
) goto errhandler_io
;
379 outputHandleJustInCase
= NULL
;
380 if (ferror(stream
)) goto errhandler_io
;
381 ret
= fclose ( stream
);
382 if (ret
== EOF
) goto errhandler_io
;
384 if (verbosity
>= 1) {
385 if (nbytes_in_lo32
== 0 && nbytes_in_hi32
== 0) {
386 fprintf ( stderr
, " no data compressed.\n");
388 Char buf_nin
[32], buf_nout
[32];
389 UInt64 nbytes_in
, nbytes_out
;
390 double nbytes_in_d
, nbytes_out_d
;
391 uInt64_from_UInt32s ( &nbytes_in
,
392 nbytes_in_lo32
, nbytes_in_hi32
);
393 uInt64_from_UInt32s ( &nbytes_out
,
394 nbytes_out_lo32
, nbytes_out_hi32
);
395 nbytes_in_d
= uInt64_to_double ( &nbytes_in
);
396 nbytes_out_d
= uInt64_to_double ( &nbytes_out
);
397 uInt64_toAscii ( buf_nin
, &nbytes_in
);
398 uInt64_toAscii ( buf_nout
, &nbytes_out
);
399 fprintf ( stderr
, "%6.3f:1, %6.3f bits/byte, "
400 "%5.2f%% saved, %s in, %s out.\n",
401 nbytes_in_d
/ nbytes_out_d
,
402 (8.0 * nbytes_out_d
) / nbytes_in_d
,
403 100.0 * (1.0 - nbytes_out_d
/ nbytes_in_d
),
413 BZ2_bzWriteClose64 ( &bzerr_dummy
, bzf
, 1,
414 &nbytes_in_lo32
, &nbytes_in_hi32
,
415 &nbytes_out_lo32
, &nbytes_out_hi32
);
417 case BZ_CONFIG_ERROR
:
418 configError(); break;
420 outOfMemory (); break;
425 panic ( "compress:unexpected error" );
428 panic ( "compress:end" );
434 /*---------------------------------------------*/
436 Bool
uncompressStream ( FILE *zStream
, FILE *stream
)
439 Int32 bzerr
, bzerr_dummy
, ret
, nread
, streamNo
, i
;
441 UChar unused
[BZ_MAX_UNUSED
];
443 void* unusedTmpV
= NULL
;
449 SET_BINARY_MODE(stream
);
450 SET_BINARY_MODE(zStream
);
452 if (ferror(stream
)) goto errhandler_io
;
453 if (ferror(zStream
)) goto errhandler_io
;
457 bzf
= BZ2_bzReadOpen (
458 &bzerr
, zStream
, verbosity
,
459 (int)smallMode
, unused
, nUnused
461 if (bzf
== NULL
|| bzerr
!= BZ_OK
) goto errhandler
;
464 while (bzerr
== BZ_OK
) {
465 nread
= BZ2_bzRead ( &bzerr
, bzf
, obuf
, 5000 );
466 if (bzerr
== BZ_DATA_ERROR_MAGIC
) goto trycat
;
467 if ((bzerr
== BZ_OK
|| bzerr
== BZ_STREAM_END
) && nread
> 0)
468 fwrite ( obuf
, sizeof(UChar
), nread
, stream
);
469 if (ferror(stream
)) goto errhandler_io
;
471 if (bzerr
!= BZ_STREAM_END
) goto errhandler
;
473 BZ2_bzReadGetUnused ( &bzerr
, bzf
, (void*)(&unusedTmpV
), &nUnused
);
474 if (bzerr
!= BZ_OK
) panic ( "decompress:bzReadGetUnused" );
476 unusedTmp
= (UChar
*)unusedTmpV
;
477 for (i
= 0; i
< nUnused
; i
++) unused
[i
] = unusedTmp
[i
];
479 BZ2_bzReadClose ( &bzerr
, bzf
);
480 if (bzerr
!= BZ_OK
) panic ( "decompress:bzReadGetUnused" );
482 if (nUnused
== 0 && myfeof(zStream
)) break;
486 if (ferror(zStream
)) goto errhandler_io
;
487 if (stream
!= stdout
) {
488 Int32 fd
= fileno ( stream
);
489 if (fd
< 0) goto errhandler_io
;
490 applySavedFileAttrToOutputFile ( fd
);
492 ret
= fclose ( zStream
);
493 if (ret
== EOF
) goto errhandler_io
;
495 if (ferror(stream
)) goto errhandler_io
;
496 ret
= fflush ( stream
);
497 if (ret
!= 0) goto errhandler_io
;
498 if (stream
!= stdout
) {
499 ret
= fclose ( stream
);
500 outputHandleJustInCase
= NULL
;
501 if (ret
== EOF
) goto errhandler_io
;
503 outputHandleJustInCase
= NULL
;
504 if (verbosity
>= 2) fprintf ( stderr
, "\n " );
508 if (forceOverwrite
) {
511 if (myfeof(zStream
)) break;
512 nread
= fread ( obuf
, sizeof(UChar
), 5000, zStream
);
513 if (ferror(zStream
)) goto errhandler_io
;
514 if (nread
> 0) fwrite ( obuf
, sizeof(UChar
), nread
, stream
);
515 if (ferror(stream
)) goto errhandler_io
;
521 BZ2_bzReadClose ( &bzerr_dummy
, bzf
);
523 case BZ_CONFIG_ERROR
:
524 configError(); break;
532 case BZ_UNEXPECTED_EOF
:
533 compressedStreamEOF();
534 case BZ_DATA_ERROR_MAGIC
:
535 if (zStream
!= stdin
) fclose(zStream
);
536 if (stream
!= stdout
) fclose(stream
);
542 "\n%s: %s: trailing garbage after EOF ignored\n",
547 panic ( "decompress:unexpected error" );
550 panic ( "decompress:end" );
551 return True
; /*notreached*/
555 /*---------------------------------------------*/
557 Bool
testStream ( FILE *zStream
)
560 Int32 bzerr
, bzerr_dummy
, ret
, nread
, streamNo
, i
;
562 UChar unused
[BZ_MAX_UNUSED
];
564 void* unusedTmpV
= NULL
;
565 UChar
* unusedTmp
= NULL
;
570 SET_BINARY_MODE(zStream
);
571 if (ferror(zStream
)) goto errhandler_io
;
575 bzf
= BZ2_bzReadOpen (
576 &bzerr
, zStream
, verbosity
,
577 (int)smallMode
, unused
, nUnused
579 if (bzf
== NULL
|| bzerr
!= BZ_OK
) goto errhandler
;
582 while (bzerr
== BZ_OK
) {
583 nread
= BZ2_bzRead ( &bzerr
, bzf
, obuf
, 5000 );
584 if (bzerr
== BZ_DATA_ERROR_MAGIC
) goto errhandler
;
586 if (bzerr
!= BZ_STREAM_END
) goto errhandler
;
588 BZ2_bzReadGetUnused ( &bzerr
, bzf
, (void*)(&unusedTmpV
), &nUnused
);
589 if (bzerr
!= BZ_OK
) panic ( "test:bzReadGetUnused" );
591 unusedTmp
= (UChar
*)unusedTmpV
;
592 for (i
= 0; i
< nUnused
; i
++) unused
[i
] = unusedTmp
[i
];
594 BZ2_bzReadClose ( &bzerr
, bzf
);
595 if (bzerr
!= BZ_OK
) panic ( "test:bzReadGetUnused" );
596 if (nUnused
== 0 && myfeof(zStream
)) break;
600 if (ferror(zStream
)) goto errhandler_io
;
601 ret
= fclose ( zStream
);
602 if (ret
== EOF
) goto errhandler_io
;
604 if (verbosity
>= 2) fprintf ( stderr
, "\n " );
608 BZ2_bzReadClose ( &bzerr_dummy
, bzf
);
610 fprintf ( stderr
, "%s: %s: ", progName
, inName
);
612 case BZ_CONFIG_ERROR
:
613 configError(); break;
619 "data integrity (CRC) error in data\n" );
623 case BZ_UNEXPECTED_EOF
:
625 "file ends unexpectedly\n" );
627 case BZ_DATA_ERROR_MAGIC
:
628 if (zStream
!= stdin
) fclose(zStream
);
631 "bad magic number (file not created by bzip2)\n" );
636 "trailing garbage after EOF ignored\n" );
640 panic ( "test:unexpected error" );
643 panic ( "test:end" );
644 return True
; /*notreached*/
648 /*---------------------------------------------------*/
649 /*--- Error [non-] handling grunge ---*/
650 /*---------------------------------------------------*/
652 /*---------------------------------------------*/
654 void setExit ( Int32 v
)
656 if (v
> exitValue
) exitValue
= v
;
660 /*---------------------------------------------*/
662 void cadvise ( void )
667 "\nIt is possible that the compressed file(s) have become corrupted.\n"
668 "You can use the -tvv option to test integrity of such files.\n\n"
669 "You can use the `bzip2recover' program to attempt to recover\n"
670 "data from undamaged sections of corrupted files.\n\n"
675 /*---------------------------------------------*/
677 void showFileNames ( void )
682 "\tInput file = %s, output file = %s\n",
688 /*---------------------------------------------*/
690 void cleanUpAndFail ( Int32 ec
)
693 struct MY_STAT statBuf
;
695 if ( srcMode
== SM_F2F
697 && deleteOutputOnInterrupt
) {
699 /* Check whether input file still exists. Delete output file
700 only if input exists to avoid loss of data. Joerg Prante, 5
701 January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean
702 this is less likely to happen. But to be ultra-paranoid, we
703 do the check anyway.) */
704 retVal
= MY_STAT ( inName
, &statBuf
);
708 "%s: Deleting output file %s, if it exists.\n",
710 if (outputHandleJustInCase
!= NULL
)
711 fclose ( outputHandleJustInCase
);
712 retVal
= remove ( outName
);
715 "%s: WARNING: deletion of output file "
716 "(apparently) failed.\n",
720 "%s: WARNING: deletion of output file suppressed\n",
723 "%s: since input file no longer exists. Output file\n",
726 "%s: `%s' may be incomplete.\n",
729 "%s: I suggest doing an integrity test (bzip2 -tv)"
735 if (noisy
&& numFileNames
> 0 && numFilesProcessed
< numFileNames
) {
737 "%s: WARNING: some files have not been processed:\n"
738 "%s: %d specified on command line, %d not processed yet.\n\n",
740 numFileNames
, numFileNames
- numFilesProcessed
);
747 /*---------------------------------------------*/
749 void panic ( const Char
* s
)
752 "\n%s: PANIC -- internal consistency error:\n"
754 "\tThis is a BUG. Please report it to me at:\n"
755 "\tjseward@bzip.org\n",
762 /*---------------------------------------------*/
764 void crcError ( void )
767 "\n%s: Data integrity error when decompressing.\n",
775 /*---------------------------------------------*/
777 void compressedStreamEOF ( void )
781 "\n%s: Compressed file ends unexpectedly;\n\t"
782 "perhaps it is corrupted? *Possible* reason follows.\n",
792 /*---------------------------------------------*/
794 void ioError ( void )
797 "\n%s: I/O or other error, bailing out. "
798 "Possible reason follows.\n",
806 /*---------------------------------------------*/
808 void mySignalCatcher ( IntNative n
)
811 "\n%s: Control-C or similar caught, quitting.\n",
817 /*---------------------------------------------*/
820 void mySIGSEGVorSIGBUScatcher ( IntNative n
)
825 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
827 " Possible causes are (most likely first):\n"
828 " (1) This computer has unreliable memory or cache hardware\n"
829 " (a surprisingly common problem; try a different machine.)\n"
830 " (2) A bug in the compiler used to create this executable\n"
831 " (unlikely, if you didn't compile bzip2 yourself.)\n"
832 " (3) A real bug in bzip2 -- I hope this should never be the case.\n"
833 " The user's manual, Section 4.3, has more info on (1) and (2).\n"
835 " If you suspect this is a bug in bzip2, or are unsure about (1)\n"
836 " or (2), feel free to report it to me at: jseward@bzip.org.\n"
837 " Section 4.3 of the user's manual describes the info a useful\n"
838 " bug report should have. If the manual is available on your\n"
839 " system, please try and read it before mailing me. If you don't\n"
840 " have the manual or can't be bothered to read it, mail me anyway.\n"
846 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
848 " Possible causes are (most likely first):\n"
849 " (1) The compressed data is corrupted, and bzip2's usual checks\n"
850 " failed to detect this. Try bzip2 -tvv my_file.bz2.\n"
851 " (2) This computer has unreliable memory or cache hardware\n"
852 " (a surprisingly common problem; try a different machine.)\n"
853 " (3) A bug in the compiler used to create this executable\n"
854 " (unlikely, if you didn't compile bzip2 yourself.)\n"
855 " (4) A real bug in bzip2 -- I hope this should never be the case.\n"
856 " The user's manual, Section 4.3, has more info on (2) and (3).\n"
858 " If you suspect this is a bug in bzip2, or are unsure about (2)\n"
859 " or (3), feel free to report it to me at: jseward@bzip.org.\n"
860 " Section 4.3 of the user's manual describes the info a useful\n"
861 " bug report should have. If the manual is available on your\n"
862 " system, please try and read it before mailing me. If you don't\n"
863 " have the manual or can't be bothered to read it, mail me anyway.\n"
869 cleanUpAndFail( 3 ); else
870 { cadvise(); cleanUpAndFail( 2 ); }
875 /*---------------------------------------------*/
877 void outOfMemory ( void )
880 "\n%s: couldn't allocate enough memory\n",
887 /*---------------------------------------------*/
889 void configError ( void )
892 "bzip2: I'm not configured correctly for this platform!\n"
893 "\tI require Int32, Int16 and Char to have sizes\n"
894 "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
895 "\tProbably you can fix this by defining them correctly,\n"
896 "\tand recompiling. Bye!\n" );
902 /*---------------------------------------------------*/
903 /*--- The main driver machinery ---*/
904 /*---------------------------------------------------*/
906 /* All rather crufty. The main problem is that input files
907 are stat()d multiple times before use. This should be
911 /*---------------------------------------------*/
916 if ( (Int32
)strlen(s
) >= longestFileName
) return;
917 for (i
= 1; i
<= longestFileName
- (Int32
)strlen(s
); i
++)
918 fprintf ( stderr
, " " );
922 /*---------------------------------------------*/
924 void copyFileName ( Char
* to
, const Char
* from
)
926 if ( strlen(from
) > FILE_NAME_LEN
-10 ) {
929 "bzip2: file name\n`%s'\n"
930 "is suspiciously (more than %d chars) long.\n"
931 "Try using a reasonable file name instead. Sorry! :-)\n",
932 from
, FILE_NAME_LEN
-10
938 strncpy(to
,from
,FILE_NAME_LEN
-10);
939 to
[FILE_NAME_LEN
-10]='\0';
943 /*---------------------------------------------*/
945 Bool
fileExists ( Char
* name
)
947 FILE *tmp
= fopen ( name
, "rb" );
948 Bool exists
= (tmp
!= NULL
);
949 if (tmp
!= NULL
) fclose ( tmp
);
954 /*---------------------------------------------*/
955 /* Open an output file safely with O_EXCL and good permissions.
956 This avoids a race condition in versions < 1.0.2, in which
957 the file was first opened and then had its interim permissions
958 set safely. We instead use open() to create the file with
959 the interim permissions required. (--- --- rw-).
961 For non-Unix platforms, if we are not worrying about
962 security issues, simple this simply behaves like fopen.
965 FILE* fopen_output_safely ( Char
* name
, const char* mode
)
970 fh
= open(name
, O_WRONLY
|O_CREAT
|O_EXCL
, S_IWUSR
|S_IRUSR
);
971 if (fh
== -1) return NULL
;
972 fp
= fdopen(fh
, mode
);
973 if (fp
== NULL
) close(fh
);
976 return fopen(name
, mode
);
981 /*---------------------------------------------*/
983 if in doubt, return True
986 Bool
notAStandardFile ( Char
* name
)
989 struct MY_STAT statBuf
;
991 i
= MY_LSTAT ( name
, &statBuf
);
992 if (i
!= 0) return True
;
993 if (MY_S_ISREG(statBuf
.st_mode
)) return False
;
998 /*---------------------------------------------*/
1000 rac 11/21/98 see if file has hard links to it
1003 Int32
countHardLinks ( Char
* name
)
1006 struct MY_STAT statBuf
;
1008 i
= MY_LSTAT ( name
, &statBuf
);
1009 if (i
!= 0) return 0;
1010 return (statBuf
.st_nlink
- 1);
1014 /*---------------------------------------------*/
1015 /* Copy modification date, access date, permissions and owner from the
1016 source to destination file. We have to copy this meta-info off
1017 into fileMetaInfo before starting to compress / decompress it,
1018 because doing it afterwards means we get the wrong access time.
1020 To complicate matters, in compress() and decompress() below, the
1021 sequence of tests preceding the call to saveInputFileMetaInfo()
1022 involves calling fileExists(), which in turn establishes its result
1023 by attempting to fopen() the file, and if successful, immediately
1024 fclose()ing it again. So we have to assume that the fopen() call
1025 does not cause the access time field to be updated.
1027 Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
1028 to imply that merely doing open() will not affect the access time.
1029 Therefore we merely need to hope that the C library only does
1030 open() as a result of fopen(), and not any kind of read()-ahead
1033 It sounds pretty fragile to me. Whether this carries across
1034 robustly to arbitrary Unix-like platforms (or even works robustly
1035 on this one, RedHat 7.2) is unknown to me. Nevertheless ...
1039 struct MY_STAT fileMetaInfo
;
1043 void saveInputFileMetaInfo ( Char
*srcName
)
1047 /* Note use of stat here, not lstat. */
1048 retVal
= MY_STAT( srcName
, &fileMetaInfo
);
1049 ERROR_IF_NOT_ZERO ( retVal
);
1055 void applySavedTimeInfoToOutputFile ( Char
*dstName
)
1059 struct utimbuf uTimBuf
;
1061 uTimBuf
.actime
= fileMetaInfo
.st_atime
;
1062 uTimBuf
.modtime
= fileMetaInfo
.st_mtime
;
1064 retVal
= utime ( dstName
, &uTimBuf
);
1065 ERROR_IF_NOT_ZERO ( retVal
);
1070 void applySavedFileAttrToOutputFile ( IntNative fd
)
1075 retVal
= fchmod ( fd
, fileMetaInfo
.st_mode
);
1076 ERROR_IF_NOT_ZERO ( retVal
);
1078 (void) fchown ( fd
, fileMetaInfo
.st_uid
, fileMetaInfo
.st_gid
);
1079 /* chown() will in many cases return with EPERM, which can
1086 /*---------------------------------------------*/
1088 Bool
containsDubiousChars ( Char
* name
)
1091 /* On unix, files can contain any characters and the file expansion
1092 * is performed by the shell.
1095 # else /* ! BZ_UNIX */
1096 /* On non-unix (Win* platforms), wildcard characters are not allowed in
1099 for (; *name
!= '\0'; name
++)
1100 if (*name
== '?' || *name
== '*') return True
;
1102 # endif /* BZ_UNIX */
1106 /*---------------------------------------------*/
1107 #define BZ_N_SUFFIX_PAIRS 4
1109 const Char
* zSuffix
[BZ_N_SUFFIX_PAIRS
]
1110 = { ".bz2", ".bz", ".tbz2", ".tbz" };
1111 const Char
* unzSuffix
[BZ_N_SUFFIX_PAIRS
]
1112 = { "", "", ".tar", ".tar" };
1115 Bool
hasSuffix ( Char
* s
, const Char
* suffix
)
1117 Int32 ns
= strlen(s
);
1118 Int32 nx
= strlen(suffix
);
1119 if (ns
< nx
) return False
;
1120 if (strcmp(s
+ ns
- nx
, suffix
) == 0) return True
;
1125 Bool
mapSuffix ( Char
* name
,
1126 const Char
* oldSuffix
,
1127 const Char
* newSuffix
)
1129 if (!hasSuffix(name
,oldSuffix
)) return False
;
1130 name
[strlen(name
)-strlen(oldSuffix
)] = 0;
1131 strcat ( name
, newSuffix
);
1136 /*---------------------------------------------*/
1138 void compress ( Char
*name
)
1143 struct MY_STAT statBuf
;
1145 deleteOutputOnInterrupt
= False
;
1147 if (name
== NULL
&& srcMode
!= SM_I2O
)
1148 panic ( "compress: bad modes\n" );
1152 copyFileName ( inName
, "(stdin)" );
1153 copyFileName ( outName
, "(stdout)" );
1156 copyFileName ( inName
, name
);
1157 copyFileName ( outName
, name
);
1158 strcat ( outName
, ".bz2" );
1161 copyFileName ( inName
, name
);
1162 copyFileName ( outName
, "(stdout)" );
1166 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1168 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1173 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1174 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1175 progName
, inName
, strerror(errno
) );
1179 for (i
= 0; i
< BZ_N_SUFFIX_PAIRS
; i
++) {
1180 if (hasSuffix(inName
, zSuffix
[i
])) {
1183 "%s: Input file %s already has %s suffix.\n",
1184 progName
, inName
, zSuffix
[i
] );
1189 if ( srcMode
== SM_F2F
|| srcMode
== SM_F2O
) {
1190 MY_STAT(inName
, &statBuf
);
1191 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1193 "%s: Input file %s is a directory.\n",
1199 if ( srcMode
== SM_F2F
&& !forceOverwrite
&& notAStandardFile ( inName
)) {
1201 fprintf ( stderr
, "%s: Input file %s is not a normal file.\n",
1206 if ( srcMode
== SM_F2F
&& fileExists ( outName
) ) {
1207 if (forceOverwrite
) {
1210 fprintf ( stderr
, "%s: Output file %s already exists.\n",
1211 progName
, outName
);
1216 if ( srcMode
== SM_F2F
&& !forceOverwrite
&&
1217 (n
=countHardLinks ( inName
)) > 0) {
1218 fprintf ( stderr
, "%s: Input file %s has %d other link%s.\n",
1219 progName
, inName
, n
, n
> 1 ? "s" : "" );
1224 if ( srcMode
== SM_F2F
) {
1225 /* Save the file's meta-info before we open it. Doing it later
1226 means we mess up the access times. */
1227 saveInputFileMetaInfo ( inName
);
1230 switch ( srcMode
) {
1235 if ( isatty ( fileno ( stdout
) ) ) {
1237 "%s: I won't write compressed data to a terminal.\n",
1239 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1240 progName
, progName
);
1247 inStr
= fopen ( inName
, "rb" );
1249 if ( isatty ( fileno ( stdout
) ) ) {
1251 "%s: I won't write compressed data to a terminal.\n",
1253 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1254 progName
, progName
);
1255 if ( inStr
!= NULL
) fclose ( inStr
);
1259 if ( inStr
== NULL
) {
1260 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1261 progName
, inName
, strerror(errno
) );
1268 inStr
= fopen ( inName
, "rb" );
1269 outStr
= fopen_output_safely ( outName
, "wb" );
1270 if ( outStr
== NULL
) {
1271 fprintf ( stderr
, "%s: Can't create output file %s: %s.\n",
1272 progName
, outName
, strerror(errno
) );
1273 if ( inStr
!= NULL
) fclose ( inStr
);
1277 if ( inStr
== NULL
) {
1278 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1279 progName
, inName
, strerror(errno
) );
1280 if ( outStr
!= NULL
) fclose ( outStr
);
1287 panic ( "compress: bad srcMode" );
1291 if (verbosity
>= 1) {
1292 fprintf ( stderr
, " %s: ", inName
);
1297 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1298 outputHandleJustInCase
= outStr
;
1299 deleteOutputOnInterrupt
= True
;
1300 compressStream ( inStr
, outStr
);
1301 outputHandleJustInCase
= NULL
;
1303 /*--- If there was an I/O error, we won't get here. ---*/
1304 if ( srcMode
== SM_F2F
) {
1305 applySavedTimeInfoToOutputFile ( outName
);
1306 deleteOutputOnInterrupt
= False
;
1307 if ( !keepInputFiles
) {
1308 IntNative retVal
= remove ( inName
);
1309 ERROR_IF_NOT_ZERO ( retVal
);
1313 deleteOutputOnInterrupt
= False
;
1317 /*---------------------------------------------*/
1319 void uncompress ( Char
*name
)
1326 struct MY_STAT statBuf
;
1328 deleteOutputOnInterrupt
= False
;
1330 if (name
== NULL
&& srcMode
!= SM_I2O
)
1331 panic ( "uncompress: bad modes\n" );
1336 copyFileName ( inName
, "(stdin)" );
1337 copyFileName ( outName
, "(stdout)" );
1340 copyFileName ( inName
, name
);
1341 copyFileName ( outName
, name
);
1342 for (i
= 0; i
< BZ_N_SUFFIX_PAIRS
; i
++)
1343 if (mapSuffix(outName
,zSuffix
[i
],unzSuffix
[i
]))
1346 strcat ( outName
, ".out" );
1349 copyFileName ( inName
, name
);
1350 copyFileName ( outName
, "(stdout)" );
1355 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1357 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1362 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1363 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1364 progName
, inName
, strerror(errno
) );
1368 if ( srcMode
== SM_F2F
|| srcMode
== SM_F2O
) {
1369 MY_STAT(inName
, &statBuf
);
1370 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1372 "%s: Input file %s is a directory.\n",
1378 if ( srcMode
== SM_F2F
&& !forceOverwrite
&& notAStandardFile ( inName
)) {
1380 fprintf ( stderr
, "%s: Input file %s is not a normal file.\n",
1385 if ( /* srcMode == SM_F2F implied && */ cantGuess
) {
1388 "%s: Can't guess original name for %s -- using %s\n",
1389 progName
, inName
, outName
);
1390 /* just a warning, no return */
1392 if ( srcMode
== SM_F2F
&& fileExists ( outName
) ) {
1393 if (forceOverwrite
) {
1396 fprintf ( stderr
, "%s: Output file %s already exists.\n",
1397 progName
, outName
);
1402 if ( srcMode
== SM_F2F
&& !forceOverwrite
&&
1403 (n
=countHardLinks ( inName
) ) > 0) {
1404 fprintf ( stderr
, "%s: Input file %s has %d other link%s.\n",
1405 progName
, inName
, n
, n
> 1 ? "s" : "" );
1410 if ( srcMode
== SM_F2F
) {
1411 /* Save the file's meta-info before we open it. Doing it later
1412 means we mess up the access times. */
1413 saveInputFileMetaInfo ( inName
);
1416 switch ( srcMode
) {
1421 if ( isatty ( fileno ( stdin
) ) ) {
1423 "%s: I won't read compressed data from a terminal.\n",
1425 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1426 progName
, progName
);
1433 inStr
= fopen ( inName
, "rb" );
1435 if ( inStr
== NULL
) {
1436 fprintf ( stderr
, "%s: Can't open input file %s:%s.\n",
1437 progName
, inName
, strerror(errno
) );
1438 if ( inStr
!= NULL
) fclose ( inStr
);
1445 inStr
= fopen ( inName
, "rb" );
1446 outStr
= fopen_output_safely ( outName
, "wb" );
1447 if ( outStr
== NULL
) {
1448 fprintf ( stderr
, "%s: Can't create output file %s: %s.\n",
1449 progName
, outName
, strerror(errno
) );
1450 if ( inStr
!= NULL
) fclose ( inStr
);
1454 if ( inStr
== NULL
) {
1455 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1456 progName
, inName
, strerror(errno
) );
1457 if ( outStr
!= NULL
) fclose ( outStr
);
1464 panic ( "uncompress: bad srcMode" );
1468 if (verbosity
>= 1) {
1469 fprintf ( stderr
, " %s: ", inName
);
1474 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1475 outputHandleJustInCase
= outStr
;
1476 deleteOutputOnInterrupt
= True
;
1477 magicNumberOK
= uncompressStream ( inStr
, outStr
);
1478 outputHandleJustInCase
= NULL
;
1480 /*--- If there was an I/O error, we won't get here. ---*/
1481 if ( magicNumberOK
) {
1482 if ( srcMode
== SM_F2F
) {
1483 applySavedTimeInfoToOutputFile ( outName
);
1484 deleteOutputOnInterrupt
= False
;
1485 if ( !keepInputFiles
) {
1486 IntNative retVal
= remove ( inName
);
1487 ERROR_IF_NOT_ZERO ( retVal
);
1491 unzFailsExist
= True
;
1492 deleteOutputOnInterrupt
= False
;
1493 if ( srcMode
== SM_F2F
) {
1494 IntNative retVal
= remove ( outName
);
1495 ERROR_IF_NOT_ZERO ( retVal
);
1498 deleteOutputOnInterrupt
= False
;
1500 if ( magicNumberOK
) {
1502 fprintf ( stderr
, "done\n" );
1506 fprintf ( stderr
, "not a bzip2 file.\n" ); else
1508 "%s: %s is not a bzip2 file.\n",
1515 /*---------------------------------------------*/
1517 void testf ( Char
*name
)
1521 struct MY_STAT statBuf
;
1523 deleteOutputOnInterrupt
= False
;
1525 if (name
== NULL
&& srcMode
!= SM_I2O
)
1526 panic ( "testf: bad modes\n" );
1528 copyFileName ( outName
, "(none)" );
1530 case SM_I2O
: copyFileName ( inName
, "(stdin)" ); break;
1531 case SM_F2F
: copyFileName ( inName
, name
); break;
1532 case SM_F2O
: copyFileName ( inName
, name
); break;
1535 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1537 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1542 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1543 fprintf ( stderr
, "%s: Can't open input %s: %s.\n",
1544 progName
, inName
, strerror(errno
) );
1548 if ( srcMode
!= SM_I2O
) {
1549 MY_STAT(inName
, &statBuf
);
1550 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1552 "%s: Input file %s is a directory.\n",
1559 switch ( srcMode
) {
1562 if ( isatty ( fileno ( stdin
) ) ) {
1564 "%s: I won't read compressed data from a terminal.\n",
1566 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1567 progName
, progName
);
1574 case SM_F2O
: case SM_F2F
:
1575 inStr
= fopen ( inName
, "rb" );
1576 if ( inStr
== NULL
) {
1577 fprintf ( stderr
, "%s: Can't open input file %s:%s.\n",
1578 progName
, inName
, strerror(errno
) );
1585 panic ( "testf: bad srcMode" );
1589 if (verbosity
>= 1) {
1590 fprintf ( stderr
, " %s: ", inName
);
1595 /*--- Now the input handle is sane. Do the Biz. ---*/
1596 outputHandleJustInCase
= NULL
;
1597 allOK
= testStream ( inStr
);
1599 if (allOK
&& verbosity
>= 1) fprintf ( stderr
, "ok\n" );
1600 if (!allOK
) testFailsExist
= True
;
1604 /*---------------------------------------------*/
1606 void license ( void )
1610 "bzip2, a block-sorting file compressor. "
1613 " Copyright (C) 1996-2007 by Julian Seward.\n"
1615 " This program is free software; you can redistribute it and/or modify\n"
1616 " it under the terms set out in the LICENSE file, which is included\n"
1617 " in the bzip2-1.0.5 source distribution.\n"
1619 " This program is distributed in the hope that it will be useful,\n"
1620 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1621 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1622 " LICENSE file for more details.\n"
1629 /*---------------------------------------------*/
1631 void usage ( Char
*fullProgName
)
1635 "bzip2, a block-sorting file compressor. "
1637 "\n usage: %s [flags and input files in any order]\n"
1639 " -h --help print this message\n"
1640 " -d --decompress force decompression\n"
1641 " -z --compress force compression\n"
1642 " -k --keep keep (don't delete) input files\n"
1643 " -f --force overwrite existing output files\n"
1644 " -t --test test compressed file integrity\n"
1645 " -c --stdout output to standard out\n"
1646 " -q --quiet suppress noncritical error messages\n"
1647 " -v --verbose be verbose (a 2nd -v gives more)\n"
1648 " -L --license display software version & license\n"
1649 " -V --version display software version & license\n"
1650 " -s --small use less memory (at most 2500k)\n"
1651 " -1 .. -9 set block size to 100k .. 900k\n"
1652 " --fast alias for -1\n"
1653 " --best alias for -9\n"
1655 " If invoked as `bzip2', default action is to compress.\n"
1656 " as `bunzip2', default action is to decompress.\n"
1657 " as `bzcat', default action is to decompress to stdout.\n"
1659 " If no file names are given, bzip2 compresses or decompresses\n"
1660 " from standard input to standard output. You can combine\n"
1661 " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
1673 /*---------------------------------------------*/
1675 void redundant ( Char
* flag
)
1679 "%s: %s is redundant in versions 0.9.5 and above\n",
1684 /*---------------------------------------------*/
1686 All the garbage from here to main() is purely to
1687 implement a linked list of command-line arguments,
1688 into which main() copies argv[1 .. argc-1].
1690 The purpose of this exercise is to facilitate
1691 the expansion of wildcard characters * and ? in
1692 filenames for OSs which don't know how to do it
1693 themselves, like MSDOS, Windows 95 and NT.
1695 The actual Dirty Work is done by the platform-
1696 specific macro APPEND_FILESPEC.
1707 /*---------------------------------------------*/
1709 void *myMalloc ( Int32 n
)
1713 p
= malloc ( (size_t)n
);
1714 if (p
== NULL
) outOfMemory ();
1719 /*---------------------------------------------*/
1721 Cell
*mkCell ( void )
1725 c
= (Cell
*) myMalloc ( sizeof ( Cell
) );
1732 /*---------------------------------------------*/
1734 Cell
*snocString ( Cell
*root
, Char
*name
)
1737 Cell
*tmp
= mkCell();
1738 tmp
->name
= (Char
*) myMalloc ( 5 + strlen(name
) );
1739 strcpy ( tmp
->name
, name
);
1743 while (tmp
->link
!= NULL
) tmp
= tmp
->link
;
1744 tmp
->link
= snocString ( tmp
->link
, name
);
1750 /*---------------------------------------------*/
1752 void addFlagsFromEnvVar ( Cell
** argList
, const Char
* varName
)
1757 envbase
= getenv(varName
);
1758 if (envbase
!= NULL
) {
1762 if (p
[i
] == 0) break;
1765 while (isspace((Int32
)(p
[0]))) p
++;
1766 while (p
[i
] != 0 && !isspace((Int32
)(p
[i
]))) i
++;
1768 k
= i
; if (k
> FILE_NAME_LEN
-10) k
= FILE_NAME_LEN
-10;
1769 for (j
= 0; j
< k
; j
++) tmpName
[j
] = p
[j
];
1771 APPEND_FLAG(*argList
, tmpName
);
1778 /*---------------------------------------------*/
1779 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
1781 IntNative
main ( IntNative argc
, Char
*argv
[] )
1789 /*-- Be really really really paranoid :-) --*/
1790 if (sizeof(Int32
) != 4 || sizeof(UInt32
) != 4 ||
1791 sizeof(Int16
) != 2 || sizeof(UInt16
) != 2 ||
1792 sizeof(Char
) != 1 || sizeof(UChar
) != 1)
1795 /*-- Initialise --*/
1796 outputHandleJustInCase
= NULL
;
1798 keepInputFiles
= False
;
1799 forceOverwrite
= False
;
1803 testFailsExist
= False
;
1804 unzFailsExist
= False
;
1806 numFilesProcessed
= 0;
1808 deleteOutputOnInterrupt
= False
;
1810 i
= j
= 0; /* avoid bogus warning from egcs-1.1.X */
1813 /*-- Set up signal handlers for mem access errors --*/
1814 signal (SIGSEGV
, mySIGSEGVorSIGBUScatcher
);
1817 signal (SIGBUS
, mySIGSEGVorSIGBUScatcher
);
1822 copyFileName ( inName
, "(none)" );
1823 copyFileName ( outName
, "(none)" );
1825 copyFileName ( progNameReally
, argv
[0] );
1826 progName
= &progNameReally
[0];
1827 for (tmp
= &progNameReally
[0]; *tmp
!= '\0'; tmp
++)
1828 if (*tmp
== PATH_SEP
) progName
= tmp
+ 1;
1831 /*-- Copy flags from env var BZIP2, and
1832 expand filename wildcards in arg list.
1835 addFlagsFromEnvVar ( &argList
, "BZIP2" );
1836 addFlagsFromEnvVar ( &argList
, "BZIP" );
1837 for (i
= 1; i
<= argc
-1; i
++)
1838 APPEND_FILESPEC(argList
, argv
[i
]);
1841 /*-- Find the length of the longest filename --*/
1842 longestFileName
= 7;
1845 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1846 if (ISFLAG("--")) { decode
= False
; continue; }
1847 if (aa
->name
[0] == '-' && decode
) continue;
1849 if (longestFileName
< (Int32
)strlen(aa
->name
) )
1850 longestFileName
= (Int32
)strlen(aa
->name
);
1854 /*-- Determine source modes; flag handling may change this too. --*/
1855 if (numFileNames
== 0)
1856 srcMode
= SM_I2O
; else srcMode
= SM_F2F
;
1859 /*-- Determine what to do (compress/uncompress/test/cat). --*/
1860 /*-- Note that subsequent flag handling may change this. --*/
1863 if ( (strstr ( progName
, "unzip" ) != 0) ||
1864 (strstr ( progName
, "UNZIP" ) != 0) )
1867 if ( (strstr ( progName
, "z2cat" ) != 0) ||
1868 (strstr ( progName
, "Z2CAT" ) != 0) ||
1869 (strstr ( progName
, "zcat" ) != 0) ||
1870 (strstr ( progName
, "ZCAT" ) != 0) ) {
1872 srcMode
= (numFileNames
== 0) ? SM_I2O
: SM_F2O
;
1876 /*-- Look at the flags. --*/
1877 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1878 if (ISFLAG("--")) break;
1879 if (aa
->name
[0] == '-' && aa
->name
[1] != '-') {
1880 for (j
= 1; aa
->name
[j
] != '\0'; j
++) {
1881 switch (aa
->name
[j
]) {
1882 case 'c': srcMode
= SM_F2O
; break;
1883 case 'd': opMode
= OM_UNZ
; break;
1884 case 'z': opMode
= OM_Z
; break;
1885 case 'f': forceOverwrite
= True
; break;
1886 case 't': opMode
= OM_TEST
; break;
1887 case 'k': keepInputFiles
= True
; break;
1888 case 's': smallMode
= True
; break;
1889 case 'q': noisy
= False
; break;
1890 case '1': blockSize100k
= 1; break;
1891 case '2': blockSize100k
= 2; break;
1892 case '3': blockSize100k
= 3; break;
1893 case '4': blockSize100k
= 4; break;
1894 case '5': blockSize100k
= 5; break;
1895 case '6': blockSize100k
= 6; break;
1896 case '7': blockSize100k
= 7; break;
1897 case '8': blockSize100k
= 8; break;
1898 case '9': blockSize100k
= 9; break;
1900 case 'L': license(); break;
1901 case 'v': verbosity
++; break;
1902 case 'h': usage ( progName
);
1905 default: fprintf ( stderr
, "%s: Bad flag `%s'\n",
1906 progName
, aa
->name
);
1915 /*-- And again ... --*/
1916 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1917 if (ISFLAG("--")) break;
1918 if (ISFLAG("--stdout")) srcMode
= SM_F2O
; else
1919 if (ISFLAG("--decompress")) opMode
= OM_UNZ
; else
1920 if (ISFLAG("--compress")) opMode
= OM_Z
; else
1921 if (ISFLAG("--force")) forceOverwrite
= True
; else
1922 if (ISFLAG("--test")) opMode
= OM_TEST
; else
1923 if (ISFLAG("--keep")) keepInputFiles
= True
; else
1924 if (ISFLAG("--small")) smallMode
= True
; else
1925 if (ISFLAG("--quiet")) noisy
= False
; else
1926 if (ISFLAG("--version")) license(); else
1927 if (ISFLAG("--license")) license(); else
1928 if (ISFLAG("--exponential")) workFactor
= 1; else
1929 if (ISFLAG("--repetitive-best")) redundant(aa
->name
); else
1930 if (ISFLAG("--repetitive-fast")) redundant(aa
->name
); else
1931 if (ISFLAG("--fast")) blockSize100k
= 1; else
1932 if (ISFLAG("--best")) blockSize100k
= 9; else
1933 if (ISFLAG("--verbose")) verbosity
++; else
1934 if (ISFLAG("--help")) { usage ( progName
); exit ( 0 ); }
1936 if (strncmp ( aa
->name
, "--", 2) == 0) {
1937 fprintf ( stderr
, "%s: Bad flag `%s'\n", progName
, aa
->name
);
1943 if (verbosity
> 4) verbosity
= 4;
1944 if (opMode
== OM_Z
&& smallMode
&& blockSize100k
> 2)
1947 if (opMode
== OM_TEST
&& srcMode
== SM_F2O
) {
1948 fprintf ( stderr
, "%s: -c and -t cannot be used together.\n",
1953 if (srcMode
== SM_F2O
&& numFileNames
== 0)
1956 if (opMode
!= OM_Z
) blockSize100k
= 0;
1958 if (srcMode
== SM_F2F
) {
1959 signal (SIGINT
, mySignalCatcher
);
1960 signal (SIGTERM
, mySignalCatcher
);
1962 signal (SIGHUP
, mySignalCatcher
);
1966 if (opMode
== OM_Z
) {
1967 if (srcMode
== SM_I2O
) {
1971 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1972 if (ISFLAG("--")) { decode
= False
; continue; }
1973 if (aa
->name
[0] == '-' && decode
) continue;
1974 numFilesProcessed
++;
1975 compress ( aa
->name
);
1981 if (opMode
== OM_UNZ
) {
1982 unzFailsExist
= False
;
1983 if (srcMode
== SM_I2O
) {
1984 uncompress ( NULL
);
1987 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1988 if (ISFLAG("--")) { decode
= False
; continue; }
1989 if (aa
->name
[0] == '-' && decode
) continue;
1990 numFilesProcessed
++;
1991 uncompress ( aa
->name
);
1994 if (unzFailsExist
) {
2001 testFailsExist
= False
;
2002 if (srcMode
== SM_I2O
) {
2006 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
2007 if (ISFLAG("--")) { decode
= False
; continue; }
2008 if (aa
->name
[0] == '-' && decode
) continue;
2009 numFilesProcessed
++;
2013 if (testFailsExist
&& noisy
) {
2016 "You can use the `bzip2recover' program to attempt to recover\n"
2017 "data from undamaged sections of corrupted files.\n\n"
2024 /* Free the argument list memory to mollify leak detectors
2025 (eg) Purify, Checker. Serves no other useful purpose.
2028 while (aa
!= NULL
) {
2029 Cell
* aa2
= aa
->link
;
2030 if (aa
->name
!= NULL
) free(aa
->name
);
2039 /*-----------------------------------------------------------*/
2040 /*--- end bzip2.c ---*/
2041 /*-----------------------------------------------------------*/