aboutsummaryrefslogtreecommitdiff
path: root/src/main/extractor_datasource.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/extractor_datasource.c')
-rw-r--r--src/main/extractor_datasource.c1083
1 files changed, 550 insertions, 533 deletions
diff --git a/src/main/extractor_datasource.c b/src/main/extractor_datasource.c
index 888e524..0b18d7c 100644
--- a/src/main/extractor_datasource.c
+++ b/src/main/extractor_datasource.c
@@ -214,35 +214,35 @@ struct CompressedFileSource
214 */ 214 */
215static int 215static int
216bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds, 216bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds,
217 uint64_t pos) 217 uint64_t pos)
218{ 218{
219 int64_t position; 219 int64_t position;
220 ssize_t rd; 220 ssize_t rd;
221 221
222 if (pos > bfds->fsize) 222 if (pos > bfds->fsize)
223 { 223 {
224 LOG ("Invalid seek operation\n"); 224 LOG ("Invalid seek operation\n");
225 return -1; /* invalid */ 225 return -1; /* invalid */
226 } 226 }
227 if (NULL == bfds->buffer) 227 if (NULL == bfds->buffer)
228 { 228 {
229 bfds->buffer_pos = pos; 229 bfds->buffer_pos = pos;
230 return 0; 230 return 0;
231 } 231 }
232 position = (int64_t) LSEEK (bfds->fd, pos, SEEK_SET); 232 position = (int64_t) LSEEK (bfds->fd, pos, SEEK_SET);
233 if (position < 0) 233 if (position < 0)
234 { 234 {
235 LOG_STRERROR ("lseek"); 235 LOG_STRERROR ("lseek");
236 return -1; 236 return -1;
237 } 237 }
238 bfds->fpos = position; 238 bfds->fpos = position;
239 bfds->buffer_pos = 0; 239 bfds->buffer_pos = 0;
240 rd = read (bfds->fd, bfds->buffer, bfds->buffer_size); 240 rd = read (bfds->fd, bfds->buffer, bfds->buffer_size);
241 if (rd < 0) 241 if (rd < 0)
242 { 242 {
243 LOG_STRERROR ("read"); 243 LOG_STRERROR ("read");
244 return -1; 244 return -1;
245 } 245 }
246 bfds->buffer_bytes = rd; 246 bfds->buffer_bytes = rd;
247 return 0; 247 return 0;
248} 248}
@@ -258,8 +258,8 @@ bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds,
258 */ 258 */
259static struct BufferedFileDataSource * 259static struct BufferedFileDataSource *
260bfds_new (const void *data, 260bfds_new (const void *data,
261 int fd, 261 int fd,
262 int64_t fsize) 262 int64_t fsize)
263{ 263{
264 struct BufferedFileDataSource *result; 264 struct BufferedFileDataSource *result;
265 size_t xtra; 265 size_t xtra;
@@ -269,19 +269,19 @@ bfds_new (const void *data,
269 else 269 else
270 xtra = (size_t) fsize; 270 xtra = (size_t) fsize;
271 if ( (-1 == fd) && (NULL == data) ) 271 if ( (-1 == fd) && (NULL == data) )
272 { 272 {
273 LOG ("Invalid arguments\n"); 273 LOG ("Invalid arguments\n");
274 return NULL; 274 return NULL;
275 } 275 }
276 if ( (-1 != fd) && (NULL != data) ) 276 if ( (-1 != fd) && (NULL != data) )
277 fd = -1; /* don't need fd */ 277 fd = -1; /* don't need fd */
278 if (NULL != data) 278 if (NULL != data)
279 xtra = 0; 279 xtra = 0;
280 if (NULL == (result = malloc (sizeof (struct BufferedFileDataSource) + xtra))) 280 if (NULL == (result = malloc (sizeof (struct BufferedFileDataSource) + xtra)))
281 { 281 {
282 LOG_STRERROR ("malloc"); 282 LOG_STRERROR ("malloc");
283 return NULL; 283 return NULL;
284 } 284 }
285 memset (result, 0, sizeof (struct BufferedFileDataSource)); 285 memset (result, 0, sizeof (struct BufferedFileDataSource));
286 result->data = (NULL != data) ? data : &result[1]; 286 result->data = (NULL != data) ? data : &result[1];
287 result->buffer = (NULL != data) ? NULL : &result[1]; 287 result->buffer = (NULL != data) ? NULL : &result[1];
@@ -318,79 +318,79 @@ bfds_delete (struct BufferedFileDataSource *bfds)
318 */ 318 */
319static int64_t 319static int64_t
320bfds_seek (struct BufferedFileDataSource *bfds, 320bfds_seek (struct BufferedFileDataSource *bfds,
321 int64_t pos, int whence) 321 int64_t pos, int whence)
322{ 322{
323 uint64_t npos; 323 uint64_t npos;
324 size_t nbpos; 324 size_t nbpos;
325 325
326 switch (whence) 326 switch (whence)
327 {
328 case SEEK_CUR:
329 npos = bfds->fpos + bfds->buffer_pos + pos;
330 if (npos > bfds->fsize)
327 { 331 {
328 case SEEK_CUR: 332 LOG ("Invalid seek operation to %lld from %llu (max is %llu)\n",
329 npos = bfds->fpos + bfds->buffer_pos + pos; 333 (long long) pos,
330 if (npos > bfds->fsize) 334 bfds->fpos + bfds->buffer_pos,
331 { 335 (unsigned long long) bfds->fsize);
332 LOG ("Invalid seek operation to %lld from %llu (max is %llu)\n", 336 return -1;
333 (long long) pos, 337 }
334 bfds->fpos + bfds->buffer_pos, 338 nbpos = bfds->buffer_pos + pos;
335 (unsigned long long) bfds->fsize); 339 if ( (NULL == bfds->buffer) ||
336 return -1; 340 (nbpos < bfds->buffer_bytes) )
337 } 341 {
338 nbpos = bfds->buffer_pos + pos; 342 bfds->buffer_pos = nbpos;
339 if ( (NULL == bfds->buffer) ||
340 (nbpos < bfds->buffer_bytes) )
341 {
342 bfds->buffer_pos = nbpos;
343 return npos;
344 }
345 if (0 != bfds_pick_next_buffer_at (bfds,
346 npos))
347 {
348 LOG ("seek operation failed\n");
349 return -1;
350 }
351 return npos; 343 return npos;
352 case SEEK_END: 344 }
353 if (pos > 0) 345 if (0 != bfds_pick_next_buffer_at (bfds,
354 { 346 npos))
355 LOG ("Invalid seek operation\n"); 347 {
356 return -1; 348 LOG ("seek operation failed\n");
357 } 349 return -1;
358 if (bfds->fsize < - pos) 350 }
359 { 351 return npos;
360 LOG ("Invalid seek operation\n"); 352 case SEEK_END:
361 return -1; 353 if (pos > 0)
362 } 354 {
363 pos = bfds->fsize + pos; 355 LOG ("Invalid seek operation\n");
364 /* fall-through! */ 356 return -1;
365 case SEEK_SET: 357 }
366 if (pos < 0) 358 if (bfds->fsize < -pos)
367 { 359 {
368 LOG ("Invalid seek operation\n"); 360 LOG ("Invalid seek operation\n");
369 return -1; 361 return -1;
370 } 362 }
371 if (pos > bfds->fsize) 363 pos = bfds->fsize + pos;
372 { 364 /* fall-through! */
373 LOG ("Invalid seek operation (%lld > %llu) %d\n", 365 case SEEK_SET:
374 (long long) pos, 366 if (pos < 0)
375 (unsigned long long) bfds->fsize, 367 {
376 SEEK_SET == whence); 368 LOG ("Invalid seek operation\n");
377 return -1; 369 return -1;
378 } 370 }
379 if ( (NULL == bfds->buffer) || 371 if (pos > bfds->fsize)
380 ( (bfds->fpos <= pos) && 372 {
381 (bfds->fpos + bfds->buffer_bytes > pos) ) ) 373 LOG ("Invalid seek operation (%lld > %llu) %d\n",
382 { 374 (long long) pos,
383 bfds->buffer_pos = pos - bfds->fpos; 375 (unsigned long long) bfds->fsize,
384 return pos; 376 SEEK_SET == whence);
385 } 377 return -1;
386 if (0 != bfds_pick_next_buffer_at (bfds, pos)) 378 }
387 { 379 if ( (NULL == bfds->buffer) ||
388 LOG ("seek operation failed\n"); 380 ( (bfds->fpos <= pos) &&
389 return -1; 381 (bfds->fpos + bfds->buffer_bytes > pos) ) )
390 } 382 {
391 ASSERT (pos == bfds->fpos + bfds->buffer_pos); 383 bfds->buffer_pos = pos - bfds->fpos;
392 return pos; 384 return pos;
393 } 385 }
386 if (0 != bfds_pick_next_buffer_at (bfds, pos))
387 {
388 LOG ("seek operation failed\n");
389 return -1;
390 }
391 ASSERT (pos == bfds->fpos + bfds->buffer_pos);
392 return pos;
393 }
394 return -1; 394 return -1;
395} 395}
396 396
@@ -407,8 +407,8 @@ bfds_seek (struct BufferedFileDataSource *bfds,
407 */ 407 */
408static ssize_t 408static ssize_t
409bfds_read (struct BufferedFileDataSource *bfds, 409bfds_read (struct BufferedFileDataSource *bfds,
410 void *buf_ptr, 410 void *buf_ptr,
411 size_t count) 411 size_t count)
412{ 412{
413 char *cbuf = buf_ptr; 413 char *cbuf = buf_ptr;
414 uint64_t old_off; 414 uint64_t old_off;
@@ -420,28 +420,28 @@ bfds_read (struct BufferedFileDataSource *bfds,
420 return 0; /* end of stream */ 420 return 0; /* end of stream */
421 ret = 0; 421 ret = 0;
422 while (count > 0) 422 while (count > 0)
423 {
424 if ( (bfds->buffer_bytes == bfds->buffer_pos) &&
425 (0 != bfds_pick_next_buffer_at (bfds,
426 bfds->fpos + bfds->buffer_bytes)) )
423 { 427 {
424 if ( (bfds->buffer_bytes == bfds->buffer_pos) && 428 /* revert to original position, invalidate buffer */
425 (0 != bfds_pick_next_buffer_at (bfds, 429 bfds->fpos = old_off;
426 bfds->fpos + bfds->buffer_bytes)) ) 430 bfds->buffer_bytes = 0;
427 { 431 bfds->buffer_pos = 0;
428 /* revert to original position, invalidate buffer */ 432 LOG ("read operation failed\n");
429 bfds->fpos = old_off; 433 return -1; /* getting more failed */
430 bfds->buffer_bytes = 0;
431 bfds->buffer_pos = 0;
432 LOG ("read operation failed\n");
433 return -1; /* getting more failed */
434 }
435 avail = bfds->buffer_bytes - bfds->buffer_pos;
436 if (avail > count)
437 avail = count;
438 if (0 == avail)
439 break;
440 memcpy (&cbuf[ret], bfds->data + bfds->buffer_pos, avail);
441 bfds->buffer_pos += avail;
442 count -= avail;
443 ret += avail;
444 } 434 }
435 avail = bfds->buffer_bytes - bfds->buffer_pos;
436 if (avail > count)
437 avail = count;
438 if (0 == avail)
439 break;
440 memcpy (&cbuf[ret], bfds->data + bfds->buffer_pos, avail);
441 bfds->buffer_pos += avail;
442 count -= avail;
443 ret += avail;
444 }
445 return ret; 445 return ret;
446} 446}
447 447
@@ -458,17 +458,17 @@ bfds_read (struct BufferedFileDataSource *bfds,
458 */ 458 */
459static int 459static int
460cfs_init_decompressor_zlib (struct CompressedFileSource *cfs, 460cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
461 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 461 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
462{ 462{
463 unsigned int gzip_header_length = 10; 463 unsigned int gzip_header_length = 10;
464 unsigned char hdata[12]; 464 unsigned char hdata[12];
465 ssize_t rsize; 465 ssize_t rsize;
466 466
467 if (0 != bfds_seek (cfs->bfds, 0, SEEK_SET)) 467 if (0 != bfds_seek (cfs->bfds, 0, SEEK_SET))
468 { 468 {
469 LOG ("Failed to seek to offset 0!\n"); 469 LOG ("Failed to seek to offset 0!\n");
470 return -1; 470 return -1;
471 } 471 }
472 /* Process gzip header */ 472 /* Process gzip header */
473 rsize = bfds_read (cfs->bfds, hdata, sizeof (hdata)); 473 rsize = bfds_read (cfs->bfds, hdata, sizeof (hdata));
474 if ( (-1 == rsize) || 474 if ( (-1 == rsize) ||
@@ -478,72 +478,74 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
478 gzip_header_length += 2 + (hdata[10] & 0xff) + ((hdata[11] & 0xff) * 256); 478 gzip_header_length += 2 + (hdata[10] & 0xff) + ((hdata[11] & 0xff) * 256);
479 479
480 if (0 != (hdata[3] & 0x8)) 480 if (0 != (hdata[3] & 0x8))
481 {
482 /* FNAME set */
483 char fname[1024];
484 char *cptr;
485 size_t len;
486 ssize_t buf_bytes;
487
488 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
489 SEEK_SET))
481 { 490 {
482 /* FNAME set */ 491 LOG ("Corrupt gzip, failed to seek to end of header\n");
483 char fname[1024]; 492 return -1;
484 char *cptr;
485 size_t len;
486 ssize_t buf_bytes;
487
488 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length, SEEK_SET))
489 {
490 LOG ("Corrupt gzip, failed to seek to end of header\n");
491 return -1;
492 }
493 buf_bytes = bfds_read (cfs->bfds, fname, sizeof (fname));
494 if (buf_bytes <= 0)
495 {
496 LOG ("Corrupt gzip, failed to read filename\n");
497 return -1;
498 }
499 if (NULL == (cptr = memchr (fname, 0, buf_bytes)))
500 {
501 LOG ("Corrupt gzip, failed to read filename terminator\n");
502 return -1;
503 }
504 len = cptr - fname;
505 if ( (NULL != proc) &&
506 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
507 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
508 fname,
509 len)) )
510 return 0; /* done */
511 gzip_header_length += len + 1;
512 } 493 }
494 buf_bytes = bfds_read (cfs->bfds, fname, sizeof (fname));
495 if (buf_bytes <= 0)
496 {
497 LOG ("Corrupt gzip, failed to read filename\n");
498 return -1;
499 }
500 if (NULL == (cptr = memchr (fname, 0, buf_bytes)))
501 {
502 LOG ("Corrupt gzip, failed to read filename terminator\n");
503 return -1;
504 }
505 len = cptr - fname;
506 if ( (NULL != proc) &&
507 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_FILENAME,
508 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
509 fname,
510 len)) )
511 return 0; /* done */
512 gzip_header_length += len + 1;
513 }
513 514
514 if (0 != (hdata[3] & 0x16)) 515 if (0 != (hdata[3] & 0x16))
516 {
517 /* FCOMMENT set */
518 char fcomment[1024];
519 char *cptr;
520 ssize_t buf_bytes;
521 size_t len;
522
523 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length,
524 SEEK_SET))
515 { 525 {
516 /* FCOMMENT set */ 526 LOG ("Corrupt gzip, failed to seek to end of header\n");
517 char fcomment[1024]; 527 return -1;
518 char *cptr; 528 }
519 ssize_t buf_bytes; 529 buf_bytes = bfds_read (cfs->bfds, fcomment, sizeof (fcomment));
520 size_t len; 530 if (buf_bytes <= 0)
521 531 {
522 if (gzip_header_length > bfds_seek (cfs->bfds, gzip_header_length, SEEK_SET)) 532 LOG ("Corrupt gzip, failed to read comment\n");
523 { 533 return -1;
524 LOG ("Corrupt gzip, failed to seek to end of header\n"); 534 }
525 return -1; 535 if (NULL == (cptr = memchr (fcomment, 0, buf_bytes)))
526 } 536 {
527 buf_bytes = bfds_read (cfs->bfds, fcomment, sizeof (fcomment)); 537 LOG ("Corrupt gzip, failed to read comment terminator\n");
528 if (buf_bytes <= 0) 538 return -1;
529 {
530 LOG ("Corrupt gzip, failed to read comment\n");
531 return -1;
532 }
533 if (NULL == (cptr = memchr (fcomment, 0, buf_bytes)))
534 {
535 LOG ("Corrupt gzip, failed to read comment terminator\n");
536 return -1;
537 }
538 len = cptr - fcomment;
539 if ( (NULL != proc) &&
540 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
541 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
542 (const char *) fcomment,
543 len)) )
544 return 0; /* done */
545 gzip_header_length += len + 1;
546 } 539 }
540 len = cptr - fcomment;
541 if ( (NULL != proc) &&
542 (0 != proc (proc_cls, "<zlib>", EXTRACTOR_METATYPE_COMMENT,
543 EXTRACTOR_METAFORMAT_C_STRING, "text/plain",
544 (const char *) fcomment,
545 len)) )
546 return 0; /* done */
547 gzip_header_length += len + 1;
548 }
547 if (0 != (hdata[3] & 0x2)) /* FCHRC set */ 549 if (0 != (hdata[3] & 0x2)) /* FCHRC set */
548 gzip_header_length += 2; 550 gzip_header_length += 2;
549 memset (&cfs->strm, 0, sizeof (z_stream)); 551 memset (&cfs->strm, 0, sizeof (z_stream));
@@ -556,10 +558,10 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
556 558
557 if (cfs->gzip_header_length != 559 if (cfs->gzip_header_length !=
558 bfds_seek (cfs->bfds, cfs->gzip_header_length, SEEK_SET)) 560 bfds_seek (cfs->bfds, cfs->gzip_header_length, SEEK_SET))
559 { 561 {
560 LOG ("Failed to seek to start to initialize gzip decompressor\n"); 562 LOG ("Failed to seek to start to initialize gzip decompressor\n");
561 return -1; 563 return -1;
562 } 564 }
563 cfs->strm.avail_out = COM_CHUNK_SIZE; 565 cfs->strm.avail_out = COM_CHUNK_SIZE;
564 /* 566 /*
565 * note: maybe plain inflateInit(&strm) is adequate, 567 * note: maybe plain inflateInit(&strm) is adequate,
@@ -567,20 +569,21 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
567 * 569 *
568 * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ; 570 * ZLIB_VERNUM isn't defined by zlib version 1.1.4 ;
569 * there might be a better check. 571 * there might be a better check.
570 */ 572 */if (Z_OK != inflateInit2 (&cfs->strm,
571 if (Z_OK != inflateInit2 (&cfs->strm,
572#ifdef ZLIB_VERNUM 573#ifdef ZLIB_VERNUM
573 15 + 32 574 15 + 32
574#else 575#else
575 - MAX_WBITS 576 -MAX_WBITS
576#endif 577#endif
577 )) 578 ))
578 { 579 {
579 LOG ("Failed to initialize zlib decompression\n"); 580 LOG ("Failed to initialize zlib decompression\n");
580 return -1; 581 return -1;
581 } 582 }
582 return 1; 583 return 1;
583} 584}
585
586
584#endif 587#endif
585 588
586 589
@@ -596,24 +599,26 @@ cfs_init_decompressor_zlib (struct CompressedFileSource *cfs,
596 */ 599 */
597static int 600static int
598cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs, 601cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
599 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 602 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
600{ 603{
601 if (0 != 604 if (0 !=
602 bfds_seek (cfs->bfds, 0, SEEK_SET)) 605 bfds_seek (cfs->bfds, 0, SEEK_SET))
603 { 606 {
604 LOG ("Failed to seek to start to initialize BZ2 decompressor\n"); 607 LOG ("Failed to seek to start to initialize BZ2 decompressor\n");
605 return -1; 608 return -1;
606 } 609 }
607 memset (&cfs->bstrm, 0, sizeof (bz_stream)); 610 memset (&cfs->bstrm, 0, sizeof (bz_stream));
608 if (BZ_OK != 611 if (BZ_OK !=
609 BZ2_bzDecompressInit (&cfs->bstrm, 0, 0)) 612 BZ2_bzDecompressInit (&cfs->bstrm, 0, 0))
610 { 613 {
611 LOG ("Failed to initialize BZ2 decompressor\n"); 614 LOG ("Failed to initialize BZ2 decompressor\n");
612 return -1; 615 return -1;
613 } 616 }
614 cfs->bstrm.avail_out = COM_CHUNK_SIZE; 617 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
615 return 1; 618 return 1;
616} 619}
620
621
617#endif 622#endif
618 623
619 624
@@ -628,24 +633,24 @@ cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs,
628 */ 633 */
629static int 634static int
630cfs_init_decompressor (struct CompressedFileSource *cfs, 635cfs_init_decompressor (struct CompressedFileSource *cfs,
631 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 636 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
632{ 637{
633 cfs->result_pos = 0; 638 cfs->result_pos = 0;
634 cfs->fpos = 0; 639 cfs->fpos = 0;
635 switch (cfs->compression_type) 640 switch (cfs->compression_type)
636 { 641 {
637#if HAVE_ZLIB 642#if HAVE_ZLIB
638 case COMP_TYPE_ZLIB: 643 case COMP_TYPE_ZLIB:
639 return cfs_init_decompressor_zlib (cfs, proc, proc_cls); 644 return cfs_init_decompressor_zlib (cfs, proc, proc_cls);
640#endif 645#endif
641#if HAVE_LIBBZ2 646#if HAVE_LIBBZ2
642 case COMP_TYPE_BZ2: 647 case COMP_TYPE_BZ2:
643 return cfs_init_decompressor_bz2 (cfs, proc, proc_cls); 648 return cfs_init_decompressor_bz2 (cfs, proc, proc_cls);
644#endif 649#endif
645 default: 650 default:
646 LOG ("invalid compression type selected\n"); 651 LOG ("invalid compression type selected\n");
647 return -1; 652 return -1;
648 } 653 }
649} 654}
650 655
651 656
@@ -662,6 +667,8 @@ cfs_deinit_decompressor_zlib (struct CompressedFileSource *cfs)
662 inflateEnd (&cfs->strm); 667 inflateEnd (&cfs->strm);
663 return 1; 668 return 1;
664} 669}
670
671
665#endif 672#endif
666 673
667 674
@@ -678,6 +685,8 @@ cfs_deinit_decompressor_bz2 (struct CompressedFileSource *cfs)
678 BZ2_bzDecompressEnd (&cfs->bstrm); 685 BZ2_bzDecompressEnd (&cfs->bstrm);
679 return 1; 686 return 1;
680} 687}
688
689
681#endif 690#endif
682 691
683 692
@@ -691,19 +700,19 @@ static int
691cfs_deinit_decompressor (struct CompressedFileSource *cfs) 700cfs_deinit_decompressor (struct CompressedFileSource *cfs)
692{ 701{
693 switch (cfs->compression_type) 702 switch (cfs->compression_type)
694 { 703 {
695#if HAVE_ZLIB 704#if HAVE_ZLIB
696 case COMP_TYPE_ZLIB: 705 case COMP_TYPE_ZLIB:
697 return cfs_deinit_decompressor_zlib (cfs); 706 return cfs_deinit_decompressor_zlib (cfs);
698#endif 707#endif
699#if HAVE_LIBBZ2 708#if HAVE_LIBBZ2
700 case COMP_TYPE_BZ2: 709 case COMP_TYPE_BZ2:
701 return cfs_deinit_decompressor_bz2 (cfs); 710 return cfs_deinit_decompressor_bz2 (cfs);
702#endif 711#endif
703 default: 712 default:
704 LOG ("invalid compression type selected\n"); 713 LOG ("invalid compression type selected\n");
705 return -1; 714 return -1;
706 } 715 }
707} 716}
708 717
709 718
@@ -750,28 +759,28 @@ cfs_destroy (struct CompressedFileSource *cfs)
750 */ 759 */
751struct CompressedFileSource * 760struct CompressedFileSource *
752cfs_new (struct BufferedFileDataSource *bfds, 761cfs_new (struct BufferedFileDataSource *bfds,
753 int64_t fsize, 762 int64_t fsize,
754 enum ExtractorCompressionType compression_type, 763 enum ExtractorCompressionType compression_type,
755 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 764 EXTRACTOR_MetaDataProcessor proc, void *proc_cls)
756{ 765{
757 struct CompressedFileSource *cfs; 766 struct CompressedFileSource *cfs;
758 767
759 if (NULL == (cfs = malloc (sizeof (struct CompressedFileSource)))) 768 if (NULL == (cfs = malloc (sizeof (struct CompressedFileSource))))
760 { 769 {
761 LOG_STRERROR ("malloc"); 770 LOG_STRERROR ("malloc");
762 return NULL; 771 return NULL;
763 } 772 }
764 memset (cfs, 0, sizeof (struct CompressedFileSource)); 773 memset (cfs, 0, sizeof (struct CompressedFileSource));
765 cfs->compression_type = compression_type; 774 cfs->compression_type = compression_type;
766 cfs->bfds = bfds; 775 cfs->bfds = bfds;
767 cfs->fsize = fsize; 776 cfs->fsize = fsize;
768 cfs->uncompressed_size = -1; 777 cfs->uncompressed_size = -1;
769 if (1 != cfs_init_decompressor (cfs, 778 if (1 != cfs_init_decompressor (cfs,
770 proc, proc_cls)) 779 proc, proc_cls))
771 { 780 {
772 free (cfs); 781 free (cfs);
773 return NULL; 782 return NULL;
774 } 783 }
775 return cfs; 784 return cfs;
776} 785}
777 786
@@ -789,8 +798,8 @@ cfs_new (struct BufferedFileDataSource *bfds,
789 */ 798 */
790static ssize_t 799static ssize_t
791cfs_read_zlib (struct CompressedFileSource *cfs, 800cfs_read_zlib (struct CompressedFileSource *cfs,
792 void *data, 801 void *data,
793 size_t size) 802 size_t size)
794{ 803{
795 char *dst = data; 804 char *dst = data;
796 int ret; 805 int ret;
@@ -799,77 +808,79 @@ cfs_read_zlib (struct CompressedFileSource *cfs,
799 unsigned char buf[COM_CHUNK_SIZE]; 808 unsigned char buf[COM_CHUNK_SIZE];
800 809
801 if (cfs->fpos == cfs->uncompressed_size) 810 if (cfs->fpos == cfs->uncompressed_size)
802 { 811 {
803 /* end of file */ 812 /* end of file */
804 return 0; 813 return 0;
805 } 814 }
806 rc = 0; 815 rc = 0;
807 if (COM_CHUNK_SIZE > cfs->strm.avail_out + cfs->result_pos) 816 if (COM_CHUNK_SIZE > cfs->strm.avail_out + cfs->result_pos)
808 { 817 {
809 /* got left-over decompressed data from previous round! */ 818 /* got left-over decompressed data from previous round! */
810 in = COM_CHUNK_SIZE - (cfs->strm.avail_out + cfs->result_pos); 819 in = COM_CHUNK_SIZE - (cfs->strm.avail_out + cfs->result_pos);
811 if (in > size) 820 if (in > size)
812 in = size; 821 in = size;
813 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in); 822 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
814 cfs->fpos += in; 823 cfs->fpos += in;
815 cfs->result_pos += in; 824 cfs->result_pos += in;
816 rc += in; 825 rc += in;
817 } 826 }
818 ret = Z_OK; 827 ret = Z_OK;
819 while ( (rc < size) && (Z_STREAM_END != ret) ) 828 while ( (rc < size) && (Z_STREAM_END != ret) )
829 {
830 /* read block from original data source */
831 in = bfds_read (cfs->bfds,
832 buf, sizeof (buf));
833 if (in < 0)
820 { 834 {
821 /* read block from original data source */ 835 LOG ("unexpected EOF\n");
822 in = bfds_read (cfs->bfds, 836 return -1; /* unexpected EOF */
823 buf, sizeof (buf));
824 if (in < 0)
825 {
826 LOG ("unexpected EOF\n");
827 return -1; /* unexpected EOF */
828 }
829 if (0 == in)
830 {
831 cfs->uncompressed_size = cfs->fpos;
832 return rc;
833 }
834 cfs->strm.next_in = buf;
835 cfs->strm.avail_in = (uInt) in;
836 cfs->strm.next_out = (unsigned char *) cfs->result;
837 cfs->strm.avail_out = COM_CHUNK_SIZE;
838 cfs->result_pos = 0;
839 ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
840 if ( (Z_OK != ret) && (Z_STREAM_END != ret) )
841 {
842 LOG ("unexpected gzip inflate error: %d\n", ret);
843 return -1; /* unexpected error */
844 }
845 /* go backwards by the number of bytes left in the buffer */
846 if (-1 == bfds_seek (cfs->bfds, - (int64_t) cfs->strm.avail_in, SEEK_CUR))
847 {
848 LOG ("seek failed\n");
849 return -1;
850 }
851 /* copy decompressed bytes to target buffer */
852 in = COM_CHUNK_SIZE - cfs->strm.avail_out;
853 if (in > size - rc)
854 {
855 if (Z_STREAM_END == ret)
856 {
857 cfs->uncompressed_size = cfs->fpos + in;
858 ret = Z_OK;
859 }
860 in = size - rc;
861 }
862 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
863 cfs->fpos += in;
864 cfs->result_pos += in;
865 rc += in;
866 } 837 }
867 if (Z_STREAM_END == ret) 838 if (0 == in)
868 { 839 {
869 cfs->uncompressed_size = cfs->fpos; 840 cfs->uncompressed_size = cfs->fpos;
841 return rc;
842 }
843 cfs->strm.next_in = buf;
844 cfs->strm.avail_in = (uInt) in;
845 cfs->strm.next_out = (unsigned char *) cfs->result;
846 cfs->strm.avail_out = COM_CHUNK_SIZE;
847 cfs->result_pos = 0;
848 ret = inflate (&cfs->strm, Z_SYNC_FLUSH);
849 if ( (Z_OK != ret) && (Z_STREAM_END != ret) )
850 {
851 LOG ("unexpected gzip inflate error: %d\n", ret);
852 return -1; /* unexpected error */
853 }
854 /* go backwards by the number of bytes left in the buffer */
855 if (-1 == bfds_seek (cfs->bfds, -(int64_t) cfs->strm.avail_in, SEEK_CUR))
856 {
857 LOG ("seek failed\n");
858 return -1;
859 }
860 /* copy decompressed bytes to target buffer */
861 in = COM_CHUNK_SIZE - cfs->strm.avail_out;
862 if (in > size - rc)
863 {
864 if (Z_STREAM_END == ret)
865 {
866 cfs->uncompressed_size = cfs->fpos + in;
867 ret = Z_OK;
868 }
869 in = size - rc;
870 } 870 }
871 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
872 cfs->fpos += in;
873 cfs->result_pos += in;
874 rc += in;
875 }
876 if (Z_STREAM_END == ret)
877 {
878 cfs->uncompressed_size = cfs->fpos;
879 }
871 return rc; 880 return rc;
872} 881}
882
883
873#endif 884#endif
874 885
875 886
@@ -886,8 +897,8 @@ cfs_read_zlib (struct CompressedFileSource *cfs,
886 */ 897 */
887static ssize_t 898static ssize_t
888cfs_read_bz2 (struct CompressedFileSource *cfs, 899cfs_read_bz2 (struct CompressedFileSource *cfs,
889 void *data, 900 void *data,
890 size_t size) 901 size_t size)
891{ 902{
892 char *dst = data; 903 char *dst = data;
893 int ret; 904 int ret;
@@ -896,77 +907,79 @@ cfs_read_bz2 (struct CompressedFileSource *cfs,
896 char buf[COM_CHUNK_SIZE]; 907 char buf[COM_CHUNK_SIZE];
897 908
898 if (cfs->fpos == cfs->uncompressed_size) 909 if (cfs->fpos == cfs->uncompressed_size)
899 { 910 {
900 /* end of file */ 911 /* end of file */
901 return 0; 912 return 0;
902 } 913 }
903 rc = 0; 914 rc = 0;
904 if (COM_CHUNK_SIZE > cfs->bstrm.avail_out + cfs->result_pos) 915 if (COM_CHUNK_SIZE > cfs->bstrm.avail_out + cfs->result_pos)
905 { 916 {
906 /* got left-over decompressed data from previous round! */ 917 /* got left-over decompressed data from previous round! */
907 in = COM_CHUNK_SIZE - (cfs->bstrm.avail_out + cfs->result_pos); 918 in = COM_CHUNK_SIZE - (cfs->bstrm.avail_out + cfs->result_pos);
908 if (in > size) 919 if (in > size)
909 in = size; 920 in = size;
910 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in); 921 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
911 cfs->fpos += in; 922 cfs->fpos += in;
912 cfs->result_pos += in; 923 cfs->result_pos += in;
913 rc += in; 924 rc += in;
914 } 925 }
915 ret = BZ_OK; 926 ret = BZ_OK;
916 while ( (rc < size) && (BZ_STREAM_END != ret) ) 927 while ( (rc < size) && (BZ_STREAM_END != ret) )
928 {
929 /* read block from original data source */
930 in = bfds_read (cfs->bfds,
931 buf, sizeof (buf));
932 if (in < 0)
917 { 933 {
918 /* read block from original data source */ 934 LOG ("unexpected EOF\n");
919 in = bfds_read (cfs->bfds, 935 return -1; /* unexpected EOF */
920 buf, sizeof (buf));
921 if (in < 0)
922 {
923 LOG ("unexpected EOF\n");
924 return -1; /* unexpected EOF */
925 }
926 if (0 == in)
927 {
928 cfs->uncompressed_size = cfs->fpos;
929 return rc;
930 }
931 cfs->bstrm.next_in = buf;
932 cfs->bstrm.avail_in = (unsigned int) in;
933 cfs->bstrm.next_out = cfs->result;
934 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
935 cfs->result_pos = 0;
936 ret = BZ2_bzDecompress (&cfs->bstrm);
937 if ( (BZ_OK != ret) && (BZ_STREAM_END != ret) )
938 {
939 LOG ("unexpected bzip2 decompress error: %d\n", ret);
940 return -1; /* unexpected error */
941 }
942 /* go backwards by the number of bytes left in the buffer */
943 if (-1 == bfds_seek (cfs->bfds, - (int64_t) cfs->bstrm.avail_in, SEEK_CUR))
944 {
945 LOG ("seek failed\n");
946 return -1;
947 }
948 /* copy decompressed bytes to target buffer */
949 in = COM_CHUNK_SIZE - cfs->bstrm.avail_out;
950 if (in > size - rc)
951 {
952 if (BZ_STREAM_END == ret)
953 {
954 cfs->uncompressed_size = cfs->fpos + in;
955 ret = BZ_OK;
956 }
957 in = size - rc;
958 }
959 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
960 cfs->fpos += in;
961 cfs->result_pos += in;
962 rc += in;
963 } 936 }
964 if (BZ_STREAM_END == ret) 937 if (0 == in)
965 { 938 {
966 cfs->uncompressed_size = cfs->fpos; 939 cfs->uncompressed_size = cfs->fpos;
940 return rc;
941 }
942 cfs->bstrm.next_in = buf;
943 cfs->bstrm.avail_in = (unsigned int) in;
944 cfs->bstrm.next_out = cfs->result;
945 cfs->bstrm.avail_out = COM_CHUNK_SIZE;
946 cfs->result_pos = 0;
947 ret = BZ2_bzDecompress (&cfs->bstrm);
948 if ( (BZ_OK != ret) && (BZ_STREAM_END != ret) )
949 {
950 LOG ("unexpected bzip2 decompress error: %d\n", ret);
951 return -1; /* unexpected error */
952 }
953 /* go backwards by the number of bytes left in the buffer */
954 if (-1 == bfds_seek (cfs->bfds, -(int64_t) cfs->bstrm.avail_in, SEEK_CUR))
955 {
956 LOG ("seek failed\n");
957 return -1;
967 } 958 }
959 /* copy decompressed bytes to target buffer */
960 in = COM_CHUNK_SIZE - cfs->bstrm.avail_out;
961 if (in > size - rc)
962 {
963 if (BZ_STREAM_END == ret)
964 {
965 cfs->uncompressed_size = cfs->fpos + in;
966 ret = BZ_OK;
967 }
968 in = size - rc;
969 }
970 memcpy (&dst[rc], &cfs->result[cfs->result_pos], in);
971 cfs->fpos += in;
972 cfs->result_pos += in;
973 rc += in;
974 }
975 if (BZ_STREAM_END == ret)
976 {
977 cfs->uncompressed_size = cfs->fpos;
978 }
968 return rc; 979 return rc;
969} 980}
981
982
970#endif 983#endif
971 984
972 985
@@ -982,23 +995,23 @@ cfs_read_bz2 (struct CompressedFileSource *cfs,
982 */ 995 */
983static ssize_t 996static ssize_t
984cfs_read (struct CompressedFileSource *cfs, 997cfs_read (struct CompressedFileSource *cfs,
985 void *data, 998 void *data,
986 size_t size) 999 size_t size)
987{ 1000{
988 switch (cfs->compression_type) 1001 switch (cfs->compression_type)
989 { 1002 {
990#if HAVE_ZLIB 1003#if HAVE_ZLIB
991 case COMP_TYPE_ZLIB: 1004 case COMP_TYPE_ZLIB:
992 return cfs_read_zlib (cfs, data, size); 1005 return cfs_read_zlib (cfs, data, size);
993#endif 1006#endif
994#if HAVE_LIBBZ2 1007#if HAVE_LIBBZ2
995 case COMP_TYPE_BZ2: 1008 case COMP_TYPE_BZ2:
996 return cfs_read_bz2 (cfs, data, size); 1009 return cfs_read_bz2 (cfs, data, size);
997#endif 1010#endif
998 default: 1011 default:
999 LOG ("invalid compression type selected\n"); 1012 LOG ("invalid compression type selected\n");
1000 return -1; 1013 return -1;
1001 } 1014 }
1002} 1015}
1003 1016
1004 1017
@@ -1014,104 +1027,105 @@ cfs_read (struct CompressedFileSource *cfs,
1014 */ 1027 */
1015static int64_t 1028static int64_t
1016cfs_seek (struct CompressedFileSource *cfs, 1029cfs_seek (struct CompressedFileSource *cfs,
1017 int64_t position, 1030 int64_t position,
1018 int whence) 1031 int whence)
1019{ 1032{
1020 uint64_t nposition; 1033 uint64_t nposition;
1021 int64_t delta; 1034 int64_t delta;
1022 1035
1023 switch (whence) 1036 switch (whence)
1037 {
1038 case SEEK_CUR:
1039 if (cfs->fpos + position < 0)
1040 {
1041 /* underflow */
1042 LOG ("Invalid seek operation\n");
1043 return -1;
1044 }
1045 if ( (-1 != cfs->uncompressed_size) &&
1046 (cfs->fpos + position > cfs->uncompressed_size) )
1047 {
1048 LOG ("Invalid seek operation\n");
1049 return -1;
1050 }
1051 nposition = cfs->fpos + position;
1052 break;
1053 case SEEK_END:
1054 ASSERT (-1 != cfs->uncompressed_size);
1055 if (position > 0)
1024 { 1056 {
1025 case SEEK_CUR:
1026 if (cfs->fpos + position < 0)
1027 {
1028 /* underflow */
1029 LOG ("Invalid seek operation\n");
1030 return -1;
1031 }
1032 if ( (-1 != cfs->uncompressed_size) &&
1033 (cfs->fpos + position > cfs->uncompressed_size) )
1034 {
1035 LOG ("Invalid seek operation\n");
1036 return -1;
1037 }
1038 nposition = cfs->fpos + position;
1039 break;
1040 case SEEK_END:
1041 ASSERT (-1 != cfs->uncompressed_size);
1042 if (position > 0)
1043 {
1044 LOG ("Invalid seek operation\n");
1045 return -1;
1046 }
1047 if (cfs->uncompressed_size < - position)
1048 {
1049 LOG ("Invalid seek operation\n");
1050 return -1;
1051 }
1052 nposition = cfs->uncompressed_size + position;
1053 break;
1054 case SEEK_SET:
1055 if (position < 0)
1056 {
1057 LOG ("Invalid seek operation\n");
1058 return -1;
1059 }
1060 if ( (-1 != cfs->uncompressed_size) &&
1061 (cfs->uncompressed_size < position ) )
1062 {
1063 LOG ("Invalid seek operation\n");
1064 return -1;
1065 }
1066 nposition = (uint64_t) position;
1067 break;
1068 default:
1069 LOG ("Invalid seek operation\n"); 1057 LOG ("Invalid seek operation\n");
1070 return -1; 1058 return -1;
1071 } 1059 }
1060 if (cfs->uncompressed_size < -position)
1061 {
1062 LOG ("Invalid seek operation\n");
1063 return -1;
1064 }
1065 nposition = cfs->uncompressed_size + position;
1066 break;
1067 case SEEK_SET:
1068 if (position < 0)
1069 {
1070 LOG ("Invalid seek operation\n");
1071 return -1;
1072 }
1073 if ( (-1 != cfs->uncompressed_size) &&
1074 (cfs->uncompressed_size < position) )
1075 {
1076 LOG ("Invalid seek operation\n");
1077 return -1;
1078 }
1079 nposition = (uint64_t) position;
1080 break;
1081 default:
1082 LOG ("Invalid seek operation\n");
1083 return -1;
1084 }
1072 delta = nposition - cfs->fpos; 1085 delta = nposition - cfs->fpos;
1073 if (delta < 0) 1086 if (delta < 0)
1087 {
1088 if (cfs->result_pos >= -delta)
1074 { 1089 {
1075 if (cfs->result_pos >= - delta) 1090 cfs->result_pos += delta;
1076 { 1091 cfs->fpos += delta;
1077 cfs->result_pos += delta; 1092 delta = 0;
1078 cfs->fpos += delta;
1079 delta = 0;
1080 }
1081 else
1082 {
1083 if (-1 == cfs_reset_stream (cfs))
1084 {
1085 LOG ("Failed to restart compressed stream for seek operation\n");
1086 return -1;
1087 }
1088 delta = nposition;
1089 }
1090 } 1093 }
1094 else
1095 {
1096 if (-1 == cfs_reset_stream (cfs))
1097 {
1098 LOG ("Failed to restart compressed stream for seek operation\n");
1099 return -1;
1100 }
1101 delta = nposition;
1102 }
1103 }
1091 while (delta > 0) 1104 while (delta > 0)
1105 {
1106 char buf[COM_CHUNK_SIZE];
1107 size_t max;
1108 int64_t ret;
1109
1110 max = (sizeof (buf) > delta) ? delta : sizeof (buf);
1111 ret = cfs_read (cfs, buf, max);
1112 if (-1 == ret)
1113 {
1114 LOG ("Failed to read decompressed stream for seek operation\n");
1115 return -1;
1116 }
1117 if (0 == ret)
1092 { 1118 {
1093 char buf[COM_CHUNK_SIZE]; 1119 LOG (
1094 size_t max; 1120 "Reached unexpected end of stream at %llu during seek operation to %llu (%d left)\n",
1095 int64_t ret; 1121 (unsigned long long) cfs->fpos,
1096 1122 (unsigned long long) nposition,
1097 max = (sizeof (buf) > delta) ? delta : sizeof (buf); 1123 delta);
1098 ret = cfs_read (cfs, buf, max); 1124 return -1;
1099 if (-1 == ret)
1100 {
1101 LOG ("Failed to read decompressed stream for seek operation\n");
1102 return -1;
1103 }
1104 if (0 == ret)
1105 {
1106 LOG ("Reached unexpected end of stream at %llu during seek operation to %llu (%d left)\n",
1107 (unsigned long long) cfs->fpos,
1108 (unsigned long long) nposition,
1109 delta);
1110 return -1;
1111 }
1112 ASSERT (ret <= delta);
1113 delta -= ret;
1114 } 1125 }
1126 ASSERT (ret <= delta);
1127 delta -= ret;
1128 }
1115 return cfs->fpos; 1129 return cfs->fpos;
1116} 1130}
1117 1131
@@ -1186,8 +1200,8 @@ struct EXTRACTOR_Datasource
1186 */ 1200 */
1187struct EXTRACTOR_Datasource * 1201struct EXTRACTOR_Datasource *
1188EXTRACTOR_datasource_create_from_file_ (const char *filename, 1202EXTRACTOR_datasource_create_from_file_ (const char *filename,
1189 EXTRACTOR_MetaDataProcessor proc, 1203 EXTRACTOR_MetaDataProcessor proc,
1190 void *proc_cls) 1204 void *proc_cls)
1191{ 1205{
1192 struct BufferedFileDataSource *bfds; 1206 struct BufferedFileDataSource *bfds;
1193 struct EXTRACTOR_Datasource *ds; 1207 struct EXTRACTOR_Datasource *ds;
@@ -1201,56 +1215,56 @@ EXTRACTOR_datasource_create_from_file_ (const char *filename,
1201#endif 1215#endif
1202 1216
1203 if (-1 == (fd = OPEN (filename, O_RDONLY | O_LARGEFILE | winmode))) 1217 if (-1 == (fd = OPEN (filename, O_RDONLY | O_LARGEFILE | winmode)))
1204 { 1218 {
1205 LOG_STRERROR_FILE ("open", filename); 1219 LOG_STRERROR_FILE ("open", filename);
1206 return NULL; 1220 return NULL;
1207 } 1221 }
1208 if ( (0 != FSTAT (fd, &sb)) || 1222 if ( (0 != FSTAT (fd, &sb)) ||
1209 (S_ISDIR (sb.st_mode)) ) 1223 (S_ISDIR (sb.st_mode)) )
1210 { 1224 {
1211 if (! S_ISDIR (sb.st_mode)) 1225 if (! S_ISDIR (sb.st_mode))
1212 LOG_STRERROR_FILE ("fstat", filename); 1226 LOG_STRERROR_FILE ("fstat", filename);
1213 else 1227 else
1214 LOG ("Skipping directory `%s'\n", filename); 1228 LOG ("Skipping directory `%s'\n", filename);
1215 (void) CLOSE (fd); 1229 (void) CLOSE (fd);
1216 return NULL; 1230 return NULL;
1217 } 1231 }
1218 fsize = (int64_t) sb.st_size; 1232 fsize = (int64_t) sb.st_size;
1219 if (0 == fsize) 1233 if (0 == fsize)
1220 { 1234 {
1221 (void) CLOSE (fd); 1235 (void) CLOSE (fd);
1222 return NULL; 1236 return NULL;
1223 } 1237 }
1224 bfds = bfds_new (NULL, fd, fsize); 1238 bfds = bfds_new (NULL, fd, fsize);
1225 if (NULL == bfds) 1239 if (NULL == bfds)
1226 { 1240 {
1227 (void) CLOSE (fd); 1241 (void) CLOSE (fd);
1228 return NULL; 1242 return NULL;
1229 } 1243 }
1230 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource)))) 1244 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource))))
1231 { 1245 {
1232 LOG_STRERROR ("malloc"); 1246 LOG_STRERROR ("malloc");
1233 bfds_delete (bfds); 1247 bfds_delete (bfds);
1234 (void) CLOSE (fd); 1248 (void) CLOSE (fd);
1235 return NULL; 1249 return NULL;
1236 } 1250 }
1237 ds->bfds = bfds; 1251 ds->bfds = bfds;
1238 ds->fd = fd; 1252 ds->fd = fd;
1239 ds->cfs = NULL; 1253 ds->cfs = NULL;
1240 ct = get_compression_type (bfds); 1254 ct = get_compression_type (bfds);
1241 if ( (COMP_TYPE_ZLIB == ct) || 1255 if ( (COMP_TYPE_ZLIB == ct) ||
1242 (COMP_TYPE_BZ2 == ct) ) 1256 (COMP_TYPE_BZ2 == ct) )
1257 {
1258 ds->cfs = cfs_new (bfds, fsize, ct, proc, proc_cls);
1259 if (NULL == ds->cfs)
1243 { 1260 {
1244 ds->cfs = cfs_new (bfds, fsize, ct, proc, proc_cls); 1261 LOG ("Failed to initialize decompressor\n");
1245 if (NULL == ds->cfs) 1262 bfds_delete (bfds);
1246 { 1263 free (ds);
1247 LOG ("Failed to initialize decompressor\n"); 1264 (void) CLOSE (fd);
1248 bfds_delete (bfds); 1265 return NULL;
1249 free (ds);
1250 (void) CLOSE (fd);
1251 return NULL;
1252 }
1253 } 1266 }
1267 }
1254 return ds; 1268 return ds;
1255} 1269}
1256 1270
@@ -1266,8 +1280,9 @@ EXTRACTOR_datasource_create_from_file_ (const char *filename,
1266 */ 1280 */
1267struct EXTRACTOR_Datasource * 1281struct EXTRACTOR_Datasource *
1268EXTRACTOR_datasource_create_from_buffer_ (const char *buf, 1282EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
1269 size_t size, 1283 size_t size,
1270 EXTRACTOR_MetaDataProcessor proc, void *proc_cls) 1284 EXTRACTOR_MetaDataProcessor proc,
1285 void *proc_cls)
1271{ 1286{
1272 struct BufferedFileDataSource *bfds; 1287 struct BufferedFileDataSource *bfds;
1273 struct EXTRACTOR_Datasource *ds; 1288 struct EXTRACTOR_Datasource *ds;
@@ -1276,32 +1291,32 @@ EXTRACTOR_datasource_create_from_buffer_ (const char *buf,
1276 if (0 == size) 1291 if (0 == size)
1277 return NULL; 1292 return NULL;
1278 if (NULL == (bfds = bfds_new (buf, -1, size))) 1293 if (NULL == (bfds = bfds_new (buf, -1, size)))
1279 { 1294 {
1280 LOG ("Failed to initialize buffer data source\n"); 1295 LOG ("Failed to initialize buffer data source\n");
1281 return NULL; 1296 return NULL;
1282 } 1297 }
1283 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource)))) 1298 if (NULL == (ds = malloc (sizeof (struct EXTRACTOR_Datasource))))
1284 { 1299 {
1285 LOG_STRERROR ("malloc"); 1300 LOG_STRERROR ("malloc");
1286 bfds_delete (bfds); 1301 bfds_delete (bfds);
1287 return NULL; 1302 return NULL;
1288 } 1303 }
1289 ds->bfds = bfds; 1304 ds->bfds = bfds;
1290 ds->fd = -1; 1305 ds->fd = -1;
1291 ds->cfs = NULL; 1306 ds->cfs = NULL;
1292 ct = get_compression_type (bfds); 1307 ct = get_compression_type (bfds);
1293 if ( (COMP_TYPE_ZLIB == ct) || 1308 if ( (COMP_TYPE_ZLIB == ct) ||
1294 (COMP_TYPE_BZ2 == ct) ) 1309 (COMP_TYPE_BZ2 == ct) )
1310 {
1311 ds->cfs = cfs_new (bfds, size, ct, proc, proc_cls);
1312 if (NULL == ds->cfs)
1295 { 1313 {
1296 ds->cfs = cfs_new (bfds, size, ct, proc, proc_cls); 1314 LOG ("Failed to initialize decompressor\n");
1297 if (NULL == ds->cfs) 1315 bfds_delete (bfds);
1298 { 1316 free (ds);
1299 LOG ("Failed to initialize decompressor\n"); 1317 return NULL;
1300 bfds_delete (bfds);
1301 free (ds);
1302 return NULL;
1303 }
1304 } 1318 }
1319 }
1305 return ds; 1320 return ds;
1306} 1321}
1307 1322
@@ -1334,8 +1349,8 @@ EXTRACTOR_datasource_destroy_ (struct EXTRACTOR_Datasource *ds)
1334 */ 1349 */
1335ssize_t 1350ssize_t
1336EXTRACTOR_datasource_read_ (void *cls, 1351EXTRACTOR_datasource_read_ (void *cls,
1337 void *data, 1352 void *data,
1338 size_t size) 1353 size_t size)
1339{ 1354{
1340 struct EXTRACTOR_Datasource *ds = cls; 1355 struct EXTRACTOR_Datasource *ds = cls;
1341 1356
@@ -1357,23 +1372,23 @@ EXTRACTOR_datasource_read_ (void *cls,
1357 */ 1372 */
1358int64_t 1373int64_t
1359EXTRACTOR_datasource_seek_ (void *cls, 1374EXTRACTOR_datasource_seek_ (void *cls,
1360 int64_t pos, 1375 int64_t pos,
1361 int whence) 1376 int whence)
1362{ 1377{
1363 struct EXTRACTOR_Datasource *ds = cls; 1378 struct EXTRACTOR_Datasource *ds = cls;
1364 1379
1365 if (NULL != ds->cfs) 1380 if (NULL != ds->cfs)
1381 {
1382 if ( (SEEK_END == whence) &&
1383 (-1 == ds->cfs->uncompressed_size) )
1366 { 1384 {
1367 if ( (SEEK_END == whence) && 1385 /* need to obtain uncompressed size */
1368 (-1 == ds->cfs->uncompressed_size) ) 1386 (void) EXTRACTOR_datasource_get_size_ (ds, 1);
1369 { 1387 if (-1 == ds->cfs->uncompressed_size)
1370 /* need to obtain uncompressed size */ 1388 return -1;
1371 (void) EXTRACTOR_datasource_get_size_ (ds, 1);
1372 if (-1 == ds->cfs->uncompressed_size)
1373 return -1;
1374 }
1375 return cfs_seek (ds->cfs, pos, whence);
1376 } 1389 }
1390 return cfs_seek (ds->cfs, pos, whence);
1391 }
1377 return bfds_seek (ds->bfds, pos, whence); 1392 return bfds_seek (ds->bfds, pos, whence);
1378} 1393}
1379 1394
@@ -1387,30 +1402,32 @@ EXTRACTOR_datasource_seek_ (void *cls,
1387 */ 1402 */
1388int64_t 1403int64_t
1389EXTRACTOR_datasource_get_size_ (void *cls, 1404EXTRACTOR_datasource_get_size_ (void *cls,
1390 int force) 1405 int force)
1391{ 1406{
1392 struct EXTRACTOR_Datasource *ds = cls; 1407 struct EXTRACTOR_Datasource *ds = cls;
1393 char buf[32 * 1024]; 1408 char buf[32 * 1024];
1394 uint64_t pos; 1409 uint64_t pos;
1395 1410
1396 if (NULL != ds->cfs) 1411 if (NULL != ds->cfs)
1412 {
1413 if ( (force) &&
1414 (-1 == ds->cfs->uncompressed_size) )
1397 { 1415 {
1398 if ( (force) && 1416 pos = ds->cfs->fpos;
1399 (-1 == ds->cfs->uncompressed_size) ) 1417 while ( (-1 == ds->cfs->uncompressed_size) &&
1400 { 1418 (-1 != cfs_read (ds->cfs, buf, sizeof (buf))) )
1401 pos = ds->cfs->fpos; 1419 ;
1402 while ( (-1 == ds->cfs->uncompressed_size) && 1420 if (-1 == cfs_seek (ds->cfs, pos, SEEK_SET))
1403 (-1 != cfs_read (ds->cfs, buf, sizeof (buf))) ) ; 1421 {
1404 if (-1 == cfs_seek (ds->cfs, pos, SEEK_SET)) 1422 LOG (
1405 { 1423 "Serious problem, I moved the buffer to determine the file size but could not restore it...\n");
1406 LOG ("Serious problem, I moved the buffer to determine the file size but could not restore it...\n"); 1424 return -1;
1407 return -1; 1425 }
1408 } 1426 if (-1 == ds->cfs->uncompressed_size)
1409 if (-1 == ds->cfs->uncompressed_size) 1427 return -1;
1410 return -1;
1411 }
1412 return ds->cfs->uncompressed_size;
1413 } 1428 }
1429 return ds->cfs->uncompressed_size;
1430 }
1414 return ds->bfds->fsize; 1431 return ds->bfds->fsize;
1415} 1432}
1416 1433