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.6 of 6 September 2010
11 Copyright (C) 1996-2010 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>
76 # define PATH_SEP '\\'
77 # define MY_LSTAT lstat
79 # define MY_S_ISREG S_ISREG
80 # define MY_S_ISDIR S_ISDIR
82 # define APPEND_FILESPEC(root, name) \
83 root=snocString((root), (name))
85 # define APPEND_FLAG(root, name) \
86 root=snocString((root), (name))
88 # define SET_BINARY_MODE(fd) /**/
91 # define NORETURN __attribute__ ((noreturn))
93 # define NORETURN /**/
96 # if defined(__DJGPP__) || defined(TARGET_MSDOS)
101 # define MY_LSTAT stat
102 # define MY_STAT stat
103 # undef SET_BINARY_MODE
104 # define SET_BINARY_MODE(fd) \
106 int retVal = setmode ( fileno ( fd ), \
108 ERROR_IF_MINUS_ONE ( retVal ); \
115 # undef SET_BINARY_MODE
116 # define SET_BINARY_MODE(fd) \
118 int retVal = setmode ( fileno ( fd ), \
120 ERROR_IF_MINUS_ONE ( retVal ); \
130 # include <sys\stat.h>
132 # define NORETURN /**/
133 # define PATH_SEP '\\'
134 # define MY_LSTAT _stat
135 # define MY_STAT _stat
136 # define MY_S_ISREG(x) ((x) & _S_IFREG)
137 # define MY_S_ISDIR(x) ((x) & _S_IFDIR)
139 # define APPEND_FLAG(root, name) \
140 root=snocString((root), (name))
142 # define APPEND_FILESPEC(root, name) \
143 root = snocString ((root), (name))
145 # define SET_BINARY_MODE(fd) \
147 int retVal = setmode ( fileno ( fd ), \
149 ERROR_IF_MINUS_ONE ( retVal ); \
152 #endif /* BZ_LCCWIN32 */
155 /*---------------------------------------------*/
157 Some more stuff for all platforms :-)
161 typedef unsigned char Bool;
162 typedef unsigned char UChar;
164 typedef unsigned int UInt32;
166 typedef unsigned short UInt16;
168 #define True ((Bool)1)
169 #define False ((Bool)0)
172 IntNative is your platform's `native' int size.
173 Only here to avoid probs with 64-bit platforms.
175 typedef int IntNative;
178 /*---------------------------------------------------*/
179 /*--- Misc (file handling) data decls ---*/
180 /*---------------------------------------------------*/
183 Bool keepInputFiles, smallMode, deleteOutputOnInterrupt;
184 Bool forceOverwrite, testFailsExist, unzFailsExist, noisy;
185 Int32 numFileNames, numFilesProcessed, blockSize100k;
188 /*-- source modes; F==file, I==stdin, O==stdout --*/
193 /*-- operation modes --*/
201 #define FILE_NAME_LEN 1034
203 Int32 longestFileName;
204 Char inName [FILE_NAME_LEN];
205 Char outName[FILE_NAME_LEN];
206 Char tmpName[FILE_NAME_LEN];
208 Char progNameReally[FILE_NAME_LEN];
209 FILE *outputHandleJustInCase;
212 static void panic ( const Char* ) NORETURN;
213 static void ioError ( void ) NORETURN;
214 static void outOfMemory ( void ) NORETURN;
215 static void configError ( void ) NORETURN;
216 static void crcError ( void ) NORETURN;
217 static void cleanUpAndFail ( Int32 ) NORETURN;
218 static void compressedStreamEOF ( void ) NORETURN;
220 static void copyFileName ( Char*, Char* );
221 static void* myMalloc ( Int32 );
222 static void applySavedFileAttrToOutputFile ( IntNative fd );
226 /*---------------------------------------------------*/
227 /*--- An implementation of 64-bit ints. Sigh. ---*/
228 /*--- Roll on widespread deployment of ANSI C9X ! ---*/
229 /*---------------------------------------------------*/
232 struct { UChar b[8]; }
237 void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
239 n->b[7] = (UChar)((hi32 >> 24) & 0xFF);
240 n->b[6] = (UChar)((hi32 >> 16) & 0xFF);
241 n->b[5] = (UChar)((hi32 >> 8) & 0xFF);
242 n->b[4] = (UChar) (hi32 & 0xFF);
243 n->b[3] = (UChar)((lo32 >> 24) & 0xFF);
244 n->b[2] = (UChar)((lo32 >> 16) & 0xFF);
245 n->b[1] = (UChar)((lo32 >> 8) & 0xFF);
246 n->b[0] = (UChar) (lo32 & 0xFF);
251 double uInt64_to_double ( UInt64* n )
256 for (i = 0; i < 8; i++) {
257 sum += base * (double)(n->b[i]);
265 Bool uInt64_isZero ( UInt64* n )
268 for (i = 0; i < 8; i++)
269 if (n->b[i] != 0) return 0;
274 /* Divide *n by 10, and return the remainder. */
276 Int32 uInt64_qrm10 ( UInt64* n )
281 for (i = 7; i >= 0; i--) {
282 tmp = rem * 256 + n->b[i];
290 /* ... and the Whole Entire Point of all this UInt64 stuff is
291 so that we can supply the following function.
294 void uInt64_toAscii ( char* outbuf, UInt64* n )
301 q = uInt64_qrm10 ( &n_copy );
304 } while (!uInt64_isZero(&n_copy));
306 for (i = 0; i < nBuf; i++)
307 outbuf[i] = buf[nBuf-i-1];
311 /*---------------------------------------------------*/
312 /*--- Processing of complete files and streams ---*/
313 /*---------------------------------------------------*/
315 /*---------------------------------------------*/
317 Bool myfeof ( FILE* f )
319 Int32 c = fgetc ( f );
320 if (c == EOF) return True;
326 /*---------------------------------------------*/
328 void compressStream ( FILE *stream, FILE *zStream )
333 UInt32 nbytes_in_lo32, nbytes_in_hi32;
334 UInt32 nbytes_out_lo32, nbytes_out_hi32;
335 Int32 bzerr, bzerr_dummy, ret;
337 SET_BINARY_MODE(stream);
338 SET_BINARY_MODE(zStream);
340 if (ferror(stream)) goto errhandler_io;
341 if (ferror(zStream)) goto errhandler_io;
343 bzf = BZ2_bzWriteOpen ( &bzerr, zStream,
344 blockSize100k, verbosity, workFactor );
345 if (bzerr != BZ_OK) goto errhandler;
347 if (verbosity >= 2) fprintf ( stderr, "\n" );
351 if (myfeof(stream)) break;
352 nIbuf = fread ( ibuf, sizeof(UChar), 5000, stream );
353 if (ferror(stream)) goto errhandler_io;
354 if (nIbuf > 0) BZ2_bzWrite ( &bzerr, bzf, (void*)ibuf, nIbuf );
355 if (bzerr != BZ_OK) goto errhandler;
359 BZ2_bzWriteClose64 ( &bzerr, bzf, 0,
360 &nbytes_in_lo32, &nbytes_in_hi32,
361 &nbytes_out_lo32, &nbytes_out_hi32 );
362 if (bzerr != BZ_OK) goto errhandler;
364 if (ferror(zStream)) goto errhandler_io;
365 ret = fflush ( zStream );
366 if (ret == EOF) goto errhandler_io;
367 if (zStream != stdout) {
368 Int32 fd = fileno ( zStream );
369 if (fd < 0) goto errhandler_io;
370 applySavedFileAttrToOutputFile ( fd );
371 ret = fclose ( zStream );
372 outputHandleJustInCase = NULL;
373 if (ret == EOF) goto errhandler_io;
375 outputHandleJustInCase = NULL;
376 if (ferror(stream)) goto errhandler_io;
377 ret = fclose ( stream );
378 if (ret == EOF) goto errhandler_io;
380 if (verbosity >= 1) {
381 if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
382 fprintf ( stderr, " no data compressed.\n");
384 Char buf_nin[32], buf_nout[32];
385 UInt64 nbytes_in, nbytes_out;
386 double nbytes_in_d, nbytes_out_d;
387 uInt64_from_UInt32s ( &nbytes_in,
388 nbytes_in_lo32, nbytes_in_hi32 );
389 uInt64_from_UInt32s ( &nbytes_out,
390 nbytes_out_lo32, nbytes_out_hi32 );
391 nbytes_in_d = uInt64_to_double ( &nbytes_in );
392 nbytes_out_d = uInt64_to_double ( &nbytes_out );
393 uInt64_toAscii ( buf_nin, &nbytes_in );
394 uInt64_toAscii ( buf_nout, &nbytes_out );
395 fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
396 "%5.2f%% saved, %s in, %s out.\n",
397 nbytes_in_d / nbytes_out_d,
398 (8.0 * nbytes_out_d) / nbytes_in_d,
399 100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
409 BZ2_bzWriteClose64 ( &bzerr_dummy, bzf, 1,
410 &nbytes_in_lo32, &nbytes_in_hi32,
411 &nbytes_out_lo32, &nbytes_out_hi32 );
413 case BZ_CONFIG_ERROR:
414 configError(); break;
416 outOfMemory (); break;
421 panic ( "compress:unexpected error" );
424 panic ( "compress:end" );
430 /*---------------------------------------------*/
432 Bool uncompressStream ( FILE *zStream, FILE *stream )
435 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
437 UChar unused[BZ_MAX_UNUSED];
445 SET_BINARY_MODE(stream);
446 SET_BINARY_MODE(zStream);
448 if (ferror(stream)) goto errhandler_io;
449 if (ferror(zStream)) goto errhandler_io;
453 bzf = BZ2_bzReadOpen (
454 &bzerr, zStream, verbosity,
455 (int)smallMode, unused, nUnused
457 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
460 while (bzerr == BZ_OK) {
461 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
462 if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
463 if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
464 fwrite ( obuf, sizeof(UChar), nread, stream );
465 if (ferror(stream)) goto errhandler_io;
467 if (bzerr != BZ_STREAM_END) goto errhandler;
469 BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
470 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
472 unusedTmp = (UChar*)unusedTmpV;
473 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
475 BZ2_bzReadClose ( &bzerr, bzf );
476 if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
478 if (nUnused == 0 && myfeof(zStream)) break;
482 if (ferror(zStream)) goto errhandler_io;
483 if (stream != stdout) {
484 Int32 fd = fileno ( stream );
485 if (fd < 0) goto errhandler_io;
486 applySavedFileAttrToOutputFile ( fd );
488 ret = fclose ( zStream );
489 if (ret == EOF) goto errhandler_io;
491 if (ferror(stream)) goto errhandler_io;
492 ret = fflush ( stream );
493 if (ret != 0) goto errhandler_io;
494 if (stream != stdout) {
495 ret = fclose ( stream );
496 outputHandleJustInCase = NULL;
497 if (ret == EOF) goto errhandler_io;
499 outputHandleJustInCase = NULL;
500 if (verbosity >= 2) fprintf ( stderr, "\n " );
504 if (forceOverwrite) {
507 if (myfeof(zStream)) break;
508 nread = fread ( obuf, sizeof(UChar), 5000, zStream );
509 if (ferror(zStream)) goto errhandler_io;
510 if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
511 if (ferror(stream)) goto errhandler_io;
517 BZ2_bzReadClose ( &bzerr_dummy, bzf );
519 case BZ_CONFIG_ERROR:
520 configError(); break;
528 case BZ_UNEXPECTED_EOF:
529 compressedStreamEOF();
530 case BZ_DATA_ERROR_MAGIC:
531 if (zStream != stdin) fclose(zStream);
532 if (stream != stdout) fclose(stream);
538 "\n%s: %s: trailing garbage after EOF ignored\n",
543 panic ( "decompress:unexpected error" );
546 panic ( "decompress:end" );
547 return True; /*notreached*/
551 /*---------------------------------------------*/
553 Bool testStream ( FILE *zStream )
556 Int32 bzerr, bzerr_dummy, ret, nread, streamNo, i;
558 UChar unused[BZ_MAX_UNUSED];
566 SET_BINARY_MODE(zStream);
567 if (ferror(zStream)) goto errhandler_io;
571 bzf = BZ2_bzReadOpen (
572 &bzerr, zStream, verbosity,
573 (int)smallMode, unused, nUnused
575 if (bzf == NULL || bzerr != BZ_OK) goto errhandler;
578 while (bzerr == BZ_OK) {
579 nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
580 if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
582 if (bzerr != BZ_STREAM_END) goto errhandler;
584 BZ2_bzReadGetUnused ( &bzerr, bzf, &unusedTmpV, &nUnused );
585 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
587 unusedTmp = (UChar*)unusedTmpV;
588 for (i = 0; i < nUnused; i++) unused[i] = unusedTmp[i];
590 BZ2_bzReadClose ( &bzerr, bzf );
591 if (bzerr != BZ_OK) panic ( "test:bzReadGetUnused" );
592 if (nUnused == 0 && myfeof(zStream)) break;
596 if (ferror(zStream)) goto errhandler_io;
597 ret = fclose ( zStream );
598 if (ret == EOF) goto errhandler_io;
600 if (verbosity >= 2) fprintf ( stderr, "\n " );
604 BZ2_bzReadClose ( &bzerr_dummy, bzf );
606 fprintf ( stderr, "%s: %s: ", progName, inName );
608 case BZ_CONFIG_ERROR:
609 configError(); break;
615 "data integrity (CRC) error in data\n" );
619 case BZ_UNEXPECTED_EOF:
621 "file ends unexpectedly\n" );
623 case BZ_DATA_ERROR_MAGIC:
624 if (zStream != stdin) fclose(zStream);
627 "bad magic number (file not created by bzip2)\n" );
632 "trailing garbage after EOF ignored\n" );
636 panic ( "test:unexpected error" );
639 panic ( "test:end" );
640 return True; /*notreached*/
644 /*---------------------------------------------------*/
645 /*--- Error [non-] handling grunge ---*/
646 /*---------------------------------------------------*/
648 /*---------------------------------------------*/
650 void setExit ( Int32 v )
652 if (v > exitValue) exitValue = v;
656 /*---------------------------------------------*/
658 void cadvise ( void )
663 "\nIt is possible that the compressed file(s) have become corrupted.\n"
664 "You can use the -tvv option to test integrity of such files.\n\n"
665 "You can use the `bzip2recover' program to attempt to recover\n"
666 "data from undamaged sections of corrupted files.\n\n"
671 /*---------------------------------------------*/
673 void showFileNames ( void )
678 "\tInput file = %s, output file = %s\n",
684 /*---------------------------------------------*/
686 void cleanUpAndFail ( Int32 ec )
689 struct MY_STAT statBuf;
691 if ( srcMode == SM_F2F
693 && deleteOutputOnInterrupt ) {
695 /* Check whether input file still exists. Delete output file
696 only if input exists to avoid loss of data. Joerg Prante, 5
697 January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean
698 this is less likely to happen. But to be ultra-paranoid, we
699 do the check anyway.) */
700 retVal = MY_STAT ( inName, &statBuf );
704 "%s: Deleting output file %s, if it exists.\n",
706 if (outputHandleJustInCase != NULL)
707 fclose ( outputHandleJustInCase );
708 retVal = remove ( outName );
711 "%s: WARNING: deletion of output file "
712 "(apparently) failed.\n",
716 "%s: WARNING: deletion of output file suppressed\n",
719 "%s: since input file no longer exists. Output file\n",
722 "%s: `%s' may be incomplete.\n",
725 "%s: I suggest doing an integrity test (bzip2 -tv)"
731 if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
733 "%s: WARNING: some files have not been processed:\n"
734 "%s: %d specified on command line, %d not processed yet.\n\n",
736 numFileNames, numFileNames - numFilesProcessed );
743 /*---------------------------------------------*/
745 void panic ( const Char* s )
748 "\n%s: PANIC -- internal consistency error:\n"
750 "\tThis is a BUG. Please report it to me at:\n"
751 "\tjseward@bzip.org\n",
758 /*---------------------------------------------*/
760 void crcError ( void )
763 "\n%s: Data integrity error when decompressing.\n",
771 /*---------------------------------------------*/
773 void compressedStreamEOF ( void )
777 "\n%s: Compressed file ends unexpectedly;\n\t"
778 "perhaps it is corrupted? *Possible* reason follows.\n",
788 /*---------------------------------------------*/
790 void ioError ( void )
793 "\n%s: I/O or other error, bailing out. "
794 "Possible reason follows.\n",
802 /*---------------------------------------------*/
804 void mySignalCatcher ( IntNative n )
807 "\n%s: Control-C or similar caught, quitting.\n",
813 /*---------------------------------------------*/
815 void mySIGSEGVorSIGBUScatcher ( IntNative n )
820 "\n%s: Caught a SIGSEGV or SIGBUS whilst compressing.\n"
822 " Possible causes are (most likely first):\n"
823 " (1) This computer has unreliable memory or cache hardware\n"
824 " (a surprisingly common problem; try a different machine.)\n"
825 " (2) A bug in the compiler used to create this executable\n"
826 " (unlikely, if you didn't compile bzip2 yourself.)\n"
827 " (3) A real bug in bzip2 -- I hope this should never be the case.\n"
828 " The user's manual, Section 4.3, has more info on (1) and (2).\n"
830 " If you suspect this is a bug in bzip2, or are unsure about (1)\n"
831 " or (2), feel free to report it to me at: jseward@bzip.org.\n"
832 " Section 4.3 of the user's manual describes the info a useful\n"
833 " bug report should have. If the manual is available on your\n"
834 " system, please try and read it before mailing me. If you don't\n"
835 " have the manual or can't be bothered to read it, mail me anyway.\n"
841 "\n%s: Caught a SIGSEGV or SIGBUS whilst decompressing.\n"
843 " Possible causes are (most likely first):\n"
844 " (1) The compressed data is corrupted, and bzip2's usual checks\n"
845 " failed to detect this. Try bzip2 -tvv my_file.bz2.\n"
846 " (2) This computer has unreliable memory or cache hardware\n"
847 " (a surprisingly common problem; try a different machine.)\n"
848 " (3) A bug in the compiler used to create this executable\n"
849 " (unlikely, if you didn't compile bzip2 yourself.)\n"
850 " (4) A real bug in bzip2 -- I hope this should never be the case.\n"
851 " The user's manual, Section 4.3, has more info on (2) and (3).\n"
853 " If you suspect this is a bug in bzip2, or are unsure about (2)\n"
854 " or (3), feel free to report it to me at: jseward@bzip.org.\n"
855 " Section 4.3 of the user's manual describes the info a useful\n"
856 " bug report should have. If the manual is available on your\n"
857 " system, please try and read it before mailing me. If you don't\n"
858 " have the manual or can't be bothered to read it, mail me anyway.\n"
864 cleanUpAndFail( 3 ); else
865 { cadvise(); cleanUpAndFail( 2 ); }
869 /*---------------------------------------------*/
871 void outOfMemory ( void )
874 "\n%s: couldn't allocate enough memory\n",
881 /*---------------------------------------------*/
883 void configError ( void )
886 "bzip2: I'm not configured correctly for this platform!\n"
887 "\tI require Int32, Int16 and Char to have sizes\n"
888 "\tof 4, 2 and 1 bytes to run properly, and they don't.\n"
889 "\tProbably you can fix this by defining them correctly,\n"
890 "\tand recompiling. Bye!\n" );
896 /*---------------------------------------------------*/
897 /*--- The main driver machinery ---*/
898 /*---------------------------------------------------*/
900 /* All rather crufty. The main problem is that input files
901 are stat()d multiple times before use. This should be
905 /*---------------------------------------------*/
910 if ( (Int32)strlen(s) >= longestFileName ) return;
911 for (i = 1; i <= longestFileName - (Int32)strlen(s); i++)
912 fprintf ( stderr, " " );
916 /*---------------------------------------------*/
918 void copyFileName ( Char* to, Char* from )
920 if ( strlen(from) > FILE_NAME_LEN-10 ) {
923 "bzip2: file name\n`%s'\n"
924 "is suspiciously (more than %d chars) long.\n"
925 "Try using a reasonable file name instead. Sorry! :-)\n",
926 from, FILE_NAME_LEN-10
932 strncpy(to,from,FILE_NAME_LEN-10);
933 to[FILE_NAME_LEN-10]='\0';
937 /*---------------------------------------------*/
939 Bool fileExists ( Char* name )
941 FILE *tmp = fopen ( name, "rb" );
942 Bool exists = (tmp != NULL);
943 if (tmp != NULL) fclose ( tmp );
948 /*---------------------------------------------*/
949 /* Open an output file safely with O_EXCL and good permissions.
950 This avoids a race condition in versions < 1.0.2, in which
951 the file was first opened and then had its interim permissions
952 set safely. We instead use open() to create the file with
953 the interim permissions required. (--- --- rw-).
955 For non-Unix platforms, if we are not worrying about
956 security issues, simple this simply behaves like fopen.
959 FILE* fopen_output_safely ( Char* name, const char* mode )
964 fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
965 if (fh == -1) return NULL;
966 fp = fdopen(fh, mode);
967 if (fp == NULL) close(fh);
970 return fopen(name, mode);
975 /*---------------------------------------------*/
977 if in doubt, return True
980 Bool notAStandardFile ( Char* name )
983 struct MY_STAT statBuf;
985 i = MY_LSTAT ( name, &statBuf );
986 if (i != 0) return True;
987 if (MY_S_ISREG(statBuf.st_mode)) return False;
992 /*---------------------------------------------*/
994 rac 11/21/98 see if file has hard links to it
997 Int32 countHardLinks ( Char* name )
1000 struct MY_STAT statBuf;
1002 i = MY_LSTAT ( name, &statBuf );
1003 if (i != 0) return 0;
1004 return (statBuf.st_nlink - 1);
1008 /*---------------------------------------------*/
1009 /* Copy modification date, access date, permissions and owner from the
1010 source to destination file. We have to copy this meta-info off
1011 into fileMetaInfo before starting to compress / decompress it,
1012 because doing it afterwards means we get the wrong access time.
1014 To complicate matters, in compress() and decompress() below, the
1015 sequence of tests preceding the call to saveInputFileMetaInfo()
1016 involves calling fileExists(), which in turn establishes its result
1017 by attempting to fopen() the file, and if successful, immediately
1018 fclose()ing it again. So we have to assume that the fopen() call
1019 does not cause the access time field to be updated.
1021 Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
1022 to imply that merely doing open() will not affect the access time.
1023 Therefore we merely need to hope that the C library only does
1024 open() as a result of fopen(), and not any kind of read()-ahead
1027 It sounds pretty fragile to me. Whether this carries across
1028 robustly to arbitrary Unix-like platforms (or even works robustly
1029 on this one, RedHat 7.2) is unknown to me. Nevertheless ...
1033 struct MY_STAT fileMetaInfo;
1037 void saveInputFileMetaInfo ( Char *srcName )
1041 /* Note use of stat here, not lstat. */
1042 retVal = MY_STAT( srcName, &fileMetaInfo );
1043 ERROR_IF_NOT_ZERO ( retVal );
1049 void applySavedTimeInfoToOutputFile ( Char *dstName )
1053 struct utimbuf uTimBuf;
1055 uTimBuf.actime = fileMetaInfo.st_atime;
1056 uTimBuf.modtime = fileMetaInfo.st_mtime;
1058 retVal = utime ( dstName, &uTimBuf );
1059 ERROR_IF_NOT_ZERO ( retVal );
1064 void applySavedFileAttrToOutputFile ( IntNative fd )
1069 /*---------------------------------------------*/
1071 Bool containsDubiousChars ( Char* name )
1074 /* On unix, files can contain any characters and the file expansion
1075 * is performed by the shell.
1078 # else /* ! BZ_UNIX */
1079 /* On non-unix (Win* platforms), wildcard characters are not allowed in
1082 for (; *name != '\0'; name++)
1083 if (*name == '?' || *name == '*') return True;
1085 # endif /* BZ_UNIX */
1089 /*---------------------------------------------*/
1090 #define BZ_N_SUFFIX_PAIRS 4
1092 const Char* zSuffix[BZ_N_SUFFIX_PAIRS]
1093 = { ".bz2", ".bz", ".tbz2", ".tbz" };
1094 const Char* unzSuffix[BZ_N_SUFFIX_PAIRS]
1095 = { "", "", ".tar", ".tar" };
1098 Bool hasSuffix ( Char* s, const Char* suffix )
1100 Int32 ns = strlen(s);
1101 Int32 nx = strlen(suffix);
1102 if (ns < nx) return False;
1103 if (strcmp(s + ns - nx, suffix) == 0) return True;
1108 Bool mapSuffix ( Char* name,
1109 const Char* oldSuffix,
1110 const Char* newSuffix )
1112 if (!hasSuffix(name,oldSuffix)) return False;
1113 name[strlen(name)-strlen(oldSuffix)] = 0;
1114 strcat ( name, newSuffix );
1119 /*---------------------------------------------*/
1121 void compress ( Char *name )
1126 struct MY_STAT statBuf;
1128 deleteOutputOnInterrupt = False;
1130 if (name == NULL && srcMode != SM_I2O)
1131 panic ( "compress: bad modes\n" );
1135 copyFileName ( inName, (Char*)"(stdin)" );
1136 copyFileName ( outName, (Char*)"(stdout)" );
1139 copyFileName ( inName, name );
1140 copyFileName ( outName, name );
1141 strcat ( outName, ".bz2" );
1144 copyFileName ( inName, name );
1145 copyFileName ( outName, (Char*)"(stdout)" );
1149 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1151 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1156 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1157 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1158 progName, inName, strerror(errno) );
1162 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++) {
1163 if (hasSuffix(inName, zSuffix[i])) {
1166 "%s: Input file %s already has %s suffix.\n",
1167 progName, inName, zSuffix[i] );
1172 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
1173 MY_STAT(inName, &statBuf);
1174 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1176 "%s: Input file %s is a directory.\n",
1182 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
1184 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
1189 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
1190 if (forceOverwrite) {
1193 fprintf ( stderr, "%s: Output file %s already exists.\n",
1194 progName, outName );
1199 if ( srcMode == SM_F2F && !forceOverwrite &&
1200 (n=countHardLinks ( inName )) > 0) {
1201 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
1202 progName, inName, n, n > 1 ? "s" : "" );
1207 if ( srcMode == SM_F2F ) {
1208 /* Save the file's meta-info before we open it. Doing it later
1209 means we mess up the access times. */
1210 saveInputFileMetaInfo ( inName );
1213 switch ( srcMode ) {
1218 if ( isatty ( fileno ( stdout ) ) ) {
1220 "%s: I won't write compressed data to a terminal.\n",
1222 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1223 progName, progName );
1230 inStr = fopen ( inName, "rb" );
1232 if ( isatty ( fileno ( stdout ) ) ) {
1234 "%s: I won't write compressed data to a terminal.\n",
1236 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1237 progName, progName );
1238 if ( inStr != NULL ) fclose ( inStr );
1242 if ( inStr == NULL ) {
1243 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1244 progName, inName, strerror(errno) );
1251 inStr = fopen ( inName, "rb" );
1252 outStr = fopen_output_safely ( outName, "wb" );
1253 if ( outStr == NULL) {
1254 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
1255 progName, outName, strerror(errno) );
1256 if ( inStr != NULL ) fclose ( inStr );
1260 if ( inStr == NULL ) {
1261 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1262 progName, inName, strerror(errno) );
1263 if ( outStr != NULL ) fclose ( outStr );
1270 panic ( "compress: bad srcMode" );
1274 if (verbosity >= 1) {
1275 fprintf ( stderr, " %s: ", inName );
1280 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1281 outputHandleJustInCase = outStr;
1282 deleteOutputOnInterrupt = True;
1283 compressStream ( inStr, outStr );
1284 outputHandleJustInCase = NULL;
1286 /*--- If there was an I/O error, we won't get here. ---*/
1287 if ( srcMode == SM_F2F ) {
1288 applySavedTimeInfoToOutputFile ( outName );
1289 deleteOutputOnInterrupt = False;
1290 if ( !keepInputFiles ) {
1291 IntNative retVal = remove ( inName );
1292 ERROR_IF_NOT_ZERO ( retVal );
1296 deleteOutputOnInterrupt = False;
1300 /*---------------------------------------------*/
1302 void uncompress ( Char *name )
1309 struct MY_STAT statBuf;
1311 deleteOutputOnInterrupt = False;
1313 if (name == NULL && srcMode != SM_I2O)
1314 panic ( "uncompress: bad modes\n" );
1319 copyFileName ( inName, (Char*)"(stdin)" );
1320 copyFileName ( outName, (Char*)"(stdout)" );
1323 copyFileName ( inName, name );
1324 copyFileName ( outName, name );
1325 for (i = 0; i < BZ_N_SUFFIX_PAIRS; i++)
1326 if (mapSuffix(outName,zSuffix[i],unzSuffix[i]))
1329 strcat ( outName, ".out" );
1332 copyFileName ( inName, name );
1333 copyFileName ( outName, (Char*)"(stdout)" );
1338 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1340 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1345 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1346 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1347 progName, inName, strerror(errno) );
1351 if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
1352 MY_STAT(inName, &statBuf);
1353 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1355 "%s: Input file %s is a directory.\n",
1361 if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
1363 fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
1368 if ( /* srcMode == SM_F2F implied && */ cantGuess ) {
1371 "%s: Can't guess original name for %s -- using %s\n",
1372 progName, inName, outName );
1373 /* just a warning, no return */
1375 if ( srcMode == SM_F2F && fileExists ( outName ) ) {
1376 if (forceOverwrite) {
1379 fprintf ( stderr, "%s: Output file %s already exists.\n",
1380 progName, outName );
1385 if ( srcMode == SM_F2F && !forceOverwrite &&
1386 (n=countHardLinks ( inName ) ) > 0) {
1387 fprintf ( stderr, "%s: Input file %s has %d other link%s.\n",
1388 progName, inName, n, n > 1 ? "s" : "" );
1393 if ( srcMode == SM_F2F ) {
1394 /* Save the file's meta-info before we open it. Doing it later
1395 means we mess up the access times. */
1396 saveInputFileMetaInfo ( inName );
1399 switch ( srcMode ) {
1404 if ( isatty ( fileno ( stdin ) ) ) {
1406 "%s: I won't read compressed data from a terminal.\n",
1408 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1409 progName, progName );
1416 inStr = fopen ( inName, "rb" );
1418 if ( inStr == NULL ) {
1419 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
1420 progName, inName, strerror(errno) );
1421 if ( inStr != NULL ) fclose ( inStr );
1428 inStr = fopen ( inName, "rb" );
1429 outStr = fopen_output_safely ( outName, "wb" );
1430 if ( outStr == NULL) {
1431 fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
1432 progName, outName, strerror(errno) );
1433 if ( inStr != NULL ) fclose ( inStr );
1437 if ( inStr == NULL ) {
1438 fprintf ( stderr, "%s: Can't open input file %s: %s.\n",
1439 progName, inName, strerror(errno) );
1440 if ( outStr != NULL ) fclose ( outStr );
1447 panic ( "uncompress: bad srcMode" );
1451 if (verbosity >= 1) {
1452 fprintf ( stderr, " %s: ", inName );
1457 /*--- Now the input and output handles are sane. Do the Biz. ---*/
1458 outputHandleJustInCase = outStr;
1459 deleteOutputOnInterrupt = True;
1460 magicNumberOK = uncompressStream ( inStr, outStr );
1461 outputHandleJustInCase = NULL;
1463 /*--- If there was an I/O error, we won't get here. ---*/
1464 if ( magicNumberOK ) {
1465 if ( srcMode == SM_F2F ) {
1466 applySavedTimeInfoToOutputFile ( outName );
1467 deleteOutputOnInterrupt = False;
1468 if ( !keepInputFiles ) {
1469 IntNative retVal = remove ( inName );
1470 ERROR_IF_NOT_ZERO ( retVal );
1474 unzFailsExist = True;
1475 deleteOutputOnInterrupt = False;
1476 if ( srcMode == SM_F2F ) {
1477 IntNative retVal = remove ( outName );
1478 ERROR_IF_NOT_ZERO ( retVal );
1481 deleteOutputOnInterrupt = False;
1483 if ( magicNumberOK ) {
1485 fprintf ( stderr, "done\n" );
1489 fprintf ( stderr, "not a bzip2 file.\n" ); else
1491 "%s: %s is not a bzip2 file.\n",
1498 /*---------------------------------------------*/
1500 void testf ( Char *name )
1504 struct MY_STAT statBuf;
1506 deleteOutputOnInterrupt = False;
1508 if (name == NULL && srcMode != SM_I2O)
1509 panic ( "testf: bad modes\n" );
1511 copyFileName ( outName, (Char*)"(none)" );
1513 case SM_I2O: copyFileName ( inName, (Char*)"(stdin)" ); break;
1514 case SM_F2F: copyFileName ( inName, name ); break;
1515 case SM_F2O: copyFileName ( inName, name ); break;
1518 if ( srcMode != SM_I2O && containsDubiousChars ( inName ) ) {
1520 fprintf ( stderr, "%s: There are no files matching `%s'.\n",
1525 if ( srcMode != SM_I2O && !fileExists ( inName ) ) {
1526 fprintf ( stderr, "%s: Can't open input %s: %s.\n",
1527 progName, inName, strerror(errno) );
1531 if ( srcMode != SM_I2O ) {
1532 MY_STAT(inName, &statBuf);
1533 if ( MY_S_ISDIR(statBuf.st_mode) ) {
1535 "%s: Input file %s is a directory.\n",
1542 switch ( srcMode ) {
1545 if ( isatty ( fileno ( stdin ) ) ) {
1547 "%s: I won't read compressed data from a terminal.\n",
1549 fprintf ( stderr, "%s: For help, type: `%s --help'.\n",
1550 progName, progName );
1557 case SM_F2O: case SM_F2F:
1558 inStr = fopen ( inName, "rb" );
1559 if ( inStr == NULL ) {
1560 fprintf ( stderr, "%s: Can't open input file %s:%s.\n",
1561 progName, inName, strerror(errno) );
1568 panic ( "testf: bad srcMode" );
1572 if (verbosity >= 1) {
1573 fprintf ( stderr, " %s: ", inName );
1578 /*--- Now the input handle is sane. Do the Biz. ---*/
1579 outputHandleJustInCase = NULL;
1580 allOK = testStream ( inStr );
1582 if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
1583 if (!allOK) testFailsExist = True;
1587 /*---------------------------------------------*/
1589 void license ( void )
1593 "bzip2, a block-sorting file compressor. "
1596 " Copyright (C) 1996-2010 by Julian Seward.\n"
1598 " This program is free software; you can redistribute it and/or modify\n"
1599 " it under the terms set out in the LICENSE file, which is included\n"
1600 " in the bzip2-1.0.6 source distribution.\n"
1602 " This program is distributed in the hope that it will be useful,\n"
1603 " but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1604 " MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1605 " LICENSE file for more details.\n"
1612 /*---------------------------------------------*/
1614 void usage ( Char *fullProgName )
1618 "bzip2, a block-sorting file compressor. "
1620 "\n usage: %s [flags and input files in any order]\n"
1622 " -h --help print this message\n"
1623 " -d --decompress force decompression\n"
1624 " -z --compress force compression\n"
1625 " -k --keep keep (don't delete) input files\n"
1626 " -f --force overwrite existing output files\n"
1627 " -t --test test compressed file integrity\n"
1628 " -c --stdout output to standard out\n"
1629 " -q --quiet suppress noncritical error messages\n"
1630 " -v --verbose be verbose (a 2nd -v gives more)\n"
1631 " -L --license display software version & license\n"
1632 " -V --version display software version & license\n"
1633 " -s --small use less memory (at most 2500k)\n"
1634 " -1 .. -9 set block size to 100k .. 900k\n"
1635 " --fast alias for -1\n"
1636 " --best alias for -9\n"
1638 " If invoked as `bzip2', default action is to compress.\n"
1639 " as `bunzip2', default action is to decompress.\n"
1640 " as `bzcat', default action is to decompress to stdout.\n"
1642 " If no file names are given, bzip2 compresses or decompresses\n"
1643 " from standard input to standard output. You can combine\n"
1644 " short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
1656 /*---------------------------------------------*/
1658 void redundant ( Char* flag )
1662 "%s: %s is redundant in versions 0.9.5 and above\n",
1667 /*---------------------------------------------*/
1669 All the garbage from here to main() is purely to
1670 implement a linked list of command-line arguments,
1671 into which main() copies argv[1 .. argc-1].
1673 The purpose of this exercise is to facilitate
1674 the expansion of wildcard characters * and ? in
1675 filenames for OSs which don't know how to do it
1676 themselves, like MSDOS, Windows 95 and NT.
1678 The actual Dirty Work is done by the platform-
1679 specific macro APPEND_FILESPEC.
1690 /*---------------------------------------------*/
1692 void *myMalloc ( Int32 n )
1696 p = malloc ( (size_t)n );
1697 if (p == NULL) outOfMemory ();
1702 /*---------------------------------------------*/
1704 Cell *mkCell ( void )
1708 c = (Cell*) myMalloc ( sizeof ( Cell ) );
1715 /*---------------------------------------------*/
1717 Cell *snocString ( Cell *root, Char *name )
1720 Cell *tmp = mkCell();
1721 tmp->name = (Char*) myMalloc ( 5 + strlen(name) );
1722 strcpy ( tmp->name, name );
1726 while (tmp->link != NULL) tmp = tmp->link;
1727 tmp->link = snocString ( tmp->link, name );
1733 /*---------------------------------------------*/
1735 void addFlagsFromEnvVar ( Cell** argList, Char* varName )
1740 envbase = getenv(varName);
1741 if (envbase != NULL) {
1745 if (p[i] == 0) break;
1748 while (isspace((Int32)(p[0]))) p++;
1749 while (p[i] != 0 && !isspace((Int32)(p[i]))) i++;
1751 k = i; if (k > FILE_NAME_LEN-10) k = FILE_NAME_LEN-10;
1752 for (j = 0; j < k; j++) tmpName[j] = p[j];
1754 APPEND_FLAG(*argList, tmpName);
1761 /*---------------------------------------------*/
1762 #define ISFLAG(s) (strcmp(aa->name, (s))==0)
1764 IntNative main ( IntNative argc, Char *argv[] )
1772 /*-- Be really really really paranoid :-) --*/
1773 if (sizeof(Int32) != 4 || sizeof(UInt32) != 4 ||
1774 sizeof(Int16) != 2 || sizeof(UInt16) != 2 ||
1775 sizeof(Char) != 1 || sizeof(UChar) != 1)
1778 /*-- Initialise --*/
1779 outputHandleJustInCase = NULL;
1781 keepInputFiles = False;
1782 forceOverwrite = False;
1786 testFailsExist = False;
1787 unzFailsExist = False;
1789 numFilesProcessed = 0;
1791 deleteOutputOnInterrupt = False;
1793 i = j = 0; /* avoid bogus warning from egcs-1.1.X */
1795 /*-- Set up signal handlers for mem access errors --*/
1796 signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
1798 copyFileName ( inName, (Char*)"(none)" );
1799 copyFileName ( outName, (Char*)"(none)" );
1801 copyFileName ( progNameReally, argv[0] );
1802 progName = &progNameReally[0];
1803 for (tmp = &progNameReally[0]; *tmp != '\0'; tmp++)
1804 if (*tmp == PATH_SEP) progName = tmp + 1;
1807 /*-- Copy flags from env var BZIP2, and
1808 expand filename wildcards in arg list.
1811 addFlagsFromEnvVar ( &argList, (Char*)"BZIP2" );
1812 addFlagsFromEnvVar ( &argList, (Char*)"BZIP" );
1813 for (i = 1; i <= argc-1; i++)
1814 APPEND_FILESPEC(argList, argv[i]);
1817 /*-- Find the length of the longest filename --*/
1818 longestFileName = 7;
1821 for (aa = argList; aa != NULL; aa = aa->link) {
1822 if (ISFLAG("--")) { decode = False; continue; }
1823 if (aa->name[0] == '-' && decode) continue;
1825 if (longestFileName < (Int32)strlen(aa->name) )
1826 longestFileName = (Int32)strlen(aa->name);
1830 /*-- Determine source modes; flag handling may change this too. --*/
1831 if (numFileNames == 0)
1832 srcMode = SM_I2O; else srcMode = SM_F2F;
1835 /*-- Determine what to do (compress/uncompress/test/cat). --*/
1836 /*-- Note that subsequent flag handling may change this. --*/
1839 if ( (strstr ( progName, "unzip" ) != 0) ||
1840 (strstr ( progName, "UNZIP" ) != 0) )
1843 if ( (strstr ( progName, "z2cat" ) != 0) ||
1844 (strstr ( progName, "Z2CAT" ) != 0) ||
1845 (strstr ( progName, "zcat" ) != 0) ||
1846 (strstr ( progName, "ZCAT" ) != 0) ) {
1848 srcMode = (numFileNames == 0) ? SM_I2O : SM_F2O;
1852 /*-- Look at the flags. --*/
1853 for (aa = argList; aa != NULL; aa = aa->link) {
1854 if (ISFLAG("--")) break;
1855 if (aa->name[0] == '-' && aa->name[1] != '-') {
1856 for (j = 1; aa->name[j] != '\0'; j++) {
1857 switch (aa->name[j]) {
1858 case 'c': srcMode = SM_F2O; break;
1859 case 'd': opMode = OM_UNZ; break;
1860 case 'z': opMode = OM_Z; break;
1861 case 'f': forceOverwrite = True; break;
1862 case 't': opMode = OM_TEST; break;
1863 case 'k': keepInputFiles = True; break;
1864 case 's': smallMode = True; break;
1865 case 'q': noisy = False; break;
1866 case '1': blockSize100k = 1; break;
1867 case '2': blockSize100k = 2; break;
1868 case '3': blockSize100k = 3; break;
1869 case '4': blockSize100k = 4; break;
1870 case '5': blockSize100k = 5; break;
1871 case '6': blockSize100k = 6; break;
1872 case '7': blockSize100k = 7; break;
1873 case '8': blockSize100k = 8; break;
1874 case '9': blockSize100k = 9; break;
1876 case 'L': license(); break;
1877 case 'v': verbosity++; break;
1878 case 'h': usage ( progName );
1881 default: fprintf ( stderr, "%s: Bad flag `%s'\n",
1882 progName, aa->name );
1891 /*-- And again ... --*/
1892 for (aa = argList; aa != NULL; aa = aa->link) {
1893 if (ISFLAG("--")) break;
1894 if (ISFLAG("--stdout")) srcMode = SM_F2O; else
1895 if (ISFLAG("--decompress")) opMode = OM_UNZ; else
1896 if (ISFLAG("--compress")) opMode = OM_Z; else
1897 if (ISFLAG("--force")) forceOverwrite = True; else
1898 if (ISFLAG("--test")) opMode = OM_TEST; else
1899 if (ISFLAG("--keep")) keepInputFiles = True; else
1900 if (ISFLAG("--small")) smallMode = True; else
1901 if (ISFLAG("--quiet")) noisy = False; else
1902 if (ISFLAG("--version")) license(); else
1903 if (ISFLAG("--license")) license(); else
1904 if (ISFLAG("--exponential")) workFactor = 1; else
1905 if (ISFLAG("--repetitive-best")) redundant(aa->name); else
1906 if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
1907 if (ISFLAG("--fast")) blockSize100k = 1; else
1908 if (ISFLAG("--best")) blockSize100k = 9; else
1909 if (ISFLAG("--verbose")) verbosity++; else
1910 if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); }
1912 if (strncmp ( aa->name, "--", 2) == 0) {
1913 fprintf ( stderr, "%s: Bad flag `%s'\n", progName, aa->name );
1919 if (verbosity > 4) verbosity = 4;
1920 if (opMode == OM_Z && smallMode && blockSize100k > 2)
1923 if (opMode == OM_TEST && srcMode == SM_F2O) {
1924 fprintf ( stderr, "%s: -c and -t cannot be used together.\n",
1929 if (srcMode == SM_F2O && numFileNames == 0)
1932 if (opMode != OM_Z) blockSize100k = 0;
1934 if (srcMode == SM_F2F) {
1935 signal (SIGINT, mySignalCatcher);
1936 signal (SIGTERM, mySignalCatcher);
1939 if (opMode == OM_Z) {
1940 if (srcMode == SM_I2O) {
1944 for (aa = argList; aa != NULL; aa = aa->link) {
1945 if (ISFLAG("--")) { decode = False; continue; }
1946 if (aa->name[0] == '-' && decode) continue;
1947 numFilesProcessed++;
1948 compress ( aa->name );
1954 if (opMode == OM_UNZ) {
1955 unzFailsExist = False;
1956 if (srcMode == SM_I2O) {
1957 uncompress ( NULL );
1960 for (aa = argList; aa != NULL; aa = aa->link) {
1961 if (ISFLAG("--")) { decode = False; continue; }
1962 if (aa->name[0] == '-' && decode) continue;
1963 numFilesProcessed++;
1964 uncompress ( aa->name );
1967 if (unzFailsExist) {
1974 testFailsExist = False;
1975 if (srcMode == SM_I2O) {
1979 for (aa = argList; aa != NULL; aa = aa->link) {
1980 if (ISFLAG("--")) { decode = False; continue; }
1981 if (aa->name[0] == '-' && decode) continue;
1982 numFilesProcessed++;
1986 if (testFailsExist && noisy) {
1989 "You can use the `bzip2recover' program to attempt to recover\n"
1990 "data from undamaged sections of corrupted files.\n\n"
1997 /* Free the argument list memory to mollify leak detectors
1998 (eg) Purify, Checker. Serves no other useful purpose.
2001 while (aa != NULL) {
2002 Cell* aa2 = aa->link;
2003 if (aa->name != NULL) free(aa->name);
2012 /*-----------------------------------------------------------*/
2013 /*--- end bzip2.c ---*/
2014 /*-----------------------------------------------------------*/