]> Dogcows Code - chaz/tar/blobdiff - src/sparse.c
Doc changes.
[chaz/tar] / src / sparse.c
index 799a00fc0bc93256b78c1e1427ad4237defb588e..9fde5080d5304a32253fd67d72e1a99a0c69bf56 100644 (file)
@@ -1,10 +1,10 @@
 /* Functions for dealing with sparse files
 
 /* Functions for dealing with sparse files
 
-   Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
 
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
-   Free Software Foundation; either version 2, or (at your option) any later
+   Free Software Foundation; either version 3, or (at your option) any later
    version.
 
    This program is distributed in the hope that it will be useful, but
    version.
 
    This program is distributed in the hope that it will be useful, but
@@ -409,15 +409,6 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
 }
 
   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
 }
 
-/* Returns true if the file represented by stat is a sparse one */
-bool
-sparse_file_p (struct tar_stat_info *st)
-{
-  return (ST_NBLOCKS (st->stat)
-         < (st->stat.st_size / ST_NBLOCKSIZE
-            + (st->stat.st_size % ST_NBLOCKSIZE != 0)));
-}
-
 bool
 sparse_member_p (struct tar_stat_info *st)
 {
 bool
 sparse_member_p (struct tar_stat_info *st)
 {
@@ -475,7 +466,7 @@ sparse_skip_file (struct tar_stat_info *st)
   file.fd = -1;
 
   rc = tar_sparse_decode_header (&file);
   file.fd = -1;
 
   rc = tar_sparse_decode_header (&file);
-  skip_file (file.stat_info->archive_file_size);
+  skip_file (file.stat_info->archive_file_size - file.dumped_size);
   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
 }
 
   return (tar_sparse_done (&file) && rc) ? dump_status_ok : dump_status_short;
 }
 
@@ -843,7 +834,6 @@ static struct tar_sparse_optab const star_optab = {
 \f
 /* GNU PAX sparse file format. There are several versions:
 
 \f
 /* GNU PAX sparse file format. There are several versions:
 
-
    * 0.0
 
    The initial version of sparse format used by tar 1.14-1.15.1.
    * 0.0
 
    The initial version of sparse format used by tar 1.14-1.15.1.
@@ -874,7 +864,7 @@ 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
    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]..."
+                       of comma-separated values "offset,size[,offset,size]..."
 
    The resulting GNU.sparse.map string can be *very* long. While POSIX does not
    impose any limit on the length of a x header variable, this can confuse some
 
    The resulting GNU.sparse.map string can be *very* long. While POSIX does not
    impose any limit on the length of a x header variable, this can confuse some
@@ -882,8 +872,8 @@ static struct tar_sparse_optab const star_optab = {
 
    * 1.0
 
 
    * 1.0
 
-   Starting from this version, the exact sparse format version is specified explicitely
-   in the header using the following variables:
+   Starting from this version, the exact sparse format version is specified
+   explicitely in the header using the following variables:
 
    GNU.sparse.major     Major version 
    GNU.sparse.minor     Minor version
 
    GNU.sparse.major     Major version 
    GNU.sparse.minor     Minor version
@@ -898,22 +888,24 @@ static struct tar_sparse_optab const star_optab = {
    "%d/GNUSparseFile.%p/%f".
    
    The sparse map itself is stored in the file data block, preceding the actual
    "%d/GNUSparseFile.%p/%f".
    
    The sparse map itself is stored in the file data block, preceding the actual
-   file data. It consists of a series of octal numbers of arbitrary length, delimited 
-   by newlines. The map is padded with nulls to the nearest block boundary.
+   file data. It consists of a series of octal numbers of arbitrary length,
+   delimited by newlines. The map is padded with nulls to the nearest block
+   boundary.
 
 
-   The first number gives the number of entries in the map. Following are map entries,
-   each one consisting of two numbers giving the offset and size of the
-   data block it describes.
+   The first number gives the number of entries in the map. Following are map
+   entries, each one consisting of two numbers giving the offset and size of
+   the data block it describes.
 
    The format is designed in such a way that non-posix aware tars and tars not
 
    The format is designed in such a way that non-posix aware tars and tars not
-   supporting GNU.sparse.* keywords will extract each sparse file in its condensed
-   form with the file map attached and will place it into a separate directory.
-   Then, using a simple program it would be possible to expand the file to its
-   original form even without GNU tar.
-
-   Bu default, v.1.0 archives are created. To use other formats, --sparse-version
-   option is provided. Additionally, v.0.0 can be obtained by deleting GNU.sparse.map
-   from 0.1 format: --sparse-version 0.1 --pax-option delete=GNU.sparse.map
+   supporting GNU.sparse.* keywords will extract each sparse file in its
+   condensed form with the file map attached and will place it into a separate
+   directory. Then, using a simple program it would be possible to expand the
+   file to its original form even without GNU tar.
+
+   Bu default, v.1.0 archives are created. To use other formats,
+   --sparse-version option is provided. Additionally, v.0.0 can be obtained
+   by deleting GNU.sparse.map from 0.1 format: --sparse-version 0.1
+   --pax-option delete=GNU.sparse.map
 */
 
 static bool
 */
 
 static bool
@@ -953,16 +945,24 @@ pax_dump_header_0 (struct tar_sparse_file *file)
       file->stat_info->file_name = xheader_format_name (file->stat_info,
                                               "%d/GNUSparseFile.%p/%f", 0);
 
       file->stat_info->file_name = xheader_format_name (file->stat_info,
                                               "%d/GNUSparseFile.%p/%f", 0);
 
-      xheader_string_begin ();
+      xheader_string_begin (&file->stat_info->xhdr);
       for (i = 0; i < file->stat_info->sparse_map_avail; i++)
        {
          if (i)
       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_add (&file->stat_info->xhdr, ",");
+         xheader_string_add (&file->stat_info->xhdr,
+                             umaxtostr (map[i].offset, nbuf));
+         xheader_string_add (&file->stat_info->xhdr, ",");
+         xheader_string_add (&file->stat_info->xhdr,
+                             umaxtostr (map[i].numbytes, nbuf));
+       }
+      if (!xheader_string_end (&file->stat_info->xhdr,
+                              "GNU.sparse.map"))
+       {
+         free (file->stat_info->file_name);
+         file->stat_info->file_name = save_file_name;
+         return false;
        }
        }
