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