]> Dogcows Code - chaz/tar/blobdiff - src/sparse.c
A sweep of the sparse code prompted by a bug report by Jim Meyering.
[chaz/tar] / src / sparse.c
index 2f5330df3344d4036f51582dff2e932da6cdd1c9..ecbbe108842bbd27366b3d16a470fc4e047a474e 100644 (file)
@@ -1,6 +1,6 @@
-/* Functions for dealing with sparse files 
+/* Functions for dealing with sparse files
 
 
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005 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
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
 
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
-   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
 
-#include "system.h"
+#include <system.h>
+#include <inttostr.h>
 #include <quotearg.h>
 #include "common.h"
 
 #include <quotearg.h>
 #include "common.h"
 
@@ -39,21 +40,57 @@ struct tar_sparse_optab
   bool (*decode_header) (struct tar_sparse_file *);
   bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
                      void *);
   bool (*decode_header) (struct tar_sparse_file *);
   bool (*scan_block) (struct tar_sparse_file *, enum sparse_scan_state,
                      void *);
-  bool (*dump_region) (struct tar_sparse_file *, size_t index);
-  bool (*extract_region) (struct tar_sparse_file *, size_t index);
+  bool (*dump_region) (struct tar_sparse_file *, size_t);
+  bool (*extract_region) (struct tar_sparse_file *, size_t);
 };
 
 struct tar_sparse_file
 {
   int fd;                           /* File descriptor */
 };
 
 struct tar_sparse_file
 {
   int fd;                           /* File descriptor */
-  size_t dumped_size;               /* Number of bytes actually written
+  bool seekable;                    /* Is fd seekable? */
+  off_t offset;                     /* Current offset in fd if seekable==false.
+                                      Otherwise unused */
+  off_t dumped_size;                /* Number of bytes actually written
                                       to the archive */
   struct tar_stat_info *stat_info;  /* Information about the file */
                                       to the archive */
   struct tar_stat_info *stat_info;  /* Information about the file */
-  struct tar_sparse_optab *optab;
+  struct tar_sparse_optab const *optab;
   void *closure;                    /* Any additional data optab calls might
   void *closure;                    /* Any additional data optab calls might
-                                      reqiure */
+                                      require */
 };
 
 };
 
