summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2010-08-24 17:28:11 -0700
committerPaul Eggert <eggert@cs.ucla.edu>2010-08-24 17:29:06 -0700
commita9895fd20c957ce184091672f1623a5bedd82407 (patch)
tree763803bfc1533d1b292fc71ad6c1d1f2afa45778
parenta59c819beb4886ee43f16dfd80ec1151fda1abe6 (diff)
downloadtar-a9895fd20c957ce184091672f1623a5bedd82407.tar.gz
tar: optimize -c --sparse when file is entirely sparse
* src/sparse.c (sparse_scan_file): If the file is entirely sparse, that is, if ST_NBLOCKS is zero, don't bother scanning for nonzero blocks. Idea by Kit Westneat, communicated by Bernd Schubert in <http://lists.gnu.org/archive/html/bug-tar/2010-08/msg00038.html>. Also, omit unnecessary lseek at start of file.
-rw-r--r--src/sparse.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/src/sparse.c b/src/sparse.c
index 8af4b47b..9680b605 100644
--- a/src/sparse.c
+++ b/src/sparse.c
@@ -217,43 +217,45 @@ 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;
+ size_t count = 0;
off_t offset = 0;
struct sp_array sp = {0, 0};
- if (!lseek_or_error (file, 0))
- return false;
-
st->archive_file_size = 0;
- if (!tar_sparse_scan (file, scan_begin, NULL))
- return false;
-
- while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
- && count != SAFE_READ_ERROR)
+ if (ST_NBLOCKS (st->stat) == 0)
+ offset = st->stat.st_size;
+ else
{
- /* Analyze the block. */
- if (zero_block_p (buffer, count))
+ if (!tar_sparse_scan (file, scan_begin, NULL))
+ return false;
+
+ while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
+ && count != SAFE_READ_ERROR)
{
- if (sp.numbytes)
+ /* Analyze the block. */
+ if (zero_block_p (buffer, count))
{
- sparse_add_map (st, &sp);
- sp.numbytes = 0;
- if (!tar_sparse_scan (file, scan_block, NULL))
+ 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;
}
- }
- 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;
+ offset += count;
+ }
}
if (sp.numbytes == 0)