2 /*-----------------------------------------------------------*/
3 /*--- A block-sorting, lossless compressor bzip2.c ---*/
4 /*-----------------------------------------------------------*/
7 This file is a part of bzip2 and/or libbzip2, a program and
8 library for lossless, block-sorting data compression.
10 Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
19 2. The origin of this software must not be misrepresented; you must
20 not claim that you wrote the original software. If you use this
21 software in a product, an acknowledgment in the product
22 documentation would be appreciated but is not required.
24 3. Altered source versions must be plainly marked as such, and must
25 not be misrepresented as being the original software.
27 4. The name of the author may not be used to endorse or promote
28 products derived from this software without specific prior written
31 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
32 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
35 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
37 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
38 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
39 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
40 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 Julian Seward, Cambridge, UK.
45 bzip2/libbzip2 version 1.0 of 21 March 2000
47 This program is based on (at least) the work of:
57 For more information on these sources, see the manual.
61 /*----------------------------------------------------*/
63 /*----------------------------------------------------*/
67 This program and library (attempts to) compress data by
68 performing several non-trivial transformations on it.
69 Unless you are 100% familiar with *all* the algorithms
70 contained herein, and with the consequences of modifying them,
71 you should NOT meddle with the compression or decompression
72 machinery. Incorrect changes can and very likely *will*
73 lead to disasterous loss of data.
76 I TAKE NO RESPONSIBILITY FOR ANY LOSS OF DATA ARISING FROM THE
77 USE OF THIS PROGRAM, HOWSOEVER CAUSED.
79 Every compression of a file implies an assumption that the
80 compressed file can be decompressed to reproduce the original.
81 Great efforts in design, coding and testing have been made to
82 ensure that this program works correctly. However, the
83 complexity of the algorithms, and, in particular, the presence
84 of various special cases in the code which occur with very low
85 but non-zero probability make it impossible to rule out the
86 possibility of bugs remaining in the program. DO NOT COMPRESS
87 ANY DATA WITH THIS PROGRAM AND/OR LIBRARY UNLESS YOU ARE PREPARED
88 TO ACCEPT THE POSSIBILITY, HOWEVER SMALL, THAT THE DATA WILL
91 That is not to say this program is inherently unreliable.
92 Indeed, I very much hope the opposite is true. bzip2/libbzip2
93 has been carefully constructed and extensively tested.
96 To the best of my knowledge, bzip2/libbzip2 does not use any
97 patented algorithms. However, I do not have the resources
98 available to carry out a full patent search. Therefore I cannot
99 give any guarantee of the above statement.
104 /*----------------------------------------------------*/
105 /*--- and now for something much more pleasant :-) ---*/
106 /*----------------------------------------------------*/
108 /*---------------------------------------------*/
110 Place a 1 beside your platform, and 0 elsewhere.
115 Also works on 64-bit Unix boxes.
121 Win32, as seen by Jacob Navia's excellent
122 port of (Chris Fraser & David Hanson)'s excellent
123 lcc compiler. Or with MS Visual C.
124 This is selected automatically if compiled by a compiler which
125 defines _WIN32, not including the Cygwin GCC.
127 #define BZ_LCCWIN32 0
129 #if defined(_WIN32) && !defined(__CYGWIN__)
131 #define BZ_LCCWIN32 1
137 /*---------------------------------------------*/
139 Some stuff for all platforms.
151 #define ERROR_IF_EOF(i) { if ((i) == EOF) ioError(); }
152 #define ERROR_IF_NOT_ZERO(i) { if ((i) != 0) ioError(); }
153 #define ERROR_IF_MINUS_ONE(i) { if ((i) == (-1)) ioError(); }
156 /*---------------------------------------------*/
158 Platform-specific stuff.
163 # include <sys/types.h>
166 # include <sys/stat.h>
167 # include <sys/times.h>
169 # define PATH_SEP '/'
170 # define MY_LSTAT lstat
171 # define MY_STAT stat
172 # define MY_S_ISREG S_ISREG
173 # define MY_S_ISDIR S_ISDIR
175 # define APPEND_FILESPEC(root, name) \
176 root=snocString((root), (name))
178 # define APPEND_FLAG(root, name) \
179 root=snocString((root), (name))
181 # define SET_BINARY_MODE(fd) /**/
184 # define NORETURN __attribute__ ((noreturn))
186 # define NORETURN /**/
194 # define MY_LSTAT stat
195 # define MY_STAT stat
196 # undef SET_BINARY_MODE
197 # define SET_BINARY_MODE(fd) \
199 int retVal = setmode ( fileno ( fd ), \
201 ERROR_IF_MINUS_ONE ( retVal ); \
208 # undef SET_BINARY_MODE
209 # define SET_BINARY_MODE(fd) \
211 int retVal = setmode ( fileno ( fd ), \
213 ERROR_IF_MINUS_ONE ( retVal ); \
223 # include <sys\stat.h>
225 # define NORETURN /**/
226 # define PATH_SEP '\\'
227 # define MY_LSTAT _stat
228 # define MY_STAT _stat
229 # define MY_S_ISREG(x) ((x) & _S_IFREG)
230 # define MY_S_ISDIR(x) ((x) & _S_IFDIR)
232 # define APPEND_FLAG(root, name) \
233 root=snocString((root), (name))
235 # define APPEND_FILESPEC(root, name) \
236 root = snocString ((root), (name))
238 # define SET_BINARY_MODE(fd) \
240 int retVal = setmode ( fileno ( fd ), \
242 ERROR_IF_MINUS_ONE ( retVal ); \
245 #endif /* BZ_LCCWIN32 */
248 /*---------------------------------------------*/
250 Some more stuff for all platforms :-)
254 typedef unsigned char Bool;
255 typedef unsigned char UChar;
257 typedef unsigned int UInt32;
259 typedef unsigned short UInt16;
261 #define True ((Bool)1)
262 #define False ((Bool)0)
265 IntNative is your platform's `native' int size.
266 Only here to avoid probs with 64-bit platforms.
268 typedef int IntNative;
271 /*---------------------------------------------------*/
272 /*--- Misc (file handling) data decls ---*/
273 /*---------------------------------------------------*/
276 Bool keepInputFiles, smallMode, deleteOutputOnInterrupt;
277 Bool forceOverwrite, testFailsExist, unzFailsExist, noisy;
278 Int32 numFileNames, numFilesProcessed, blockSize100k;
281 /*-- source modes; F==file, I==stdin, O==stdout --*/
286 /*-- operation modes --*/
294 #define FILE_NAME_LEN 1034
296 Int32 longestFileName;
297 Char inName [FILE_NAME_LEN];
298 Char outName[FILE_NAME_LEN];
299 Char tmpName[FILE_NAME_LEN];
301 Char progNameReally[FILE_NAME_LEN];
302 FILE *outputHandleJustInCase;
305 static void panic ( Char* ) NORETURN;
306 static void ioError ( void ) NORETURN;
307 static void outOfMemory ( void ) NORETURN;
308 static void configError ( void ) NORETURN;
309 static void crcError ( void ) NORETURN;
310 static void cleanUpAndFail ( Int32 ) NORETURN;
311 static void compressedStreamEOF ( void ) NORETURN;
313 static void copyFileName ( Char*, Char* );
314 static void* myMalloc ( Int32 );
318 /*---------------------------------------------------*/
319 /*--- An implementation of 64-bit ints. Sigh. ---*/
320 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
321 /*---------------------------------------------------*/
324 struct { UChar b[8]; }
329 void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
331 n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
332 n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
333 n->b[5] = (UChar)((hi32 >> 8) & 0xFF);
334 n->b[4] = (UChar) (hi32 & 0xFF);
335 n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
336 n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
337 n->b[1] = (UChar)((lo32 >> 8) & 0xFF);
338 n->b[0] = (UChar) (lo32 & 0xFF);
343 double uInt64_to_double ( UInt64* n )
348 for (i = 0; i < 8; i++) {
349 sum += base * (double)(n->b[i]);
357 Bool uInt64_isZero ( UInt64* n )
360 for (i = 0; i < 8; i++)
361 if (n->b[i] != 0) return 0;
366 /* Divide *n by 10, and return the remainder. */
368 Int32 uInt64_qrm10 ( UInt64* n )
373 for (i = 7; i >= 0; i--) {
374 tmp = rem * 256 + n->b[i];
382 /* ... and the Whole Entire Point of all this UInt64 stuff is
383 so that we can supply the following function.
386 void uInt64_toAscii ( char* outbuf, UInt64* n )
393 q = uInt64_qrm10 ( &n_copy );
396 } while (!uInt64_isZero(&n_copy));
398 for (i = 0; i < nBuf; i++)
399 outbuf[i] = buf[nBuf-i-1];
403 /*---------------------------------------------------*/
404 /*--- Processing of complete files and streams ---*/
405 /*---------------------------------------------------*/
407 /*---------------------------------------------*/
409 Bool myfeof ( FILE* f )
411 Int32 c = fgetc ( f );
412 if (c == EOF) return True;
418 /*---------------------------------------------*/
420 void compressStream ( FILE *stream, FILE *zStream )
425 UInt32 nbytes_in_lo32, nbytes_in_hi32;
426 UInt32 nbytes_out_lo32, nbytes_out_hi32;
427 Int32 bzerr, bzerr_dummy, ret;
429 SET_BINARY_MODE(stream);
430 SET_BINARY_MODE(zStream);
432 if (ferror(stream)) goto errhandler_io;
433 if (ferror(zStream)) goto errhandler_io;
435 bzf = BZ2_bzWriteOpen ( &bzerr, zStream,
436 blockSize100k, verbosity, workFactor );
437 if (bzerr != BZ_OK) goto errhandler;
439 if (verbosity >= 2) fprintf ( stderr, "\n" );
443 if (myfeof(stream)) break;
444 nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
445 if (ferror(stream)) goto errhandler_io;
446 if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
447 if (bzerr != BZ_OK) goto errhandler;
451 BZ2_bzWriteClose64 ( &bzerr, bzf, 0,
452 &nbytes_in_lo32, &nbytes_in_hi32,
453 &nbytes_out_lo32, &nbytes_out_hi32 );
454 if (bzerr != BZ_OK) goto errhandler;
456 if (ferror(zStream)) goto errhandler_io;
457 ret = fflush ( zStream );
458 if (ret == EOF) goto errhandler_io;
459 if (zStream != stdout) {
460 ret = fclose ( zStream );
461 outputHandleJustInCase = NULL;
462 if (ret == EOF) goto errhandler_io;
464 outputHandleJustInCase = NULL;
465 if (ferror(stream)) goto errhandler_io;
466 ret = fclose ( stream );
467 if (ret == EOF) goto errhandler_io;
469 if (verbosity >= 1) {
470 if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
471 fprintf ( stderr, " no data compressed.\n");
473 Char buf_nin[32], buf_nout[32];
474 UInt64 nbytes_in, nbytes_out;
475 double nbytes_in_d, nbytes_out_d;
476 uInt64_from_UInt32s ( &nbytes_in,
477 nbytes_in_lo32, nbytes_in_hi32 );
478 uInt64_from_UInt32s ( &nbytes_out,
479 nbytes_out_lo32, nbytes_out_hi32 );
480 nbytes_in_d = uInt64_to_double ( &nbytes_in );
481 nbytes_out_d = uInt64_to_double ( &nbytes_out );
482 uInt64_toAscii ( buf_nin, &nbytes_in );
483 uInt64_toAscii ( buf_nout, &nbytes_out );
484 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
485 "%5.2f%% saved, %s in, %s out.\n",
486 nbytes_in_d / nbytes_out_d,
487 (8.0 * nbytes_out_d) / nbytes_in_d,
488 100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
498 BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1,
499 &nbytes_in_lo32, &nbytes_in_hi32,
500 &nbytes_out_lo32, &nbytes_out_hi32 );
502 case BZ_CONFIG_ERROR:
503 configError(); break;
505 outOfMemory (); break;
510 panic ( "compress:unexpected error" );
513 panic ( "compress:end" );
519 /*---------------------------------------------*/
521 Bool uncompressStream ( FILE *zStream, FILE *stream )
524 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
526 UChar unused[BZ_MAX_UNUSED];
533 SET_BINARY_MODE(stream);
534 SET_BINARY_MODE(zStream);
536 if (ferror(stream)) goto errhandler_io;
537 if (ferror(zStream)) goto errhandler_io;
541 bzf = BZ2_bzReadOpen (
542 &bzerr, zStream, verbosity,
543 (int)smallMode, unused, nUnused
545 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
548 while (bzerr == BZ_OK) {
549 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
550 if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
551 if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
552 fwrite ( obuf, sizeof(UChar), nread, stream );
553 if (ferror(stream)) goto errhandler_io;
555 if (bzerr != BZ_STREAM_END) goto errhandler;
557 BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused );
558 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
560 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
562 BZ2_bzReadClose ( &bzerr, bzf );
563 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
565 if (nUnused == 0 && myfeof(zStream)) break;
569 if (ferror(zStream)) goto errhandler_io;
570 ret = fclose ( zStream );
571 if (ret == EOF) goto errhandler_io;
573 if (ferror(stream)) goto errhandler_io;
574 ret = fflush ( stream );
575 if (ret != 0) goto errhandler_io;
576 if (stream != stdout) {
577 ret = fclose ( stream );
578 outputHandleJustInCase = NULL;
579 if (ret == EOF) goto errhandler_io;
581 outputHandleJustInCase = NULL;
582 if (verbosity >= 2) fprintf ( stderr, "\n " );
586 if (forceOverwrite) {
589 if (myfeof(zStream)) break;
590 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
591 if (ferror(zStream)) goto errhandler_io;
592 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
593 if (ferror(stream)) goto errhandler_io;
599 BZ2_bzReadClose ( &bzerr_dummy, bzf );
601 case BZ_CONFIG_ERROR:
602 configError(); break;
610 case BZ_UNEXPECTED_EOF:
611 compressedStreamEOF();
612 case BZ_DATA_ERROR_MAGIC:
613 if (zStream != stdin) fclose(zStream);
614 if (stream != stdout) fclose(stream);
620 "\n%s: %s: trailing garbage after EOF ignored\n",
625 panic ( "decompress:unexpected error" );
628 panic ( "decompress:end" );
629 return True; /*notreached*/
633 /*---------------------------------------------*/
635 Bool testStream ( FILE *zStream )
638 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
640 UChar unused[BZ_MAX_UNUSED];
647 SET_BINARY_MODE(zStream);
648 if (ferror(zStream)) goto errhandler_io;
652 bzf = BZ2_bzReadOpen (
653 &bzerr, zStream, verbosity,
654 (int)smallMode, unused, nUnused
656 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
659 while (bzerr == BZ_OK) {
660 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
661 if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
663 if (bzerr != BZ_STREAM_END) goto errhandler;
665 BZ2_bzReadGetUnused ( &bzerr, bzf, (void**)(&unusedTmp), &nUnused );
666 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
668 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
670 BZ2_bzReadClose ( &bzerr, bzf );
671 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
672 if (nUnused == 0 && myfeof(zStream)) break;
676 if (ferror(zStream)) goto errhandler_io;
677 ret = fclose ( zStream );
678 if (ret == EOF) goto errhandler_io;
680 if (verbosity >= 2) fprintf ( stderr, "\n " );
684 BZ2_bzReadClose ( &bzerr_dummy, bzf );
686 fprintf ( stderr, "%s: %s: ", progName, inName );
688 case BZ_CONFIG_ERROR:
689 configError(); break;
695 "data integrity (CRC) error in data\n" );
699 case BZ_UNEXPECTED_EOF:
701 "file ends unexpectedly\n" );
703 case BZ_DATA_ERROR_MAGIC:
704 if (zStream != stdin) fclose(zStream);
707 "bad magic number (file not created by bzip2)\n" );
712 "trailing garbage after EOF ignored\n" );
716 panic ( "test:unexpected error" );
719 panic ( "test:end" );
720 return True; /*notreached*/
724 /*---------------------------------------------------*/
725 /*--- Error [non-] handling grunge ---*/
726 /*---------------------------------------------------*/
728 /*---------------------------------------------*/
730 void setExit ( Int32 v )
732 if (v > exitValue) exitValue = v;
736 /*---------------------------------------------*/
738 void cadvise ( void )
743 "\nIt is possible that the compressed file(s) have become corrupted.\n"
744 "You can use the -tvv option to test integrity of such files.\n\n"
745 "You can use the `bzip2recover' program to attempt to recover\n"
746 "data from undamaged sections of corrupted files.\n\n"
751 /*---------------------------------------------*/
753 void showFileNames ( void )
758 "\tInput file = %s, output file = %s\n",
764 /*---------------------------------------------*/
766 void cleanUpAndFail ( Int32 ec )
769 struct MY_STAT statBuf;
771 if ( srcMode == SM_F2F
773 && deleteOutputOnInterrupt ) {
775 /* Check whether input file still exists. Delete output file
776 only if input exists to avoid loss of data. Joerg Prante, 5
777 January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean
778 this is less likely to happen. But to be ultra-paranoid, we
779 do the check anyway.) */
780 retVal = MY_STAT ( inName, &statBuf );
784 "%s: Deleting output file %s, if it exists.\n",
786 if (outputHandleJustInCase != NULL)
787 fclose ( outputHandleJustInCase );
788 retVal = remove ( outName );
791 "%s: WARNING: deletion of output file "
792 "(apparently) failed.\n",
796 "%s: WARNING: deletion of output file suppressed\n",
799 "%s: since input file no longer exists. Output file\n",
802 "%s: `%s' may be incomplete.\n",
805 "%s: I suggest doing an integrity test (bzip2 -tv)"
811 if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
813 "%s: WARNING: some files have not been processed:\n"
814 "%s: %d specified on command line, %d not processed yet.\n\n",
816 numFileNames, numFileNames - numFilesProcessed );
823 /*---------------------------------------------*/
825 void panic ( Char* s )
828 "\n%s: PANIC -- internal consistency error:\n"
830 "\tThis is a BUG. Please report it to me at:\n"
831 "\tjseward@acm.org\n",
838 /*---------------------------------------------*/
840 void crcError ( void )
843 "\n%s: Data integrity error when decompressing.\n",
851 /*---------------------------------------------*/
853 void compressedStreamEOF ( void )
857 "\n%s: Compressed file ends unexpectedly;\n\t"
858 "perhaps it is corrupted? *Possible* reason follows.\n",
868 /*---------------------------------------------*/
870 void ioError ( void )
873 "\n%s: I/O or other error, bailing out. "
874 "Possible reason follows.\n",
882 /*---------------------------------------------*/
884 void mySignalCatcher ( IntNative n )
887 "\n%s: Control-C or similar caught, quitting.\n",
893 /*---------------------------------------------*/
895 void mySIGSEGVorSIGBUScatcher ( IntNative n )
900 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
902 " Possible causes are (most likely first):\n"
903 " (1) This computer has unreliable memory or cache hardware\n"
904 " (a surprisingly common problem; try a different machine.)\n"
905 " (2) A bug in the compiler used to create this executable\n"
906 " (unlikely, if you didn't compile bzip2 yourself.)\n"
907 " (3) A real bug in bzip2 -- I hope this should never be the case.\n"
908 " The user's manual, Section 4.3, has more info on (1) and (2).\n"
910 " If you suspect this is a bug in bzip2, or are unsure about (1)\n"
911 " or (2), feel free to report it to me at: jseward@acm.org.\n"
912 " Section 4.3 of the user's manual describes the info a useful\n"
913 " bug report should have. If the manual is available on your\n"
914 " system, please try and read it before mailing me. If you don't\n"
915 " have the manual or can't be bothered to read it, mail me anyway.\n"
921 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
923 " Possible causes are (most likely first):\n"
924 " (1) The compressed data is corrupted, and bzip2's usual checks\n"
925 " failed to detect this. Try bzip2 -tvv my_file.bz2.\n"
926 " (2) This computer has unreliable memory or cache hardware\n"
927 " (a surprisingly common problem; try a different machine.)\n"
928 " (3) A bug in the compiler used to create this executable\n"
929 " (unlikely, if you didn't compile bzip2 yourself.)\n"
930 " (4) A real bug in bzip2 -- I hope this should never be the case.\n"
931 " The user's manual, Section 4.3, has more info on (2) and (3).\n"
933 " If you suspect this is a bug in bzip2, or are unsure about (2)\n"
934 " or (3), feel free to report it to me at: jseward@acm.org.\n"
935 " Section 4.3 of the user's manual describes the info a useful\n"
936 " bug report should have. If the manual is available on your\n"
937 " system, please try and read it before mailing me. If you don't\n"
938 " have the manual or can't be bothered to read it, mail me anyway.\n"
944 cleanUpAndFail( 3 ); else
945 { cadvise(); cleanUpAndFail( 2 ); }
949 /*---------------------------------------------*/
951 void outOfMemory ( void )
954 "\n%s: couldn't allocate enough memory\n",
961 /*---------------------------------------------*/
963 void configError ( void )
966 "bzip2: I'm not configured correctly for this platform!\n"
967 "\tI require Int32, Int16 and Char to have sizes\n"
968 "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
969 "\tProbably you can fix this by defining them correctly,\n"
970 "\tand recompiling. Bye!\n" );
976 /*---------------------------------------------------*/
977 /*--- The main driver machinery ---*/
978 /*---------------------------------------------------*/
980 /* All rather crufty. The main problem is that input files
981 are stat()d multiple times before use. This should be
985 /*---------------------------------------------*/
990 if ( (Int32)strlen(s) >= longestFileName ) return;
991 for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
992 fprintf ( stderr, " " );
996 /*---------------------------------------------*/
998 void copyFileName ( Char* to, Char* from )
1000 if ( strlen(from) > FILE_NAME_LEN-10 ) {
1003 "bzip2: file name\n`%s'\n"
1004 "is suspiciously (more than %d chars) long.\n"
1005 "Try using a reasonable file name instead. Sorry! :-)\n",
1006 from, FILE_NAME_LEN-10
1012 strncpy(to,from,FILE_NAME_LEN-10);
1013 to[FILE_NAME_LEN-10]='\0';
1017 /*---------------------------------------------*/
1019 Bool fileExists ( Char* name )
1021 FILE *tmp = fopen ( name, "rb" );
1022 Bool exists = (tmp != NULL);
1023 if (tmp != NULL) fclose ( tmp );
1028 /*---------------------------------------------*/
1029 /* Open an output file safely with O_EXCL and good permissions.
1030 This avoids a race condition in versions < 1.0.2, in which
1031 the file was first opened and then had its interim permissions
1032 set safely. We instead use open() to create the file with
1033 the interim permissions required. (--- --- rw-).
1035 For non-Unix platforms, if we are not worrying about
1036 security issues, simple this simply behaves like fopen.
1038 FILE* fopen_output_safely ( Char* name, const char* mode )
1043 fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
1044 if (fh == -1) return NULL;
1045 fp = fdopen(fh, mode);
1046 if (fp == NULL) close(fh);
1049 return fopen(name, mode);
1054 /*---------------------------------------------*/
1056 if in doubt, return True
1059 Bool notAStandardFile ( Char* name )
1062 struct MY_STAT statBuf;
1064 i = MY_LSTAT ( name, &statBuf );
1065 if (i != 0) return True;
1066 if (MY_S_ISREG(statBuf.st_mode)) return False;
1071 /*---------------------------------------------*/
1073 rac 11/21/98 see if file has hard links to it
1076 Int32 countHardLinks ( Char* name )
1079 struct MY_STAT statBuf;
1081 i = MY_LSTAT ( name, &statBuf );
1082 if (i != 0) return 0;
1083 return (statBuf.st_nlink - 1);
1087 /*---------------------------------------------*/
1088 /* Copy modification date, access date, permissions and owner from the
1089 source to destination file. We have to copy this meta-info off
1090 into fileMetaInfo before starting to compress / decompress it,
1091 because doing it afterwards means we get the wrong access time.
1093 To complicate matters, in compress() and decompress() below, the
1094 sequence of tests preceding the call to saveInputFileMetaInfo()
1095 involves calling fileExists(), which in turn establishes its result
1096 by attempting to fopen() the file, and if successful, immediately
1097 fclose()ing it again. So we have to assume that the fopen() call
1098 does not cause the access time field to be updated.
1100 Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
1101 to imply that merely doing open() will not affect the access time.
1102 Therefore we merely need to hope that the C library only does
1103 open() as a result of fopen(), and not any kind of read()-ahead
1106 It sounds pretty fragile to me. Whether this carries across
1107 robustly to arbitrary Unix-like platforms (or even works robustly
1108 on this one, RedHat 7.2) is unknown to me. Nevertheless ...
1112 struct MY_STAT fileMetaInfo;
1116 void saveInputFileMetaInfo ( Char *srcName )
1120 /* Note use of stat here, not lstat. */
1121 retVal = MY_STAT( srcName, &fileMetaInfo );
1122 ERROR_IF_NOT_ZERO ( retVal );
1128 void applySavedMetaInfoToOutputFile ( Char *dstName )
1132 struct utimbuf uTimBuf;
1134 uTimBuf.actime = fileMetaInfo.st_atime;
1135 uTimBuf.modtime = fileMetaInfo.st_mtime;
1137 retVal = chmod ( dstName, fileMetaInfo.st_mode );
1138 ERROR_IF_NOT_ZERO ( retVal );
1140 retVal = utime ( dstName, &uTimBuf );
1141 ERROR_IF_NOT_ZERO ( retVal );
1143 retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
1144 /* chown() will in many cases return with EPERM, which can
1151 /*---------------------------------------------*/
1153 Bool containsDubiousChars ( Char* name )
1156 /* On unix, files can contain any characters and the file expansion
1157 * is performed by the shell.
1160 # else /* ! BZ_UNIX */
1161 /* On non-unix (Win* platforms), wildcard characters are not allowed in
1164 for (; *name != '\0'; name++)
1165 if (*name == '?' || *name == '*') return True;
1167 # endif /* BZ_UNIX */
1171 /*---------------------------------------------*/
1172 #define BZ_N_SUFFIX_PAIRS 4
1174 Char* zSuffix[BZ_N_SUFFIX_PAIRS]
1175 = { ".bz2", ".bz", ".tbz2", ".tbz" };
1176 Char* unzSuffix[BZ_N_SUFFIX_PAIRS]
1177 = { "", "", ".tar", ".tar" };
1180 Bool hasSuffix ( Char* s, Char* suffix )
1182 Int32 ns = strlen(s);
1183 Int32 nx = strlen(suffix);
1184 if (ns < nx) return False;
1185 if (strcmp(s + ns - nx, suffix) == 0) return True;
1190 Bool mapSuffix ( Char* name,
1191 Char* oldSuffix, Char* newSuffix )
1193 if (!hasSuffix(name,oldSuffix)) return False;
1194 name[strlen(name)-strlen(oldSuffix)] = 0;
1195 strcat ( name, newSuffix );
1200 /*---------------------------------------------*/
1202 void compress ( Char *name )
1207 struct MY_STAT statBuf;
1209 deleteOutputOnInterrupt = False;
1211 if (name == NULL && srcMode != SM_I2O)
1212 panic ( "compress: bad modes\n" );
1216 copyFileName ( inName, "(stdin)" );
1217 copyFileName ( outName, "(stdout)" );
1220 copyFileName ( inName, name );
1221 copyFileName ( outName, name );
1222 strcat ( outName, ".bz2" );
1225 copyFileName ( inName, name );
1226 copyFileName ( outName, "(stdout)" );
1230 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1232 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1237 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1238 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1239 progName, inName, strerror(errno) );
1243 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
1244 if (hasSuffix(inName, zSuffix[i])) {
1247 "%s: Input file %s already has %s suffix.\n",
1248 progName, inName, zSuffix[i] );
1253 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
1254 MY_STAT(inName, &statBuf);
1255 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1257 "%s: Input file %s is a directory.\n",
1263 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
1265 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
1270 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
1271 if (forceOverwrite) {
1274 fprintf ( stderr, "%s: Output file %s already exists.\n",
1275 progName, outName );
1280 if ( srcMode == SM_F2F && !forceOverwrite &&
1281 (n=countHardLinks ( inName )) > 0) {
1282 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
1283 progName, inName, n, n > 1 ? "s" : "" );
1288 if ( srcMode == SM_F2F ) {
1289 /* Save the file's meta-info before we open it. Doing it later
1290 means we mess up the access times. */
1291 saveInputFileMetaInfo ( inName );
1294 switch ( srcMode ) {
1299 if ( isatty ( fileno ( stdout ) ) ) {
1301 "%s: I won't write compressed data to a terminal.\n",
1303 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1304 progName, progName );
1311 inStr = fopen ( inName, "rb" );
1313 if ( isatty ( fileno ( stdout ) ) ) {
1315 "%s: I won't write compressed data to a terminal.\n",
1317 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1318 progName, progName );
1319 if ( inStr != NULL ) fclose ( inStr );
1323 if ( inStr == NULL ) {
1324 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1325 progName, inName, strerror(errno) );
1332 inStr = fopen ( inName, "rb" );
1333 outStr = fopen_output_safely ( outName, "wb" );
1334 if ( outStr == NULL) {
1335 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
1336 progName, outName, strerror(errno) );
1337 if ( inStr != NULL ) fclose ( inStr );
1341 if ( inStr == NULL ) {
1342 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1343 progName, inName, strerror(errno) );
1344 if ( outStr != NULL ) fclose ( outStr );
1351 panic ( "compress: bad srcMode" );
1355 if (verbosity >= 1) {
1356 fprintf ( stderr, " %s: ", inName );
1361 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1362 outputHandleJustInCase = outStr;
1363 deleteOutputOnInterrupt = True;
1364 compressStream ( inStr, outStr );
1365 outputHandleJustInCase = NULL;
1367 /*--- If there was an I/O error, we won't get here. ---*/
1368 if ( srcMode == SM_F2F ) {
1369 applySavedMetaInfoToOutputFile ( outName );
1370 deleteOutputOnInterrupt = False;
1371 if ( !keepInputFiles ) {
1372 IntNative retVal = remove ( inName );
1373 ERROR_IF_NOT_ZERO ( retVal );
1377 deleteOutputOnInterrupt = False;
1381 /*---------------------------------------------*/
1383 void uncompress ( Char *name )
1390 struct MY_STAT statBuf;
1392 deleteOutputOnInterrupt = False;
1394 if (name == NULL && srcMode != SM_I2O)
1395 panic ( "uncompress: bad modes\n" );
1400 copyFileName ( inName, "(stdin)" );
1401 copyFileName ( outName, "(stdout)" );
1404 copyFileName ( inName, name );
1405 copyFileName ( outName, name );
1406 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
1407 if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
1410 strcat ( outName, ".out" );
1413 copyFileName ( inName, name );
1414 copyFileName ( outName, "(stdout)" );
1419 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1421 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1426 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1427 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1428 progName, inName, strerror(errno) );
1432 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
1433 MY_STAT(inName, &statBuf);
1434 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1436 "%s: Input file %s is a directory.\n",
1442 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
1444 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
1449 if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
1452 "%s: Can't guess original name for %s -- using %s\n",
1453 progName, inName, outName );
1454 /* just a warning, no return */
1456 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
1457 if (forceOverwrite) {
1460 fprintf ( stderr, "%s: Output file %s already exists.\n",
1461 progName, outName );
1466 if ( srcMode == SM_F2F && !forceOverwrite &&
1467 (n=countHardLinks ( inName ) ) > 0) {
1468 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
1469 progName, inName, n, n > 1 ? "s" : "" );
1474 if ( srcMode == SM_F2F ) {
1475 /* Save the file's meta-info before we open it. Doing it later
1476 means we mess up the access times. */
1477 saveInputFileMetaInfo ( inName );
1480 switch ( srcMode ) {
1485 if ( isatty ( fileno ( stdin ) ) ) {
1487 "%s: I won't read compressed data from a terminal.\n",
1489 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1490 progName, progName );
1497 inStr = fopen ( inName, "rb" );
1499 if ( inStr == NULL ) {
1500 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
1501 progName, inName, strerror(errno) );
1502 if ( inStr != NULL ) fclose ( inStr );
1509 inStr = fopen ( inName, "rb" );
1510 outStr = fopen_output_safely ( outName, "wb" );
1511 if ( outStr == NULL) {
1512 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
1513 progName, outName, strerror(errno) );
1514 if ( inStr != NULL ) fclose ( inStr );
1518 if ( inStr == NULL ) {
1519 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1520 progName, inName, strerror(errno) );
1521 if ( outStr != NULL ) fclose ( outStr );
1528 panic ( "uncompress: bad srcMode" );
1532 if (verbosity >= 1) {
1533 fprintf ( stderr, " %s: ", inName );
1538 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1539 outputHandleJustInCase = outStr;
1540 deleteOutputOnInterrupt = True;
1541 magicNumberOK = uncompressStream ( inStr, outStr );
1542 outputHandleJustInCase = NULL;
1544 /*--- If there was an I/O error, we won't get here. ---*/
1545 if ( magicNumberOK ) {
1546 if ( srcMode == SM_F2F ) {
1547 applySavedMetaInfoToOutputFile ( outName );
1548 deleteOutputOnInterrupt = False;
1549 if ( !keepInputFiles ) {
1550 IntNative retVal = remove ( inName );
1551 ERROR_IF_NOT_ZERO ( retVal );
1555 unzFailsExist = True;
1556 deleteOutputOnInterrupt = False;
1557 if ( srcMode == SM_F2F ) {
1558 IntNative retVal = remove ( outName );
1559 ERROR_IF_NOT_ZERO ( retVal );
1562 deleteOutputOnInterrupt = False;
1564 if ( magicNumberOK ) {
1566 fprintf ( stderr, "done\n" );
1570 fprintf ( stderr, "not a bzip2 file.\n" ); else
1572 "%s: %s is not a bzip2 file.\n",
1579 /*---------------------------------------------*/
1581 void testf ( Char *name )
1585 struct MY_STAT statBuf;
1587 deleteOutputOnInterrupt = False;
1589 if (name == NULL && srcMode != SM_I2O)
1590 panic ( "testf: bad modes\n" );
1592 copyFileName ( outName, "(none)" );
1594 case SM_I2O: copyFileName ( inName, "(stdin)" ); break;
1595 case SM_F2F: copyFileName ( inName, name ); break;
1596 case SM_F2O: copyFileName ( inName, name ); break;
1599 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1601 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1606 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1607 fprintf ( stderr, "%s: Can't open input %s: %s.\n",
1608 progName, inName, strerror(errno) );
1612 if ( srcMode != SM_I2O ) {
1613 MY_STAT(inName, &statBuf);
1614 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1616 "%s: Input file %s is a directory.\n",
1623 switch ( srcMode ) {
1626 if ( isatty ( fileno ( stdin ) ) ) {
1628 "%s: I won't read compressed data from a terminal.\n",
1630 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1631 progName, progName );
1638 case SM_F2O: case SM_F2F:
1639 inStr = fopen ( inName, "rb" );
1640 if ( inStr == NULL ) {
1641 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
1642 progName, inName, strerror(errno) );
1649 panic ( "testf: bad srcMode" );
1653 if (verbosity >= 1) {
1654 fprintf ( stderr, " %s: ", inName );
1659 /*--- Now the input handle is sane. Do the Biz. ---*/
1660 outputHandleJustInCase = NULL;
1661 allOK = testStream ( inStr );
1663 if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
1664 if (!allOK) testFailsExist = True;
1668 /*---------------------------------------------*/
1670 void license ( void )
1674 "bzip2, a block-sorting file compressor. "
1677 " Copyright (C) 1996-2002 by Julian Seward.\n"
1679 " This program is free software; you can redistribute it and/or modify\n"
1680 " it under the terms set out in the LICENSE file, which is included\n"
1681 " in the bzip2-1.0 source distribution.\n"
1683 " This program is distributed in the hope that it will be useful,\n"
1684 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1685 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1686 " LICENSE file for more details.\n"
1693 /*---------------------------------------------*/
1695 void usage ( Char *fullProgName )
1699 "bzip2, a block-sorting file compressor. "
1701 "\n usage: %s [flags and input files in any order]\n"
1703 " -h --help print this message\n"
1704 " -d --decompress force decompression\n"
1705 " -z --compress force compression\n"
1706 " -k --keep keep (don't delete) input files\n"
1707 " -f --force overwrite existing output files\n"
1708 " -t --test test compressed file integrity\n"
1709 " -c --stdout output to standard out\n"
1710 " -q --quiet suppress noncritical error messages\n"
1711 " -v --verbose be verbose (a 2nd -v gives more)\n"
1712 " -L --license display software version & license\n"
1713 " -V --version display software version & license\n"
1714 " -s --small use less memory (at most 2500k)\n"
1715 " -1 .. -9 set block size to 100k .. 900k\n"
1716 " --fast alias for -1\n"
1717 " --best alias for -9\n"
1719 " If invoked as `bzip2', default action is to compress.\n"
1720 " as `bunzip2', default action is to decompress.\n"
1721 " as `bzcat', default action is to decompress to stdout.\n"
1723 " If no file names are given, bzip2 compresses or decompresses\n"
1724 " from standard input to standard output. You can combine\n"
1725 " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
1737 /*---------------------------------------------*/
1739 void redundant ( Char* flag )
1743 "%s: %s is redundant in versions 0.9.5 and above\n",
1748 /*---------------------------------------------*/
1750 All the garbage from here to main() is purely to
1751 implement a linked list of command-line arguments,
1752 into which main() copies argv[1 .. argc-1].
1754 The purpose of this exercise is to facilitate
1755 the expansion of wildcard characters * and ? in
1756 filenames for OSs which don't know how to do it
1757 themselves, like MSDOS, Windows 95 and NT.
1759 The actual Dirty Work is done by the platform-
1760 specific macro APPEND_FILESPEC.
1771 /*---------------------------------------------*/
1773 void *myMalloc ( Int32 n )
1777 p = malloc ( (size_t)n );
1778 if (p == NULL) outOfMemory ();
1783 /*---------------------------------------------*/
1785 Cell *mkCell ( void )
1789 c = (Cell*) myMalloc ( sizeof ( Cell ) );
1796 /*---------------------------------------------*/
1798 Cell *snocString ( Cell *root, Char *name )
1801 Cell *tmp = mkCell();
1802 tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
1803 strcpy ( tmp->name, name );
1807 while (tmp->link != NULL) tmp = tmp->link;
1808 tmp->link = snocString ( tmp->link, name );
1814 /*---------------------------------------------*/
1816 void addFlagsFromEnvVar ( Cell** argList, Char* varName )
1821 envbase = getenv(varName);
1822 if (envbase != NULL) {
1826 if (p[i] == 0) break;
1829 while (isspace((Int32)(p[0]))) p++;
1830 while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
1832 k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
1833 for (j = 0; j < k; j++) tmpName[j] = p[j];
1835 APPEND_FLAG(*argList, tmpName);
1842 /*---------------------------------------------*/
1843 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
1845 IntNative main ( IntNative argc, Char *argv[] )
1853 /*-- Be really really really paranoid :-) --*/
1854 if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 ||
1855 sizeof(Int16) != 2 || sizeof(UInt16) != 2 ||
1856 sizeof(Char) != 1 || sizeof(UChar) != 1)
1859 /*-- Initialise --*/
1860 outputHandleJustInCase = NULL;
1862 keepInputFiles = False;
1863 forceOverwrite = False;
1867 testFailsExist = False;
1868 unzFailsExist = False;
1870 numFilesProcessed = 0;
1872 deleteOutputOnInterrupt = False;
1874 i = j = 0; /* avoid bogus warning from egcs-1.1.X */
1876 /*-- Set up signal handlers for mem access errors --*/
1877 signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
1880 signal (SIGBUS, mySIGSEGVorSIGBUScatcher);
1884 copyFileName ( inName, "(none)" );
1885 copyFileName ( outName, "(none)" );
1887 copyFileName ( progNameReally, argv[0] );
1888 progName = &progNameReally[0];
1889 for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
1890 if (*tmp == PATH_SEP) progName = tmp + 1;
1893 /*-- Copy flags from env var BZIP2, and
1894 expand filename wildcards in arg list.
1897 addFlagsFromEnvVar ( &argList, "BZIP2" );
1898 addFlagsFromEnvVar ( &argList, "BZIP" );
1899 for (i = 1; i <= argc-1; i++)
1900 APPEND_FILESPEC(argList, argv[i]);
1903 /*-- Find the length of the longest filename --*/
1904 longestFileName = 7;
1907 for (aa = argList; aa != NULL; aa = aa->link) {
1908 if (ISFLAG("--")) { decode = False; continue; }
1909 if (aa->name[0] == '-' && decode) continue;
1911 if (longestFileName < (Int32)strlen(aa->name) )
1912 longestFileName = (Int32)strlen(aa->name);
1916 /*-- Determine source modes; flag handling may change this too. --*/
1917 if (numFileNames == 0)
1918 srcMode = SM_I2O; else srcMode = SM_F2F;
1921 /*-- Determine what to do (compress/uncompress/test/cat). --*/
1922 /*-- Note that subsequent flag handling may change this. --*/
1925 if ( (strstr ( progName, "unzip" ) != 0) ||
1926 (strstr ( progName, "UNZIP" ) != 0) )
1929 if ( (strstr ( progName, "z2cat" ) != 0) ||
1930 (strstr ( progName, "Z2CAT" ) != 0) ||
1931 (strstr ( progName, "zcat" ) != 0) ||
1932 (strstr ( progName, "ZCAT" ) != 0) ) {
1934 srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
1938 /*-- Look at the flags. --*/
1939 for (aa = argList; aa != NULL; aa = aa->link) {
1940 if (ISFLAG("--")) break;
1941 if (aa->name[0] == '-' && aa->name[1] != '-') {
1942 for (j = 1; aa->name[j] != '\0'; j++) {
1943 switch (aa->name[j]) {
1944 case 'c': srcMode = SM_F2O; break;
1945 case 'd': opMode = OM_UNZ; break;
1946 case 'z': opMode = OM_Z; break;
1947 case 'f': forceOverwrite = True; break;
1948 case 't': opMode = OM_TEST; break;
1949 case 'k': keepInputFiles = True; break;
1950 case 's': smallMode = True; break;
1951 case 'q': noisy = False; break;
1952 case '1': blockSize100k = 1; break;
1953 case '2': blockSize100k = 2; break;
1954 case '3': blockSize100k = 3; break;
1955 case '4': blockSize100k = 4; break;
1956 case '5': blockSize100k = 5; break;
1957 case '6': blockSize100k = 6; break;
1958 case '7': blockSize100k = 7; break;
1959 case '8': blockSize100k = 8; break;
1960 case '9': blockSize100k = 9; break;
1962 case 'L': license(); break;
1963 case 'v': verbosity++; break;
1964 case 'h': usage ( progName );
1967 default: fprintf ( stderr, "%s: Bad flag `%s'\n",
1968 progName, aa->name );
1977 /*-- And again ... --*/
1978 for (aa = argList; aa != NULL; aa = aa->link) {
1979 if (ISFLAG("--")) break;
1980 if (ISFLAG("--stdout")) srcMode = SM_F2O; else
1981 if (ISFLAG("--decompress")) opMode = OM_UNZ; else
1982 if (ISFLAG("--compress")) opMode = OM_Z; else
1983 if (ISFLAG("--force")) forceOverwrite = True; else
1984 if (ISFLAG("--test")) opMode = OM_TEST; else
1985 if (ISFLAG("--keep")) keepInputFiles = True; else
1986 if (ISFLAG("--small")) smallMode = True; else
1987 if (ISFLAG("--quiet")) noisy = False; else
1988 if (ISFLAG("--version")) license(); else
1989 if (ISFLAG("--license")) license(); else
1990 if (ISFLAG("--exponential")) workFactor = 1; else
1991 if (ISFLAG("--repetitive-best")) redundant(aa->name); else
1992 if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
1993 if (ISFLAG("--fast")) blockSize100k = 1; else
1994 if (ISFLAG("--best")) blockSize100k = 9; else
1995 if (ISFLAG("--verbose")) verbosity++; else
1996 if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); }
1998 if (strncmp ( aa->name, "--", 2) == 0) {
1999 fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
2005 if (verbosity > 4) verbosity = 4;
2006 if (opMode == OM_Z && smallMode && blockSize100k > 2)
2009 if (opMode == OM_TEST && srcMode == SM_F2O) {
2010 fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
2015 if (srcMode == SM_F2O && numFileNames == 0)
2018 if (opMode != OM_Z) blockSize100k = 0;
2020 if (srcMode == SM_F2F) {
2021 signal (SIGINT, mySignalCatcher);
2022 signal (SIGTERM, mySignalCatcher);
2024 signal (SIGHUP, mySignalCatcher);
2028 if (opMode == OM_Z) {
2029 if (srcMode == SM_I2O) {
2033 for (aa = argList; aa != NULL; aa = aa->link) {
2034 if (ISFLAG("--")) { decode = False; continue; }
2035 if (aa->name[0] == '-' && decode) continue;
2036 numFilesProcessed++;
2037 compress ( aa->name );
2043 if (opMode == OM_UNZ) {
2044 unzFailsExist = False;
2045 if (srcMode == SM_I2O) {
2046 uncompress ( NULL );
2049 for (aa = argList; aa != NULL; aa = aa->link) {
2050 if (ISFLAG("--")) { decode = False; continue; }
2051 if (aa->name[0] == '-' && decode) continue;
2052 numFilesProcessed++;
2053 uncompress ( aa->name );
2056 if (unzFailsExist) {
2063 testFailsExist = False;
2064 if (srcMode == SM_I2O) {
2068 for (aa = argList; aa != NULL; aa = aa->link) {
2069 if (ISFLAG("--")) { decode = False; continue; }
2070 if (aa->name[0] == '-' && decode) continue;
2071 numFilesProcessed++;
2075 if (testFailsExist && noisy) {
2078 "You can use the `bzip2recover' program to attempt to recover\n"
2079 "data from undamaged sections of corrupted files.\n\n"
2086 /* Free the argument list memory to mollify leak detectors
2087 (eg) Purify, Checker. Serves no other useful purpose.
2090 while (aa != NULL) {
2091 Cell* aa2 = aa->link;
2092 if (aa->name != NULL) free(aa->name);
2101 /*-----------------------------------------------------------*/
2102 /*--- end bzip2.c ---*/
2103 /*-----------------------------------------------------------*/