Browse Source

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.
Paul Eggert 14 years ago
parent
commit
a9895fd20c
1 changed files with 28 additions and 26 deletions
  1. 28 26
      src/sparse.c

+ 28 - 26
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)