summaryrefslogtreecommitdiffstats
path: root/contrib/bzip2/bzip2.c
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2002-02-01 16:28:01 +0000
committersobomax <sobomax@FreeBSD.org>2002-02-01 16:28:01 +0000
commitb718740c2fa9f3e14e09fba90eca26f829b7d43a (patch)
treea3ca69a02ff78d685a9ad50cd867c166ab387609 /contrib/bzip2/bzip2.c
parentda41d3ce6ee0a7c399e6438525caf651b761080b (diff)
downloadFreeBSD-src-b718740c2fa9f3e14e09fba90eca26f829b7d43a.zip
FreeBSD-src-b718740c2fa9f3e14e09fba90eca26f829b7d43a.tar.gz
Virgin import (trimmed) of Bzip2 version 1.0.2
Diffstat (limited to 'contrib/bzip2/bzip2.c')
-rw-r--r--contrib/bzip2/bzip2.c533
1 files changed, 296 insertions, 237 deletions
diff --git a/contrib/bzip2/bzip2.c b/contrib/bzip2/bzip2.c
index 56adfdc..807f420 100644
--- a/contrib/bzip2/bzip2.c
+++ b/contrib/bzip2/bzip2.c
@@ -7,7 +7,7 @@
This file is a part of bzip2 and/or libbzip2, a program and
library for lossless, block-sorting data compression.
- Copyright (C) 1996-2000 Julian R Seward. All rights reserved.
+ Copyright (C) 1996-2002 Julian R Seward. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@@ -113,13 +113,16 @@
/*--
Generic 32-bit Unix.
Also works on 64-bit Unix boxes.
+ This is the default.
--*/
#define BZ_UNIX 1
/*--
Win32, as seen by Jacob Navia's excellent
port of (Chris Fraser & David Hanson)'s excellent
- lcc compiler.
+ lcc compiler. Or with MS Visual C.
+ This is selected automatically if compiled by a compiler which
+ defines _WIN32, not including the Cygwin GCC.
--*/
#define BZ_LCCWIN32 0
@@ -156,6 +159,7 @@
--*/
#if BZ_UNIX
+# include <fcntl.h>
# include <sys/types.h>
# include <utime.h>
# include <unistd.h>
@@ -164,8 +168,9 @@
# define PATH_SEP '/'
# define MY_LSTAT lstat
-# define MY_S_IFREG S_ISREG
# define MY_STAT stat
+# define MY_S_ISREG S_ISREG
+# define MY_S_ISDIR S_ISDIR
# define APPEND_FILESPEC(root, name) \
root=snocString((root), (name))
@@ -180,19 +185,23 @@
# else
# define NORETURN /**/
# endif
+
# ifdef __DJGPP__
# include <io.h>
# include <fcntl.h>
# undef MY_LSTAT
+# undef MY_STAT
# define MY_LSTAT stat
+# define MY_STAT stat
# undef SET_BINARY_MODE
# define SET_BINARY_MODE(fd) \
do { \
int retVal = setmode ( fileno ( fd ), \
- O_BINARY ); \
+ O_BINARY ); \
ERROR_IF_MINUS_ONE ( retVal ); \
} while ( 0 )
# endif
+
# ifdef __CYGWIN__
# include <io.h>
# include <fcntl.h>
@@ -200,11 +209,11 @@
# define SET_BINARY_MODE(fd) \
do { \
int retVal = setmode ( fileno ( fd ), \
- O_BINARY ); \
+ O_BINARY ); \
ERROR_IF_MINUS_ONE ( retVal ); \
} while ( 0 )
# endif
-#endif
+#endif /* BZ_UNIX */
@@ -217,46 +226,23 @@
# define PATH_SEP '\\'
# define MY_LSTAT _stat
# define MY_STAT _stat
-# define MY_S_IFREG(x) ((x) & _S_IFREG)
+# define MY_S_ISREG(x) ((x) & _S_IFREG)
+# define MY_S_ISDIR(x) ((x) & _S_IFDIR)
# define APPEND_FLAG(root, name) \
root=snocString((root), (name))
-# if 0
- /*-- lcc-win32 seems to expand wildcards itself --*/
-# define APPEND_FILESPEC(root, spec) \
- do { \
- if ((spec)[0] == '-') { \
- root = snocString((root), (spec)); \
- } else { \
- struct _finddata_t c_file; \
- long hFile; \
- hFile = _findfirst((spec), &c_file); \
- if ( hFile == -1L ) { \
- root = snocString ((root), (spec)); \
- } else { \
- int anInt = 0; \
- while ( anInt == 0 ) { \
- root = snocString((root), \
- &c_file.name[0]); \
- anInt = _findnext(hFile, &c_file); \
- } \
- } \
- } \
- } while ( 0 )
-# else
# define APPEND_FILESPEC(root, name) \
root = snocString ((root), (name))
-# endif
# define SET_BINARY_MODE(fd) \
do { \
int retVal = setmode ( fileno ( fd ), \
- O_BINARY ); \
+ O_BINARY ); \
ERROR_IF_MINUS_ONE ( retVal ); \
} while ( 0 )
-#endif
+#endif /* BZ_LCCWIN32 */
/*---------------------------------------------*/
@@ -338,6 +324,7 @@ typedef
struct { UChar b[8]; }
UInt64;
+
static
void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
{
@@ -351,6 +338,7 @@ void uInt64_from_UInt32s ( UInt64* n, UInt32 lo32, UInt32 hi32 )
n->b[0] = (UChar) (lo32 & 0xFF);
}
+
static
double uInt64_to_double ( UInt64* n )
{
@@ -364,77 +352,6 @@ double uInt64_to_double ( UInt64* n )
return sum;
}
-static
-void uInt64_add ( UInt64* src, UInt64* dst )
-{
- Int32 i;
- Int32 carry = 0;
- for (i = 0; i < 8; i++) {
- carry += ( ((Int32)src->b[i]) + ((Int32)dst->b[i]) );
- dst->b[i] = (UChar)(carry & 0xFF);
- carry >>= 8;
- }
-}
-
-static
-void uInt64_sub ( UInt64* src, UInt64* dst )
-{
- Int32 t, i;
- Int32 borrow = 0;
- for (i = 0; i < 8; i++) {
- t = ((Int32)dst->b[i]) - ((Int32)src->b[i]) - borrow;
- if (t < 0) {
- dst->b[i] = (UChar)(t + 256);
- borrow = 1;
- } else {
- dst->b[i] = (UChar)t;
- borrow = 0;
- }
- }
-}
-
-static
-void uInt64_mul ( UInt64* a, UInt64* b, UInt64* r_hi, UInt64* r_lo )
-{
- UChar sum[16];
- Int32 ia, ib, carry;
- for (ia = 0; ia < 16; ia++) sum[ia] = 0;
- for (ia = 0; ia < 8; ia++) {
- carry = 0;
- for (ib = 0; ib < 8; ib++) {
- carry += ( ((Int32)sum[ia+ib])
- + ((Int32)a->b[ia]) * ((Int32)b->b[ib]) );
- sum[ia+ib] = (UChar)(carry & 0xFF);
- carry >>= 8;
- }
- sum[ia+8] = (UChar)(carry & 0xFF);
- if ((carry >>= 8) != 0) panic ( "uInt64_mul" );
- }
-
- for (ia = 0; ia < 8; ia++) r_hi->b[ia] = sum[ia+8];
- for (ia = 0; ia < 8; ia++) r_lo->b[ia] = sum[ia];
-}
-
-
-static
-void uInt64_shr1 ( UInt64* n )
-{
- Int32 i;
- for (i = 0; i < 8; i++) {
- n->b[i] >>= 1;
- if (i < 7 && (n->b[i+1] & 1)) n->b[i] |= 0x80;
- }
-}
-
-static
-void uInt64_shl1 ( UInt64* n )
-{
- Int32 i;
- for (i = 7; i >= 0; i--) {
- n->b[i] <<= 1;
- if (i > 0 && (n->b[i-1] & 0x80)) n->b[i]++;
- }
-}
static
Bool uInt64_isZero ( UInt64* n )
@@ -445,49 +362,23 @@ Bool uInt64_isZero ( UInt64* n )
return 1;
}
-static
+
+/* Divide *n by 10, and return the remainder. */
+static
Int32 uInt64_qrm10 ( UInt64* n )
{
- /* Divide *n by 10, and return the remainder. Long division
- is difficult, so we cheat and instead multiply by
- 0xCCCC CCCC CCCC CCCD, which is 0.8 (viz, 0.1 << 3).
- */
+ UInt32 rem, tmp;
Int32 i;
- UInt64 tmp1, tmp2, n_orig, zero_point_eight;
-
- zero_point_eight.b[1] = zero_point_eight.b[2] =
- zero_point_eight.b[3] = zero_point_eight.b[4] =
- zero_point_eight.b[5] = zero_point_eight.b[6] =
- zero_point_eight.b[7] = 0xCC;
- zero_point_eight.b[0] = 0xCD;
-
- n_orig = *n;
-
- /* divide n by 10,
- by multiplying by 0.8 and then shifting right 3 times */
- uInt64_mul ( n, &zero_point_eight, &tmp1, &tmp2 );
- uInt64_shr1(&tmp1); uInt64_shr1(&tmp1); uInt64_shr1(&tmp1);
- *n = tmp1;
-
- /* tmp1 = 8*n, tmp2 = 2*n */
- uInt64_shl1(&tmp1); uInt64_shl1(&tmp1); uInt64_shl1(&tmp1);
- tmp2 = *n; uInt64_shl1(&tmp2);
-
- /* tmp1 = 10*n */
- uInt64_add ( &tmp2, &tmp1 );
-
- /* n_orig = n_orig - 10*n */
- uInt64_sub ( &tmp1, &n_orig );
-
- /* n_orig should now hold quotient, in range 0 .. 9 */
- for (i = 7; i >= 1; i--)
- if (n_orig.b[i] != 0) panic ( "uInt64_qrm10(1)" );
- if (n_orig.b[0] > 9)
- panic ( "uInt64_qrm10(2)" );
-
- return (int)n_orig.b[0];
+ rem = 0;
+ for (i = 7; i >= 0; i--) {
+ tmp = rem * 256 + n->b[i];
+ n->b[i] = tmp / 10;
+ rem = tmp % 10;
+ }
+ return rem;
}
+
/* ... and the Whole Entire Point of all this UInt64 stuff is
so that we can supply the following function.
*/
@@ -504,7 +395,8 @@ void uInt64_toAscii ( char* outbuf, UInt64* n )
nBuf++;
} while (!uInt64_isZero(&n_copy));
outbuf[nBuf] = 0;
- for (i = 0; i < nBuf; i++) outbuf[i] = buf[nBuf-i-1];
+ for (i = 0; i < nBuf; i++)
+ outbuf[i] = buf[nBuf-i-1];
}
@@ -566,35 +458,38 @@ void compressStream ( FILE *stream, FILE *zStream )
if (ret == EOF) goto errhandler_io;
if (zStream != stdout) {
ret = fclose ( zStream );
+ outputHandleJustInCase = NULL;
if (ret == EOF) goto errhandler_io;
}
+ outputHandleJustInCase = NULL;
if (ferror(stream)) goto errhandler_io;
ret = fclose ( stream );
if (ret == EOF) goto errhandler_io;
- if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0)
- nbytes_in_lo32 = 1;
-
if (verbosity >= 1) {
- Char buf_nin[32], buf_nout[32];
- UInt64 nbytes_in, nbytes_out;
- double nbytes_in_d, nbytes_out_d;
- uInt64_from_UInt32s ( &nbytes_in,
- nbytes_in_lo32, nbytes_in_hi32 );
- uInt64_from_UInt32s ( &nbytes_out,
- nbytes_out_lo32, nbytes_out_hi32 );
- nbytes_in_d = uInt64_to_double ( &nbytes_in );
- nbytes_out_d = uInt64_to_double ( &nbytes_out );
- uInt64_toAscii ( buf_nin, &nbytes_in );
- uInt64_toAscii ( buf_nout, &nbytes_out );
- fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
- "%5.2f%% saved, %s in, %s out.\n",
- nbytes_in_d / nbytes_out_d,
- (8.0 * nbytes_out_d) / nbytes_in_d,
- 100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
- buf_nin,
- buf_nout
- );
+ if (nbytes_in_lo32 == 0 && nbytes_in_hi32 == 0) {
+ fprintf ( stderr, " no data compressed.\n");
+ } else {
+ Char buf_nin[32], buf_nout[32];
+ UInt64 nbytes_in, nbytes_out;
+ double nbytes_in_d, nbytes_out_d;
+ uInt64_from_UInt32s ( &nbytes_in,
+ nbytes_in_lo32, nbytes_in_hi32 );
+ uInt64_from_UInt32s ( &nbytes_out,
+ nbytes_out_lo32, nbytes_out_hi32 );
+ nbytes_in_d = uInt64_to_double ( &nbytes_in );
+ nbytes_out_d = uInt64_to_double ( &nbytes_out );
+ uInt64_toAscii ( buf_nin, &nbytes_in );
+ uInt64_toAscii ( buf_nout, &nbytes_out );
+ fprintf ( stderr, "%6.3f:1, %6.3f bits/byte, "
+ "%5.2f%% saved, %s in, %s out.\n",
+ nbytes_in_d / nbytes_out_d,
+ (8.0 * nbytes_out_d) / nbytes_in_d,
+ 100.0 * (1.0 - nbytes_out_d / nbytes_in_d),
+ buf_nin,
+ buf_nout
+ );
+ }
}
return;
@@ -652,7 +547,7 @@ Bool uncompressStream ( FILE *zStream, FILE *stream )
while (bzerr == BZ_OK) {
nread = BZ2_bzRead ( &bzerr, bzf, obuf, 5000 );
- if (bzerr == BZ_DATA_ERROR_MAGIC) goto errhandler;
+ if (bzerr == BZ_DATA_ERROR_MAGIC) goto trycat;
if ((bzerr == BZ_OK || bzerr == BZ_STREAM_END) && nread > 0)
fwrite ( obuf, sizeof(UChar), nread, stream );
if (ferror(stream)) goto errhandler_io;
@@ -668,9 +563,9 @@ Bool uncompressStream ( FILE *zStream, FILE *stream )
if (bzerr != BZ_OK) panic ( "decompress:bzReadGetUnused" );
if (nUnused == 0 && myfeof(zStream)) break;
-
}
+ closeok:
if (ferror(zStream)) goto errhandler_io;
ret = fclose ( zStream );
if (ret == EOF) goto errhandler_io;
@@ -680,11 +575,26 @@ Bool uncompressStream ( FILE *zStream, FILE *stream )
if (ret != 0) goto errhandler_io;
if (stream != stdout) {
ret = fclose ( stream );
+ outputHandleJustInCase = NULL;
if (ret == EOF) goto errhandler_io;
}
+ outputHandleJustInCase = NULL;
if (verbosity >= 2) fprintf ( stderr, "\n " );
return True;
+ trycat:
+ if (forceOverwrite) {
+ rewind(zStream);
+ while (True) {
+ if (myfeof(zStream)) break;
+ nread = fread ( obuf, sizeof(UChar), 5000, zStream );
+ if (ferror(zStream)) goto errhandler_io;
+ if (nread > 0) fwrite ( obuf, sizeof(UChar), nread, stream );
+ if (ferror(stream)) goto errhandler_io;
+ }
+ goto closeok;
+ }
+
errhandler:
BZ2_bzReadClose ( &bzerr_dummy, bzf );
switch (bzerr) {
@@ -832,7 +742,7 @@ void cadvise ( void )
stderr,
"\nIt is possible that the compressed file(s) have become corrupted.\n"
"You can use the -tvv option to test integrity of such files.\n\n"
- "You can use the `bzip2recover' program to *attempt* to recover\n"
+ "You can use the `bzip2recover' program to attempt to recover\n"
"data from undamaged sections of corrupted files.\n\n"
);
}
@@ -855,28 +765,55 @@ void showFileNames ( void )
static
void cleanUpAndFail ( Int32 ec )
{
- IntNative retVal;
+ IntNative retVal;
+ struct MY_STAT statBuf;
if ( srcMode == SM_F2F
&& opMode != OM_TEST
&& deleteOutputOnInterrupt ) {
- if (noisy)
- fprintf ( stderr, "%s: Deleting output file %s, if it exists.\n",
- progName, outName );
- if (outputHandleJustInCase != NULL)
- fclose ( outputHandleJustInCase );
- retVal = remove ( outName );
- if (retVal != 0)
+
+ /* Check whether input file still exists. Delete output file
+ only if input exists to avoid loss of data. Joerg Prante, 5
+ January 2002. (JRS 06-Jan-2002: other changes in 1.0.2 mean
+ this is less likely to happen. But to be ultra-paranoid, we
+ do the check anyway.) */
+ retVal = MY_STAT ( inName, &statBuf );
+ if (retVal == 0) {
+ if (noisy)
+ fprintf ( stderr,
+ "%s: Deleting output file %s, if it exists.\n",
+ progName, outName );
+ if (outputHandleJustInCase != NULL)
+ fclose ( outputHandleJustInCase );
+ retVal = remove ( outName );
+ if (retVal != 0)
+ fprintf ( stderr,
+ "%s: WARNING: deletion of output file "
+ "(apparently) failed.\n",
+ progName );
+ } else {
fprintf ( stderr,
- "%s: WARNING: deletion of output file (apparently) failed.\n",
+ "%s: WARNING: deletion of output file suppressed\n",
+ progName );
+ fprintf ( stderr,
+ "%s: since input file no longer exists. Output file\n",
progName );
+ fprintf ( stderr,
+ "%s: `%s' may be incomplete.\n",
+ progName, outName );
+ fprintf ( stderr,
+ "%s: I suggest doing an integrity test (bzip2 -tv)"
+ " of it.\n",
+ progName );
+ }
}
+
if (noisy && numFileNames > 0 && numFilesProcessed < numFileNames) {
fprintf ( stderr,
"%s: WARNING: some files have not been processed:\n"
- "\t%d specified on command line, %d not processed yet.\n\n",
- progName, numFileNames,
- numFileNames - numFilesProcessed );
+ "%s: %d specified on command line, %d not processed yet.\n\n",
+ progName, progName,
+ numFileNames, numFileNames - numFilesProcessed );
}
setExit(ec);
exit(exitValue);
@@ -915,14 +852,16 @@ void crcError ( void )
static
void compressedStreamEOF ( void )
{
- fprintf ( stderr,
- "\n%s: Compressed file ends unexpectedly;\n\t"
- "perhaps it is corrupted? *Possible* reason follows.\n",
- progName );
- perror ( progName );
- showFileNames();
- cadvise();
- cleanUpAndFail( 2 );
+ if (noisy) {
+ fprintf ( stderr,
+ "\n%s: Compressed file ends unexpectedly;\n\t"
+ "perhaps it is corrupted? *Possible* reason follows.\n",
+ progName );
+ perror ( progName );
+ showFileNames();
+ cadvise();
+ }
+ cleanUpAndFail( 2 );
}
@@ -1038,6 +977,11 @@ void configError ( void )
/*--- The main driver machinery ---*/
/*---------------------------------------------------*/
+/* All rather crufty. The main problem is that input files
+ are stat()d multiple times before use. This should be
+ cleaned up.
+*/
+
/*---------------------------------------------*/
static
void pad ( Char *s )
@@ -1082,6 +1026,32 @@ Bool fileExists ( Char* name )
/*---------------------------------------------*/
+/* Open an output file safely with O_EXCL and good permissions.
+ This avoids a race condition in versions < 1.0.2, in which
+ the file was first opened and then had its interim permissions
+ set safely. We instead use open() to create the file with
+ the interim permissions required. (--- --- rw-).
+
+ For non-Unix platforms, if we are not worrying about
+ security issues, simple this simply behaves like fopen.
+*/
+FILE* fopen_output_safely ( Char* name, const char* mode )
+{
+# if BZ_UNIX
+ FILE* fp;
+ IntNative fh;
+ fh = open(name, O_WRONLY|O_CREAT|O_EXCL, S_IWUSR|S_IRUSR);
+ if (fh == -1) return NULL;
+ fp = fdopen(fh, mode);
+ if (fp == NULL) close(fh);
+ return fp;
+# else
+ return fopen(name, mode);
+# endif
+}
+
+
+/*---------------------------------------------*/
/*--
if in doubt, return True
--*/
@@ -1093,7 +1063,7 @@ Bool notAStandardFile ( Char* name )
i = MY_LSTAT ( name, &statBuf );
if (i != 0) return True;
- if (MY_S_IFREG(statBuf.st_mode)) return False;
+ if (MY_S_ISREG(statBuf.st_mode)) return False;
return True;
}
@@ -1115,42 +1085,66 @@ Int32 countHardLinks ( Char* name )
/*---------------------------------------------*/
+/* Copy modification date, access date, permissions and owner from the
+ source to destination file. We have to copy this meta-info off
+ into fileMetaInfo before starting to compress / decompress it,
+ because doing it afterwards means we get the wrong access time.
+
+ To complicate matters, in compress() and decompress() below, the
+ sequence of tests preceding the call to saveInputFileMetaInfo()
+ involves calling fileExists(), which in turn establishes its result
+ by attempting to fopen() the file, and if successful, immediately
+ fclose()ing it again. So we have to assume that the fopen() call
+ does not cause the access time field to be updated.
+
+ Reading of the man page for stat() (man 2 stat) on RedHat 7.2 seems
+ to imply that merely doing open() will not affect the access time.
+ Therefore we merely need to hope that the C library only does
+ open() as a result of fopen(), and not any kind of read()-ahead
+ cleverness.
+
+ It sounds pretty fragile to me. Whether this carries across
+ robustly to arbitrary Unix-like platforms (or even works robustly
+ on this one, RedHat 7.2) is unknown to me. Nevertheless ...
+*/
+#if BZ_UNIX
+static
+struct MY_STAT fileMetaInfo;
+#endif
+
static
-void copyDatePermissionsAndOwner ( Char *srcName, Char *dstName )
+void saveInputFileMetaInfo ( Char *srcName )
{
-#if BZ_UNIX
+# if BZ_UNIX
+ IntNative retVal;
+ /* Note use of stat here, not lstat. */
+ retVal = MY_STAT( srcName, &fileMetaInfo );
+ ERROR_IF_NOT_ZERO ( retVal );
+# endif
+}
+
+
+static
+void applySavedMetaInfoToOutputFile ( Char *dstName )
+{
+# if BZ_UNIX
IntNative retVal;
- struct MY_STAT statBuf;
struct utimbuf uTimBuf;
- retVal = MY_LSTAT ( srcName, &statBuf );
- ERROR_IF_NOT_ZERO ( retVal );
- uTimBuf.actime = statBuf.st_atime;
- uTimBuf.modtime = statBuf.st_mtime;
+ uTimBuf.actime = fileMetaInfo.st_atime;
+ uTimBuf.modtime = fileMetaInfo.st_mtime;
- retVal = chmod ( dstName, statBuf.st_mode );
+ retVal = chmod ( dstName, fileMetaInfo.st_mode );
ERROR_IF_NOT_ZERO ( retVal );
retVal = utime ( dstName, &uTimBuf );
ERROR_IF_NOT_ZERO ( retVal );
- retVal = chown ( dstName, statBuf.st_uid, statBuf.st_gid );
+ retVal = chown ( dstName, fileMetaInfo.st_uid, fileMetaInfo.st_gid );
/* chown() will in many cases return with EPERM, which can
be safely ignored.
*/
-#endif
-}
-
-
-/*---------------------------------------------*/
-static
-void setInterimPermissions ( Char *dstName )
-{
-#if BZ_UNIX
- IntNative retVal;
- retVal = chmod ( dstName, S_IRUSR | S_IWUSR );
- ERROR_IF_NOT_ZERO ( retVal );
-#endif
+# endif
}
@@ -1158,10 +1152,19 @@ void setInterimPermissions ( Char *dstName )
static
Bool containsDubiousChars ( Char* name )
{
- Bool cdc = False;
+# if BZ_UNIX
+ /* On unix, files can contain any characters and the file expansion
+ * is performed by the shell.
+ */
+ return False;
+# else /* ! BZ_UNIX */
+ /* On non-unix (Win* platforms), wildcard characters are not allowed in
+ * filenames.
+ */
for (; *name != '\0'; name++)
- if (*name == '?' || *name == '*') cdc = True;
- return cdc;
+ if (*name == '?' || *name == '*') return True;
+ return False;
+# endif /* BZ_UNIX */
}
@@ -1201,6 +1204,7 @@ void compress ( Char *name )
FILE *inStr;
FILE *outStr;
Int32 n, i;
+ struct MY_STAT statBuf;
deleteOutputOnInterrupt = False;
@@ -1246,6 +1250,16 @@ void compress ( Char *name )
return;
}
}
+ if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+ MY_STAT(inName, &statBuf);
+ if ( MY_S_ISDIR(statBuf.st_mode) ) {
+ fprintf( stderr,
+ "%s: Input file %s is a directory.\n",
+ progName,inName);
+ setExit(1);
+ return;
+ }
+ }
if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
if (noisy)
fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
@@ -1253,11 +1267,15 @@ void compress ( Char *name )
setExit(1);
return;
}
- if ( srcMode == SM_F2F && !forceOverwrite && fileExists ( outName ) ) {
- fprintf ( stderr, "%s: Output file %s already exists.\n",
- progName, outName );
- setExit(1);
- return;
+ if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+ if (forceOverwrite) {
+ remove(outName);
+ } else {
+ fprintf ( stderr, "%s: Output file %s already exists.\n",
+ progName, outName );
+ setExit(1);
+ return;
+ }
}
if ( srcMode == SM_F2F && !forceOverwrite &&
(n=countHardLinks ( inName )) > 0) {
@@ -1267,6 +1285,12 @@ void compress ( Char *name )
return;
}
+ if ( srcMode == SM_F2F ) {
+ /* Save the file's meta-info before we open it. Doing it later
+ means we mess up the access times. */
+ saveInputFileMetaInfo ( inName );
+ }
+
switch ( srcMode ) {
case SM_I2O:
@@ -1306,7 +1330,7 @@ void compress ( Char *name )
case SM_F2F:
inStr = fopen ( inName, "rb" );
- outStr = fopen ( outName, "wb" );
+ outStr = fopen_output_safely ( outName, "wb" );
if ( outStr == NULL) {
fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
progName, outName, strerror(errno) );
@@ -1321,7 +1345,6 @@ void compress ( Char *name )
setExit(1);
return;
};
- setInterimPermissions ( outName );
break;
default:
@@ -1343,7 +1366,7 @@ void compress ( Char *name )
/*--- If there was an I/O error, we won't get here. ---*/
if ( srcMode == SM_F2F ) {
- copyDatePermissionsAndOwner ( inName, outName );
+ applySavedMetaInfoToOutputFile ( outName );
deleteOutputOnInterrupt = False;
if ( !keepInputFiles ) {
IntNative retVal = remove ( inName );
@@ -1364,6 +1387,7 @@ void uncompress ( Char *name )
Int32 n, i;
Bool magicNumberOK;
Bool cantGuess;
+ struct MY_STAT statBuf;
deleteOutputOnInterrupt = False;
@@ -1405,6 +1429,16 @@ void uncompress ( Char *name )
setExit(1);
return;
}
+ if ( srcMode == SM_F2F || srcMode == SM_F2O ) {
+ MY_STAT(inName, &statBuf);
+ if ( MY_S_ISDIR(statBuf.st_mode) ) {
+ fprintf( stderr,
+ "%s: Input file %s is a directory.\n",
+ progName,inName);
+ setExit(1);
+ return;
+ }
+ }
if ( srcMode == SM_F2F && !forceOverwrite && notAStandardFile ( inName )) {
if (noisy)
fprintf ( stderr, "%s: Input file %s is not a normal file.\n",
@@ -1419,11 +1453,15 @@ void uncompress ( Char *name )
progName, inName, outName );
/* just a warning, no return */
}
- if ( srcMode == SM_F2F && !forceOverwrite && fileExists ( outName ) ) {
- fprintf ( stderr, "%s: Output file %s already exists.\n",
- progName, outName );
- setExit(1);
- return;
+ if ( srcMode == SM_F2F && fileExists ( outName ) ) {
+ if (forceOverwrite) {
+ remove(outName);
+ } else {
+ fprintf ( stderr, "%s: Output file %s already exists.\n",
+ progName, outName );
+ setExit(1);
+ return;
+ }
}
if ( srcMode == SM_F2F && !forceOverwrite &&
(n=countHardLinks ( inName ) ) > 0) {
@@ -1433,6 +1471,12 @@ void uncompress ( Char *name )
return;
}
+ if ( srcMode == SM_F2F ) {
+ /* Save the file's meta-info before we open it. Doing it later
+ means we mess up the access times. */
+ saveInputFileMetaInfo ( inName );
+ }
+
switch ( srcMode ) {
case SM_I2O:
@@ -1463,7 +1507,7 @@ void uncompress ( Char *name )
case SM_F2F:
inStr = fopen ( inName, "rb" );
- outStr = fopen ( outName, "wb" );
+ outStr = fopen_output_safely ( outName, "wb" );
if ( outStr == NULL) {
fprintf ( stderr, "%s: Can't create output file %s: %s.\n",
progName, outName, strerror(errno) );
@@ -1478,7 +1522,6 @@ void uncompress ( Char *name )
setExit(1);
return;
};
- setInterimPermissions ( outName );
break;
default:
@@ -1501,7 +1544,7 @@ void uncompress ( Char *name )
/*--- If there was an I/O error, we won't get here. ---*/
if ( magicNumberOK ) {
if ( srcMode == SM_F2F ) {
- copyDatePermissionsAndOwner ( inName, outName );
+ applySavedMetaInfoToOutputFile ( outName );
deleteOutputOnInterrupt = False;
if ( !keepInputFiles ) {
IntNative retVal = remove ( inName );
@@ -1539,6 +1582,7 @@ void testf ( Char *name )
{
FILE *inStr;
Bool allOK;
+ struct MY_STAT statBuf;
deleteOutputOnInterrupt = False;
@@ -1565,6 +1609,16 @@ void testf ( Char *name )
setExit(1);
return;
}
+ if ( srcMode != SM_I2O ) {
+ MY_STAT(inName, &statBuf);
+ if ( MY_S_ISDIR(statBuf.st_mode) ) {
+ fprintf( stderr,
+ "%s: Input file %s is a directory.\n",
+ progName,inName);
+ setExit(1);
+ return;
+ }
+ }
switch ( srcMode ) {
@@ -1603,6 +1657,7 @@ void testf ( Char *name )
}
/*--- Now the input handle is sane. Do the Biz. ---*/
+ outputHandleJustInCase = NULL;
allOK = testStream ( inStr );
if (allOK && verbosity >= 1) fprintf ( stderr, "ok\n" );
@@ -1619,7 +1674,7 @@ void license ( void )
"bzip2, a block-sorting file compressor. "
"Version %s.\n"
" \n"
- " Copyright (C) 1996-2000 by Julian Seward.\n"
+ " Copyright (C) 1996-2002 by Julian Seward.\n"
" \n"
" This program is free software; you can redistribute it and/or modify\n"
" it under the terms set out in the LICENSE file, which is included\n"
@@ -1658,6 +1713,8 @@ void usage ( Char *fullProgName )
" -V --version display software version & license\n"
" -s --small use less memory (at most 2500k)\n"
" -1 .. -9 set block size to 100k .. 900k\n"
+ " --fast alias for -1\n"
+ " --best alias for -9\n"
"\n"
" If invoked as `bzip2', default action is to compress.\n"
" as `bunzip2', default action is to decompress.\n"
@@ -1666,9 +1723,9 @@ void usage ( Char *fullProgName )
" If no file names are given, bzip2 compresses or decompresses\n"
" from standard input to standard output. You can combine\n"
" short flags, so `-v -4' means the same as -v4 or -4v, &c.\n"
-#if BZ_UNIX
+# if BZ_UNIX
"\n"
-#endif
+# endif
,
BZ2_bzlibVersion(),
@@ -1818,11 +1875,11 @@ IntNative main ( IntNative argc, Char *argv[] )
/*-- Set up signal handlers for mem access errors --*/
signal (SIGSEGV, mySIGSEGVorSIGBUScatcher);
-#if BZ_UNIX
-#ifndef __DJGPP__
+# if BZ_UNIX
+# ifndef __DJGPP__
signal (SIGBUS, mySIGSEGVorSIGBUScatcher);
-#endif
-#endif
+# endif
+# endif
copyFileName ( inName, "(none)" );
copyFileName ( outName, "(none)" );
@@ -1933,6 +1990,8 @@ IntNative main ( IntNative argc, Char *argv[] )
if (ISFLAG("--exponential")) workFactor = 1; else
if (ISFLAG("--repetitive-best")) redundant(aa->name); else
if (ISFLAG("--repetitive-fast")) redundant(aa->name); else
+ if (ISFLAG("--fast")) blockSize100k = 1; else
+ if (ISFLAG("--best")) blockSize100k = 9; else
if (ISFLAG("--verbose")) verbosity++; else
if (ISFLAG("--help")) { usage ( progName ); exit ( 0 ); }
else
OpenPOWER on IntegriCloud