+/* Dump zeros to file->fd until offset is reached. It is used instead of
+   lseek if the output file is not seekable */
+static bool
+dump_zeros (struct tar_sparse_file *file, off_t offset)
+{
+  static char const zero_buf[BLOCKSIZE];
+
+  if (offset < file->offset)
+    {
+      errno = EINVAL;
+      return false;
+    }
+
+  while (file->offset < offset)
+    {
+      size_t size = (BLOCKSIZE < offset - file->offset
+                    ? BLOCKSIZE
+                    : offset - file->offset);
+      ssize_t wrbytes;
+
+      wrbytes = write (file->fd, zero_buf, size);
+      if (wrbytes <= 0)
+       {
+         if (wrbytes == 0)
+           errno = EINVAL;
+         return false;
+       }
+      file->offset += wrbytes;
+    }
+
+  return true;
+}
+
 static bool
 tar_sparse_member_p (struct tar_sparse_file *file)
 {
 static bool
 tar_sparse_member_p (struct tar_sparse_file *file)
 {
@@ -65,7 +102,6 @@ tar_sparse_member_p (struct tar_sparse_file *file)
 static bool
 tar_sparse_init (struct tar_sparse_file *file)
 {
 static bool
 tar_sparse_init (struct tar_sparse_file *file)
 {
-  file->dumped_size = 0;
   if (file->optab->init)
     return file->optab->init (file);
   return true;
   if (file->optab->init)
     return file->optab->init (file);
   return true;
@@ -89,18 +125,18 @@ tar_sparse_scan (struct tar_sparse_file *file, enum sparse_scan_state state,
 }
 
 static bool
 }
 
 static bool
-tar_sparse_dump_region (struct tar_sparse_file *file, size_t index)
+tar_sparse_dump_region (struct tar_sparse_file *file, size_t i)
 {
   if (file->optab->dump_region)
 {
   if (file->optab->dump_region)
-    return file->optab->dump_region (file, index);
+    return file->optab->dump_region (file, i);
   return false;
 }
 
 static bool
   return false;
 }
 
 static bool
-tar_sparse_extract_region (struct tar_sparse_file *file, size_t index)
+tar_sparse_extract_region (struct tar_sparse_file *file, size_t i)
 {
   if (file->optab->extract_region)
 {
   if (file->optab->extract_region)
-    return file->optab->extract_region (file, index);
+    return file->optab->extract_region (file, i);
   return false;
 }
 
   return false;
 }
 
@@ -130,9 +166,11 @@ tar_sparse_fixup_header (struct tar_sparse_file *file)
 
 \f
 static bool
 
 \f
 static bool
-lseek_or_error (struct tar_sparse_file *file, off_t offset, int whence)
+lseek_or_error (struct tar_sparse_file *file, off_t offset)
 {
 {
-  if (lseek (file->fd, offset, whence) < 0)
+  if (file->seekable
+      ? lseek (file->fd, offset, SEEK_SET) < 0
+      : ! dump_zeros (file, offset))
     {
       seek_diag_details (file->stat_info->orig_file_name, offset);
       return false;
     {
       seek_diag_details (file->stat_info->orig_file_name, offset);
       return false;
@@ -144,7 +182,7 @@ lseek_or_error (struct tar_sparse_file *file, off_t offset, int whence)
    it's made *entirely* of zeros, returning a 0 the instant it finds
    something that is a nonzero, i.e., useful data.  */
 static bool
    it's made *entirely* of zeros, returning a 0 the instant it finds
    something that is a nonzero, i.e., useful data.  */
 static bool
-zero_block_p (char *buffer, size_t size)
+zero_block_p (char const *buffer, size_t size)
 {
   while (size--)
     if (*buffer++)
 {
   while (size--)
     if (*buffer++)
@@ -152,57 +190,44 @@ zero_block_p (char *buffer, size_t size)
   return true;
 }
 
   return true;
 }
 
-#define clear_block(p) memset (p, 0, BLOCKSIZE);
-
-#define SPARSES_INIT_COUNT SPARSES_IN_SPARSE_HEADER
-
 static void
 static void
-sparse_add_map (struct tar_sparse_file *file, struct sp_array *sp)
+sparse_add_map (struct tar_stat_info *st, struct sp_array const *sp)
 {
 {
-  if (file->stat_info->sparse_map == NULL)
-    {
-      file->stat_info->sparse_map =
-       xmalloc (SPARSES_INIT_COUNT * sizeof file->stat_info->sparse_map[0]);
-      file->stat_info->sparse_map_size = SPARSES_INIT_COUNT;
-    }
-  else if (file->stat_info->sparse_map_avail == file->stat_info->sparse_map_size)
-    {
-      file->stat_info->sparse_map_size *= 2;
-      file->stat_info->sparse_map =
-       xrealloc (file->stat_info->sparse_map,
-                 file->stat_info->sparse_map_size
-                 * sizeof file->stat_info->sparse_map[0]);
-    }
-  file->stat_info->sparse_map[file->stat_info->sparse_map_avail++] = *sp;
+  struct sp_array *sparse_map = st->sparse_map;
+  size_t avail = st->sparse_map_avail;
+  if (avail == st->sparse_map_size)
+    st->sparse_map = sparse_map =
+      x2nrealloc (sparse_map, &st->sparse_map_size, sizeof *sparse_map);
+  sparse_map[avail] = *sp;
+  st->sparse_map_avail = avail + 1;
 }
 
 /* Scan the sparse file and create its map */
 static bool
 sparse_scan_file (struct tar_sparse_file *file)
 {
 }
 
 /* Scan the sparse file and create its map */
 static bool
 sparse_scan_file (struct tar_sparse_file *file)
 {
-  static char buffer[BLOCKSIZE];
+  struct tar_stat_info *st = file->stat_info;
+  int fd = file->fd;
+  char buffer[BLOCKSIZE];
   size_t count;
   size_t count;
-  size_t offset = 0;
+  off_t offset = 0;
   struct sp_array sp = {0, 0};
 
   struct sp_array sp = {0, 0};
 
-  if (!lseek_or_error (file, 0, SEEK_SET))
+  if (!lseek_or_error (file, 0))
     return false;
     return false;
-  clear_block (buffer);
 
 
-  file->stat_info->sparse_map_size = 0;
-  file->stat_info->archive_file_size = 0;
-  
   if (!tar_sparse_scan (file, scan_begin, NULL))
     return false;
 
   if (!tar_sparse_scan (file, scan_begin, NULL))
     return false;
 
-  while ((count = safe_read (file->fd, buffer, sizeof buffer)) > 0)
+  while ((count = safe_read (fd, buffer, sizeof buffer)) != 0
+        && count != SAFE_READ_ERROR)
     {
     {
-      /* Analize the block */
+      /* Analyze the block.  */
       if (zero_block_p (buffer, count))
        {
          if (sp.numbytes)
            {
       if (zero_block_p (buffer, count))
        {
          if (sp.numbytes)
            {
-             sparse_add_map (file, &sp);
+             sparse_add_map (st, &sp);
              sp.numbytes = 0;
              if (!tar_sparse_scan (file, scan_block, NULL))
                return false;
              sp.numbytes = 0;
              if (!tar_sparse_scan (file, scan_block, NULL))
                return false;
@@ -213,26 +238,25 @@ sparse_scan_file (struct tar_sparse_file *file)
          if (sp.numbytes == 0)
            sp.offset = offset;
          sp.numbytes += count;
          if (sp.numbytes == 0)
            sp.offset = offset;
          sp.numbytes += count;
-         file->stat_info->archive_file_size += count;
+         st->archive_file_size += count;
          if (!tar_sparse_scan (file, scan_block, buffer))
            return false;
        }
          if (!tar_sparse_scan (file, scan_block, buffer))
            return false;
        }
-      
+
       offset += count;
       offset += count;
-      clear_block (buffer);
     }
     }
-      
+
   if (sp.numbytes == 0)
     sp.offset = offset;
 
   if (sp.numbytes == 0)
     sp.offset = offset;
 
-  sparse_add_map (file, &sp);
-  file->stat_info->archive_file_size += count;
+  sparse_add_map (st, &sp);
+  st->archive_file_size += count;
   return tar_sparse_scan (file, scan_end, NULL);
 }
 
   return tar_sparse_scan (file, scan_end, NULL);
 }
 
-static struct tar_sparse_optab oldgnu_optab;
-static struct tar_sparse_optab star_optab;
-static struct tar_sparse_optab pax_optab;
+static struct tar_sparse_optab const oldgnu_optab;
+static struct tar_sparse_optab const star_optab;
+static struct tar_sparse_optab const pax_optab;
 
 static bool
 sparse_select_optab (struct tar_sparse_file *file)
 
 static bool
 sparse_select_optab (struct tar_sparse_file *file)
@@ -255,7 +279,7 @@ sparse_select_optab (struct tar_sparse_file *file)
     case STAR_FORMAT:
       file->optab = &star_optab;
       break;
     case STAR_FORMAT:
       file->optab = &star_optab;
       break;
-       
+
     default:
       return false;
     }
     default:
       return false;
     }
@@ -263,33 +287,32 @@ sparse_select_optab (struct tar_sparse_file *file)
 }
 
 static bool
 }
 
 static bool
-sparse_dump_region (struct tar_sparse_file *file, size_t index)
+sparse_dump_region (struct tar_sparse_file *file, size_t i)
 {
   union block *blk;
 {
   union block *blk;
-  off_t bytes_left = file->stat_info->sparse_map[index].numbytes;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
-                      SEEK_SET))
+  off_t bytes_left = file->stat_info->sparse_map[i].numbytes;
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
     return false;
 
   while (bytes_left > 0)
     {
       size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
     return false;
 
   while (bytes_left > 0)
     {
       size_t bufsize = (bytes_left > BLOCKSIZE) ? BLOCKSIZE : bytes_left;
-      off_t bytes_read;
-      
+      size_t bytes_read;
+
       blk = find_next_block ();
       blk = find_next_block ();
-      memset (blk->buffer, 0, BLOCKSIZE);
       bytes_read = safe_read (file->fd, blk->buffer, bufsize);
       bytes_read = safe_read (file->fd, blk->buffer, bufsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
        {
           read_diag_details (file->stat_info->orig_file_name,
        {
           read_diag_details (file->stat_info->orig_file_name,
-                            file->stat_info->sparse_map[index].offset
-                                + file->stat_info->sparse_map[index].numbytes
-                                - bytes_left,
-                    bufsize);
+                            (file->stat_info->sparse_map[i].offset
+                             + file->stat_info->sparse_map[i].numbytes
+                             - bytes_left),
+                            bufsize);
          return false;
        }
 
          return false;
        }
 
+      memset (blk->buffer + bytes_read, 0, BLOCKSIZE - bytes_read);
       bytes_left -= bytes_read;
       file->dumped_size += bytes_read;
       set_next_block_after (blk);
       bytes_left -= bytes_read;
       file->dumped_size += bytes_read;
       set_next_block_after (blk);
@@ -299,20 +322,19 @@ sparse_dump_region (struct tar_sparse_file *file, size_t index)
 }
 
 static bool
 }
 
 static bool
-sparse_extract_region (struct tar_sparse_file *file, size_t index)
+sparse_extract_region (struct tar_sparse_file *file, size_t i)
 {
   size_t write_size;
 {
   size_t write_size;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
-                      SEEK_SET))
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
     return false;
 
     return false;
 
-  write_size = file->stat_info->sparse_map[index].numbytes;
+  write_size = file->stat_info->sparse_map[i].numbytes;
 
   if (write_size == 0)
     {
       /* Last block of the file is a hole */
 
   if (write_size == 0)
     {
       /* Last block of the file is a hole */
-      if (sys_truncate (file->fd))
+      if (file->seekable && sys_truncate (file->fd))
        truncate_warn (file->stat_info->orig_file_name);
     }
   else while (write_size > 0)
        truncate_warn (file->stat_info->orig_file_name);
     }
   else while (write_size > 0)
@@ -329,6 +351,7 @@ sparse_extract_region (struct tar_sparse_file *file, size_t index)
       count = full_write (file->fd, blk->buffer, wrbytes);
       write_size -= count;
       file->dumped_size += count;
       count = full_write (file->fd, blk->buffer, wrbytes);
       write_size -= count;
       file->dumped_size += count;
+      file->offset += count;
       if (count != wrbytes)
        {
          write_error_details (file->stat_info->orig_file_name,
       if (count != wrbytes)
        {
          write_error_details (file->stat_info->orig_file_name,
@@ -343,13 +366,14 @@ sparse_extract_region (struct tar_sparse_file *file, size_t index)
 
 /* Interface functions */
 enum dump_status
 
 /* Interface functions */
 enum dump_status
-sparse_dump_file (int fd, struct tar_stat_info *stat)
+sparse_dump_file (int fd, struct tar_stat_info *st)
 {
   bool rc;
 {
   bool rc;
-  struct tar_sparse_file file;
+  struct tar_sparse_file file = { 0, };
 
 
-  file.stat_info = stat;
+  file.stat_info = st;
   file.fd = fd;
   file.fd = fd;
+  file.seekable = true; /* File *must* be seekable for dump to work */
 
   if (!sparse_select_optab (&file)
       || !tar_sparse_init (&file))
 
   if (!sparse_select_optab (&file)
       || !tar_sparse_init (&file))
@@ -369,50 +393,52 @@ sparse_dump_file (int fd, struct tar_stat_info *stat)
        }
     }
 
        }
     }
 
-  pad_archive(file.stat_info->archive_file_size - file.dumped_size);
+  pad_archive (file.stat_info->archive_file_size - file.dumped_size);
   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
   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 *stat)
+sparse_file_p (struct tar_stat_info *st)
 {
 {
-  return (ST_NBLOCKS (stat->stat)
-         < (stat->stat.st_size / ST_NBLOCKSIZE
-            + (stat->stat.st_size % ST_NBLOCKSIZE != 0)));
+  return (ST_NBLOCKS (st->stat)
+         < (st->stat.st_size / ST_NBLOCKSIZE
+            + (st->stat.st_size % ST_NBLOCKSIZE != 0)));
 }
 
 bool
 }
 
 bool
-sparse_member_p (struct tar_stat_info *stat)
+sparse_member_p (struct tar_stat_info *st)
 {
   struct tar_sparse_file file;
 {
   struct tar_sparse_file file;
-  
+
   if (!sparse_select_optab (&file))
     return false;
   if (!sparse_select_optab (&file))
     return false;
-  file.stat_info = stat;
+  file.stat_info = st;
   return tar_sparse_member_p (&file);
 }
 
 bool
   return tar_sparse_member_p (&file);
 }
 
 bool
-sparse_fixup_header (struct tar_stat_info *stat)
+sparse_fixup_header (struct tar_stat_info *st)
 {
   struct tar_sparse_file file;
 {
   struct tar_sparse_file file;
-  
+
   if (!sparse_select_optab (&file))
     return false;
   if (!sparse_select_optab (&file))
     return false;
-  file.stat_info = stat;
+  file.stat_info = st;
   return tar_sparse_fixup_header (&file);
 }
 
 enum dump_status
   return tar_sparse_fixup_header (&file);
 }
 
 enum dump_status
-sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
+sparse_extract_file (int fd, struct tar_stat_info *st, off_t *size)
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = fd;
   file.fd = fd;
+  file.seekable = lseek (fd, 0, SEEK_SET) == 0;
+  file.offset = 0;
 
   if (!sparse_select_optab (&file)
       || !tar_sparse_init (&file))
 
   if (!sparse_select_optab (&file)
       || !tar_sparse_init (&file))
@@ -426,12 +452,12 @@ sparse_extract_file (int fd, struct tar_stat_info *stat, off_t *size)
 }
 
 enum dump_status
 }
 
 enum dump_status
-sparse_skip_file (struct tar_stat_info *stat)
+sparse_skip_file (struct tar_stat_info *st)
 {
   bool rc = true;
   struct tar_sparse_file file;
 {
   bool rc = true;
   struct tar_sparse_file file;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = -1;
 
   if (!sparse_select_optab (&file)
   file.fd = -1;
 
   if (!sparse_select_optab (&file)
@@ -444,24 +470,20 @@ sparse_skip_file (struct tar_stat_info *stat)
 }
 
 \f
 }
 
 \f
-static char diff_buffer[BLOCKSIZE];
-                  
 static bool
 check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
 {
 static bool
 check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
 {
-  if (!lseek_or_error (file, beg, SEEK_SET))
+  if (!lseek_or_error (file, beg))
     return false;
     return false;
-  
+
   while (beg < end)
     {
       size_t bytes_read;
   while (beg < end)
     {
       size_t bytes_read;
-      size_t rdsize = end - beg;
-      
-      if (rdsize > BLOCKSIZE)
-       rdsize = BLOCKSIZE;
-      clear_block (diff_buffer);
+      size_t rdsize = BLOCKSIZE < end - beg ? BLOCKSIZE : end - beg;
+      char diff_buffer[BLOCKSIZE];
+
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
        {
           read_diag_details (file->stat_info->orig_file_name,
                             beg,
        {
           read_diag_details (file->stat_info->orig_file_name,
                             beg,
@@ -470,8 +492,10 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
        }
       if (!zero_block_p (diff_buffer, bytes_read))
        {
        }
       if (!zero_block_p (diff_buffer, bytes_read))
        {
+         char begbuf[INT_BUFSIZE_BOUND (off_t)];
          report_difference (file->stat_info,
          report_difference (file->stat_info,
-                            _("File fragment at %lu is not a hole"), beg);
+                            _("File fragment at %s is not a hole"),
+                            offtostr (beg, begbuf));
          return false;
        }
 
          return false;
        }
 
@@ -481,19 +505,19 @@ check_sparse_region (struct tar_sparse_file *file, off_t beg, off_t end)
 }
 
 static bool
 }
 
 static bool
-check_data_region (struct tar_sparse_file *file, size_t index)
+check_data_region (struct tar_sparse_file *file, size_t i)
 {
   size_t size_left;
 {
   size_t size_left;
-  
-  if (!lseek_or_error (file, file->stat_info->sparse_map[index].offset,
-                      SEEK_SET))
+
+  if (!lseek_or_error (file, file->stat_info->sparse_map[i].offset))
     return false;
     return false;
-  size_left = file->stat_info->sparse_map[index].numbytes;
+  size_left = file->stat_info->sparse_map[i].numbytes;
   while (size_left > 0)
     {
       size_t bytes_read;
       size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
   while (size_left > 0)
     {
       size_t bytes_read;
       size_t rdsize = (size_left > BLOCKSIZE) ? BLOCKSIZE : size_left;
-      
+      char diff_buffer[BLOCKSIZE];
+
       union block *blk = find_next_block ();
       if (!blk)
        {
       union block *blk = find_next_block ();
       if (!blk)
        {
@@ -502,12 +526,12 @@ check_data_region (struct tar_sparse_file *file, size_t index)
        }
       set_next_block_after (blk);
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
        }
       set_next_block_after (blk);
       bytes_read = safe_read (file->fd, diff_buffer, rdsize);
-      if (bytes_read < 0)
+      if (bytes_read == SAFE_READ_ERROR)
        {
           read_diag_details (file->stat_info->orig_file_name,
        {
           read_diag_details (file->stat_info->orig_file_name,
-                            file->stat_info->sparse_map[index].offset
-                                + file->stat_info->sparse_map[index].numbytes
-                                - size_left,
+                            (file->stat_info->sparse_map[i].offset
+                             + file->stat_info->sparse_map[i].numbytes
+                             - size_left),
                             rdsize);
          return false;
        }
                             rdsize);
          return false;
        }
@@ -523,14 +547,14 @@ check_data_region (struct tar_sparse_file *file, size_t index)
 }
 
 bool
 }
 
 bool
-sparse_diff_file (int fd, struct tar_stat_info *stat)
+sparse_diff_file (int fd, struct tar_stat_info *st)
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
   off_t offset = 0;
 {
   bool rc = true;
   struct tar_sparse_file file;
   size_t i;
   off_t offset = 0;
-  
-  file.stat_info = stat;
+
+  file.stat_info = st;
   file.fd = fd;
 
   if (!sparse_select_optab (&file)
   file.fd = fd;
 
   if (!sparse_select_optab (&file)
@@ -554,14 +578,14 @@ sparse_diff_file (int fd, struct tar_stat_info *stat)
   return rc;
 }
 
   return rc;
 }
 
-\f     
+\f
 /* Old GNU Format. The sparse file information is stored in the
    oldgnu_header in the following manner:
 
    The header is marked with type 'S'. Its `size' field contains
    the cumulative size of all non-empty blocks of the file. The
    actual file size is stored in `realsize' member of oldgnu_header.
 /* Old GNU Format. The sparse file information is stored in the
    oldgnu_header in the following manner:
 
    The header is marked with type 'S'. Its `size' field contains
    the cumulative size of all non-empty blocks of the file. The
    actual file size is stored in `realsize' member of oldgnu_header.
-   
+
    The map of the file is stored in a list of `struct sparse'.
    Each struct contains offset to the block of data and its
    size (both as octal numbers). The first file header contains
    The map of the file is stored in a list of `struct sparse'.
    Each struct contains offset to the block of data and its
    size (both as octal numbers). The first file header contains
@@ -581,13 +605,13 @@ enum oldgnu_add_status
   };
 
 static bool
   };
 
 static bool
-oldgnu_sparse_member_p (struct tar_sparse_file *file_unused)
+oldgnu_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
 
 /* Add a sparse item to the sparse file and its obstack */
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
 
 /* Add a sparse item to the sparse file and its obstack */
-static enum oldgnu_add_status 
+static enum oldgnu_add_status
 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
 {
   struct sp_array sp;
 oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
 {
   struct sp_array sp;
@@ -601,7 +625,7 @@ oldgnu_add_sparse (struct tar_sparse_file *file, struct sparse *s)
       || file->stat_info->archive_file_size < 0)
     return add_fail;
 
       || file->stat_info->archive_file_size < 0)
     return add_fail;
 
-  sparse_add_map (file, &sp);
+  sparse_add_map (file->stat_info, &sp);
   return add_ok;
 }
 
   return add_ok;
 }
 
@@ -612,7 +636,7 @@ oldgnu_fixup_header (struct tar_sparse_file *file)
      which actually contains archived size. The following fixes it */
   file->stat_info->archive_file_size = file->stat_info->stat.st_size;
   file->stat_info->stat.st_size =
      which actually contains archived size. The following fixes it */
   file->stat_info->archive_file_size = file->stat_info->stat.st_size;
   file->stat_info->stat.st_size =
-                OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
+    OFF_FROM_HEADER (current_header->oldgnu_header.realsize);
   return true;
 }
 
   return true;
 }
 
@@ -623,9 +647,9 @@ oldgnu_get_sparse_info (struct tar_sparse_file *file)
   size_t i;
   union block *h = current_header;
   int ext_p;
   size_t i;
   union block *h = current_header;
   int ext_p;
-  static enum oldgnu_add_status rc;
-  
-  file->stat_info->sparse_map_size = 0;
+  enum oldgnu_add_status rc;
+
+  file->stat_info->sparse_map_avail = 0;
   for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
     {
       rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
   for (i = 0; i < SPARSES_IN_OLDGNU_HEADER; i++)
     {
       rc = oldgnu_add_sparse (file, &h->oldgnu_header.sp[i]);
@@ -676,7 +700,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
   off_t block_ordinal = current_block_ordinal ();
   union block *blk;
   size_t i;
   off_t block_ordinal = current_block_ordinal ();
   union block *blk;
   size_t i;
-    
+
   blk = start_header (file->stat_info);
   blk->header.typeflag = GNUTYPE_SPARSE;
   if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
   blk = start_header (file->stat_info);
   blk->header.typeflag = GNUTYPE_SPARSE;
   if (file->stat_info->sparse_map_avail > SPARSES_IN_OLDGNU_HEADER)
@@ -693,7 +717,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
                            SPARSES_IN_OLDGNU_HEADER);
   blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
   finish_header (file->stat_info, blk, block_ordinal);
                            SPARSES_IN_OLDGNU_HEADER);
   blk->oldgnu_header.isextended = i < file->stat_info->sparse_map_avail;
   finish_header (file->stat_info, blk, block_ordinal);
-  
+
   while (i < file->stat_info->sparse_map_avail)
     {
       blk = find_next_block ();
   while (i < file->stat_info->sparse_map_avail)
     {
       blk = find_next_block ();
@@ -710,7 +734,7 @@ oldgnu_dump_header (struct tar_sparse_file *file)
   return true;
 }
 
   return true;
 }
 
-static struct tar_sparse_optab oldgnu_optab = {
+static struct tar_sparse_optab const oldgnu_optab = {
   NULL,  /* No init function */
   NULL,  /* No done function */
   oldgnu_sparse_member_p,
   NULL,  /* No init function */
   NULL,  /* No done function */
   oldgnu_sparse_member_p,
@@ -726,7 +750,7 @@ static struct tar_sparse_optab oldgnu_optab = {
 /* Star */
 
 static bool
 /* Star */
 
 static bool
-star_sparse_member_p (struct tar_sparse_file *file_unused)
+star_sparse_member_p (struct tar_sparse_file *file __attribute__ ((unused)))
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
 {
   return current_header->header.typeflag == GNUTYPE_SPARSE;
 }
@@ -749,9 +773,9 @@ star_get_sparse_info (struct tar_sparse_file *file)
   size_t i;
   union block *h = current_header;
   int ext_p;
   size_t i;
   union block *h = current_header;
   int ext_p;
-  static enum oldgnu_add_status rc;
-  
-  file->stat_info->sparse_map_size = 0;
+  enum oldgnu_add_status rc = add_ok;
+
+  file->stat_info->sparse_map_avail = 0;
 
   if (h->star_in_header.prefix[0] == '\0'
       && h->star_in_header.sp[0].offset[10] != '\0')
 
   if (h->star_in_header.prefix[0] == '\0'
       && h->star_in_header.sp[0].offset[10] != '\0')
@@ -791,7 +815,7 @@ star_get_sparse_info (struct tar_sparse_file *file)
 }
 
 
 }
 
 
-static struct tar_sparse_optab star_optab = {
+static struct tar_sparse_optab const star_optab = {
   NULL,  /* No init function */
   NULL,  /* No done function */
   star_sparse_member_p,
   NULL,  /* No init function */
   NULL,  /* No done function */
   star_sparse_member_p,
@@ -799,7 +823,7 @@ static struct tar_sparse_optab star_optab = {
   star_fixup_header,
   star_get_sparse_info,
   NULL,  /* No scan_block function */
   star_fixup_header,
   star_get_sparse_info,
   NULL,  /* No scan_block function */
-  NULL, /* No dump region function */ 
+  NULL, /* No dump region function */
   sparse_extract_region,
 };
 
   sparse_extract_region,
 };
 
@@ -836,7 +860,7 @@ pax_dump_header (struct tar_sparse_file *file)
       xheader_store ("GNU.sparse.offset", file->stat_info, &i);
       xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
     }
       xheader_store ("GNU.sparse.offset", file->stat_info, &i);
       xheader_store ("GNU.sparse.numbytes", file->stat_info, &i);
     }
-  
+
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
   blk = start_header (file->stat_info);
   /* Store the effective (shrunken) file size */
   OFF_TO_CHARS (file->stat_info->archive_file_size, blk->header.size);
@@ -844,7 +868,7 @@ pax_dump_header (struct tar_sparse_file *file)
   return true;
 }
 
   return true;
 }
 
-static struct tar_sparse_optab pax_optab = {
+static struct tar_sparse_optab const pax_optab = {
   NULL,  /* No init function */
   NULL,  /* No done function */
   pax_sparse_member_p,
   NULL,  /* No init function */
   NULL,  /* No done function */
   pax_sparse_member_p,
@@ -855,4 +879,3 @@ static struct tar_sparse_optab pax_optab = {
   sparse_dump_region,
   sparse_extract_region,
 };
   sparse_dump_region,
   sparse_extract_region,
 };
-
This page took 0.040108 seconds and 4 git commands to generate.