-      xheader_string_end ("GNU.sparse.map");
     }
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
     }
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
@@ -1017,6 +1017,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
     }
   size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
   file->stat_info->archive_file_size += size * BLOCKSIZE;
     }
   size = (size + BLOCKSIZE - 1) / BLOCKSIZE;
   file->stat_info->archive_file_size += size * BLOCKSIZE;
+  file->dumped_size += size * BLOCKSIZE;
   
   /* Store sparse file identification */
   xheader_store ("GNU.sparse.major", file->stat_info, NULL);
   
   /* Store sparse file identification */
   xheader_store ("GNU.sparse.major", file->stat_info, NULL);
@@ -1058,11 +1059,9 @@ pax_dump_header (struct tar_sparse_file *file)
 {
   file->stat_info->sparse_major = tar_sparse_major;
   file->stat_info->sparse_minor = tar_sparse_minor;
 {
   file->stat_info->sparse_major = tar_sparse_major;
   file->stat_info->sparse_minor = tar_sparse_minor;
-  
-  if (file->stat_info->sparse_major == 0)
-    pax_dump_header_0 (file);
-  else
-    pax_dump_header_1 (file);
+
+  return (file->stat_info->sparse_major == 0) ?
+           pax_dump_header_0 (file) : pax_dump_header_1 (file);
 }
 
 static bool
 }
 
 static bool
@@ -1102,14 +1101,15 @@ pax_decode_header (struct tar_sparse_file *file)
      {                                                             \
        if (dst == buf + UINTMAX_STRSIZE_BOUND -1)                  \
          {                                                         \
      {                                                             \
        if (dst == buf + UINTMAX_STRSIZE_BOUND -1)                  \
          {                                                         \
-           ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"),   \
+           ERROR ((0, 0, _("%s: numeric overflow in sparse archive member"), \
                  file->stat_info->orig_file_name));               \
            return false;                                           \
          }                                                         \
                  file->stat_info->orig_file_name));               \
            return false;                                           \
          }                                                         \
-        if (src == endp)                                           \
+       if (src == endp)                                            \
         {                                                         \
           set_next_block_after (b);                               \
         {                                                         \
           set_next_block_after (b);                               \
-          b = find_next_block ();                                 \
+           file->dumped_size += BLOCKSIZE;                         \
+           b = find_next_block ();                                 \
            src = b->buffer;                                        \
           endp = b->buffer + BLOCKSIZE;                           \
         }                                                         \
            src = b->buffer;                                        \
           endp = b->buffer + BLOCKSIZE;                           \
         }                                                         \
@@ -1120,6 +1120,7 @@ pax_decode_header (struct tar_sparse_file *file)
  } while (0)                       
 
       set_next_block_after (current_header);
  } while (0)                       
 
       set_next_block_after (current_header);
+      file->dumped_size += BLOCKSIZE;
       blk = find_next_block ();
       p = blk->buffer;
       COPY_BUF (blk,nbuf,p);
       blk = find_next_block ();
       p = blk->buffer;
       COPY_BUF (blk,nbuf,p);
This page took 0.033162 seconds and 4 git commands to generate.