]> Dogcows Code - chaz/tar/blobdiff - src/sparse.c
Keep a detailed map of archive members stored in the record buffer.
[chaz/tar] / src / sparse.c
index 8d1ff9071ae5a96463b01321325a0b779b547060..67e5a857166df9f31c98644dd024a4423cf01520 100644 (file)
@@ -1,10 +1,10 @@
 /* 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
-   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
@@ -224,7 +224,7 @@ sparse_scan_file (struct tar_sparse_file *file)
     return false;
 
   st->archive_file_size = 0;
-  
+
   if (!tar_sparse_scan (file, scan_begin, NULL))
     return false;
 
@@ -324,7 +324,6 @@ sparse_dump_region (struct tar_sparse_file *file, size_t i)
       memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
       bytes_left -= bytes_read;
       file->dumped_size += bytes_read;
-      mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
       set_next_block_after (blk);
     }
 
@@ -398,10 +397,11 @@ sparse_dump_file (int fd, struct tar_stat_info *st)
        {
          size_t i;
 
-         mv_begin (file.stat_info);
+         mv_begin_write (file.stat_info->file_name,
+                         file.stat_info->stat.st_size,
+                         file.stat_info->archive_file_size - file.dumped_size);
          for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
            rc = tar_sparse_dump_region (&file, i);
-         mv_end ();
        }
     }
 
@@ -466,7 +466,7 @@ sparse_skip_file (struct tar_stat_info *st)
   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;
 }
 
@@ -514,7 +514,7 @@ check_data_region (struct tar_sparse_file *file, size_t i)
     return false;
   size_left = file->stat_info->sparse_map[i].numbytes;
   mv_size_left (file->stat_info->archive_file_size - file->dumped_size);
-      
+
   while (size_left > 0)
     {
       size_t bytes_read;
@@ -564,9 +564,9 @@ 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);
-  mv_begin (st);
+  mv_begin_read (st);
   for (i = 0; rc && i < file.stat_info->sparse_map_avail; i++)
     {
       rc = check_sparse_region (&file,
@@ -579,7 +579,7 @@ sparse_diff_file (int fd, struct tar_stat_info *st)
   if (!rc)
     skip_file (file.stat_info->archive_file_size - file.dumped_size);
   mv_end ();
-  
+
   tar_sparse_done (&file);
   return rc;
 }
@@ -851,13 +851,13 @@ static struct tar_sparse_optab const star_optab = {
    instances of GNU.sparse.offset/GNU.sparse.numbytes variables, whereas
    POSIX requires the latest occurrence of the variable to override all
    previous occurrences.
-   
+
    To avoid this incompatibility two following versions were introduced.
 
    * 0.1
 
    Used by tar 1.15.2 -- 1.15.91 (alpha releases).
-   
+
    The sparse file map is stored in
    x header:
 
@@ -875,18 +875,18 @@ static struct tar_sparse_optab const star_optab = {
    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.major     Major version
    GNU.sparse.minor     Minor version
 
    X header keeps the following variables:
-   
+
    GNU.sparse.name      Real file name of the sparse file
    GNU.sparse.realsize  Real size of the stored file (corresponds to the old
                         GNU.sparse.size variable)
 
    The name field of the ustar header is constructed using the pattern
    "%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
@@ -924,11 +924,11 @@ pax_dump_header_0 (struct tar_sparse_file *file)
   char nbuf[UINTMAX_STRSIZE_BOUND];
   struct sp_array *map = file->stat_info->sparse_map;
   char *save_file_name = NULL;
-  
+
   /* Store the real file size */
   xheader_store ("GNU.sparse.size", file->stat_info, NULL);
   xheader_store ("GNU.sparse.numblocks", file->stat_info, NULL);
-  
+
   if (xheader_keyword_deleted_p ("GNU.sparse.map")
       || tar_sparse_minor == 0)
     {
@@ -945,16 +945,19 @@ 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);
 
-      xheader_string_begin ();
+      xheader_string_begin (&file->stat_info->xhdr);
       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 ("GNU.sparse.map"))
