2 /*-----------------------------------------------------------*/
3 /*--- A block-sorting, lossless compressor bzip2.c ---*/
4 /*-----------------------------------------------------------*/
6 /* ------------------------------------------------------------------
7 This file is part of bzip2/libbzip2, a program and library for
8 lossless, block-sorting data compression.
10 bzip2/libbzip2 version 1.0.5 of 10 December 2007
11 Copyright (C) 1996-2007 Julian Seward <jseward@bzip.org>
13 Please read the WARNING, DISCLAIMER and PATENTS sections in the
16 This program is released under the terms of the license contained
18 ------------------------------------------------------------------ */
21 /* Place a 1 beside your platform, and 0 elsewhere.
23 Also works on 64-bit Unix boxes.
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.
37 #if defined(_WIN32) && !defined(__CYGWIN__)
45 /*---------------------------------------------*/
47 Some stuff for all platforms.
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(); }
64 /*---------------------------------------------*/
66 Platform-specific stuff.
71 # include <sys/types.h>
74 # include <sys/stat.h>
75 # include <sys/times.h>
78 # define MY_LSTAT lstat
80 # define MY_S_ISREG S_ISREG
81 # define MY_S_ISDIR S_ISDIR
83 # define APPEND_FILESPEC(root, name) \
84 root=snocString((root), (name))
86 # define APPEND_FLAG(root, name) \
87 root=snocString((root), (name))
89 # define SET_BINARY_MODE(fd) /**/
92 # define NORETURN __attribute__ ((noreturn))
94 # define NORETURN /**/
102 # define MY_LSTAT stat
103 # define MY_STAT stat
104 # undef SET_BINARY_MODE
105 # define SET_BINARY_MODE(fd) \
107 int retVal = setmode ( fileno ( fd ), \
109 ERROR_IF_MINUS_ONE ( retVal ); \
116 # undef SET_BINARY_MODE
117 # define SET_BINARY_MODE(fd) \
119 int retVal = setmode ( fileno ( fd ), \
121 ERROR_IF_MINUS_ONE ( retVal ); \
131 # include <sys\stat.h>
133 # define NORETURN /**/
134 # define PATH_SEP '\\'
135 # define MY_LSTAT _stat
136 # define MY_STAT _stat
137 # define MY_S_ISREG(x) ((x) & _S_IFREG)
138 # define MY_S_ISDIR(x) ((x) & _S_IFDIR)
140 # define APPEND_FLAG(root, name) \
141 root=snocString((root), (name))
143 # define APPEND_FILESPEC(root, name) \
144 root = snocString ((root), (name))
146 # define SET_BINARY_MODE(fd) \
148 int retVal = setmode ( fileno ( fd ), \
150 ERROR_IF_MINUS_ONE ( retVal ); \
153 #endif /* BZ_LCCWIN32 */
156 /*---------------------------------------------*/
158 Some more stuff for all platforms :-)
162 typedef unsigned char Bool
;
163 typedef unsigned char UChar
;
165 typedef unsigned int UInt32
;
167 typedef unsigned short UInt16
;
169 #define True ((Bool)1)
170 #define False ((Bool)0)
173 IntNative is your platform's `native' int size.
174 Only here to avoid probs with 64-bit platforms.
176 typedef int IntNative
;
179 /*---------------------------------------------------*/
180 /*--- Misc (file handling) data decls ---*/
181 /*---------------------------------------------------*/
184 Bool keepInputFiles
, smallMode
, deleteOutputOnInterrupt
;
185 Bool forceOverwrite
, testFailsExist
, unzFailsExist
, noisy
;
186 Int32 numFileNames
, numFilesProcessed
, blockSize100k
;
189 /*-- source modes; F==file, I==stdin, O==stdout --*/
194 /*-- operation modes --*/
202 #define FILE_NAME_LEN 1034
204 Int32 longestFileName
;
205 Char inName
[FILE_NAME_LEN
];
206 Char outName
[FILE_NAME_LEN
];
207 Char tmpName
[FILE_NAME_LEN
];
209 Char progNameReally
[FILE_NAME_LEN
];
210 FILE *outputHandleJustInCase
;
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
;
221 static void copyFileName ( Char
*, Char
* );
222 static void* myMalloc ( Int32
);
223 static void applySavedFileAttrToOutputFile ( IntNative fd
);
227 /*---------------------------------------------------*/
228 /*--- An implementation of 64-bit ints. Sigh. ---*/
229 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
230 /*---------------------------------------------------*/
233 struct { UChar b
[8]; }
238 void uInt64_from_UInt32s ( UInt64
* n
, UInt32 lo32
, UInt32 hi32
)
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);
252 double uInt64_to_double ( UInt64
* n
)
257 for (i
= 0; i
< 8; i
++) {
258 sum
+= base
* (double)(n
->b
[i
]);
266 Bool
uInt64_isZero ( UInt64
* n
)
269 for (i
= 0; i
< 8; i
++)
270 if (n
->b
[i
] != 0) return 0;
275 /* Divide *n by 10, and return the remainder. */
277 Int32
uInt64_qrm10 ( UInt64
* n
)
282 for (i
= 7; i
>= 0; i
--) {
283 tmp
= rem
* 256 + n
->b
[i
];
291 /* ... and the Whole Entire Point of all this UInt64 stuff is
292 so that we can supply the following function.
295 void uInt64_toAscii ( char* outbuf
, UInt64
* n
)
302 q
= uInt64_qrm10 ( &n_copy
);
305 } while (!uInt64_isZero(&n_copy
));
307 for (i
= 0; i
< nBuf
; i
++)
308 outbuf
[i
] = buf
[nBuf
-i
-1];
312 /*---------------------------------------------------*/
313 /*--- Processing of complete files and streams ---*/
314 /*---------------------------------------------------*/
316 /*---------------------------------------------*/
318 Bool
myfeof ( FILE* f
)
320 Int32 c
= fgetc ( f
);
321 if (c
== EOF
) return True
;
327 /*---------------------------------------------*/
329 void compressStream ( FILE *stream
, FILE *zStream
)
334 UInt32 nbytes_in_lo32
, nbytes_in_hi32
;
335 UInt32 nbytes_out_lo32
, nbytes_out_hi32
;
336 Int32 bzerr
, bzerr_dummy
, ret
;
338 SET_BINARY_MODE(stream
);
339 SET_BINARY_MODE(zStream
);
341 if (ferror(stream
)) goto errhandler_io
;
342 if (ferror(zStream
)) goto errhandler_io
;
344 bzf
= BZ2_bzWriteOpen ( &bzerr
, zStream
,
345 blockSize100k
, verbosity
, workFactor
);
346 if (bzerr
!= BZ_OK
) goto errhandler
;
348 if (verbosity
>= 2) fprintf ( stderr
, "\n" );
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
;
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
;
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
;
376 outputHandleJustInCase
= NULL
;
377 if (ferror(stream
)) goto errhandler_io
;
378 ret
= fclose ( stream
);
379 if (ret
== EOF
) goto errhandler_io
;
381 if (verbosity
>= 1) {
382 if (nbytes_in_lo32
== 0 && nbytes_in_hi32
== 0) {
383 fprintf ( stderr
, " no data compressed.\n");
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
),
410 BZ2_bzWriteClose64 ( &bzerr_dummy
, bzf
, 1,
411 &nbytes_in_lo32
, &nbytes_in_hi32
,
412 &nbytes_out_lo32
, &nbytes_out_hi32
);
414 case BZ_CONFIG_ERROR
:
415 configError(); break;
417 outOfMemory (); break;
422 panic ( "compress:unexpected error" );
425 panic ( "compress:end" );
431 /*---------------------------------------------*/
433 Bool
uncompressStream ( FILE *zStream
, FILE *stream
)
436 Int32 bzerr
, bzerr_dummy
, ret
, nread
, streamNo
, i
;
438 UChar unused
[BZ_MAX_UNUSED
];
446 SET_BINARY_MODE(stream
);
447 SET_BINARY_MODE(zStream
);
449 if (ferror(stream
)) goto errhandler_io
;
450 if (ferror(zStream
)) goto errhandler_io
;
454 bzf
= BZ2_bzReadOpen (
455 &bzerr
, zStream
, verbosity
,
456 (int)smallMode
, unused
, nUnused
458 if (bzf
== NULL
|| bzerr
!= BZ_OK
) goto errhandler
;
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
;
468 if (bzerr
!= BZ_STREAM_END
) goto errhandler
;
470 BZ2_bzReadGetUnused ( &bzerr
, bzf
, &unusedTmpV
, &nUnused
);
471 if (bzerr
!= BZ_OK
) panic ( "decompress:bzReadGetUnused" );
473 unusedTmp
= (UChar
*)unusedTmpV
;
474 for (i
= 0; i
< nUnused
; i
++) unused
[i
] = unusedTmp
[i
];
476 BZ2_bzReadClose ( &bzerr
, bzf
);
477 if (bzerr
!= BZ_OK
) panic ( "decompress:bzReadGetUnused" );
479 if (nUnused
== 0 && myfeof(zStream
)) break;
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
);
489 ret
= fclose ( zStream
);
490 if (ret
== EOF
) goto errhandler_io
;
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
;
500 outputHandleJustInCase
= NULL
;
501 if (verbosity
>= 2) fprintf ( stderr
, "\n " );
505 if (forceOverwrite
) {
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
;
518 BZ2_bzReadClose ( &bzerr_dummy
, bzf
);
520 case BZ_CONFIG_ERROR
:
521 configError(); break;
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
);
539 "\n%s: %s: trailing garbage after EOF ignored\n",
544 panic ( "decompress:unexpected error" );
547 panic ( "decompress:end" );
548 return True
; /*notreached*/
552 /*---------------------------------------------*/
554 Bool
testStream ( FILE *zStream
)
557 Int32 bzerr
, bzerr_dummy
, ret
, nread
, streamNo
, i
;
559 UChar unused
[BZ_MAX_UNUSED
];
567 SET_BINARY_MODE(zStream
);
568 if (ferror(zStream
)) goto errhandler_io
;
572 bzf
= BZ2_bzReadOpen (
573 &bzerr
, zStream
, verbosity
,
574 (int)smallMode
, unused
, nUnused
576 if (bzf
== NULL
|| bzerr
!= BZ_OK
) goto errhandler
;
579 while (bzerr
== BZ_OK
) {
580 nread
= BZ2_bzRead ( &bzerr
, bzf
, obuf
, 5000 );
581 if (bzerr
== BZ_DATA_ERROR_MAGIC
) goto errhandler
;
583 if (bzerr
!= BZ_STREAM_END
) goto errhandler
;
585 BZ2_bzReadGetUnused ( &bzerr
, bzf
, &unusedTmpV
, &nUnused
);
586 if (bzerr
!= BZ_OK
) panic ( "test:bzReadGetUnused" );
588 unusedTmp
= (UChar
*)unusedTmpV
;
589 for (i
= 0; i
< nUnused
; i
++) unused
[i
] = unusedTmp
[i
];
591 BZ2_bzReadClose ( &bzerr
, bzf
);
592 if (bzerr
!= BZ_OK
) panic ( "test:bzReadGetUnused" );
593 if (nUnused
== 0 && myfeof(zStream
)) break;
597 if (ferror(zStream
)) goto errhandler_io
;
598 ret
= fclose ( zStream
);
599 if (ret
== EOF
) goto errhandler_io
;
601 if (verbosity
>= 2) fprintf ( stderr
, "\n " );
605 BZ2_bzReadClose ( &bzerr_dummy
, bzf
);
607 fprintf ( stderr
, "%s: %s: ", progName
, inName
);
609 case BZ_CONFIG_ERROR
:
610 configError(); break;
616 "data integrity (CRC) error in data\n" );
620 case BZ_UNEXPECTED_EOF
:
622 "file ends unexpectedly\n" );
624 case BZ_DATA_ERROR_MAGIC
:
625 if (zStream
!= stdin
) fclose(zStream
);
628 "bad magic number (file not created by bzip2)\n" );
633 "trailing garbage after EOF ignored\n" );
637 panic ( "test:unexpected error" );
640 panic ( "test:end" );
641 return True
; /*notreached*/
645 /*---------------------------------------------------*/
646 /*--- Error [non-] handling grunge ---*/
647 /*---------------------------------------------------*/
649 /*---------------------------------------------*/
651 void setExit ( Int32 v
)
653 if (v
> exitValue
) exitValue
= v
;
657 /*---------------------------------------------*/
659 void cadvise ( void )
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"
672 /*---------------------------------------------*/
674 void showFileNames ( void )
679 "\tInput file = %s, output file = %s\n",
685 /*---------------------------------------------*/
687 void cleanUpAndFail ( Int32 ec
)
690 struct MY_STAT statBuf
;
692 if ( srcMode
== SM_F2F
694 && deleteOutputOnInterrupt
) {
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
);
705 "%s: Deleting output file %s, if it exists.\n",
707 if (outputHandleJustInCase
!= NULL
)
708 fclose ( outputHandleJustInCase
);
709 retVal
= remove ( outName
);
712 "%s: WARNING: deletion of output file "
713 "(apparently) failed.\n",
717 "%s: WARNING: deletion of output file suppressed\n",
720 "%s: since input file no longer exists. Output file\n",
723 "%s: `%s' may be incomplete.\n",
726 "%s: I suggest doing an integrity test (bzip2 -tv)"
732 if (noisy
&& numFileNames
> 0 && numFilesProcessed
< numFileNames
) {
734 "%s: WARNING: some files have not been processed:\n"
735 "%s: %d specified on command line, %d not processed yet.\n\n",
737 numFileNames
, numFileNames
- numFilesProcessed
);
744 /*---------------------------------------------*/
746 void panic ( const Char
* s
)
749 "\n%s: PANIC -- internal consistency error:\n"
751 "\tThis is a BUG. Please report it to me at:\n"
752 "\tjseward@bzip.org\n",
759 /*---------------------------------------------*/
761 void crcError ( void )
764 "\n%s: Data integrity error when decompressing.\n",
772 /*---------------------------------------------*/
774 void compressedStreamEOF ( void )
778 "\n%s: Compressed file ends unexpectedly;\n\t"
779 "perhaps it is corrupted? *Possible* reason follows.\n",
789 /*---------------------------------------------*/
791 void ioError ( void )
794 "\n%s: I/O or other error, bailing out. "
795 "Possible reason follows.\n",
803 /*---------------------------------------------*/
805 void mySignalCatcher ( IntNative n
)
808 "\n%s: Control-C or similar caught, quitting.\n",
814 /*---------------------------------------------*/
816 void mySIGSEGVorSIGBUScatcher ( IntNative n
)
821 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\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"
831 " If you suspect this is a bug in bzip2, or are unsure about (1)\n"
832 " or (2), feel free to report it to me at: jseward@bzip.org.\n"
833 " Section 4.3 of the user's manual describes the info a useful\n"
834 " bug report should have. If the manual is available on your\n"
835 " system, please try and read it before mailing me. If you don't\n"
836 " have the manual or can't be bothered to read it, mail me anyway.\n"
842 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\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"
854 " If you suspect this is a bug in bzip2, or are unsure about (2)\n"
855 " or (3), feel free to report it to me at: jseward@bzip.org.\n"
856 " Section 4.3 of the user's manual describes the info a useful\n"
857 " bug report should have. If the manual is available on your\n"
858 " system, please try and read it before mailing me. If you don't\n"
859 " have the manual or can't be bothered to read it, mail me anyway.\n"
865 cleanUpAndFail( 3 ); else
866 { cadvise(); cleanUpAndFail( 2 ); }
870 /*---------------------------------------------*/
872 void outOfMemory ( void )
875 "\n%s: couldn't allocate enough memory\n",
882 /*---------------------------------------------*/
884 void configError ( void )
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" );
897 /*---------------------------------------------------*/
898 /*--- The main driver machinery ---*/
899 /*---------------------------------------------------*/
901 /* All rather crufty. The main problem is that input files
902 are stat()d multiple times before use. This should be
906 /*---------------------------------------------*/
911 if ( (Int32
)strlen(s
) >= longestFileName
) return;
912 for (i
= 1; i
<= longestFileName
- (Int32
)strlen(s
); i
++)
913 fprintf ( stderr
, " " );
917 /*---------------------------------------------*/
919 void copyFileName ( Char
* to
, Char
* from
)
921 if ( strlen(from
) > FILE_NAME_LEN
-10 ) {
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
933 strncpy(to
,from
,FILE_NAME_LEN
-10);
934 to
[FILE_NAME_LEN
-10]='\0';
938 /*---------------------------------------------*/
940 Bool
fileExists ( Char
* name
)
942 FILE *tmp
= fopen ( name
, "rb" );
943 Bool exists
= (tmp
!= NULL
);
944 if (tmp
!= NULL
) fclose ( tmp
);
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-).
956 For non-Unix platforms, if we are not worrying about
957 security issues, simple this simply behaves like fopen.
960 FILE* fopen_output_safely ( Char
* name
, const char* mode
)
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
);
971 return fopen(name
, mode
);
976 /*---------------------------------------------*/
978 if in doubt, return True
981 Bool
notAStandardFile ( Char
* name
)
984 struct MY_STAT statBuf
;
986 i
= MY_LSTAT ( name
, &statBuf
);
987 if (i
!= 0) return True
;
988 if (MY_S_ISREG(statBuf
.st_mode
)) return False
;
993 /*---------------------------------------------*/
995 rac 11/21/98 see if file has hard links to it
998 Int32
countHardLinks ( Char
* name
)
1001 struct MY_STAT statBuf
;
1003 i
= MY_LSTAT ( name
, &statBuf
);
1004 if (i
!= 0) return 0;
1005 return (statBuf
.st_nlink
- 1);
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.
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.
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
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 ...
1034 struct MY_STAT fileMetaInfo
;
1038 void saveInputFileMetaInfo ( Char
*srcName
)
1042 /* Note use of stat here, not lstat. */
1043 retVal
= MY_STAT( srcName
, &fileMetaInfo
);
1044 ERROR_IF_NOT_ZERO ( retVal
);
1050 void applySavedTimeInfoToOutputFile ( Char
*dstName
)
1054 struct utimbuf uTimBuf
;
1056 uTimBuf
.actime
= fileMetaInfo
.st_atime
;
1057 uTimBuf
.modtime
= fileMetaInfo
.st_mtime
;
1059 retVal
= utime ( dstName
, &uTimBuf
);
1060 ERROR_IF_NOT_ZERO ( retVal
);
1065 void applySavedFileAttrToOutputFile ( IntNative fd
)
1070 retVal
= fchmod ( fd
, fileMetaInfo
.st_mode
);
1071 ERROR_IF_NOT_ZERO ( retVal
);
1073 (void) fchown ( fd
, fileMetaInfo
.st_uid
, fileMetaInfo
.st_gid
);
1074 /* chown() will in many cases return with EPERM, which can
1081 /*---------------------------------------------*/
1083 Bool
containsDubiousChars ( Char
* name
)
1086 /* On unix, files can contain any characters and the file expansion
1087 * is performed by the shell.
1090 # else /* ! BZ_UNIX */
1091 /* On non-unix (Win* platforms), wildcard characters are not allowed in
1094 for (; *name
!= '\0'; name
++)
1095 if (*name
== '?' || *name
== '*') return True
;
1097 # endif /* BZ_UNIX */
1101 /*---------------------------------------------*/
1102 #define BZ_N_SUFFIX_PAIRS 4
1104 const Char
* zSuffix
[BZ_N_SUFFIX_PAIRS
]
1105 = { ".bz2", ".bz", ".tbz2", ".tbz" };
1106 const Char
* unzSuffix
[BZ_N_SUFFIX_PAIRS
]
1107 = { "", "", ".tar", ".tar" };
1110 Bool
hasSuffix ( Char
* s
, const Char
* suffix
)
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
;
1120 Bool
mapSuffix ( Char
* name
,
1121 const Char
* oldSuffix
,
1122 const Char
* newSuffix
)
1124 if (!hasSuffix(name
,oldSuffix
)) return False
;
1125 name
[strlen(name
)-strlen(oldSuffix
)] = 0;
1126 strcat ( name
, newSuffix
);
1131 /*---------------------------------------------*/
1133 void compress ( Char
*name
)
1138 struct MY_STAT statBuf
;
1140 deleteOutputOnInterrupt
= False
;
1142 if (name
== NULL
&& srcMode
!= SM_I2O
)
1143 panic ( "compress: bad modes\n" );
1147 copyFileName ( inName
, (Char
*)"(stdin)" );
1148 copyFileName ( outName
, (Char
*)"(stdout)" );
1151 copyFileName ( inName
, name
);
1152 copyFileName ( outName
, name
);
1153 strcat ( outName
, ".bz2" );
1156 copyFileName ( inName
, name
);
1157 copyFileName ( outName
, (Char
*)"(stdout)" );
1161 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1163 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1168 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1169 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1170 progName
, inName
, strerror(errno
) );
1174 for (i
= 0; i
< BZ_N_SUFFIX_PAIRS
; i
++) {
1175 if (hasSuffix(inName
, zSuffix
[i
])) {
1178 "%s: Input file %s already has %s suffix.\n",
1179 progName
, inName
, zSuffix
[i
] );
1184 if ( srcMode
== SM_F2F
|| srcMode
== SM_F2O
) {
1185 MY_STAT(inName
, &statBuf
);
1186 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1188 "%s: Input file %s is a directory.\n",
1194 if ( srcMode
== SM_F2F
&& !forceOverwrite
&& notAStandardFile ( inName
)) {
1196 fprintf ( stderr
, "%s: Input file %s is not a normal file.\n",
1201 if ( srcMode
== SM_F2F
&& fileExists ( outName
) ) {
1202 if (forceOverwrite
) {
1205 fprintf ( stderr
, "%s: Output file %s already exists.\n",
1206 progName
, outName
);
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" : "" );
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
);
1225 switch ( srcMode
) {
1230 if ( isatty ( fileno ( stdout
) ) ) {
1232 "%s: I won't write compressed data to a terminal.\n",
1234 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1235 progName
, progName
);
1242 inStr
= fopen ( inName
, "rb" );
1244 if ( isatty ( fileno ( stdout
) ) ) {
1246 "%s: I won't write compressed data to a terminal.\n",
1248 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1249 progName
, progName
);
1250 if ( inStr
!= NULL
) fclose ( inStr
);
1254 if ( inStr
== NULL
) {
1255 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1256 progName
, inName
, strerror(errno
) );
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
);
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
);
1282 panic ( "compress: bad srcMode" );
1286 if (verbosity
>= 1) {
1287 fprintf ( stderr
, " %s: ", inName
);
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
;
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
);
1308 deleteOutputOnInterrupt
= False
;
1312 /*---------------------------------------------*/
1314 void uncompress ( Char
*name
)
1321 struct MY_STAT statBuf
;
1323 deleteOutputOnInterrupt
= False
;
1325 if (name
== NULL
&& srcMode
!= SM_I2O
)
1326 panic ( "uncompress: bad modes\n" );
1331 copyFileName ( inName
, (Char
*)"(stdin)" );
1332 copyFileName ( outName
, (Char
*)"(stdout)" );
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
]))
1341 strcat ( outName
, ".out" );
1344 copyFileName ( inName
, name
);
1345 copyFileName ( outName
, (Char
*)"(stdout)" );
1350 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1352 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1357 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1358 fprintf ( stderr
, "%s: Can't open input file %s: %s.\n",
1359 progName
, inName
, strerror(errno
) );
1363 if ( srcMode
== SM_F2F
|| srcMode
== SM_F2O
) {
1364 MY_STAT(inName
, &statBuf
);
1365 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1367 "%s: Input file %s is a directory.\n",
1373 if ( srcMode
== SM_F2F
&& !forceOverwrite
&& notAStandardFile ( inName
)) {
1375 fprintf ( stderr
, "%s: Input file %s is not a normal file.\n",
1380 if ( /* srcMode == SM_F2F implied && */ cantGuess
) {
1383 "%s: Can't guess original name for %s -- using %s\n",
1384 progName
, inName
, outName
);
1385 /* just a warning, no return */
1387 if ( srcMode
== SM_F2F
&& fileExists ( outName
) ) {
1388 if (forceOverwrite
) {
1391 fprintf ( stderr
, "%s: Output file %s already exists.\n",
1392 progName
, outName
);
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" : "" );
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
);
1411 switch ( srcMode
) {
1416 if ( isatty ( fileno ( stdin
) ) ) {
1418 "%s: I won't read compressed data from a terminal.\n",
1420 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1421 progName
, progName
);
1428 inStr
= fopen ( inName
, "rb" );
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
);
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
);
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
);
1459 panic ( "uncompress: bad srcMode" );
1463 if (verbosity
>= 1) {
1464 fprintf ( stderr
, " %s: ", inName
);
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
;
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
);
1486 unzFailsExist
= True
;
1487 deleteOutputOnInterrupt
= False
;
1488 if ( srcMode
== SM_F2F
) {
1489 IntNative retVal
= remove ( outName
);
1490 ERROR_IF_NOT_ZERO ( retVal
);
1493 deleteOutputOnInterrupt
= False
;
1495 if ( magicNumberOK
) {
1497 fprintf ( stderr
, "done\n" );
1501 fprintf ( stderr
, "not a bzip2 file.\n" ); else
1503 "%s: %s is not a bzip2 file.\n",
1510 /*---------------------------------------------*/
1512 void testf ( Char
*name
)
1516 struct MY_STAT statBuf
;
1518 deleteOutputOnInterrupt
= False
;
1520 if (name
== NULL
&& srcMode
!= SM_I2O
)
1521 panic ( "testf: bad modes\n" );
1523 copyFileName ( outName
, (Char
*)"(none)" );
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;
1530 if ( srcMode
!= SM_I2O
&& containsDubiousChars ( inName
) ) {
1532 fprintf ( stderr
, "%s: There are no files matching `%s'.\n",
1537 if ( srcMode
!= SM_I2O
&& !fileExists ( inName
) ) {
1538 fprintf ( stderr
, "%s: Can't open input %s: %s.\n",
1539 progName
, inName
, strerror(errno
) );
1543 if ( srcMode
!= SM_I2O
) {
1544 MY_STAT(inName
, &statBuf
);
1545 if ( MY_S_ISDIR(statBuf
.st_mode
) ) {
1547 "%s: Input file %s is a directory.\n",
1554 switch ( srcMode
) {
1557 if ( isatty ( fileno ( stdin
) ) ) {
1559 "%s: I won't read compressed data from a terminal.\n",
1561 fprintf ( stderr
, "%s: For help, type: `%s --help'.\n",
1562 progName
, progName
);
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
) );
1580 panic ( "testf: bad srcMode" );
1584 if (verbosity
>= 1) {
1585 fprintf ( stderr
, " %s: ", inName
);
1590 /*--- Now the input handle is sane. Do the Biz. ---*/
1591 outputHandleJustInCase
= NULL
;
1592 allOK
= testStream ( inStr
);
1594 if (allOK
&& verbosity
>= 1) fprintf ( stderr
, "ok\n" );
1595 if (!allOK
) testFailsExist
= True
;
1599 /*---------------------------------------------*/
1601 void license ( void )
1605 "bzip2, a block-sorting file compressor. "
1608 " Copyright (C) 1996-2007 by Julian Seward.\n"
1610 " This program is free software; you can redistribute it and/or modify\n"
1611 " it under the terms set out in the LICENSE file, which is included\n"
1612 " in the bzip2-1.0.5 source distribution.\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"
1624 /*---------------------------------------------*/
1626 void usage ( Char
*fullProgName
)
1630 "bzip2, a block-sorting file compressor. "
1632 "\n usage: %s [flags and input files in any order]\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"
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"
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"
1668 /*---------------------------------------------*/
1670 void redundant ( Char
* flag
)
1674 "%s: %s is redundant in versions 0.9.5 and above\n",
1679 /*---------------------------------------------*/
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].
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.
1690 The actual Dirty Work is done by the platform-
1691 specific macro APPEND_FILESPEC.
1702 /*---------------------------------------------*/
1704 void *myMalloc ( Int32 n
)
1708 p
= malloc ( (size_t)n
);
1709 if (p
== NULL
) outOfMemory ();
1714 /*---------------------------------------------*/
1716 Cell
*mkCell ( void )
1720 c
= (Cell
*) myMalloc ( sizeof ( Cell
) );
1727 /*---------------------------------------------*/
1729 Cell
*snocString ( Cell
*root
, Char
*name
)
1732 Cell
*tmp
= mkCell();
1733 tmp
->name
= (Char
*) myMalloc ( 5 + strlen(name
) );
1734 strcpy ( tmp
->name
, name
);
1738 while (tmp
->link
!= NULL
) tmp
= tmp
->link
;
1739 tmp
->link
= snocString ( tmp
->link
, name
);
1745 /*---------------------------------------------*/
1747 void addFlagsFromEnvVar ( Cell
** argList
, Char
* varName
)
1752 envbase
= getenv(varName
);
1753 if (envbase
!= NULL
) {
1757 if (p
[i
] == 0) break;
1760 while (isspace((Int32
)(p
[0]))) p
++;
1761 while (p
[i
] != 0 && !isspace((Int32
)(p
[i
]))) i
++;
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
];
1766 APPEND_FLAG(*argList
, tmpName
);
1773 /*---------------------------------------------*/
1774 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
1776 IntNative
main ( IntNative argc
, Char
*argv
[] )
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)
1790 /*-- Initialise --*/
1791 outputHandleJustInCase
= NULL
;
1793 keepInputFiles
= False
;
1794 forceOverwrite
= False
;
1798 testFailsExist
= False
;
1799 unzFailsExist
= False
;
1801 numFilesProcessed
= 0;
1803 deleteOutputOnInterrupt
= False
;
1805 i
= j
= 0; /* avoid bogus warning from egcs-1.1.X */
1807 /*-- Set up signal handlers for mem access errors --*/
1808 signal (SIGSEGV
, mySIGSEGVorSIGBUScatcher
);
1811 signal (SIGBUS
, mySIGSEGVorSIGBUScatcher
);
1815 copyFileName ( inName
, (Char
*)"(none)" );
1816 copyFileName ( outName
, (Char
*)"(none)" );
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;
1824 /*-- Copy flags from env var BZIP2, and
1825 expand filename wildcards in arg list.
1828 addFlagsFromEnvVar ( &argList
, (Char
*)"BZIP2" );
1829 addFlagsFromEnvVar ( &argList
, (Char
*)"BZIP" );
1830 for (i
= 1; i
<= argc
-1; i
++)
1831 APPEND_FILESPEC(argList
, argv
[i
]);
1834 /*-- Find the length of the longest filename --*/
1835 longestFileName
= 7;
1838 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
1839 if (ISFLAG("--")) { decode
= False
; continue; }
1840 if (aa
->name
[0] == '-' && decode
) continue;
1842 if (longestFileName
< (Int32
)strlen(aa
->name
) )
1843 longestFileName
= (Int32
)strlen(aa
->name
);
1847 /*-- Determine source modes; flag handling may change this too. --*/
1848 if (numFileNames
== 0)
1849 srcMode
= SM_I2O
; else srcMode
= SM_F2F
;
1852 /*-- Determine what to do (compress/uncompress/test/cat). --*/
1853 /*-- Note that subsequent flag handling may change this. --*/
1856 if ( (strstr ( progName
, "unzip" ) != 0) ||
1857 (strstr ( progName
, "UNZIP" ) != 0) )
1860 if ( (strstr ( progName
, "z2cat" ) != 0) ||
1861 (strstr ( progName
, "Z2CAT" ) != 0) ||
1862 (strstr ( progName
, "zcat" ) != 0) ||
1863 (strstr ( progName
, "ZCAT" ) != 0) ) {
1865 srcMode
= (numFileNames
== 0) ? SM_I2O
: SM_F2O
;
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;
1893 case 'L': license(); break;
1894 case 'v': verbosity
++; break;
1895 case 'h': usage ( progName
);
1898 default: fprintf ( stderr
, "%s: Bad flag `%s'\n",
1899 progName
, aa
->name
);
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 ); }
1929 if (strncmp ( aa
->name
, "--", 2) == 0) {
1930 fprintf ( stderr
, "%s: Bad flag `%s'\n", progName
, aa
->name
);
1936 if (verbosity
> 4) verbosity
= 4;
1937 if (opMode
== OM_Z
&& smallMode
&& blockSize100k
> 2)
1940 if (opMode
== OM_TEST
&& srcMode
== SM_F2O
) {
1941 fprintf ( stderr
, "%s: -c and -t cannot be used together.\n",
1946 if (srcMode
== SM_F2O
&& numFileNames
== 0)
1949 if (opMode
!= OM_Z
) blockSize100k
= 0;
1951 if (srcMode
== SM_F2F
) {
1952 signal (SIGINT
, mySignalCatcher
);
1953 signal (SIGTERM
, mySignalCatcher
);
1955 signal (SIGHUP
, mySignalCatcher
);
1959 if (opMode
== OM_Z
) {
1960 if (srcMode
== SM_I2O
) {
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
);
1974 if (opMode
== OM_UNZ
) {
1975 unzFailsExist
= False
;
1976 if (srcMode
== SM_I2O
) {
1977 uncompress ( NULL
);
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
);
1987 if (unzFailsExist
) {
1994 testFailsExist
= False
;
1995 if (srcMode
== SM_I2O
) {
1999 for (aa
= argList
; aa
!= NULL
; aa
= aa
->link
) {
2000 if (ISFLAG("--")) { decode
= False
; continue; }
2001 if (aa
->name
[0] == '-' && decode
) continue;
2002 numFilesProcessed
++;
2006 if (testFailsExist
&& noisy
) {
2009 "You can use the `bzip2recover' program to attempt to recover\n"
2010 "data from undamaged sections of corrupted files.\n\n"
2017 /* Free the argument list memory to mollify leak detectors
2018 (eg) Purify, Checker. Serves no other useful purpose.
2021 while (aa
!= NULL
) {
2022 Cell
* aa2
= aa
->link
;
2023 if (aa
->name
!= NULL
) free(aa
->name
);
2032 /*-----------------------------------------------------------*/
2033 /*--- end bzip2.c ---*/
2034 /*-----------------------------------------------------------*/