]> Dogcows Code - chaz/tar/commitdiff
(sparse_diff_file): Bugfix: set seekable.
authorSergey Poznyakoff <gray@gnu.org.ua>
Mon, 7 Nov 2005 02:49:45 +0000 (02:49 +0000)
committerSergey Poznyakoff <gray@gnu.org.ua>
Mon, 7 Nov 2005 02:49:45 +0000 (02:49 +0000)
(pax_dump_header): Store sparse map in GNU.sparse.map. If this
variable has been explicitely deleted, use GNU.sparse.offset/
GNU.sparse.numbytes variables.

src/sparse.c

index d16efc79ef170ea9d178ee2c2dfe72604d4849bb..a39d0ed424b5d1c176fe1793ab316fd601b8e150 100644 (file)
@@ -54,7 +54,7 @@ struct tar_sparse_file
   off_t dumped_size;                /* Number of bytes actually written
                                       to the archive */
   struct tar_stat_info *stat_info;  /* Information about the file */
-  struct tar_sparse_optab const *optab;
+  struct tar_sparse_optab const *optab; /* Operation table */
   void *closure;                    /* Any additional data optab calls might
                                       require */
 };
@@ -565,13 +565,14 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
 
   file.stat_info = st;
   file.fd = fd;
-
+  file.seekable = true; /* File *must* be seekable for compare to work */
+  
   rc = tar_sparse_decode_header (&file);
   for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
     {
       rc = check_sparse_region (&file,
                                offset, file.stat_info->sparse_map[i].offset)
-       && check_data_region (&file, i);
+           && check_data_region (&file, i);
       offset = file.stat_info->sparse_map[i].offset
                + file.stat_info->sparse_map[i].numbytes;
     }
@@ -838,10 +839,28 @@ static struct tar_sparse_optab const star_optab = {
 
    GNU.sparse.size      Real size of the stored file
    GNU.sparse.numblocks Number of blocks in the sparse map
+   GNU.sparse.map       Map of non-null data chunks. A string consisting
+                       of comma-separated values "offset,size[,offset,size]..."
+
+   Tar versions 1.14-1.15.1 instead of the latter used:
+   
    repeat numblocks time
      GNU.sparse.offset    Offset of the next data block
      GNU.sparse.numbytes  Size of the next data block
    end repeat
+
+   This has been reported as conflicting with the POSIX specs. The reason is
+   that offsets and sizes of non-zero data blocks were stored in multiple
+   instances of GNU.sparse.offset/GNU.sparse.numbytes variables. However,
+   POSIX requires the latest occurrence of the variable to override all
+   previous occurrences.
+     
+   To avoid this incompatibility new keyword GNU.sparse.map was introduced
+   in tar 1.15.2. Some people might still need the 1.14 way of handling
+   sparse files for the compatibility reasons: it can be achieved by
+   specifying `--pax-option delete=GNU.sparse.map' in the command line.
+
+   See FIXME-1.14-1.15.1-1.20, below.
 */
 
 static bool
@@ -856,16 +875,40 @@ pax_dump_header (struct tar_sparse_file *file)
   off_t block_ordinal = current_block_ordinal ();
   union block *blk;
   size_t i;
-
+  char nbuf[UINTMAX_STRSIZE_BOUND];
+  struct sp_array *map = file->stat_info->sparse_map;
+    
   /* Store the real file size */
   xheader_store ("GNU.sparse.size", file->stat_info, NULL);
   xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
-  for (i = 0; i < file->stat_info->sparse_map_avail; i++)
+
+  /* FIXME-1.14-1.15.1-1.20: See the comment above.
+     Starting with 1.17 this should display a warning about POSIX-incompatible
+     keywords being generated. In 1.20, the true branch of the if block below
+     will be removed and GNU.sparse.map will be marked in xhdr_tab as
+     protected. */
+  
+  if (xheader_keyword_deleted_p ("GNU.sparse.map"))
     {
-      xheader_store ("GNU.sparse.offset", file->stat_info, &i);
-      xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
+      for (i = 0; i < file->stat_info->sparse_map_avail; i++)
+       {
+         xheader_store ("GNU.sparse.offset", file->stat_info, &i);
+         xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
+       }
+    }
+  else
+    {
+      xheader_string_begin ();
+      for (i = 0; i < file->stat_info->sparse_map_avail; i++)
+       {
+         if (i)
+           xheader_string_add (",");
+         xheader_string_add (umaxtostr (map[i].offset, nbuf));
+         xheader_string_add (",");
+         xheader_string_add (umaxtostr (map[i].numbytes, nbuf));
+       }
+      xheader_string_end ("GNU.sparse.map");
     }
-
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
This page took 0.024756 seconds and 4 git commands to generate.