+      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;
@@ -988,7 +991,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
 #define COPY_STRING(b,dst,src) do                \
  {                                               \
    char *endp = b->buffer + BLOCKSIZE;           \
-   char *srcp = src;                             \
+   char const *srcp = src;                       \
    while (*srcp)                                 \
      {                                           \
        if (dst == endp)                          \
@@ -1000,7 +1003,7 @@ pax_dump_header_1 (struct tar_sparse_file *file)
         }                                       \
        *dst++ = *srcp++;                         \
      }                                           \
-   } while (0)                       
+   } while (0)
 
   /* Compute stored file size */
   p = umaxtostr (file->stat_info->sparse_map_avail, nbuf);
@@ -1014,13 +1017,14 @@ pax_dump_header_1 (struct tar_sparse_file *file)
     }
   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);
   xheader_store ("GNU.sparse.minor", file->stat_info, NULL);
   xheader_store ("GNU.sparse.name", file->stat_info, NULL);
   xheader_store ("GNU.sparse.realsize", file->stat_info, NULL);
-  
+
   file->stat_info->file_name = xheader_format_name (file->stat_info,
                                            "%d/GNUSparseFile.%p/%f", 0);
 
@@ -1068,12 +1072,12 @@ decode_num (uintmax_t *num, char const *arg, uintmax_t maxval)
 
   if (!ISDIGIT (*arg))
     return false;
-  
+
   u = strtoumax (arg, &arg_lim, 10);
 
   if (! (u <= maxval && errno != ERANGE) || *arg_lim)
     return false;
-  
+
   *num = u;
   return true;
 }
@@ -1104,7 +1108,8 @@ pax_decode_header (struct tar_sparse_file *file)
        if (src == endp)                                            \
         {                                                         \
           set_next_block_after (b);                               \
-          b = find_next_block ();                                 \
+           file->dumped_size += BLOCKSIZE;                         \
+           b = find_next_block ();                                 \
            src = b->buffer;                                        \
           endp = b->buffer + BLOCKSIZE;                           \
         }                                                         \
@@ -1112,15 +1117,16 @@ pax_decode_header (struct tar_sparse_file *file)
      }                                                             \
    while (*dst++ != '\n');                                         \
    dst[-1] = 0;                                                    \
- } while (0)                       
+ } while (0)
 
       set_next_block_after (current_header);
+      file->dumped_size += BLOCKSIZE;
       blk = find_next_block ();
       p = blk->buffer;
       COPY_BUF (blk,nbuf,p);
       if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
        {
-         ERROR ((0, 0, _("%s: malformed sparse archive member"), 
+         ERROR ((0, 0, _("%s: malformed sparse archive member"),
                  file->stat_info->orig_file_name));
          return false;
        }
@@ -1131,11 +1137,11 @@ pax_decode_header (struct tar_sparse_file *file)
       for (i = 0; i < file->stat_info->sparse_map_size; i++)
        {
          struct sp_array sp;
-         
+
          COPY_BUF (blk,nbuf,p);
          if (!decode_num (&u, nbuf, TYPE_MAXIMUM (off_t)))
            {
-             ERROR ((0, 0, _("%s: malformed sparse archive member"), 
+             ERROR ((0, 0, _("%s: malformed sparse archive member"),
                      file->stat_info->orig_file_name));
              return false;
            }
@@ -1143,7 +1149,7 @@ pax_decode_header (struct tar_sparse_file *file)
          COPY_BUF (blk,nbuf,p);
          if (!decode_num (&u, nbuf, TYPE_MAXIMUM (size_t)))
            {
-             ERROR ((0, 0, _("%s: malformed sparse archive member"), 
+             ERROR ((0, 0, _("%s: malformed sparse archive member"),
                      file->stat_info->orig_file_name));
              return false;
            }
@@ -1152,7 +1158,7 @@ pax_decode_header (struct tar_sparse_file *file)
        }
       set_next_block_after (blk);
     }
-  
+
   return true;
 }
 
@@ -1162,7 +1168,7 @@ static struct tar_sparse_optab const pax_optab = {
   pax_sparse_member_p,
   pax_dump_header,
   NULL,
-  pax_decode_header,  
+  pax_decode_header,
   NULL,  /* No scan_block function */
   sparse_dump_region,
   sparse_extract_region,
This page took 0.026864 seconds and 4 git commands to generate.