00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <errno.h>
00028 #include <assert.h>
00029
00030 #include "libdefs.h"
00031 #include "error.h"
00032 #include "fileutils.h"
00033 #include "filereader.h"
00034
00035 #define READ_BUFFERSIZE (65536UL)
00036 #define WRITE_BUFFERSIZE (2UL*65536UL)
00037
00038 #ifdef WITH_DECOMPRESSION
00039 #undef WITH_DECOMPRESSION
00040 #endif
00041
00042 #if defined WITH_ZLIB_SUPPORT || defined WITH_LIBBZ2_SUPPORT || defined WITH_XZ_SUPPORT
00043 #define WITH_DECOMPRESSION
00044 #endif
00045
00046 #ifdef WITH_DECOMPRESSION
00047
00048
00049
00050 static int has_extension(const char *filename, size_t fnamelen,
00051 const char *ext, size_t extlen)
00052 {
00053 return (fnamelen > extlen &&
00054 memcmp(filename+fnamelen-extlen,ext,extlen) == 0)?1:0;
00055 }
00056 #endif
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 int filereader_open(Filereader *reader, const char *filename, fid_Error *error)
00092 {
00093 #ifdef WITH_LIBBZ2_SUPPORT
00094 int err;
00095 #endif
00096 #ifdef WITH_DECOMPRESSION
00097 size_t fnamelen;
00098 #endif
00099
00100 assert(reader != NULL);
00101 assert(filename != NULL);
00102
00103 reader->buffer=NULL;
00104 reader->buffersize=0;
00105 if((reader->filename=strdup(filename)) == NULL)
00106 {
00107 fid_OUTOFMEM(error);
00108 return -1;
00109 }
00110
00111 #ifdef WITH_DECOMPRESSION
00112 fnamelen=strlen(filename);
00113 #endif
00114
00115 #ifdef WITH_ZLIB_SUPPORT
00116 if(has_extension(filename,fnamelen,".gz",3) &&
00117 (reader->gzfile=gzopen(filename,"r")) != NULL)
00118 {
00119 reader->type=FILETYPE_GZIP;
00120 return 0;
00121 }
00122 #endif
00123
00124 #ifdef WITH_LIBBZ2_SUPPORT
00125 if(has_extension(filename,fnamelen,".bz2",4) &&
00126 (reader->file=fopen(filename,"r")) != NULL)
00127 {
00128 if((reader->bzfile=BZ2_bzReadOpen(&err,reader->file,0,0,NULL,0)) != NULL &&
00129 err == BZ_OK)
00130 {
00131 reader->type=FILETYPE_BZIP2;
00132 return 0;
00133 }
00134 (void)fclose(reader->file);
00135 reader->file=NULL;
00136 }
00137 #endif
00138
00139 #ifdef WITH_XZ_SUPPORT
00140 if(has_extension(filename,fnamelen,".xz",3) &&
00141 (reader->file=fopen(filename,"r")) != NULL)
00142 {
00143 reader->type=FILETYPE_XZ;
00144 return 0;
00145 }
00146 #endif
00147
00148 if(fid_file_map(&reader->flatfile,filename,0,0,error) == 0)
00149 {
00150 reader->type=FILETYPE_FLAT;
00151 return 0;
00152 }
00153
00154 return -1;
00155 }
00156
00157
00158
00159 #ifdef WITH_ZLIB_SUPPORT
00160
00161
00162
00163 static int read_complete_gzip(Filereader *reader, fid_Error *error)
00164 {
00165 int readbytes=WRITE_BUFFERSIZE;
00166 size_t offset=0;
00167
00168 while(readbytes == WRITE_BUFFERSIZE)
00169 {
00170 reader->buffer=(unsigned char *)realloc(reader->buffer,offset+WRITE_BUFFERSIZE);
00171 readbytes=gzread(reader->gzfile,reader->buffer+offset,WRITE_BUFFERSIZE);
00172 offset+=readbytes;
00173 if(readbytes == -1)
00174 {
00175 fid_error_throw(error,"Failed to decompress gzipped file \"%s\".",reader->filename);
00176 free(reader->buffer);
00177 reader->buffer=NULL;
00178 return -1;
00179 }
00180 }
00181
00182 if(offset == 0)
00183 {
00184 fid_error_throw(error,"Decompressed 0 bytes from gzipped file \"%s\".",reader->filename);
00185 free(reader->buffer);
00186 reader->buffer=NULL;
00187 return -1;
00188 }
00189
00190 reader->buffer=(unsigned char *)realloc(reader->buffer,offset);
00191 reader->buffersize=offset;
00192 return 0;
00193 }
00194
00195 #endif
00196
00197 #ifdef WITH_LIBBZ2_SUPPORT
00198
00199
00200
00201 static int read_complete_bzip2(Filereader *reader, fid_Error *error)
00202 {
00203 size_t offset=0;
00204 int readbytes;
00205 int err;
00206
00207 while(1)
00208 {
00209 reader->buffer=(unsigned char *)realloc(reader->buffer,offset+WRITE_BUFFERSIZE);
00210 readbytes=BZ2_bzRead(&err,reader->bzfile,reader->buffer+offset,WRITE_BUFFERSIZE);
00211 offset+=readbytes;
00212 if(err == BZ_STREAM_END)
00213 {
00214 break;
00215 }
00216 else if(err != BZ_OK)
00217 {
00218 fid_error_throw(error,"Failed to decompress bzipped file \"%s\".",reader->filename);
00219 free(reader->buffer);
00220 reader->buffer=NULL;
00221 return -1;
00222 }
00223 }
00224
00225 if(offset == 0)
00226 {
00227 fid_error_throw(error,"Decompressed 0 bytes from bzipped file \"%s\".",reader->filename);
00228 free(reader->buffer);
00229 reader->buffer=NULL;
00230 return -1;
00231 }
00232
00233 reader->buffer=(unsigned char *)realloc(reader->buffer,offset);
00234 reader->buffersize=offset;
00235 return 0;
00236 }
00237
00238 #endif
00239
00240 #ifdef WITH_XZ_SUPPORT
00241
00242
00243
00244
00245
00246
00247 static int init_lzma_dec(lzma_stream *strm)
00248 {
00249 lzma_stream temp=LZMA_STREAM_INIT;
00250
00251 *strm=temp;
00252 return (lzma_stream_decoder(strm,256UL*1024UL*1024UL,0) == LZMA_OK)?0:-1;
00253 }
00254
00255
00256 static int read_complete_xz(Filereader *reader, fid_Error *error)
00257 {
00258 size_t offset=0;
00259 lzma_ret ret;
00260 int retval=0;
00261 unsigned char *input_buffer=(unsigned char *)malloc(READ_BUFFERSIZE);
00262
00263 if(init_lzma_dec(&reader->strm) == -1)
00264 {
00265 fid_error_throw(error,"Failed initializing xz decoder.");
00266 return -1;
00267 }
00268
00269 if(input_buffer == NULL)
00270 {
00271 fid_OUTOFMEM(error);
00272 return -1;
00273 }
00274
00275 reader->buffer=(unsigned char *)malloc(WRITE_BUFFERSIZE);
00276 reader->strm.next_out=reader->buffer;
00277 reader->strm.avail_out=WRITE_BUFFERSIZE;
00278
00279 reader->strm.avail_in=0;
00280
00281 for(;;)
00282 {
00283 if(reader->strm.avail_in == 0)
00284 {
00285 reader->strm.next_in=input_buffer;
00286 reader->strm.avail_in=fread(input_buffer,1,READ_BUFFERSIZE,
00287 reader->file);
00288
00289 if(ferror(reader->file))
00290 {
00291 fid_error_throw_errno(error,errno,"Failed reading input file \"%s\".",
00292 reader->filename);
00293 goto cleanup_exit;
00294 }
00295 }
00296
00297 ret=lzma_code(&reader->strm,LZMA_RUN);
00298
00299 if(reader->strm.avail_out == 0 || ret != LZMA_OK)
00300 {
00301 offset+=WRITE_BUFFERSIZE;
00302 reader->buffer=(unsigned char *)realloc(reader->buffer,offset+WRITE_BUFFERSIZE);
00303 reader->strm.next_out=reader->buffer+offset;
00304 reader->strm.avail_out=WRITE_BUFFERSIZE;
00305 }
00306
00307 if(ret != LZMA_OK)
00308 {
00309 switch(ret)
00310 {
00311 case LZMA_STREAM_END:
00312 break;
00313 case LZMA_MEM_ERROR:
00314 fid_OUTOFMEM(error);
00315 goto cleanup_exit;
00316 case LZMA_MEMLIMIT_ERROR:
00317 fid_error_throw(error,"Memory limit for xz decompression exceeded.");
00318 goto cleanup_exit;
00319 case LZMA_DATA_ERROR:
00320 fid_error_throw(error,"xz compressed file \"%s\" is corrupt.",
00321 reader->filename);
00322 goto cleanup_exit;
00323 case LZMA_BUF_ERROR:
00324 fid_error_throw(error,"Unexpected end of input in file \"%s\".",
00325 reader->filename);
00326 goto cleanup_exit;
00327 default:
00328 fid_error_throw(error,"Error while decompressing file \"%s\".",
00329 reader->filename);
00330 goto cleanup_exit;
00331 }
00332 break;
00333 }
00334 }
00335
00336 if(0)
00337 {
00338 cleanup_exit:
00339 free(reader->buffer);
00340 reader->buffer=NULL;
00341 retval=-1;
00342 }
00343
00344 if(reader->buffer != NULL)
00345 {
00346 reader->buffersize=reader->strm.total_out;
00347 reader->buffer=(unsigned char *)realloc(reader->buffer,reader->buffersize);
00348 }
00349
00350 lzma_end(&reader->strm);
00351 free(input_buffer);
00352 return retval;
00353 }
00354
00355 #endif
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 int filereader_read_complete(Filereader *reader, fid_Error *error)
00373 {
00374 assert(reader != NULL);
00375 assert(reader->buffer == NULL);
00376 #ifdef S_SPLINT_S
00377 error=NULL;
00378 #endif
00379
00380 switch(reader->type)
00381 {
00382 #ifdef WITH_ZLIB_SUPPORT
00383 case FILETYPE_GZIP:
00384 return read_complete_gzip(reader,error);
00385 #endif
00386
00387 #ifdef WITH_LIBBZ2_SUPPORT
00388 case FILETYPE_BZIP2:
00389 return read_complete_bzip2(reader,error);
00390 #endif
00391
00392 #ifdef WITH_XZ_SUPPORT
00393 case FILETYPE_XZ:
00394 return read_complete_xz(reader,error);
00395 #endif
00396
00397 default:
00398 assert(reader->flatfile.occupied > 0);
00399 reader->buffer=reader->flatfile.content;
00400 reader->buffersize=reader->flatfile.occupied;
00401 return 0;
00402 }
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416 void filereader_close(Filereader *reader)
00417 {
00418 #ifdef WITH_LIBBZ2_SUPPORT
00419 int err;
00420 #endif
00421
00422 assert(reader != NULL);
00423 assert(reader->filename != NULL);
00424
00425 switch(reader->type)
00426 {
00427 #ifdef WITH_ZLIB_SUPPORT
00428 case FILETYPE_GZIP:
00429 assert(reader->gzfile != NULL);
00430 (void)gzclose(reader->gzfile);
00431 if(reader->buffer != NULL)
00432 {
00433 free(reader->buffer);
00434 }
00435 break;
00436 #endif
00437
00438 #ifdef WITH_LIBBZ2_SUPPORT
00439 case FILETYPE_BZIP2:
00440 assert(reader->bzfile != NULL);
00441 BZ2_bzReadClose(&err,reader->bzfile);
00442 (void)fclose(reader->file);
00443 if(reader->buffer != NULL)
00444 {
00445 free(reader->buffer);
00446 }
00447 break;
00448 #endif
00449
00450 #ifdef WITH_XZ_SUPPORT
00451 case FILETYPE_XZ:
00452 (void)fclose(reader->file);
00453 if(reader->buffer != NULL)
00454 {
00455 free(reader->buffer);
00456 }
00457 break;
00458 #endif
00459
00460 default:
00461 fid_file_unmap(&reader->flatfile);
00462 break;
00463 }
00464
00465 free(reader->filename);
00466 reader->buffer=NULL;
00467 reader->filename=NULL;
00468 }
00469
00470