static bool check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end) { if (!lseek_or_error (file, beg)) return false; while (beg < end) { size_t bytes_read; size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg; char diff_buffer[BLOCKSIZE]; bytes_read = safe_read (file->fd, diff_buffer, rdsize); if (bytes_read == SAFE_READ_ERROR) { read_diag_details (file->stat_info->orig_file_name, beg, rdsize); return false; } if (!zero_block_p (diff_buffer, bytes_read)) { char begbuf[INT_BUFSIZE_BOUND (off_t)]; report_difference (file->stat_info, _("File fragment at %s is not a hole"), offtostr (beg, begbuf)); return false; } beg += bytes_read; } return true; }
static bool check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end) { if (!lseek_or_error (file, beg, SEEK_SET)) return false; while (beg < end) { size_t bytes_read; size_t rdsize = end - beg; if (rdsize > BLOCKSIZE) rdsize = BLOCKSIZE; clear_block (diff_buffer); bytes_read = safe_read (file->fd, diff_buffer, rdsize); if (bytes_read == SAFE_READ_ERROR) { read_diag_details (file->stat_info->orig_file_name, beg, rdsize); return false; } if (!zero_block_p (diff_buffer, bytes_read)) { report_difference (file->stat_info, _("File fragment at %lu is not a hole"), beg); return false; } beg += bytes_read; } return true; }
/* Scan the sparse file and create its map */ static bool sparse_scan_file (struct tar_sparse_file *file) { struct tar_stat_info *st = file->stat_info; int fd = file->fd; char buffer[BLOCKSIZE]; size_t count = 0; off_t offset = 0; struct sp_array sp = {0, 0}; st->archive_file_size = 0; if (ST_NBLOCKS (st->stat) == 0) offset = st->stat.st_size; else { if (!tar_sparse_scan (file, scan_begin, NULL)) return false; while ((count = blocking_read (fd, buffer, sizeof buffer)) != 0 && count != SAFE_READ_ERROR) { /* Analyze the block. */ if (zero_block_p (buffer, count)) { if (sp.numbytes) { sparse_add_map (st, &sp); sp.numbytes = 0; if (!tar_sparse_scan (file, scan_block, NULL)) return false; } } else { if (sp.numbytes == 0) sp.offset = offset; sp.numbytes += count; st->archive_file_size += count; if (!tar_sparse_scan (file, scan_block, buffer)) return false; } offset += count; } } if (sp.numbytes == 0) sp.offset = offset; sparse_add_map (st, &sp); st->archive_file_size += count; return tar_sparse_scan (file, scan_end, NULL); }
/* Scan the sparse file and create its map */ static bool sparse_scan_file (struct tar_sparse_file *file) { static char buffer[BLOCKSIZE]; size_t count; size_t offset = 0; struct sp_array sp = {0, 0}; if (!lseek_or_error (file, 0, SEEK_SET)) return false; clear_block (buffer); file->stat_info->sparse_map_avail = 0; file->stat_info->archive_file_size = 0; if (!tar_sparse_scan (file, scan_begin, NULL)) return false; while ((count = safe_read (file->fd, buffer, sizeof buffer)) != 0 && count != SAFE_READ_ERROR) { /* Analize the block */ if (zero_block_p (buffer, count)) { if (sp.numbytes) { sparse_add_map (file, &sp); sp.numbytes = 0; if (!tar_sparse_scan (file, scan_block, NULL)) return false; } } else { if (sp.numbytes == 0) sp.offset = offset; sp.numbytes += count; file->stat_info->archive_file_size += count; if (!tar_sparse_scan (file, scan_block, buffer)) return false; } offset += count; clear_block (buffer); } if (sp.numbytes == 0) sp.offset = offset; sparse_add_map (file, &sp); file->stat_info->archive_file_size += count; return tar_sparse_scan (file, scan_end, NULL); }