diff options
Diffstat (limited to 'src/main/extractor_datasource.c')
-rw-r--r-- | src/main/extractor_datasource.c | 1083 |
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 | */ |
215 | static int | 215 | static int |
216 | bfds_pick_next_buffer_at (struct BufferedFileDataSource *bfds, | 216 | bfds_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 | */ |
259 | static struct BufferedFileDataSource * | 259 | static struct BufferedFileDataSource * |
260 | bfds_new (const void *data, | 260 | bfds_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 | */ |
319 | static int64_t | 319 | static int64_t |
320 | bfds_seek (struct BufferedFileDataSource *bfds, | 320 | bfds_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 | */ |
408 | static ssize_t | 408 | static ssize_t |
409 | bfds_read (struct BufferedFileDataSource *bfds, | 409 | bfds_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 | */ |
459 | static int | 459 | static int |
460 | cfs_init_decompressor_zlib (struct CompressedFileSource *cfs, | 460 | cfs_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 | */ |
597 | static int | 600 | static int |
598 | cfs_init_decompressor_bz2 (struct CompressedFileSource *cfs, | 601 | cfs_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 | */ |
629 | static int | 634 | static int |
630 | cfs_init_decompressor (struct CompressedFileSource *cfs, | 635 | cfs_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 | |||
691 | cfs_deinit_decompressor (struct CompressedFileSource *cfs) | 700 | cfs_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 | */ |
751 | struct CompressedFileSource * | 760 | struct CompressedFileSource * |
752 | cfs_new (struct BufferedFileDataSource *bfds, | 761 | cfs_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 | */ |
790 | static ssize_t | 799 | static ssize_t |
791 | cfs_read_zlib (struct CompressedFileSource *cfs, | 800 | cfs_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 | */ |
887 | static ssize_t | 898 | static ssize_t |
888 | cfs_read_bz2 (struct CompressedFileSource *cfs, | 899 | cfs_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 | */ |
983 | static ssize_t | 996 | static ssize_t |
984 | cfs_read (struct CompressedFileSource *cfs, | 997 | cfs_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 | */ |
1015 | static int64_t | 1028 | static int64_t |
1016 | cfs_seek (struct CompressedFileSource *cfs, | 1029 | cfs_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 | */ |
1187 | struct EXTRACTOR_Datasource * | 1201 | struct EXTRACTOR_Datasource * |
1188 | EXTRACTOR_datasource_create_from_file_ (const char *filename, | 1202 | EXTRACTOR_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 | */ |
1267 | struct EXTRACTOR_Datasource * | 1281 | struct EXTRACTOR_Datasource * |
1268 | EXTRACTOR_datasource_create_from_buffer_ (const char *buf, | 1282 | EXTRACTOR_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 | */ |
1335 | ssize_t | 1350 | ssize_t |
1336 | EXTRACTOR_datasource_read_ (void *cls, | 1351 | EXTRACTOR_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 | */ |
1358 | int64_t | 1373 | int64_t |
1359 | EXTRACTOR_datasource_seek_ (void *cls, | 1374 | EXTRACTOR_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 | */ |
1388 | int64_t | 1403 | int64_t |
1389 | EXTRACTOR_datasource_get_size_ (void *cls, | 1404 | EXTRACTOR_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 | ||