00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "config.h"
00033
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <fcntl.h>
00037 #if HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040
00041 #include <cstdio>
00042 #include <cstring>
00043 #include <cerrno>
00044
00045 #include "BESUncompressZ.h"
00046 #include "BESInternalError.h"
00047 #include "BESDebug.h"
00048
00049
00055 void
00056 BESUncompressZ::uncompress( const string &src, const string &target )
00057 {
00058 int srcFile = 0 ;
00059 int destFile = 0 ;
00060 int my_errno = 0 ;
00061
00062
00063
00064
00065
00066 BESDEBUG( "bes", "BESUncompressZ::uncompress - src=" << src.c_str() << endl ) ;
00067
00068 srcFile = open( src.c_str(), O_RDONLY ) ;
00069 my_errno = errno ;
00070 if( srcFile == -1 )
00071 {
00072 string err = "Unable to open the compressed file " + src
00073 + ": " ;
00074 char *serr = strerror( my_errno ) ;
00075 if( serr )
00076 {
00077 err.append( serr ) ;
00078 }
00079 else
00080 {
00081 err.append( "unknown error occurred" ) ;
00082 }
00083 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00084 }
00085
00086
00087
00088
00089 BESDEBUG( "bes", "BESUncompressZ::uncompress - target=" << target.c_str() << endl ) ;
00090
00091 destFile = open( target.c_str(), O_WRONLY | O_CREAT | O_TRUNC
00092 , S_IRUSR | S_IWUSR ) ;
00093 if( destFile == -1)
00094 {
00095 string err = "Unable to create the uncompressed file "
00096 + target + ": " ;
00097 char *serr = strerror( my_errno ) ;
00098 if( serr )
00099 {
00100 err.append( serr ) ;
00101 }
00102 else
00103 {
00104 err.append( "unknown error occurred" ) ;
00105 }
00106 close( srcFile ) ;
00107 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00108 }
00109
00110
00111
00112
00113
00114
00115 BESDEBUG( "bes", "BESUncompressZ::uncompress - start decompress" << endl) ;
00116
00117 #define FIRSTBYTE (unsigned char)'\037'
00118 #define SECONDBYTE (unsigned char)'\235'
00119 #define FIRST 257
00120 #define BIT_MASK 0x1f
00121 #define BLOCK_MODE 0x80
00122 #define MAXCODE(n) (1L << (n))
00123 #define BITS 16
00124 #define INIT_BITS 9
00125 #define CLEAR 256
00126 #define HBITS 17
00127 #define HSIZE (1<<HBITS)
00128 #define HMASK (HSIZE-1)
00129 #define BITS 16
00130 #define de_stack ((unsigned char *)&(htab[HSIZE-1]))
00131 #define BYTEORDER 0000
00132 #define NOALLIGN 0
00133
00134 unsigned char htab[HSIZE*4];
00135 unsigned short codetab[HSIZE];
00136
00137 int block_mode = BLOCK_MODE;
00138 int maxbits = BITS;
00139 unsigned char inbuf[BUFSIZ+64];
00140 unsigned char outbuf[BUFSIZ+2048];
00141 unsigned char *stackp;
00142 long int code;
00143 int finchar;
00144 long int oldcode;
00145 long int incode;
00146 int inbits;
00147 int posbits;
00148 int outpos;
00149 int insize;
00150 int bitmask;
00151 long int free_ent;
00152 long int maxcode;
00153 long int maxmaxcode;
00154 int n_bits;
00155 int rsize;
00156
00157 insize = 0;
00158
00159 BESDEBUG( "bes", "BESUncompressZ::uncompress - read file" << endl); ;
00160
00161
00162
00163 while( insize < 3 && (rsize = read(srcFile, inbuf+insize, BUFSIZ)) > 0) {
00164 insize += rsize;
00165 }
00166 BESDEBUG( "bes", "BESUncompressZ::uncompress - insize: " << insize << endl); ;
00167
00168
00169
00170
00171 if( (insize < 3) || (inbuf[0] != FIRSTBYTE) || (inbuf[1] != SECONDBYTE)) {
00172 BESDEBUG( "bes", "BESUncompressZ::uncompress - not a compress file" << endl); ;
00173 if( rsize < 0) {
00174 string err = "Could not read file ";
00175 err += src.c_str() ;
00176 close( srcFile ) ;
00177 close( destFile ) ;
00178 remove( target.c_str() ) ;
00179 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00180 }
00181
00182 if( insize > 0) {
00183 string err = src.c_str();
00184 err += ": not in compressed format";
00185 close( srcFile ) ;
00186 close( destFile ) ;
00187 remove( target.c_str() ) ;
00188 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00189 }
00190
00191 string err = "unknown error";
00192 close( srcFile ) ;
00193 close( destFile ) ;
00194 remove( target.c_str() ) ;
00195 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00196
00197 }
00198
00199
00200
00201
00202 maxbits = inbuf[2] & BIT_MASK;
00203 block_mode = inbuf[2] & BLOCK_MODE;
00204 maxmaxcode = MAXCODE(maxbits);
00205
00206 if( maxbits > BITS ) {
00207 string err = src.c_str();
00208 err += ": compressed with " ;
00209 err += maxbits ;
00210 err += " bits, can only handle";
00211 err += BITS;
00212 close( srcFile ) ;
00213 close( destFile ) ;
00214 remove( target.c_str() ) ;
00215 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00216 }
00217
00218 maxcode = MAXCODE(n_bits = INIT_BITS)-1;
00219 bitmask = (1<<n_bits)-1;
00220 oldcode = -1;
00221 finchar = 0;
00222 outpos = 0;
00223 posbits = 3<<3;
00224
00225 free_ent = ((block_mode) ? FIRST : 256);
00226
00227 BESDEBUG( "bes", "BESUncompressZ::uncompress - entering loop" << endl) ;
00228
00229 memset(codetab, 0, 256);
00230
00231 for (code = 255 ; code >= 0 ; --code){
00232 ((unsigned char *)(htab))[code] = (unsigned char) code;
00233 }
00234
00235 do
00236 {
00237 resetbuf: ;
00238 {
00239 int i;
00240 int e;
00241 int o;
00242
00243 e = insize - ( o = ( posbits >> 3 ) );
00244
00245 for (i = 0 ; i < e ; ++i)
00246 inbuf[i] = inbuf[i+o];
00247
00248 insize = e;
00249 posbits = 0;
00250 }
00251
00252 if( insize < sizeof( inbuf ) - BUFSIZ ) {
00253 if( ( rsize = read( srcFile, inbuf + insize, BUFSIZ )) < 0) {
00254 string err = "Could not read file ";
00255 err += src.c_str() ;
00256 close( srcFile ) ;
00257 close( destFile ) ;
00258 remove( target.c_str() ) ;
00259 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00260 }
00261
00262 insize += rsize;
00263 }
00264
00265 inbits = ( ( rsize > 0 ) ? ( insize - insize % n_bits ) << 3 :
00266 ( insize << 3 ) - ( n_bits - 1 ));
00267
00268 while( inbits > posbits ){
00269 if( free_ent > maxcode ) {
00270 posbits = ( ( posbits-1 ) +
00271 ( ( n_bits << 3 ) -
00272 ( posbits-1 + ( n_bits << 3)) %
00273 ( n_bits<<3 ) )
00274 );
00275
00276 ++n_bits;
00277 if( n_bits == maxbits)
00278 maxcode = maxmaxcode;
00279 else
00280 maxcode = MAXCODE(n_bits)-1;
00281
00282 bitmask = (1<<n_bits)-1;
00283 goto resetbuf;
00284 }
00285
00286 unsigned char*p = &inbuf[posbits>>3];
00287
00288 code = ( ( ( (long) ( p[0] ) ) | ( ( long )( p[1] ) << 8 ) |
00289 ( (long) ( p[2] ) << 16 ) ) >> ( posbits & 0x7 ) ) &
00290 bitmask;
00291
00292 posbits += n_bits;
00293
00294
00295 if( oldcode == -1) {
00296 if( code >= 256) {
00297 string err = "oldcode:-1 code: ";
00298 err += code ;
00299 err += " !!!! uncompress: corrupt input!!!";
00300 close( srcFile ) ;
00301 close( destFile ) ;
00302 remove( target.c_str() ) ;
00303 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00304 }
00305 outbuf[outpos++] = (unsigned char)(finchar =
00306 (int)(oldcode = code));
00307 continue;
00308 }
00309
00310
00311 if( code == CLEAR && block_mode) {
00312 memset(codetab, 0, 256);
00313 free_ent = FIRST - 1;
00314 posbits = ( ( posbits - 1 ) +
00315 ( ( n_bits << 3 ) -
00316 ( posbits - 1 + ( n_bits << 3 ) ) %
00317 ( n_bits<<3) ) );
00318 maxcode = MAXCODE( n_bits = INIT_BITS ) - 1;
00319 bitmask = ( 1 << n_bits )-1;
00320 goto resetbuf;
00321 }
00322
00323 incode = code;
00324 stackp = de_stack;
00325
00326
00327 if( code >= free_ent ) {
00328 if( code > free_ent ) {
00329 unsigned char *p;
00330 posbits -= n_bits;
00331 p = &inbuf[posbits>>3];
00332
00333 string err = "uncompress: corrupt input";
00334 close( srcFile ) ;
00335 close( destFile ) ;
00336 remove( target.c_str() ) ;
00337 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00338 }
00339
00340 *--stackp = ( unsigned char )finchar;
00341 code = oldcode;
00342 }
00343
00344
00345 while( (unsigned long)code >= (unsigned long)256) {
00346 *--stackp = htab[code];
00347 code = codetab[code];
00348 }
00349
00350 *--stackp = (unsigned char)(finchar = htab[code]);
00351
00352
00353 {
00354 int i;
00355 if( outpos+(i = (de_stack-stackp)) >= BUFSIZ) {
00356 do {
00357
00358 if( i > BUFSIZ-outpos) {
00359 i = BUFSIZ-outpos;
00360 }
00361
00362 if( i > 0) {
00363 memcpy(outbuf+outpos, stackp, i);
00364 outpos += i;
00365 }
00366
00367 if( outpos >= BUFSIZ) {
00368 if( write(destFile, outbuf,outpos) != outpos) {
00369 string err = "uncompress: write eror";
00370 close( srcFile ) ;
00371 close( destFile ) ;
00372 remove( target.c_str() ) ;
00373 throw BESInternalError( err,
00374 __FILE__,
00375 __LINE__ ) ;
00376 }
00377 outpos = 0;
00378 }
00379 stackp+= i;
00380 }
00381 while( (i = (de_stack-stackp)) > 0) ;
00382 }
00383 else {
00384 memcpy(outbuf+outpos, stackp, i);
00385 outpos += i;
00386 }
00387 }
00388
00389 if( (code = free_ent) < maxmaxcode) {
00390 codetab[code] = (unsigned short)oldcode;
00391 htab[code] = (unsigned char)finchar;
00392 free_ent = code+1;
00393 }
00394
00395 oldcode = incode;
00396 }
00397 }
00398
00399 while( rsize > 0);
00400
00401 if( outpos > 0 && write(destFile, outbuf, outpos) != outpos) {
00402 string err = "uncompress: write eror";
00403 close( srcFile ) ;
00404 close( destFile ) ;
00405 remove( target.c_str() ) ;
00406 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00407 }
00408
00409 close( srcFile ) ;
00410 close( destFile ) ;
00411
00412 BESDEBUG( "bes", "BESUncompressZ::uncompress - end decompres" << endl) ;
00413 }
00414