| 130 |
{ |
{ |
| 131 |
while (size--) |
while (size--) |
| 132 |
if (*buffer++) |
if (*buffer++) |
| 133 |
return 0; |
return false; |
| 134 |
return 1; |
return true; |
| 135 |
} |
} |
| 136 |
|
|
| 137 |
#define clear_block(p) memset (p, 0, BLOCKSIZE); |
#define clear_block(p) memset (p, 0, BLOCKSIZE); |
| 374 |
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short; |
return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short; |
| 375 |
} |
} |
| 376 |
|
|
| 377 |
|
|
| 378 |
|
static char diff_buffer[BLOCKSIZE]; |
| 379 |
|
|
| 380 |
|
static bool |
| 381 |
|
check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end) |
| 382 |
|
{ |
| 383 |
|
if (!lseek_or_error (file, beg, SEEK_SET)) |
| 384 |
|
return false; |
| 385 |
|
|
| 386 |
|
while (beg < end) |
| 387 |
|
{ |
| 388 |
|
size_t bytes_read; |
| 389 |
|
size_t rdsize = end - beg; |
| 390 |
|
|
| 391 |
|
if (rdsize > BLOCKSIZE) |
| 392 |
|
rdsize = BLOCKSIZE; |
| 393 |
|
clear_block (diff_buffer); |
| 394 |
|
bytes_read = safe_read (file->fd, diff_buffer, rdsize); |
| 395 |
|
if (bytes_read < 0) |
| 396 |
|
{ |
| 397 |
|
read_diag_details (file->stat_info->orig_file_name, |
| 398 |
|
beg, |
| 399 |
|
rdsize); |
| 400 |
|
return false; |
| 401 |
|
} |
| 402 |
|
if (!zero_block_p (diff_buffer, bytes_read)) |
| 403 |
|
{ |
| 404 |
|
report_difference (file->stat_info, |
| 405 |
|
_("File fragment at %lu is not a hole"), beg); |
| 406 |
|
return false; |
| 407 |
|
} |
| 408 |
|
|
| 409 |
|
beg += bytes_read; |
| 410 |
|
} |
| 411 |
|
return true; |
| 412 |
|
} |
| 413 |
|
|
| 414 |
|
static bool |
| 415 |
|
check_data_region (struct tar_sparse_file *file, size_t index) |
| 416 |
|
{ |
| 417 |
|
size_t size_left; |
| 418 |
|
|
| 419 |
|
if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset, |
| 420 |
|
SEEK_SET)) |
| 421 |
|
return false; |
| 422 |
|
size_left = file->stat_info->sparse_map[index].numbytes; |
| 423 |
|
while (size_left > 0) |
| 424 |
|
{ |
| 425 |
|
size_t bytes_read; |
| 426 |
|
size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left; |
| 427 |
|
|
| 428 |
|
union block *blk = find_next_block (); |
| 429 |
|
if (!blk) |
| 430 |
|
{ |
| 431 |
|
ERROR ((0, 0, _("Unexpected EOF in archive"))); |
| 432 |
|
return false; |
| 433 |
|
} |
| 434 |
|
set_next_block_after (blk); |
| 435 |
|
bytes_read = safe_read (file->fd, diff_buffer, rdsize); |
| 436 |
|
if (bytes_read < 0) |
| 437 |
|
{ |
| 438 |
|
read_diag_details (file->stat_info->orig_file_name, |
| 439 |
|
file->stat_info->sparse_map[index].offset |
| 440 |
|
+ file->stat_info->sparse_map[index].numbytes |
| 441 |
|
- size_left, |
| 442 |
|
rdsize); |
| 443 |
|
return false; |
| 444 |
|
} |
| 445 |
|
file->dumped_size += bytes_read; |
| 446 |
|
size_left -= bytes_read; |
| 447 |
|
if (memcmp (blk->buffer, diff_buffer, rdsize)) |
| 448 |
|
{ |
| 449 |
|
report_difference (file->stat_info, _("Contents differ")); |
| 450 |
|
return false; |
| 451 |
|
} |
| 452 |
|
} |
| 453 |
|
return true; |
| 454 |
|
} |
| 455 |
|
|
| 456 |
|
bool |
| 457 |
|
sparse_diff_file (int fd, struct tar_stat_info *stat) |
| 458 |
|
{ |
| 459 |
|
bool rc = true; |
| 460 |
|
struct tar_sparse_file file; |
| 461 |
|
size_t i; |
| 462 |
|
off_t offset = 0; |
| 463 |
|
|
| 464 |
|
file.stat_info = stat; |
| 465 |
|
file.fd = fd; |
| 466 |
|
|
| 467 |
|
if (!sparse_select_optab (&file) |
| 468 |
|
|| !tar_sparse_init (&file)) |
| 469 |
|
return dump_status_not_implemented; |
| 470 |
|
|
| 471 |
|
rc = tar_sparse_decode_header (&file); |
| 472 |
|
for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++) |
| 473 |
|
{ |
| 474 |
|
rc = check_sparse_region (&file, |
| 475 |
|
offset, file.stat_info->sparse_map[i].offset) |
| 476 |
|
&& check_data_region (&file, i); |
| 477 |
|
offset = file.stat_info->sparse_map[i].offset |
| 478 |
|
+ file.stat_info->sparse_map[i].numbytes; |
| 479 |
|
} |
| 480 |
|
|
| 481 |
|
if (rc) |
| 482 |
|
skip_file (file.stat_info->archive_file_size - file.dumped_size); |
| 483 |
|
|
| 484 |
|
tar_sparse_done (&file); |
| 485 |
|
return rc; |
| 486 |
|
} |
| 487 |
|
|
| 488 |
|
|
| 489 |
/* Old GNU Format. The sparse file information is stored in the |
/* Old GNU Format. The sparse file information is stored in the |
| 490 |
oldgnu_header in the following manner: |
oldgnu_header in the following manner: |