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 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00179 }
00180
00181 if( insize > 0) {
00182 string err = src.c_str();
00183 err += ": not in compressed format";
00184 close( srcFile ) ;
00185 close( destFile ) ;
00186 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00187 }
00188
00189 string err = "unknown error";
00190 close( srcFile ) ;
00191 close( destFile ) ;
00192 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00193
00194 }
00195
00196
00197
00198
00199 maxbits = inbuf[2] & BIT_MASK;
00200 block_mode = inbuf[2] & BLOCK_MODE;
00201 maxmaxcode = MAXCODE(maxbits);
00202
00203 if( maxbits > BITS ) {
00204 string err = src.c_str();
00205 err += ": compressed with " ;
00206 err += maxbits ;
00207 err += " bits, can only handle";
00208 err += BITS;
00209 close( srcFile ) ;
00210 close( destFile ) ;
00211 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00212 }
00213
00214 maxcode = MAXCODE(n_bits = INIT_BITS)-1;
00215 bitmask = (1<<n_bits)-1;
00216 oldcode = -1;
00217 finchar = 0;
00218 outpos = 0;
00219 posbits = 3<<3;
00220
00221 free_ent = ((block_mode) ? FIRST : 256);
00222
00223 BESDEBUG( "bes", "BESUncompressZ::uncompress - entering loop" << endl) ;
00224
00225 memset(codetab, 0, 256);
00226
00227 for (code = 255 ; code >= 0 ; --code){
00228 ((unsigned char *)(htab))[code] = (unsigned char) code;
00229 }
00230
00231 do
00232 {
00233 resetbuf: ;
00234 {
00235 int i;
00236 int e;
00237 int o;
00238
00239 e = insize - ( o = ( posbits >> 3 ) );
00240
00241 for (i = 0 ; i < e ; ++i)
00242 inbuf[i] = inbuf[i+o];
00243
00244 insize = e;
00245 posbits = 0;
00246 }
00247
00248 if( insize < sizeof( inbuf ) - BUFSIZ ) {
00249 if( ( rsize = read( srcFile, inbuf + insize, BUFSIZ )) < 0) {
00250 string err = "Could not read file ";
00251 err += src.c_str() ;
00252 close( srcFile ) ;
00253 close( destFile ) ;
00254 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00255 }
00256
00257 insize += rsize;
00258 }
00259
00260 inbits = ( ( rsize > 0 ) ? ( insize - insize % n_bits ) << 3 :
00261 ( insize << 3 ) - ( n_bits - 1 ));
00262
00263 while( inbits > posbits ){
00264 if( free_ent > maxcode ) {
00265 posbits = ( ( posbits-1 ) +
00266 ( ( n_bits << 3 ) -
00267 ( posbits-1 + ( n_bits << 3)) %
00268 ( n_bits<<3 ) )
00269 );
00270
00271 ++n_bits;
00272 if( n_bits == maxbits)
00273 maxcode = maxmaxcode;
00274 else
00275 maxcode = MAXCODE(n_bits)-1;
00276
00277 bitmask = (1<<n_bits)-1;
00278 goto resetbuf;
00279 }
00280
00281 unsigned char*p = &inbuf[posbits>>3];
00282
00283 code = ( ( ( (long) ( p[0] ) ) | ( ( long )( p[1] ) << 8 ) |
00284 ( (long) ( p[2] ) << 16 ) ) >> ( posbits & 0x7 ) ) &
00285 bitmask;
00286
00287 posbits += n_bits;
00288
00289
00290 if( oldcode == -1) {
00291 if( code >= 256) {
00292 string err = "oldcode:-1 code: ";
00293 err += code ;
00294 err += " !!!! uncompress: corrupt input!!!";
00295 close( srcFile ) ;
00296 close( destFile ) ;
00297 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00298 }
00299 outbuf[outpos++] = (unsigned char)(finchar =
00300 (int)(oldcode = code));
00301 continue;
00302 }
00303
00304
00305 if( code == CLEAR && block_mode) {
00306 memset(codetab, 0, 256);
00307 free_ent = FIRST - 1;
00308 posbits = ( ( posbits - 1 ) +
00309 ( ( n_bits << 3 ) -
00310 ( posbits - 1 + ( n_bits << 3 ) ) %
00311 ( n_bits<<3) ) );
00312 maxcode = MAXCODE( n_bits = INIT_BITS ) - 1;
00313 bitmask = ( 1 << n_bits )-1;
00314 goto resetbuf;
00315 }
00316
00317 incode = code;
00318 stackp = de_stack;
00319
00320
00321 if( code >= free_ent ) {
00322 if( code > free_ent ) {
00323 unsigned char *p;
00324 posbits -= n_bits;
00325 p = &inbuf[posbits>>3];
00326
00327 string err = "uncompress: corrupt input";
00328 close( srcFile ) ;
00329 close( destFile ) ;
00330 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00331 }
00332
00333 *--stackp = ( unsigned char )finchar;
00334 code = oldcode;
00335 }
00336
00337
00338 while( (unsigned long)code >= (unsigned long)256) {
00339 *--stackp = htab[code];
00340 code = codetab[code];
00341 }
00342
00343 *--stackp = (unsigned char)(finchar = htab[code]);
00344
00345
00346 {
00347 int i;
00348 if( outpos+(i = (de_stack-stackp)) >= BUFSIZ) {
00349 do {
00350
00351 if( i > BUFSIZ-outpos) {
00352 i = BUFSIZ-outpos;
00353 }
00354
00355 if( i > 0) {
00356 memcpy(outbuf+outpos, stackp, i);
00357 outpos += i;
00358 }
00359
00360 if( outpos >= BUFSIZ) {
00361 if( write(destFile, outbuf,outpos) != outpos) {
00362 string err = "uncompress: write eror";
00363 close( srcFile ) ;
00364 close( destFile ) ;
00365 throw BESInternalError( err,
00366 __FILE__,
00367 __LINE__ ) ;
00368 }
00369 outpos = 0;
00370 }
00371 stackp+= i;
00372 }
00373 while( (i = (de_stack-stackp)) > 0) ;
00374 }
00375 else {
00376 memcpy(outbuf+outpos, stackp, i);
00377 outpos += i;
00378 }
00379 }
00380
00381 if( (code = free_ent) < maxmaxcode) {
00382 codetab[code] = (unsigned short)oldcode;
00383 htab[code] = (unsigned char)finchar;
00384 free_ent = code+1;
00385 }
00386
00387 oldcode = incode;
00388 }
00389 }
00390
00391 while( rsize > 0);
00392
00393 if( outpos > 0 && write(destFile, outbuf, outpos) != outpos) {
00394 string err = "uncompress: write eror";
00395 close( srcFile ) ;
00396 close( destFile ) ;
00397 throw BESInternalError( err, __FILE__, __LINE__ ) ;
00398 }
00399
00400 close( srcFile ) ;
00401 close( destFile ) ;
00402
00403 BESDEBUG( "bes", "BESUncompressZ::uncompress - end decompres" << endl) ;
00404 }
00405